还不完整, 继续整理中
// 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 #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) { 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; } } //在指定位置分配空间 BOOL AllocShellSize() { 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); 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; } //成功,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 BOOL isAlloc = AllocShellSize(); //ResumeThread(pi.hThread); return 0; }
0则评论给“文件加壳实现(三) —— ZwUnmapViewOfSection”