Всем привет. есть код: Код (Text): typedef struct { WORD Offset:12; WORD Type:4; } IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY; void ProcessRelocs( PVOID Image, PVOID NewImageBase ) { PIMAGE_DOS_HEADER dHeader = (PIMAGE_DOS_HEADER)Image; PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)RVATOVA(Image, dHeader->e_lfanew); ULONG RelRVA = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; ULONG RelSize = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; ULONG Delta = (ULONG)NewImageBase - ntHeaders->OptionalHeader.ImageBase; if ( RelRVA && RelSize && !(ntHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) && RelRVA + RelSize <= ntHeaders->OptionalHeader.SizeOfImage ) { PIMAGE_BASE_RELOCATION Reloc = (PIMAGE_BASE_RELOCATION)RVATOVA(Image, RelRVA); BOOLEAN bFirstChunk = TRUE; while ( bFirstChunk || Reloc->VirtualAddress ) { PIMAGE_FIXUP_ENTRY Fixup = (PIMAGE_FIXUP_ENTRY)((ULONG)Reloc + sizeof(IMAGE_BASE_RELOCATION)); ULONG r, dwPointerRva; bFirstChunk = FALSE; for ( r = 0; r < (Reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) >> 1; r++ ) { if ( Fixup->Type == IMAGE_REL_BASED_HIGHLOW ) { dwPointerRva = Reloc->VirtualAddress + Fixup->Offset; if ( dwPointerRva > ntHeaders->OptionalHeader.SizeOfImage ) { return; } *(PULONG)((ULONG)dHeader + dwPointerRva) += Delta; } Fixup++; } Reloc = (PIMAGE_BASE_RELOCATION)((ULONG)Reloc + Reloc->SizeOfBlock); } } } DWORD InjectCode( HANDLE hProcess, LPTHREAD_START_ROUTINE lpStartProc ) { HMODULE hModule = (HMODULE)GetImageBase(); PIMAGE_DOS_HEADER pDH = (PIMAGE_DOS_HEADER)hModule; PIMAGE_NT_HEADERS pPE = (PIMAGE_NT_HEADERS) ((LPSTR)pDH + pDH->e_lfanew); DWORD dwSize = pPE->OptionalHeader.SizeOfImage; LPVOID lpNewAddr = MemAlloc( dwSize ); if ( lpNewAddr == NULL ) { return -1; } m_memcpy( lpNewAddr, hModule, dwSize ); LPVOID lpNewModule = NULL; DWORD dwAddr = -1; HMODULE hNewModule = NULL; if ( (NTSTATUS)ZwAllocateVirtualMemory( hProcess, &lpNewModule, 0, &dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE ) == STATUS_SUCCESS ) { hNewModule = (HMODULE)lpNewModule; ProcessRelocs( lpNewAddr, hNewModule ); dwNewBase = (DWORD)hNewModule; if ( (NTSTATUS)ZwWriteVirtualMemory( hProcess, hNewModule, lpNewAddr, dwSize, NULL ) == STATUS_SUCCESS ) { dwAddr = (DWORD)lpStartProc - (DWORD)hModule + (DWORD)hNewModule; } } DWORD dwOldProtect = 0; ZwProtectVirtualMemory( hProcess, hNewModule, &dwSize, PAGE_EXECUTE_READWRITE, &dwOldProtect ); MemFree( lpNewAddr ); return dwAddr; } Код ProcessRelocs был взят с wasm.ru, инжект работает нормально, но дело в том что после запаковки программы upx он работать перестает, причем upx я пакую с --strip-relocs=0, даже если ехе распаковать обратно, работоспособность так же теряется, если нужно могу выложить ехе, я так понимаю проблема именно в релоках, т.к. отладочный вывод работает нормально, не работает именно инжект или я криво обращаюсь с пакером? делаю так upx -9 --strip-relocs=0 inject.exe
ilja_, Я не уверен в том, что UPX воссоздаёт в памяти таблицу перемещения. Точнее, я проверил 3.05w на jview.exe: не воссоздаёт. В заголовке в памяти таблица с единственным фиксом внутри распаковщика (секция UPX1), как и в упакованном файле на диске. Возможно, какой-нибудь упаковщик и воссоздаёт в памяти точный образ загруженного незапакованного файла, но UPX на него не похож.
Посмотрите в отладчике, вроде нада еще импорт настроить для загрузчика UPX поэтому тупо инжектировать не прокатит, стаб UPX не находит API динамически.
freyr, Сам UPX уже отработал, импорты в порядке (относительном: перемещение кода подразумевает коррекцию ссылок на элементы IAT). Проблема в том, что элемент каталога данных с индексом IMAGE_DIRECTORY_ENTRY_BASERELOC ссылается на таблицу перемещения UPXа (ту самую с одним фиксапом) вместо оригинальной таблицы исходного файла, вот алгоритм перемещения и не работает (точнее он корректирует уже ненужный dword внутри кода UPX). Можно, наверное, изгалиться и выполнить кусок кода UPXа, ответственный за применение запакованной родной таблицы исходного файла или реализовать его алгоритм вместо использованного.
а кто вам даст гарантию, что в процессе, в который выполняется инжект разные длл не загруженны по иным базовым адресам (ASLR/etc).
Мне, собственно, гарантия ни к чему. Я пытаюсь подсказать тов. ilja_ в чём может быть проблема вышеприведённого кода, если (подчёркивание моё) В общем, надо ждать реакции автора темы.
baldr, freyr спасибо за ответы, дело в том что импорт я не использую, т.е. восстанавливать его не нужно, апи получаю динамически. я тоже думаю что проблема именно в этом, но тут что то универсальное нужно, темболее что файл может быть запакован не только upx, а может вобще быть не запакован (:.
универсальным решением будет базонезависимый код, либо еще вариант - носить за собой "секцию" fixup'ов, который упх и дургие пакеры не затронут, например в конце кода ее втулить и перед исполнением кода настраивать ее вручную.
у меня работает, хотя я фиксапы самостоятельно не юзаю, это системный загрузчик делает(а зачем они, если уже в систему встороен функционал для релокации..).
Clerk Если вам не сложно, вы не могли бы более подробно осветить ваш пост, так я мало чего понял из этого, если я делаю инжект, как тут учавствует системный загрузчик?
ilja_ Лень сейчас описывать. Какраз собираюсь сейчас писать в параллельный топик про релокацию. Поиск используйте, там всё просто.