早上起来忙了两个小时, 主要参考的红色病毒的代码,一直在更改中
还有四步才能实现
帖一下半成品的代码
// TestShell.cpp : Defines the entry point for the application. // #include "stdafx.h" #include <windows.h> #include <stdio.h> #include <stdlib.h> #include "PEOperate.h" /* 以挂起的形式创建进程, 获取Context */ #define KEY 0x56 #define isDebug 0 #pragma pack(push, 1) typedef struct{ unsigned long VirtualAddress; unsigned long SizeOfBlock; } *PImageBaseRelocation; #pragma pack(pop) // 重定向PE用到的地址 //void DoRelocation(PIMAGE_NT_HEADERS peH, void *OldBase, void *NewBase) void DoRelocation(LPVOID pFileBuffer, void *OldBase, void *NewBase) { PIMAGE_DOS_HEADER pDosHeader = NULL; pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; PIMAGE_NT_HEADERS peH = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); unsigned long Delta = (unsigned long)NewBase - peH->OptionalHeader.ImageBase; PImageBaseRelocation p = (PImageBaseRelocation)((unsigned long)OldBase + peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); while(p->VirtualAddress + p->SizeOfBlock) { unsigned short *pw = (unsigned short *)((int)p + sizeof(*p)); for(unsigned int i=1; i <= (p->SizeOfBlock - sizeof(*p)) / 2; ++i) { if((*pw) & 0xF000 == 0x3000){ unsigned long *t = (unsigned long *)((unsigned long)(OldBase) + p->VirtualAddress + ((*pw) & 0x0FFF)); *t += Delta; } ++pw; } p = (PImageBaseRelocation)pw; } } VOID GetNtHeaderInfo(LPVOID pFileBuffer,DWORD &ImageBase,DWORD &ImageSize) { PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; //pFileBuffer= ReadPEFile(lpszFile); if(!pFileBuffer) { printf("文件读取失败\n"); return; } //MZ标志 if(*((PWORD)pFileBuffer)!=IMAGE_DOS_SIGNATURE) { printf("不是有效的MZ标志\n"); free(pFileBuffer); return; } pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; //打印DOS头 printf("------------DOS头------------\n"); printf("MZ标志: %x\n",pDosHeader->e_magic); printf("PE偏移: %x\n",pDosHeader->e_lfanew); //判断是否是有效的PE if(*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew))!=IMAGE_NT_SIGNATURE) { printf("不是有效的PE标志\n"); free(pFileBuffer); return; } pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); //打印NT头 printf("------------NT头------------\n"); printf("Signature: %x\n",pNTHeader->Signature); pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4); printf("------------标准PE头--------\n"); printf("Machine: %x\n",pPEHeader->Machine); printf("节的数量: %x\n",pPEHeader->NumberOfSections); printf("SizeOfOptionHeaders: %x\n",pPEHeader->SizeOfOptionalHeader); //可选择PE头 pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER); printf("------------OPTION_PE头--------\n"); printf("Machine: %x \n",pOptionHeader->Magic); printf("OEP: %x \n",pOptionHeader->AddressOfEntryPoint); printf("ImageBase: %x \n",pOptionHeader->ImageBase); printf("SectionAlignment: %x \n",pOptionHeader->SectionAlignment); printf("FileAlignment: %x \n",pOptionHeader->FileAlignment); printf("SizeOfImage: %x \n",pOptionHeader->SizeOfImage); printf("SizeOfHeaders: %x \n",pOptionHeader->SizeOfHeaders); //获取信息 ImageBase = pOptionHeader->ImageBase; ImageSize = pOptionHeader->SizeOfImage; } //是否有重定位表 BOOL HasRelocationTable(LPVOID pFileBuffer) { /* LPVOID pFileBuffer = NULL; pFileBuffer= ReadPEFile(lpszFile); if(!pFileBuffer) { printf("文件读取失败\n"); return; } */ PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; PIMAGE_DATA_DIRECTORY DataDirectory=NULL; //Header信息 pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader); //定位Directory_Data; DataDirectory = pOptionHeader->DataDirectory; //重定位表 printf("IMAGE_DIRECTORY_ENTRY_BASERELOC: Address: %x ,Size: %x \n",DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); return (DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) && (DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); } //BOOL isAlloc = AllocShellSize(shellDirectory,pi.hProcess,encryptFileBuffer); //在指定位置分配空间 BOOL AllocShellSize(LPSTR shellDirectory,HANDLE shellProcess,LPVOID encryptFileBuffer) { typedef void *(__stdcall *pfVirtualAllocEx)(unsigned long, void *, unsigned long, unsigned long, unsigned long); pfVirtualAllocEx MyVirtualAllocEx = NULL; MyVirtualAllocEx = (pfVirtualAllocEx)GetProcAddress(GetModuleHandle("Kernel32.dll"), "VirtualAllocEx"); //p = MyVirtualAllocEx((unsigned long)res, (void *)peH->OptionalHeader.ImageBase, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); //p = MyVirtualAllocEx((unsigned long)res, NULL, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); //定位原始的shell的信息 LPVOID pShellBuffer = ReadPEFile(shellDirectory); //LPVOID encryptFileBuffer; //获得ImageBase ImageSize, 进行信息比较 DWORD shellImageBase=0; DWORD shellImageSize=0; DWORD encryptImageBase=0; DWORD encryptImageSize=0; GetNtHeaderInfo(pShellBuffer,shellImageBase,shellImageSize); GetNtHeaderInfo(encryptFileBuffer,encryptImageBase,encryptImageSize); /* TCHAR szTempStr[256]={0}; sprintf(szTempStr,"shell: Base-%x,Size-%x, Encrypt: Base-%x,Size-%x",shellImageBase,shellImageSize,encryptImageBase,encryptImageSize); MessageBox(0,szTempStr,"info",MB_OK); */ if(shellImageBase == 0 || shellImageSize==0) { MessageBox(0,"申请空间失败1","失败1",0); return FALSE; } if(encryptImageBase == 0 || encryptImageSize==0) { MessageBox(0,"申请空间失败2","失败2",0); if(isDebug){ return FALSE; } } void *p = NULL; //在指定进程中分配内存 if(shellImageBase == encryptImageBase && shellImageSize>=encryptImageSize) { // 最好的分配方式 p = VirtualAllocEx(shellProcess,(void*)shellImageBase,shellImageSize,MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); }else { //自定义分配内存 p = VirtualAllocEx(shellProcess,(void*)encryptImageBase,encryptImageSize,MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); } // 分配内存失败并且目标进程支持重定向 if((p == NULL) && HasRelocationTable(encryptFileBuffer)){ //任意位置分配空间 p = VirtualAllocEx(shellProcess, NULL, encryptImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); //开始重定位处理 if(p) DoRelocation(encryptFileBuffer, (void*)encryptImageBase, p); // 重定向 }else { MessageBox(0,"申请空间失败3","失败3",0); if(isDebug){ return FALSE; } } //把代码贴入该内存中 return FALSE; } // 卸载原外壳占用内存 BOOL UnloadShell(HANDLE ProcHnd, unsigned long BaseAddr) { typedef unsigned long (__stdcall *pfZwUnmapViewOfSection)(unsigned long, unsigned long); pfZwUnmapViewOfSection ZwUnmapViewOfSection = NULL; BOOL res = FALSE; HMODULE m = LoadLibrary("ntdll.dll"); if(m){ ZwUnmapViewOfSection = (pfZwUnmapViewOfSection)GetProcAddress(m, "ZwUnmapViewOfSection"); //MessageBox(0,"1111",0,0); if(ZwUnmapViewOfSection) res = (ZwUnmapViewOfSection((unsigned long)ProcHnd, BaseAddr) == 0); FreeLibrary(m); } return res; } LPVOID GetLastSecData(LPSTR lpszFile,DWORD &fileSize) { LPVOID pFileBuffer = NULL; pFileBuffer= ReadPEFile(lpszFile); if(!pFileBuffer) { printf("文件读取失败\n"); return NULL; } PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader_LAST = NULL; //Header信息 pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader); pSectionHeader_LAST = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+(pPEHeader->NumberOfSections-1)*40); int fileLength = pSectionHeader_LAST->PointerToRawData+pSectionHeader_LAST->SizeOfRawData; //判断是否已经加壳 if(strcmp((char*)pSectionHeader_LAST->Name,".enSec")!=0) { MessageBox(0,"没有加壳","错误",0); return NULL; } fileSize = pSectionHeader_LAST->SizeOfRawData; LPVOID pEncryptBuffer = malloc(fileSize); memset(pEncryptBuffer,0,fileSize); CHAR* pNew = (CHAR*)pEncryptBuffer; CHAR* pOld = (CHAR*)((DWORD)pFileBuffer+pSectionHeader_LAST->PointerToRawData); //将最后一个段的数据拷贝到pEncryptBuffer中,并解密 for(int i=0;i<(int)fileSize;i++) { pNew[i] = pOld[i]^KEY; } //关闭文件 free(pFileBuffer); return pEncryptBuffer; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. TCHAR shellDirectory[256]={0}; GetModuleFileName(NULL,shellDirectory,256); //MessageBox(0,shellDirectory,0,0); DWORD encryptSize = 0; LPVOID encryptFileBuffer = NULL; encryptFileBuffer = GetLastSecData(shellDirectory,encryptSize); //失败则结束 if(encryptFileBuffer == NULL) { MessageBox(0,"解密失败","失败",0); //return 0; if(isDebug){ return 0; } } //成功,goon //WirteToFile(encryptFileBuffer,encryptSize,"C:\\aaa.exe"); //MessageBox(0,"结束","写出完成",MB_OK); //以挂起的形式创建进程 STARTUPINFO si={0}; si.cb = sizeof(STARTUPINFO); PROCESS_INFORMATION pi; CreateProcess(shellDirectory, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si,&pi); TCHAR szTempStr[256]={0}; sprintf(szTempStr,"进程消息: %x , %x \n",pi.hProcess,pi.hThread); CONTEXT contx; contx.ContextFlags = CONTEXT_FULL; GetThreadContext(pi.hThread,&contx); DWORD shellOEP = contx.Eax; //获取IMAGE_BASE的信息 char* baseAddress = (CHAR*)contx.Ebx+8; TCHAR szBuffer[4]={0}; ReadProcessMemory(pi.hProcess,baseAddress,szBuffer,4,NULL); int* fileImageBase; fileImageBase = (int*)szBuffer; DWORD shellImageBase = *fileImageBase; //卸载外壳程序内存 BOOL isUnload = UnloadShell(pi.hProcess,shellImageBase); /* if(isUnload) { MessageBox(0,"成功","1",0); }else { MessageBox(0,"失败","0",0); } */ //在指定位置分配空间 //位置: Src的ImageBase //大小: Src的SizeOfImage //shellDirectory BOOL isAlloc = AllocShellSize(shellDirectory,pi.hProcess,encryptFileBuffer); ResumeThread(pi.hThread); //TerminateProcess(pi.hThread,2); return 0; }
0则评论给“文件加壳实现(四) —— VirtualAllocEx”