|
认真请教:有没有人实现过从内存运行EXE?
2013年干过这事, 当时是在windows xp上试的, 原理是把exe当成资源编译到你的程序中, 然后读到内在加载, 如果还不放心, 可以先把exe用upx加壳, 再放到资源中, 代码如下: /////////////////////////////////////////////////// // date: 2013.08.15 // author: 刘立向 // email: llxxhm@126.com // qq: 515311445 /////////////////////////////////////////////////// #include <windows.h> #pragma pack(push, 1) typedef struct { DWORD VirtualAddress; DWORD SizeOfBlock; } *PImageBaseRelocation; #pragma pack(pop) typedef IMAGE_SECTION_HEADER (*PIMAGE_SECTION_HEADERS)[1]; HANDLE MemExecute(VOID *MemBuffer, DWORD dwBufSize); BOOL AlignPEToMem( VOID *MemBuffer, DWORD dwBufSize, PIMAGE_NT_HEADERS &peHead, PIMAGE_SECTION_HEADERS &peSecHead, VOID *&MemPtr, DWORD &ImageSize); DWORD CalcTotalImageSize(PIMAGE_DOS_HEADER szMzHead, DWORD dwBufSize, PIMAGE_NT_HEADERS peHead, PIMAGE_SECTION_HEADERS peSecHead); DWORD GetAlignedSize(DWORD Origin, DWORD Alignment); HANDLE AttachPE(PIMAGE_NT_HEADERS peHead, VOID *MemPtr, DWORD ImageSize); BOOL CreateMemProcess(CONTEXT &Context, HANDLE &hHandle, HANDLE &hThread, DWORD &BaseAddr, DWORD &ImageSize); BOOL UnloadShell(HANDLE hProcess, DWORD BaseAddr); BOOL HasRelocationTable(PIMAGE_NT_HEADERS peHead); VOID DoRelocation(PIMAGE_NT_HEADERS peHead, VOID *OldBase, VOID *NewBase); /* 运行资源中的EXE文件使用方法: HRSRC hResource = FindResource(GetModuleHandle(NULL),MAKEINTRESOURCE(IDR_FILE_STC_ISP),TEXT("File")); if(hResource) { HGLOBAL hg = LoadResource(GetModuleHandle(NULL),hResource); if(hg) { LPVOID pData = LockResource(hg); if(pData) { DWORD dwSize = SizeofResource(GetModuleHandle(NULL),hResource); hProcess = MemExecute(pData,dwSize); if(hProcess != INVALID_HANDLE_VALUE) { CloseHandle(CreateThread(NULL,0,WaitProcessExit,hWnd,NULL,0)); return TRUE; } } } } */ /////////////////////////////////////////////////// // date: 2013.08.15 // author: 刘立向 // email: llxxhm@126.com // qq: 515311445 /////////////////////////////////////////////////// #include "PeApi.h" HANDLE MemExecute(VOID *MemBuffer, DWORD dwBufSize) { DWORD ImageSize = 0; VOID *MemPtr = NULL; PIMAGE_NT_HEADERS peHead; PIMAGE_SECTION_HEADERS peSecHead; HANDLE hProcess = INVALID_HANDLE_VALUE; if(AlignPEToMem(MemBuffer, dwBufSize, peHead, peSecHead, MemPtr, ImageSize)) { hProcess = AttachPE(peHead, MemPtr, ImageSize); VirtualFree(MemPtr, ImageSize, MEM_DECOMMIT); } return hProcess; } // 加载pe到内存并对齐所有节 BOOL AlignPEToMem( VOID *MemBuffer, DWORD dwBufSize, PIMAGE_NT_HEADERS &peHead, PIMAGE_SECTION_HEADERS &peSecHead, VOID *&MemPtr, DWORD &ImageSize) { PIMAGE_SECTION_HEADERS szPeSecHead;// 节表 PIMAGE_DOS_HEADER szMzHead = (PIMAGE_DOS_HEADER)MemBuffer; // DOS头 if( dwBufSize < sizeof(IMAGE_DOS_HEADER) ) return FALSE; if( szMzHead->e_magic != IMAGE_DOS_SIGNATURE ) return FALSE; if( dwBufSize < szMzHead->e_lfanew + (DWORD)sizeof(IMAGE_NT_HEADERS) ) return FALSE; PIMAGE_NT_HEADERS SrcPeH = (PIMAGE_NT_HEADERS)((int)szMzHead + szMzHead->e_lfanew); //PE头 if( SrcPeH->Signature != IMAGE_NT_SIGNATURE ) return FALSE; if( (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_DLL) || (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE == 0) || (SrcPeH->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)) ) return FALSE; szPeSecHead = (PIMAGE_SECTION_HEADERS)((int)SrcPeH + sizeof(IMAGE_NT_HEADERS)); ImageSize = CalcTotalImageSize( szMzHead, dwBufSize, SrcPeH, szPeSecHead); if(ImageSize == 0) return FALSE; MemPtr = VirtualAlloc( NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // 分配内存 if( MemPtr != NULL ) { // 计算需要复制的PE头字节数 DWORD dwHeadSize = SrcPeH->OptionalHeader.SizeOfHeaders; for( int i = 0; i < SrcPeH->FileHeader.NumberOfSections; ++i) { if( (szPeSecHead[i]->PointerToRawData) && (szPeSecHead[i]->PointerToRawData < dwHeadSize) ) { dwHeadSize = szPeSecHead[i]->PointerToRawData; } } memmove( MemPtr, szMzHead, dwHeadSize); peHead = (PIMAGE_NT_HEADERS)((int)MemPtr + ((PIMAGE_DOS_HEADER)MemPtr)->e_lfanew); peSecHead = (PIMAGE_SECTION_HEADERS)((int)peHead + sizeof(IMAGE_NT_HEADERS)); VOID *Pt = (VOID *)((DWORD)MemPtr + GetAlignedSize( peHead->OptionalHeader.SizeOfHeaders, peHead->OptionalHeader.SectionAlignment)); for( i = 0; i < peHead->FileHeader.NumberOfSections; ++i) { // 定位该节在内存中的位置 if(peSecHead[i]->VirtualAddress) Pt = (VOID *)((DWORD)MemPtr + peSecHead[i]->VirtualAddress); if(peSecHead[i]->SizeOfRawData) { // 复制数据到内存 memmove(Pt, (CONST VOID *)((DWORD)(szMzHead) + peSecHead[i]->PointerToRawData), peSecHead[i]->SizeOfRawData); if(peSecHead[i]->Misc.VirtualSize < peSecHead[i]->SizeOfRawData) Pt = (VOID *)((DWORD)Pt + GetAlignedSize(peSecHead[i]->SizeOfRawData, peHead->OptionalHeader.SectionAlignment)); else // pt 定位到下一节开始位置 Pt = (VOID *)((DWORD)Pt + GetAlignedSize(peSecHead[i]->Misc.VirtualSize, peHead->OptionalHeader.SectionAlignment)); } else { Pt = (VOID *)((DWORD)Pt + GetAlignedSize(peSecHead[i]->Misc.VirtualSize, peHead->OptionalHeader.SectionAlignment)); } } } return TRUE; } // 计算加载pe并对齐需要占用多少内存 // 未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0 DWORD CalcTotalImageSize(PIMAGE_DOS_HEADER szMzHead, DWORD dwBufSize, PIMAGE_NT_HEADERS peHead, PIMAGE_SECTION_HEADERS peSecHead) { DWORD ImageSize = GetAlignedSize( peHead->OptionalHeader.SizeOfHeaders, peHead->OptionalHeader.SectionAlignment);// 计算pe头的大小 // 计算所有节的大小 for( int i = 0; i < peHead->FileHeader.NumberOfSections; ++i) { // 超出文件范围 if(peSecHead[i]->PointerToRawData + peSecHead[i]->SizeOfRawData > dwBufSize) { return 0; } else if(peSecHead[i]->VirtualAddress)//计算对齐后某节的大小 { if(peSecHead[i]->Misc.VirtualSize) { ImageSize = GetAlignedSize( peSecHead[i]->VirtualAddress + peSecHead[i]->Misc.VirtualSize, peHead->OptionalHeader.SectionAlignment); } else { ImageSize = GetAlignedSize( peSecHead[i]->VirtualAddress + peSecHead[i]->SizeOfRawData, peHead->OptionalHeader.SectionAlignment); } } else if( peSecHead[i]->Misc.VirtualSize < peSecHead[i]->SizeOfRawData ) { ImageSize += GetAlignedSize( peSecHead[i]->SizeOfRawData, peHead->OptionalHeader.SectionAlignment); } else { ImageSize += GetAlignedSize( peSecHead[i]->Misc.VirtualSize, peHead->OptionalHeader.SectionAlignment); } } return ImageSize; } // 计算对齐后的大小 DWORD GetAlignedSize(DWORD Origin, DWORD Alignment) { return (Origin + Alignment - 1) / Alignment * Alignment; } // 创建外壳进程并用目标进程替换它然后执行 HANDLE AttachPE(PIMAGE_NT_HEADERS peHead, VOID *MemPtr, DWORD ImageSize) { CONTEXT Context; DWORD BaseAddr = 0; DWORD imageSize = 0; HANDLE hProcess = INVALID_HANDLE_VALUE; HANDLE hThread = INVALID_HANDLE_VALUE; if(CreateMemProcess(Context, hProcess, hThread, BaseAddr, imageSize)) { VOID *pBaseAddr = NULL; DWORD OldProtect = 0; if((peHead->OptionalHeader.ImageBase == BaseAddr) && (imageSize >= ImageSize)) {// 外壳进程可以容纳目标进程并且加载地址一致 pBaseAddr = (VOID *)BaseAddr; VirtualProtectEx(hProcess, pBaseAddr, imageSize, PAGE_EXECUTE_READWRITE, &OldProtect); } else { if(UnloadShell(hProcess, BaseAddr)) {// 卸载外壳进程占有内存 pBaseAddr = VirtualAllocEx((VOID *)hProcess, (VOID *)peHead->OptionalHeader.ImageBase, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); } if((pBaseAddr == NULL) && HasRelocationTable(peHead)) {// 分配内存失败并且目标进程支持重定向 pBaseAddr = VirtualAllocEx((VOID *)hProcess, NULL, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if(pBaseAddr) DoRelocation(peHead, MemPtr, pBaseAddr); // 重定向 } } if(pBaseAddr) { WriteProcessMemory(hProcess, (VOID *)(Context.Ebx+8), &pBaseAddr, sizeof(DWORD), &OldProtect); // 重置目标进程运行环境中的基址 peHead->OptionalHeader.ImageBase = (DWORD)pBaseAddr; if(WriteProcessMemory(hProcess, pBaseAddr, MemPtr, ImageSize, &OldProtect)) {// 复制PE数据到目标进程 Context.ContextFlags = CONTEXT_FULL; if((DWORD)pBaseAddr == BaseAddr) Context.Eax = peHead->OptionalHeader.ImageBase + peHead->OptionalHeader.AddressOfEntryPoint; // 重置运行环境中的入口地址 else Context.Eax = (DWORD)pBaseAddr + peHead->OptionalHeader.AddressOfEntryPoint; SetThreadContext(hThread, &Context);// 更新运行环境 ResumeThread(hThread);// 执行 CloseHandle(hThread); } else {// 加载失败,杀掉外壳进程 TerminateProcess(hProcess, 0); CloseHandle(hThread); hThread = INVALID_HANDLE_VALUE; CloseHandle(hProcess); hProcess = INVALID_HANDLE_VALUE; } } else {// 加载失败,杀掉外壳进程 TerminateProcess(hProcess, 0); CloseHandle(hThread); hThread = INVALID_HANDLE_VALUE; CloseHandle(hProcess); hProcess = INVALID_HANDLE_VALUE; } } return hProcess; } // 创建外壳进程并获取其基址、大小和当前运行状态 BOOL CreateMemProcess(CONTEXT &Context, HANDLE &hProcess, HANDLE &hThread, DWORD &BaseAddr, DWORD &ImageSize) { STARTUPINFOA si; DWORD dwReadSize = 0; PROCESS_INFORMATION pi; MEMORY_BASIC_INFORMATION MemInfo; memset(&si, 0, sizeof(si)); memset(&pi, 0, sizeof(pi)); si.cb = sizeof(si); char szCmd[MAX_PATH] = {0}; GetModuleFileName(0, szCmd, MAX_PATH); if(CreateProcess(NULL, szCmd, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))// 以挂起方式运行进程 { hProcess = pi.hProcess; hThread = pi.hThread; // 获取外壳进程运行状态,[Context.Ebx+8]内存处存的是外壳进程的加载基址,Context.Eax存放有外壳进程的入口地址 Context.ContextFlags = CONTEXT_FULL; GetThreadContext(hThread, &Context); ReadProcessMemory(hProcess, (VOID *)(Context.Ebx+8), &BaseAddr, sizeof(DWORD), &dwReadSize); // 读取加载基址 VOID *pBaseAddr = (VOID *)BaseAddr; // 计算外壳进程占有的内存 while(VirtualQueryEx(hProcess, pBaseAddr, &MemInfo, sizeof(MemInfo))) { if(MemInfo.State = MEM_FREE) break; pBaseAddr = (VOID *)((DWORD)pBaseAddr + MemInfo.RegionSize); } ImageSize = (DWORD)pBaseAddr - (DWORD)BaseAddr; return TRUE; } return FALSE; } // 卸载原外壳占用内存 BOOL UnloadShell(HANDLE hProcess, DWORD BaseAddr) { BOOL bRet = FALSE; typedef DWORD (__stdcall *pfZwUnmapViewOfSection)(DWORD, DWORD); pfZwUnmapViewOfSection ZwUnmapViewOfSection = NULL; HMODULE hModel = LoadLibrary("ntdll.dll"); if(hModel) { ZwUnmapViewOfSection = (pfZwUnmapViewOfSection)GetProcAddress(hModel, "ZwUnmapViewOfSection"); if(ZwUnmapViewOfSection) bRet = (ZwUnmapViewOfSection((DWORD)hProcess, BaseAddr) == 0); FreeLibrary(hModel); } return bRet; } // 是否包含可重定向列表 BOOL HasRelocationTable(PIMAGE_NT_HEADERS peHead) { return (peHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) && (peHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); } // 重定向PE用到的地址 VOID DoRelocation(PIMAGE_NT_HEADERS peHead, VOID *OldBase, VOID *NewBase) { DWORD Delta = (DWORD)NewBase - peHead->OptionalHeader.ImageBase; PImageBaseRelocation pImageBaseRelocation = (PImageBaseRelocation)((DWORD)OldBase + peHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); while(pImageBaseRelocation->VirtualAddress + pImageBaseRelocation->SizeOfBlock) { DWORD *pImageBaseRelocationW = (DWORD *)((DWORD)pImageBaseRelocation + sizeof(*pImageBaseRelocation)); for(unsigned int i=1; i <= (pImageBaseRelocation->SizeOfBlock - sizeof(*pImageBaseRelocation)) / 2; ++i) { if((*pImageBaseRelocationW) & 0xF000 == 0x3000){ DWORD *t = (DWORD *)((DWORD)(OldBase) + pImageBaseRelocation->VirtualAddress + ((*pImageBaseRelocationW) & 0x0FFF)); *t += Delta; } ++pImageBaseRelocationW; } pImageBaseRelocation = (PImageBaseRelocation)pImageBaseRelocationW; } } |
|
被一骗子骗了骗钱,那位大神能帮帮忙吗
报警是没有用的, 警察不管这些, 我报过警, 人家跟本不管 |
|
for循环算法优化
需要怎么优化呢? 有没有方法把for循环搞少一个? |
|
for循环算法优化
2楼的思路非常好,但本人对GPU也是一知半解 |
|
5年的老用户今天正式升级成会员了,泪奔啊
我是2011年5月注册的,当时还发过贴子,几年没上了,今天一上,是临时会员,不能发贴,真是汗! |
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
能力排名:
No.{{ rank_num }}
等 级:
LV{{ rank_lv-100 }}
活跃值:
在线值:
浏览人数:{{ visits }}
最近活跃:{{ last_active_time }}
注册时间:{{ user_info.create_date_jsonfmt }}
勋章
兑换勋章
证书
证书查询 >
能力值