Process Hollowing实现触发访问违例错误c0000005求助
Process Hollowing(RunPE)实现后触发访问违例的调试思路请求
我参考教程结合自身知识,用C语言实现Process Hollowing(RunPE)技术:创建挂起状态的calc.exe进程,找到其PEB及镜像基址并解除内存映射,读取notepad.exe的PE头、节区等内容写入目标进程内存,通过重定位表修补字节,修改线程上下文将EAX设为新进程入口点后恢复主线程。经WinDbg调试确认内存写入正常,但恢复线程后触发如下访问违例错误:
(216c.3d84): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=02fc1860 ebx=030a4000 ecx=00000000 edx=00000000 esi=00000000 edi=00000000 eip=76f35080 esp=02f6fe58 ebp=00000000 iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 ntdll!RtlUserThreadStart: 76f35080 833ddc69fe7600 cmp dword ptr [ntdll!LdrDelegatedRtlUserThreadStart (76fe69dc)],0 ds:002b:76fe69dc=00000000
我是逆向新手,请求提供进一步调试的思路。以下是我的main.c代码:
#include <Windows.h> #include <stdio.h> #include <winternl.h> typedef NTSTATUS(NTAPI* NtUnmapViewOfSection)( HANDLE ProcessHandle, PVOID BaseAddress ); int main(int argc, char* argv[]) { printf("Creating process\r\n"); LPSTARTUPINFOA si = (LPSTARTUPINFOA)calloc(1, sizeof(STARTUPINFOA)); LPPROCESS_INFORMATION pi = (LPPROCESS_INFORMATION)calloc(1, sizeof(PROCESS_INFORMATION)); // Start process in suspended state if (!CreateProcessA ( "C:\\Windows\\sysWOW64\\calc.exe", NULL, NULL, NULL, NULL, CREATE_SUSPENDED, NULL, NULL, si, pi )) { printf("Error with CreateProcessA - %d", GetLastError()); return 1; } if (!pi->hProcess) { printf("Error creating process - %d", GetLastError()); return 1; } HANDLE hDestProcess = pi->hProcess; PROCESS_BASIC_INFORMATION* pbi = (PROCESS_BASIC_INFORMATION*)calloc(1, sizeof(PROCESS_BASIC_INFORMATION)); DWORD retLen = 0; // Find PEB if (NtQueryInformationProcess(hDestProcess, ProcessBasicInformation, pbi, sizeof(PROCESS_BASIC_INFORMATION), &retLen)) { printf("Error finding peb - %d", GetLastError()); return 1; } printf("PEB address: %p\n", pbi->PebBaseAddress); DWORD pebImageBaseOffset = (DWORD)pbi->PebBaseAddress + 0x8; LPVOID destImageBase = 0; SIZE_T bytesRead; // Find image base by PEB's offset 0x8 if (!ReadProcessMemory(hDestProcess, (LPCVOID)pebImageBaseOffset, &destImageBase, 0x4, &bytesRead)) { printf("Error getting process's image base - %d", GetLastError()); return 1; } printf("Process image base: %p\n", destImageBase); // Read other exe file HANDLE sourceFile = CreateFileA("C:\\Windows\\sysWOW64\\notepad.exe", GENERIC_READ, NULL, NULL, OPEN_EXISTING, NULL, NULL); DWORD sourceFileSize = GetFileSize(sourceFile, NULL); DWORD fileBytesRead = 0; LPVOID sourceFileStart = (LPVOID)malloc(sourceFileSize); ReadFile(sourceFile, sourceFileStart, sourceFileSize, &fileBytesRead, NULL); PIMAGE_DOS_HEADER sourceDosHeader = (PIMAGE_DOS_HEADER)sourceFileStart; PIMAGE_NT_HEADERS sourceNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)sourceFileStart + sourceDosHeader->e_lfanew); SIZE_T sourceSize = sourceNtHeaders->OptionalHeader.SizeOfImage; // Get the NtUnmapViewOfSection function and unmap the memory NtUnmapViewOfSection NtUnmapViewOfSectionFunc = (NtUnmapViewOfSection)GetProcAddress(GetModuleHandleA("ntdll"), "NtUnmapViewOfSection"); if (NtUnmapViewOfSectionFunc == NULL) { printf("Problem finding NtUnmapViewOfSection - %d", GetLastError()); return 1; } if (NtUnmapViewOfSectionFunc(hDestProcess, destImageBase)) { printf("Problem unmapping process virtual memory"); return 1; } printf("Memory unammped\n"); PVOID newDestImageBase = VirtualAllocEx(hDestProcess, NULL, sourceSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); printf("New allocated image base: %p\n", newDestImageBase); sourceNtHeaders->OptionalHeader.ImageBase = (DWORD)destImageBase; // Write headers if (!WriteProcessMemory(hDestProcess, newDestImageBase, sourceFileStart, sourceNtHeaders->OptionalHeader.SizeOfHeaders, NULL)) { printf("Problem writing headers - %d", GetLastError()); return 1; } PIMAGE_SECTION_HEADER sourceSection = IMAGE_FIRST_SECTION(sourceNtHeaders); PIMAGE_SECTION_HEADER sourceSectionOld = sourceSection; // Save the reloc table pointer for later DWORD sourceRelocTableRaw; // Write sections for (int i = 0; i < sourceNtHeaders->FileHeader.NumberOfSections; i++) { if (!sourceSection->PointerToRawData) continue; PVOID destSectionAddr = (PVOID)((DWORD)newDestImageBase + sourceSection->VirtualAddress); PVOID sourceSectionAddr = (PVOID)((DWORD)sourceFileStart + sourceSection->PointerToRawData); printf("Writing %s section to %p\r\n", sourceSection->Name, destSectionAddr); if (!WriteProcessMemory(hDestProcess, destSectionAddr, sourceSectionAddr, sourceSection->SizeOfRawData, NULL)) { printf("Problem writing sections - %d", GetLastError()); return 1; } if (memcmp(sourceSection->Name, ".reloc", 6) == 0) { sourceRelocTableRaw = sourceSection->PointerToRawData; } sourceSection++; } // Getting the difference between the real based address and the preferred base address, for relocations DWORD deltaImageBase = (DWORD)newDestImageBase - sourceNtHeaders->OptionalHeader.ImageBase; IMAGE_DATA_DIRECTORY relocTable = sourceNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; DWORD relocOffset = 0; while (relocOffset < relocTable.Size) { PIMAGE_BASE_RELOCATION relocBlock = (PIMAGE_BASE_RELOCATION)((DWORD)sourceFileStart + sourceRelocTableRaw + relocOffset); relocOffset += sizeof(IMAGE_BASE_RELOCATION); DWORD relocEntryCount = (relocBlock->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); PWORD relocEntries = (PWORD)((DWORD)sourceFileStart + sourceRelocTableRaw + relocOffset); for (DWORD i = 0; i < relocEntryCount; i++) { relocOffset += sizeof(WORD); if (relocEntries[i] & 0xF000 == IMAGE_REL_BASED_ABSOLUTE) { // Skip this entry, since it represents an absolute address continue; } DWORD patchAddrRVA = relocBlock->VirtualAddress + (relocEntries[i] & 0x0FFF); DWORD patchedBuff = 0; if (!ReadProcessMemory(hDestProcess, (DWORD)newDestImageBase + patchAddrRVA, &patchedBuff, sizeof(DWORD), &bytesRead)) { printf("Problem reading bytes to patch - %d", GetLastError()); return 1; } // Add the difference between the actual image base and the preferred image base patchedBuff += deltaImageBase; if (!WriteProcessMemory(hDestProcess, (DWORD)newDestImageBase + patchAddrRVA, &patchedBuff, sizeof(DWORD), NULL)) { printf("Problem writing patched bytes - %d", GetLastError()); return 1; } } } printf("Relocation bytes patched\n"); // Get context of the main thread LPCONTEXT context = (LPCONTEXT)malloc(sizeof(CONTEXT));; context->ContextFlags = CONTEXT_INTEGER; GetThreadContext(pi->hThread, context); // Change entry point DWORD newEntryPoint = (DWORD)newDestImageBase + sourceNtHeaders->OptionalHeader.AddressOfEntryPoint; context->Eax = newEntryPoint; printf("New entry point addr: %p\n", newEntryPoint); // Set the main thread context with eax containing the new entry point SetThreadContext(pi->hThread, context); // Finally, resume the main thread ResumeThread(pi->hThread); printf("Process main thread resumed"); // Close handles CloseHandle(pi->hProcess); CloseHandle(pi->hThread); return 0; }
恳请各位提供调试建议,非常感谢!
内容的提问来源于stack exchange,提问作者nortain32
相关产品推荐
相关产品推荐

