【发布时间】:2014-03-02 15:20:12
【问题描述】:
我一直在寻找如何将 exe 读入内存并直接从内存中执行。然后我通过了这个非常有用的答案CreateProcess from memory buffer。
幸运的是,我找到了一些实现上述想法的代码。经过一些调整后,我得到了它的工作。
#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>
void RunFromMemory(unsigned char* pImage,char* pPath)
{
DWORD dwWritten = 0;
DWORD dwHeader = 0;
DWORD dwImageSize = 0;
DWORD dwSectionCount = 0;
DWORD dwSectionSize = 0;
DWORD firstSection = 0;
DWORD previousProtection = 0;
DWORD jmpSize = 0;
IMAGE_NT_HEADERS INH;
IMAGE_DOS_HEADER IDH;
IMAGE_SECTION_HEADER Sections[1000];
PROCESS_INFORMATION peProcessInformation;
STARTUPINFO peStartUpInformation;
CONTEXT pContext;
SECURITY_ATTRIBUTES secAttrib;
char* pMemory;
char* pFile;
memcpy(&IDH,pImage,sizeof(IDH));
memcpy(&INH,(void*)((DWORD)pImage+IDH.e_lfanew),sizeof(INH));
dwImageSize = INH.OptionalHeader.SizeOfImage;
pMemory = (char*)malloc(dwImageSize);
memset(pMemory,0,dwImageSize);
pFile = pMemory;
dwHeader = INH.OptionalHeader.SizeOfHeaders;
firstSection = (DWORD)(((DWORD)pImage+IDH.e_lfanew) + sizeof(IMAGE_NT_HEADERS));
memcpy(Sections,(char*)(firstSection),sizeof(IMAGE_SECTION_HEADER)*INH.FileHeader.NumberOfSections);
memcpy(pFile,pImage,dwHeader);
if((INH.OptionalHeader.SizeOfHeaders % INH.OptionalHeader.SectionAlignment)==0)
{
jmpSize = INH.OptionalHeader.SizeOfHeaders;
}
else
{
jmpSize = INH.OptionalHeader.SizeOfHeaders / INH.OptionalHeader.SectionAlignment;
jmpSize += 1;
jmpSize *= INH.OptionalHeader.SectionAlignment;
}
pFile = (char*)((DWORD)pFile + jmpSize);
for(dwSectionCount = 0; dwSectionCount < INH.FileHeader.NumberOfSections; dwSectionCount++)
{
jmpSize = 0;
dwSectionSize = Sections[dwSectionCount].SizeOfRawData;
memcpy(pFile,(char*)(pImage + Sections[dwSectionCount].PointerToRawData),dwSectionSize);
if((Sections[dwSectionCount].Misc.VirtualSize % INH.OptionalHeader.SectionAlignment)==0)
{
jmpSize = Sections[dwSectionCount].Misc.VirtualSize;
}
else
{
jmpSize = Sections[dwSectionCount].Misc.VirtualSize / INH.OptionalHeader.SectionAlignment;
jmpSize += 1;
jmpSize *= INH.OptionalHeader.SectionAlignment;
}
pFile = (char*)((DWORD)pFile + jmpSize);
}
memset(&peStartUpInformation,0,sizeof(STARTUPINFO));
memset(&peProcessInformation,0,sizeof(PROCESS_INFORMATION));
memset(&pContext,0,sizeof(CONTEXT));
peStartUpInformation.cb = sizeof(peStartUpInformation);
if(CreateProcess(NULL,pPath,NULL,NULL,false,CREATE_SUSPENDED, NULL,NULL,&peStartUpInformation,&peProcessInformation))
{
pContext.ContextFlags = CONTEXT_FULL;
GetThreadContext(peProcessInformation.hThread,&pContext);
VirtualProtectEx(peProcessInformation.hProcess,(void*)((DWORD)INH.OptionalHeader.ImageBase),dwImageSize,PAGE_EXECUTE_READWRITE,&previousProtection);
WriteProcessMemory(peProcessInformation.hProcess,(void*)((DWORD)INH.OptionalHeader.ImageBase),pMemory,dwImageSize,&dwWritten);
WriteProcessMemory(peProcessInformation.hProcess,(void*)((DWORD)pContext.Ebx + 8),&INH.OptionalHeader.ImageBase,4,&dwWritten);
pContext.Eax = INH.OptionalHeader.ImageBase + INH.OptionalHeader.AddressOfEntryPoint;
SetThreadContext(peProcessInformation.hThread,&pContext);
VirtualProtectEx(peProcessInformation.hProcess,(void*)((DWORD)INH.OptionalHeader.ImageBase),dwImageSize,previousProtection,0);
ResumeThread(peProcessInformation.hThread);
}
else{
// for debugging
DWORD er = GetLastError();
DWORD x = er;
}
free(pMemory);
}
int main()
{
//*********** open file to encrypt ************
char exe_path[] = "C:\\prog.exe";
FILE *inFile = fopen(exe_path, "rb");
fseek(inFile , 0 , SEEK_END);
unsigned long dwSize = ftell(inFile);
rewind(inFile);
unsigned char *lpMemory = (unsigned char*) malloc (sizeof(unsigned char)*dwSize);
fread(lpMemory,1,dwSize,inFile);
fclose (inFile);
//**********************************************
//********* execute ***********
RunFromMemory(lpMemory,exe_path);
return 0;
}
我将一个名为 prog.exe 的示例程序放入我的 C 驱动器中,这段代码将它读入内存并执行它。此代码在 Windows XP 上完美运行,但我无法让它在 Windows 7 上运行,因为它会启动此错误消息。
The application was unable to start correctly (0xc000000c). Click OK to close the application.
我不明白它在 Windows XP 上正常工作但在 Windows 7 上不能正常工作的原因。Windows 7 是否对 PE 格式或标题或其他内容进行了一些更改??
提前致谢。如果有人想测试它,请不要忘记将您的示例 exe 设置为 C:\prog.exe 或根据需要更改代码中的路径。
【问题讨论】:
-
这是一个不受支持的黑客攻击。如果在 XP 和 Win7 之间发生变化,您为什么会感到惊讶?您确实意识到病毒扫描程序不会喜欢您的程序。
-
对于初学者,您可以尝试不让程序存根驻留在 c:\。
-
只有一个合法用途(在 32 位资源中打包一个 64 位版本),它被各种 sysinternals 实用程序使用......但即使它们只是解压缩到同一个文件夹中。您真的不想尝试复制加载器的功能,它非常复杂,并且比您更了解过程和加载它。