将shellcode放在PE文件新增的节表中
// InsertShellCodeToPE.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <Windows.h> #define FILENAME "hello.exe" //自定义的shellcode char shellcode[] = "\x90\x90\x90\x90\xb8\x90\x90\x90\x90\xff\xe0\x00"; /************************************************************************/ /* 函数说明:将dwNum按dwAlign大小生成对齐大小 */ /* 参数:dwNum 待对齐的数据长度 */ /* dwAlign 对齐粒度 */ /* 返回值:返回按指定粒度对齐后的大小 */ /************************************************************************/ DWORD Align(DWORD dwNum, DWORD dwAlign) { if (dwNum % dwAlign == 0) { return dwNum; } else { return (dwNum / dwAlign + 1) * dwAlign; } } int main(int argc, char* argv[]) { HANDLE hFile = ::CreateFile(FILENAME, FILE_GENERIC_READ|FILE_GENERIC_WRITE|FILE_GENERIC_EXECUTE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (NULL == hFile) { printf("createfile error"); return -1; } HANDLE hFileMap = ::CreateFileMapping(hFile, NULL, PAGE_EXECUTE_READWRITE, 0, 0, NULL); int n = GetLastError(); if (NULL == hFileMap) { printf("CreateFileMapping error"); return -1; } LPVOID lpMemory = ::MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (NULL == lpMemory) { printf("MapViewOfFile error"); return -1; } PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpMemory; PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)lpMemory + pDosHeader->e_lfanew); PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)&(pNTHeader->FileHeader); PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNTHeader->OptionalHeader; PIMAGE_SECTION_HEADER pSection = NULL; IMAGE_SECTION_HEADER secToAdd = {0}; if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE || pNTHeader->Signature != IMAGE_NT_SIGNATURE) { printf("Not valid PE file..."); return -1; } pSection = (PIMAGE_SECTION_HEADER)((BYTE*)pOptionalHeader + pFileHeader->SizeOfOptionalHeader); DWORD dwSectionNum = pFileHeader->NumberOfSections; DWORD dwSectionAlign = pOptionalHeader->SectionAlignment; DWORD dwOEP = pOptionalHeader->AddressOfEntryPoint; dwOEP = (DWORD)(pOptionalHeader->ImageBase + dwOEP); pSection = pSection + dwSectionNum - 1; //pSection指向了最后一个section节表的起始,下面根据最后一个section节表设置新的节表数据 strcpy((char *)secToAdd.Name, ".xiaoju"); secToAdd.Characteristics = pSection->Characteristics; secToAdd.VirtualAddress = pSection->VirtualAddress + Align(pSection->Misc.VirtualSize, dwSectionAlign); secToAdd.Misc.VirtualSize = dwSectionAlign; secToAdd.PointerToRawData = pSection->PointerToRawData + pSection->SizeOfRawData; secToAdd.SizeOfRawData = dwSectionAlign; pSection++; //pSection指向了所有节表的最后 //写入新的节表 memcpy(pSection, &secToAdd, sizeof(IMAGE_SECTION_HEADER)); //改写pe文件中节表的数量 pFileHeader->NumberOfSections++; //将shellcode中的预留位填充好 *(DWORD*)&shellcode[5] = dwOEP; //增加文件大小 BYTE bNum = '\x0'; DWORD dwWritten = 0; ::SetFilePointer(hFile, 0, 0, FILE_END); ::WriteFile(hFile, &bNum, dwSectionAlign, &dwWritten, NULL); //在新增节表的PointerToRawData处写入shellcode ::SetFilePointer(hFile, pSection->PointerToRawData, 0, FILE_BEGIN); ::WriteFile(hFile, shellcode, strlen(shellcode)+3, &dwWritten, NULL); //修改程序的映象大小和OEP pOptionalHeader->SizeOfImage = pOptionalHeader->SizeOfImage + dwSectionAlign; pOptionalHeader->AddressOfEntryPoint = pSection->VirtualAddress; ::UnmapViewOfFile(lpMemory); ::CloseHandle(hFileMap); ::CloseHandle(hFile); return 0; }
原始hello.exe
程序运行后,修改后的hello.exe