Хаюшки. Где-то писалось, что обнуление секции релоков( в дата директори) не должно вызывать проблем у ехешников. Пробую обнулить, но какие бы файлы не брал и не обнулял -файл считается испорченным. Вообще механизм работы с релоками не очень понятен и его назначение) Ну например, релоки используются, если файл загружается в область памяти, которая уже занята)(но ведь с ехе файлами изначально не так) А если это длл, подгружая длл в уже занятый адрес - необходимо использовать релоки, а релоки это смещение, а если это смещение на такой же занятый адрес, то получается что и релоки не гарантируют нормальной загрузки. Что к чему, каким образом и как?
в случае с екзешником ты что-то неправильно делаешь, а в случае с длл, если адрес занят то длл мапится на другой адрес а релоки используются для настройки переходов и прочего
По релокам лучше прочитать это: http://msdn.microsoft.com/en-us/magazine/ms809762.aspx Если общими словами, то получается примерно так: библиотека скомпонована для адреса, например, 0x10000000. Соответственно, чтение глобальной переменной будет выглядеть, например, так: 010001000: mov eax, [0x10002000] Код инструкции будет выглядеть так: 0xA1 0x00 0x20 0x00 0x10. Т.е. в инструкции будет сохранен не RVA, а VA переменной. Если библиотека не может быть загружена по этому адресу, то адрес, сохраненный в инструкции надо скорректировать. Релоки как раз и описывают все участки кода, которые подлежат корректировке. Когда загрузчик понимает, что библиотека не может быть загружена по базовому адресу, указанному в библиотеке, он выделяет для нее новый базовый адрес, высчитывает дельту (разницу между новым и старым базовыми адресами) и прибавляет дельту ко всем участкам, перечисленным в релоках. Если, в приведенном примере новый базовый адрес будет 0x30000000, то дельта будет: 0x30000000 - 0x10000000 = 0x20000000. Это значение будет прибалено к значению по адресу 010001001, в результате мы получим 0xA1 0x00 0x20 0x00 0x30. Т.е.010001000: 010001000: mov eax, [0x30002000] Формат релоков описан в статье.
sl0n Беру Internet Explorer из WinXP зануляю там релоки (8байт) и он не запускается. я пробовал на разных файлах. Все вылетают. Правда сам сижу под вистой. И я точно зануляю именно то, что думаю
sl0n, yes. Я обнуляю Image_Optional_Header.DataDirectory[IMAGE_DIRECOTORY_ENTRY_BASERELOC].VirtualAddress && isize
Luzer Помимо обнуления RVA и размера диры нужно поставить нулевой битик в Flags (PEHeader+0x16) вот только тогда будет считаться что у имейджа нет релоков.
Luzer Учти, что бит IMAGE_FILE_RELOCS_STRIPPED в FileHeader.Characteristics, про который говорит dermatolog, в старых ОСях имеет особый смысл: - Бит снят: если обнулить RVA и Size релоков в DATA_DIRECTORY, то будет считаться, что имадж может быть загружен по любому адресу (и не нужно ничего фиксить). - Бит выставлен в единицу: имадж может быть загружен только по базовому адресу, независимо от наличия RVA и Size в директории релоков (и релоки в этом случае не обрабатываются: имадж либо удалось загрузить по базовому адресу, и тогда нет необходимости что-либо фиксить, либо не удалось – тогда загрузка просто останавливается ). В новых виндах при выставленном бите имадж будет пытаться загрузиться по базовому адресу, однако при неудаче загрузится по другому; релоки не будут обработаны (верно по крайней мере для exe-шников; возможно, есть нюансы). Luzer ASLR. Address Space Layout Randomization. Т.е. твои exe-файлы грузятся по рандомному адресу, а без релоков многие адреса не фиксятся же. IMAGE_FILE_RELOCS_STRIPPED исправит ситуацию, да.
Sol_Ksacap Не болтайте ерундой. При выставленом бите IMAGE_FILE_RELOCS_STRIPPED на всех версиях венды файл может быть загружен ТОЛЬКО по своей базе. При снятом бите IMAGE_FILE_RELOCS_STRIPPED на новых версиях винды [/b]имейдж может загружен на любую базу[/b] даже если это EXE файл.
dermatolog >верно по крайней мере для exe-шников >даже если это EXE файл "По крайней мере" в данном случае имело значение "как минимум". Но, в общем-то, оказалось, что для dll наше утверждение тоже держит правду. dermatolog Ошибаешься. Code (Text): 0:000> vertarget Windows Server 2008/Windows Vista Version 6001 (Service Pack 1) MP (2 procs) Free x64 Product: Server, suite: Enterprise TerminalServer SingleUserTS kernel32.dll version: 6.0.6001.18000 (longhorn_rtm.080118-1840) Machine Name: Debug session time: Fri Sep 11 17:12:37.189 2009 (GMT+4) System Uptime: 1 days 13:46:14.127 Process Uptime: 0 days 0:03:24.433 Kernel time: 0 days 0:00:00.015 User time: 0 days 0:00:00.000 0:000> lmM notepad* start end module name 00000000`00010000 00000000`0003f000 notepad (pdb symbols) ... $$ Note actual ImageBase 0:000> .shell -i- copy notepad.exe notepad2.exe 1 file(s) copied. .shell: Process exited $$ Copy coz ".readmem" has a bug 0:000> .dvalloc 1000 Allocated 1000 bytes starting at 00000000`00050000 0:000> as buff 00050000 0:000> .readmem notepad2.exe buff L1000 Reading 1000 bytes.. 0:000> r $t0=${buff}+dwo(${buff}+3c) 0:000> as pNtHeaders (@@c++((_IMAGE_NT_HEADERS64*)(@$t0))) 0:000> ?? pNtHeaders ->OptionalHeader.ImageBase unsigned int64 0x7ffe0000 $$ Note physical, on-disk ImageBase 0:000> ?? pNtHeaders ->FileHeader.Characteristics unsigned short 0x23 0:000> .printf "IMAGE_FILE_RELOCS_STRIPPED == %d\n", @@( pNtHeaders ->FileHeader.Characteristics ) & 1 IMAGE_FILE_RELOCS_STRIPPED == 1 Релоки не фиксятся в этом случае. И не важно, какой тип имаджа – для 32х-битного процесса можно наблюдать то же самое.
Upd: ну и, разумеется, без дебаггера файл тоже запускается, доходит до entry point и вскоре падает с исключением – напарывается на непофикшенные релоки.
Sol_Ksacap Да и видимо не только я но, еще и WinDBG под Win7 x64 ) Блокнот с релоками бит IMAGE_FILE_RELOCS_STRIPPED = 0 Code (Text): CommandLine: D:\Windows\notepad.exe Symbol search path is: *** Invalid *** **************************************************************************** * Symbol loading may be unreliable without a symbol search path. * * Use .symfix to have the debugger choose a symbol path. * * After setting your symbol path, use .reload to refresh symbol locations. * **************************************************************************** Executable search path is: ModLoad: 00000000`ff1e0000 00000000`ff215000 notepad.exe Блокнот с релоками бит IMAGE_FILE_RELOCS_STRIPPED = 1 Code (Text): CommandLine: D:\Test\notepad_sr.exe Symbol search path is: *** Invalid *** **************************************************************************** * Symbol loading may be unreliable without a symbol search path. * * Use .symfix to have the debugger choose a symbol path. * * After setting your symbol path, use .reload to refresh symbol locations. * **************************************************************************** Executable search path is: ModLoad: 00000001`00000000 00000001`00097000 image00000001`00000000
dermatolog Ах ты ж. Вот уж не подумали бы, что в висте сменят алгоритм, а в семёрке вернут предыдущее поведение. Возможно, взглянем на это поближе через пару дней.
Sol_Ksacap Эм... вообще у меня на Vista SP1 тоже с выставленным этим флагом notepad не грузится по занятому адресу.
Неудачно сформулировал. В общем не грузится с флагом IMAGE_FILE_RELOCS_STRIPPED по какому-либо другому адресу, если адрес ImageBase уже занят.
Дизрассматривайте ^этот^ пост. Он алогичен. Время было позднее – нам показалось, что в посте у dermatolog'а блокнот во втором случае не подгрузился. dermatolog Твой последний пост демонстрирует, что блокнот загрузился по базовому адресу, разве нет? Теперь оставь флаг IMAGE_FILE_RELOCS_STRIPPED включённым и измени OptionalHeader.ImageBase на "плохое" значение – лайк, нуль или 7FFE00000, для примера. В этом случае образ должен подгрузиться по другому адресу. По крайней мере мы видим именно это на висте х64. Если что, ^это^ был не сарказм – просто такой речевой шаблон, ага. Luzer Помимо IMAGE_FILE_RELOCS_STRIPPED отлючить ASLR для образа можно другим путём – убрать флаг IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40) в OptionalHeader.DllCharacteristics. l_inc Виста x32?
Собрали тестилку. Тестилка запускается, показывает дефолтную и текущую ImageBase, а также узнаёт, применены ли релоки. Затем делает свою копию, в которой устанавливает "неправильную" ImageBase и флаг IMAGE_FILE_RELOCS_STRIPPED, запускает её. Копия детектирует, что она копия, после чего передаёт родителю информацию о своей ImageBase и о том, применены ли релоки. Родитель выводит всю инфу и удаляет потомка. Прошу потестить на своих системах и показать вывод. На х64 желательно тестить обе версии. Вывод для Vista x64 SP1: Code (Text): WinVer: 6.0.6001 sp1, SuiteMask: 274, x64 process: 1, wow64: 0 Current process: IMAGE_FILE_RELOCS_STRIPPED = 0 Default ImageBase: 0000000140000000 ImageBase: 000000013F740000 Relocs applied: 1 Trying to create child process... SUCCESS Child process: IMAGE_FILE_RELOCS_STRIPPED = 1 Default ImageBase: 000000007FFE0000 ImageBase: 0000000000010000 Relocs applied: 0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ WinVer: 6.0.6001 sp1, SuiteMask: 274, x64 process: 0, wow64: 1 Current process: IMAGE_FILE_RELOCS_STRIPPED = 0 Default ImageBase: 00400000 ImageBase: 00840000 Relocs applied: 1 Trying to create child process... SUCCESS Child process: IMAGE_FILE_RELOCS_STRIPPED = 1 Default ImageBase: 7FFE0000 ImageBase: 00010000 Relocs applied: 0 l_inc >думал, что эта архитектура называется x86 А это было такое противопоставление: х32 — x64. Лайк, некий сорт дизамбиции – тут сразу видно, что имеется в виду именно х86, а не всякая x86-64 ) Great: аттач удалить не могу, вот ссылка на новый: http://multi-up.com/144231 (по просьбе автора)
Sol_Ksacap Мой последний пост подтверждает мою же теорию. Если на висте будет работать все как ты говоришь - проги без релоков (с IMAGE_FILE_RELOCS_STRIPPED=1) будут тупо падать, т.к. не рассчитаны на загрузку по другой базе! За это МС бы уже давно повесили за яйца. Возможно на поведение твоего примера также влияет флаг IMAGE_FILE_LARGE_ADDRESS_AWARE - видимо он может жить отдельно от IMAGE_FILE_RELOCS_STRIPPED и грузит имейдж в верхние адреса независимо от отсутствия релоков (IMAGE_FILE_RELOCS_STRIPPED=1).