在內存中運行可執行程序,好處是可以給程序加殼,加密源程序,靜態反匯編無法獲得PE輸入節,但是因為運行后仍然是獨立的進程,所以沒辦法防止遠程線程注入,掛接API鉤子。
?? typedef IMAGE_SECTION_HEADER ( * PIMAGE_SECTION_HEADERS)[ 1 ];??
?
?//? 計算對齊后的大小???
?unsigned? long? GetAlignedSize(unsigned? long? Origin, unsigned? long? Alignment)??
? {??
???? return? (Origin? +? Alignment? -?? 1 )? /? Alignment? *? Alignment;??
}???
?
?//? 計算加載pe并對齊需要占用多少內存??
?//? 未直接使用OptionalHeader.SizeOfImage作為結果是因為據說有的編譯器生成的exe這個值會填0???
?unsigned? long? CalcTotalImageSize(PIMAGE_DOS_HEADER MzH??
???????????????????????????????? , unsigned? long? FileLen??
???????????????????????????????? , PIMAGE_NT_HEADERS peH??
???????????????????????????????? , PIMAGE_SECTION_HEADERS peSecH)??
? {??
??? unsigned? long? res;??
???? //? 計算pe頭的大小???
???? res? =? GetAlignedSize( peH -> OptionalHeader.SizeOfHeaders , peH -> OptionalHeader.SectionAlignment);??
?
???? //? 計算所有節的大小???
????? for (? int? i? =?? 0 ; i? <? peH -> FileHeader.NumberOfSections;? ++ i)??
????? {??
???????? //? 超出文件范圍???
????????? if (peSecH[i] -> PointerToRawData? +? peSecH[i] -> SizeOfRawData? >? FileLen)?
????????? {
???????????? return?? 0 ;??
??????? }
???????? else?? if (peSecH[i] -> VirtualAddress) // 計算對齊后某節的大小???
??????????? {??
???????????? if (peSecH[i] -> Misc.VirtualSize)??
????????????? {??
??????????????? res? =? GetAlignedSize( peSecH[i] -> VirtualAddress? +? peSecH[i] -> Misc.VirtualSize??
??????????????????? , peH -> OptionalHeader.SectionAlignment);??
??????????? }???
???????????? else??
????????????? {??
??????????????? res? =? GetAlignedSize( peSecH[i] -> VirtualAddress? +? peSecH[i] -> SizeOfRawData??
??????????????????? , peH -> OptionalHeader.SectionAlignment);??
??????????? }???
??????? }???
???????? else?? if ( peSecH[i] -> Misc.VirtualSize? <? peSecH[i] -> SizeOfRawData )??
????????? {??
??????????? res? +=? GetAlignedSize( peSecH[i] -> SizeOfRawData??
??????????????? , peH -> OptionalHeader.SectionAlignment);??
??????? }???
???????? else??
????????? {??
??????????? res? +=? GetAlignedSize( peSecH[i] -> Misc.VirtualSize??
??????????????? , peH -> OptionalHeader.SectionAlignment);??
??????? } //? if_else???
???? } //? for???
???????
???? return? res;??
}???
?
?//? 加載pe到內存并對齊所有節???
?BOOL AlignPEToMem(? void?? * Buf??
????????????????? ,? long? Len??
????????????????? , PIMAGE_NT_HEADERS? & peH??
????????????????? , PIMAGE_SECTION_HEADERS? & peSecH??
????????????????? ,? void?? *& Mem??
????????????????? , unsigned? long?? & ImageSize)??
? {??
??? PIMAGE_DOS_HEADER SrcMz; //? DOS頭???
???? PIMAGE_NT_HEADERS SrcPeH; //? PE頭???
???? PIMAGE_SECTION_HEADERS SrcPeSecH; //? 節表???
???????
??? SrcMz? =? (PIMAGE_DOS_HEADER)Buf;??
?
???? if ( Len? <?? sizeof (IMAGE_DOS_HEADER) )???
???????? return? FALSE;??
??????
???? if ( SrcMz -> e_magic? !=? IMAGE_DOS_SIGNATURE )??
???????? return? FALSE;??
??????
???? if ( Len? <? SrcMz -> e_lfanew? +? ( long ) sizeof (IMAGE_NT_HEADERS) )??
???????? return? FALSE;??
?
??? SrcPeH? =? (PIMAGE_NT_HEADERS)(( int )SrcMz? +? SrcMz -> e_lfanew);??
???? 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;??
??? }???
?
?
??? SrcPeSecH? =? (PIMAGE_SECTION_HEADERS)(( int )SrcPeH? +?? sizeof (IMAGE_NT_HEADERS));??
??? ImageSize? =? CalcTotalImageSize( SrcMz, Len, SrcPeH, SrcPeSecH);??
?
???? if ( ImageSize? ==?? 0? )??
???????? return? FALSE;??
??????
??? Mem? =? VirtualAlloc( NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);? //? 分配內存???
????? if ( Mem? !=? NULL )??
????? {??
???????? //? 計算需要復制的PE頭字節數???
???????? unsigned? long? l? =? SrcPeH -> OptionalHeader.SizeOfHeaders;??
???????? for (? int? i? =?? 0 ; i? <? SrcPeH -> FileHeader.NumberOfSections;? ++ i)??
????????? {??
???????????? if ( (SrcPeSecH[i] -> PointerToRawData)? &&???
??????????????? (SrcPeSecH[i] -> PointerToRawData? <? l) )??
????????????? {??
??????????????? l? =? SrcPeSecH[i] -> PointerToRawData;??
??????????? }???
??????? }???
??????? memmove( Mem, SrcMz, l);??
??????? peH? =? (PIMAGE_NT_HEADERS)(( int )Mem? +? ((PIMAGE_DOS_HEADER)Mem) -> e_lfanew);??
??????? peSecH? =? (PIMAGE_SECTION_HEADERS)(( int )peH? +?? sizeof (IMAGE_NT_HEADERS));??
?
???????? void?? * Pt? =? ( void?? * )((unsigned? long )Mem???
???????????? +? GetAlignedSize( peH -> OptionalHeader.SizeOfHeaders??
??????????? , peH -> OptionalHeader.SectionAlignment)??
??????????? );??
?
???????? for ( i? =?? 0 ; i? <? peH -> FileHeader.NumberOfSections;? ++ i)??
????????? {??
???????????? //? 定位該節在內存中的位置???
????????????? if (peSecH[i] -> VirtualAddress)??
??????????????? Pt? =? ( void?? * )((unsigned? long )Mem? +? peSecH[i] -> VirtualAddress);??
?
???????????? if (peSecH[i] -> SizeOfRawData)??
????????????? {??
???????????????? //? 復制數據到內存???
???????????????? memmove(Pt, ( const?? void?? * )((unsigned? long )(SrcMz)? +? peSecH[i] -> PointerToRawData), peSecH[i] -> SizeOfRawData);??
???????????????? if (peSecH[i] -> Misc.VirtualSize? <? peSecH[i] -> SizeOfRawData)??
??????????????????? Pt? =? ( void?? * )((unsigned? long )Pt? +? GetAlignedSize(peSecH[i] -> SizeOfRawData, peH -> OptionalHeader.SectionAlignment));??
???????????????? else?? //? pt 定位到下一節開始位置???
???????????????????? Pt? =? ( void?? * )((unsigned? long )Pt? +? GetAlignedSize(peSecH[i] -> Misc.VirtualSize, peH -> OptionalHeader.SectionAlignment));??
??????????? }???
???????????? else??
????????????? {??
??????????????? Pt? =? ( void?? * )((unsigned? long )Pt? +? GetAlignedSize(peSecH[i] -> Misc.VirtualSize, peH -> OptionalHeader.SectionAlignment));??
??????????? }???
??????? }???
??? }???
???? return? TRUE;??
}???
?
???
typedef? void?? * (__stdcall? * pfVirtualAllocEx)(unsigned? long ,? void?? * , unsigned? long , unsigned? long , unsigned? long );??
pfVirtualAllocEx MyVirtualAllocEx? =? NULL;??
?
BOOL IsNT()??
? {??
???? return? MyVirtualAllocEx != NULL;??
}???
?
?//? 生成外殼程序命令行???
?char?? * PrepareShellExe( char?? * CmdParam, unsigned? long? BaseAddr, unsigned? long? ImageSize)??
? {??
???? if (IsNT())??
????? {??
???????? char?? * Buf? =?? new?? char [ 256 ];??
??????? memset(Buf,? 0 ,? 256 );??
??????? GetModuleFileName( 0 , Buf,? 256 );??
??????? strcat(Buf, CmdParam);??
???????? return? Buf;? //? 請記得釋放內存;-)???
???? }???
???? else??
????? {??
???????? //? Win98下的處理請參考原文;-)??
???????? //?? http://community.csdn.net/Expert/topic/4416/4416252.xml?temp=8.709133E-03????
????????? return? NULL;??
??? }???
}???
?
?//? 是否包含可重定向列表???
?BOOL HasRelocationTable(PIMAGE_NT_HEADERS peH)??
? {??
???? return? (peH -> OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)??
???????? &&? (peH -> OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);??
}???
?
#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 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 " );??
???????? if (ZwUnmapViewOfSection)??
??????????? res? =? (ZwUnmapViewOfSection((unsigned? long )ProcHnd, BaseAddr)? ==?? 0 );??
??????? FreeLibrary(m);??
??? }???
???? return? res;??
}???
?
?//? 創建外殼進程并獲取其基址、大小和當前運行狀態???
?BOOL CreateChild( char?? * Cmd, CONTEXT? & Ctx, HANDLE? & ProcHnd, HANDLE? & ThrdHnd,???
???????????????? unsigned? long?? & ProcId, unsigned? long?? & BaseAddr, unsigned? long?? & ImageSize)??
? {??
??? STARTUPINFOA si;??
??? PROCESS_INFORMATION pi;??
??? unsigned? long? old;??
??? MEMORY_BASIC_INFORMATION MemInfo;??
??? memset( & si,? 0 ,? sizeof (si));??
??? memset( & pi,? 0 ,? sizeof (pi));??
??? si.cb? =?? sizeof (si);??
??????
??? BOOL res? =? CreateProcess(NULL, Cmd, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL,? & si,? & pi);? //? 以掛起方式運行進程;???
?????? if (res)? {??
??????? ProcHnd? =? pi.hProcess;??
??????? ThrdHnd? =? pi.hThread;??
??????? ProcId? =? pi.dwProcessId;??
???????? //? 獲取外殼進程運行狀態,[ctx.Ebx+8]內存處存的是外殼進程的加載基址,ctx.Eax存放有外殼進程的入口地址???
???????? Ctx.ContextFlags? =? CONTEXT_FULL;??
??????? GetThreadContext(ThrdHnd,? & Ctx);??
??????? ReadProcessMemory(ProcHnd, ( void?? * )(Ctx.Ebx + 8 ),? & BaseAddr,? sizeof (unsigned? long ),? & old);? //? 讀取加載基址???
????????? void?? * p? =? ( void?? * )BaseAddr;??
???????? //? 計算外殼進程占有的內存???
????????? while (VirtualQueryEx(ProcHnd, p,? & MemInfo,? sizeof (MemInfo)))??
????????? {??
???????????? if (MemInfo.State? =? MEM_FREE)? break ;??
??????????? p? =? ( void?? * )((unsigned? long )p? +? MemInfo.RegionSize);??
??????? }???
??????? ImageSize? =? (unsigned? long )p? -? (unsigned? long )BaseAddr;??
??? }???
???? return? res;??
}???
?
?//? 創建外殼進程并用目標進程替換它然后執行???
?HANDLE AttachPE( char?? * CmdParam, PIMAGE_NT_HEADERS peH, PIMAGE_SECTION_HEADERS peSecH,???
???????????????? void?? * Ptr, unsigned? long? ImageSize, unsigned? long?? & ProcId)??
? {??
??? HANDLE res? =? INVALID_HANDLE_VALUE;??
??? CONTEXT Ctx;??
??? HANDLE Thrd;??
??? unsigned? long? Addr, Size;??
???? char?? * s? =? PrepareShellExe(CmdParam, peH -> OptionalHeader.ImageBase, ImageSize);??
???? if (s == NULL)? return? res;??
???? if (CreateChild(s, Ctx, res, Thrd, ProcId, Addr, Size))? {??
???????? void?? * p? =? NULL;??
??????? unsigned? long? old;??
???????? if ((peH -> OptionalHeader.ImageBase? ==? Addr)? &&? (Size? >=? ImageSize))? { //? 外殼進程可以容納目標進程并且加載地址一致???
???????????? p? =? ( void?? * )Addr;??
??????????? VirtualProtectEx(res, p, Size, PAGE_EXECUTE_READWRITE,? & old);??
??????? }???
???????? else?? if (IsNT())? {??
???????????? if (UnloadShell(res, Addr))? { //? 卸載外殼進程占有內存???
???????????????? p? =? MyVirtualAllocEx((unsigned? long )res, ( void?? * )peH -> OptionalHeader.ImageBase, ImageSize, MEM_RESERVE? |? MEM_COMMIT, PAGE_EXECUTE_READWRITE);??
??????????? }???
???????????? if ((p? ==? NULL)? &&? HasRelocationTable(peH))? { //? 分配內存失敗并且目標進程支持重定向???
???????????????? p? =? MyVirtualAllocEx((unsigned? long )res, NULL, ImageSize, MEM_RESERVE? |? MEM_COMMIT, PAGE_EXECUTE_READWRITE);??
???????????????? if (p) DoRelocation(peH, Ptr, p);? //? 重定向???
???????????? }???
??????? }???
???????? if (p)? {??
??????????? WriteProcessMemory(res, ( void?? * )(Ctx.Ebx + 8 ),? & p,? sizeof (DWORD),? & old);? //? 重置目標進程運行環境中的基址???
???????????? peH -> OptionalHeader.ImageBase? =? (unsigned? long )p;??
???????????? if (WriteProcessMemory(res, p, Ptr, ImageSize,? & old))? { //? 復制PE數據到目標進程???
???????????????? Ctx.ContextFlags? =? CONTEXT_FULL;??
???????????????? if ((unsigned? long )p? ==? Addr)??
??????????????????? Ctx.Eax? =? peH -> OptionalHeader.ImageBase? +? peH -> OptionalHeader.AddressOfEntryPoint;? //? 重置運行環境中的入口地址???
????????????????? else??
??????????????????? Ctx.Eax? =? (unsigned? long )p? +? peH -> OptionalHeader.AddressOfEntryPoint;??
??????????????? SetThreadContext(Thrd,? & Ctx); //? 更新運行環境???
???????????????? ResumeThread(Thrd); //? 執行???
???????????????? CloseHandle(Thrd);??
??????????? }???
???????????? else? { //? 加載失敗,殺掉外殼進程???
???????????????? TerminateProcess(res,? 0 );??
??????????????? CloseHandle(Thrd);??
??????????????? CloseHandle(res);??
??????????????? res? =? INVALID_HANDLE_VALUE;??
??????????? }???
??????? }???
???????? else? { //? 加載失敗,殺掉外殼進程???
???????????? TerminateProcess(res,? 0 );??
??????????? CloseHandle(Thrd);??
??????????? CloseHandle(res);??
??????????? res? =? INVALID_HANDLE_VALUE;??
??????? }???
??? }???
??? delete[] s;??
???? return? res;??
}???
?
? /**/ /**/ /**/ /* ******************************************************/?
{ ******************************************************* }?
{ *???????????????? 從內存中加載并運行exe?????????????? * }?
{ ******************************************************* }?
{ * 參數:??????????????????????????????????????????????? }?
{ * Buffer: 內存中的exe地址?????????????????????????????? }?
{ * Len: 內存中exe占用長度??????????????????????????????? }?
{ * CmdParam: 命令行參數(不包含exe文件名的剩余命令行參數)}?
{ * ProcessId: 返回的進程Id?????????????????????????????? }?
{ * 返回值: 如果成功則返回進程的Handle(ProcessHandle),?? }?
{??????????? 如果失敗則返回INVALID_HANDLE_VALUE?????????? }?
{ ******************************************************* }?
?/****************************************************** */??
HANDLE MemExecute( void?? * ABuffer,? long? Len,? char?? * CmdParam, unsigned? long?? * ProcessId)??
? {??
??? HANDLE res? =? INVALID_HANDLE_VALUE;??
??? PIMAGE_NT_HEADERS peH;??
??? PIMAGE_SECTION_HEADERS peSecH;??
???? void?? * Ptr;??
??? unsigned? long? peSz;??
???? if (AlignPEToMem(ABuffer, Len, peH, peSecH, Ptr, peSz))??
????? {??
??????? res? =? AttachPE(CmdParam, peH, peSecH, Ptr, peSz,? * ProcessId);??
??????? VirtualFree(Ptr, peSz, MEM_DECOMMIT);??
??? }???
???? return? res;??
}???
?
?//? 初始化???
?class? CInit??
? {??
?public :??
??? CInit()??
????? {??
??????? MyVirtualAllocEx? =? (pfVirtualAllocEx)GetProcAddress(GetModuleHandle( " Kernel32.dll " ),? " VirtualAllocEx " );??
??? }???
} Init;??
?
?int? main( int? argc,? char *? argv[])
? {
??? FILE *? fp;
??? fp? =? fopen( " E://CProject//DBGVIEW.EXE " , " rb " );
?if? ( fp )
????? {
??????? fseek(fp, 0l ,SEEK_END);
???????? int? file_size = ftell(fp); /**/ /* 獲取文件長度 */
???????? fseek(fp, 0l ,SEEK_SET); /**/ /* 回到文件頭部 */???
???????
???????
??????? LPBYTE pBuf? =?? new? BYTE[file_size];??
??????? memset( pBuf,? 0 , file_size);?
??????? fread(pBuf,file_size, 1 ,fp);
??????? DWORD id? =? GetCurrentProcessId();
??????? unsigned? long? ulProcessId? =?? 0 ;??
??????? MemExecute( pBuf, file_size,? "" ,? & ulProcessId);??
??????? delete[] pBuf;??
???????
??? }??
???
???? return?? 0 ;
}