Relocation, .reloc. обнуление-проблема

Discussion in 'WASM.BEGINNERS' started by Luzer, Sep 9, 2009.

  1. Luzer

    Luzer New Member

    Blog Posts:
    0
    Хаюшки.
    Где-то писалось, что обнуление секции релоков( в дата директори) не должно вызывать проблем у ехешников. Пробую обнулить, но какие бы файлы не брал и не обнулял -файл считается испорченным.
    Вообще механизм работы с релоками не очень понятен и его назначение)
    Ну например, релоки используются, если файл загружается в область памяти, которая уже занята)(но ведь с ехе файлами изначально не так) А если это длл, подгружая длл в уже занятый адрес - необходимо использовать релоки, а релоки это смещение, а если это смещение на такой же занятый адрес, то получается что и релоки не гарантируют нормальной загрузки.
    Что к чему, каким образом и как?
     
  2. sl0n

    sl0n Мамонт дзена **

    Blog Posts:
    0
    в случае с екзешником ты что-то неправильно делаешь, а в случае с длл, если адрес занят то длл мапится на другой адрес а релоки используются для настройки переходов и прочего
     
  3. Mika0x65

    Mika0x65 New Member

    Blog Posts:
    0
    По релокам лучше прочитать это: 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]

    Формат релоков описан в статье.
     
  4. Luzer

    Luzer New Member

    Blog Posts:
    0
    sl0n
    Беру Internet Explorer из WinXP зануляю там релоки (8байт) и он не запускается. я пробовал на разных файлах. Все вылетают. Правда сам сижу под вистой.
    И я точно зануляю именно то, что думаю :)
     
  5. sl0n

    sl0n Мамонт дзена **

    Blog Posts:
    0
    А в хедере ты обнуляешь рва релоков ?
     
  6. Luzer

    Luzer New Member

    Blog Posts:
    0
    sl0n, yes. Я обнуляю
    Image_Optional_Header.DataDirectory[IMAGE_DIRECOTORY_ENTRY_BASERELOC].VirtualAddress && isize
     
  7. dermatolog

    dermatolog Member

    Blog Posts:
    0
    Luzer
    Помимо обнуления RVA и размера диры нужно поставить нулевой битик в Flags (PEHeader+0x16) вот только тогда будет считаться что у имейджа нет релоков.
     
  8. Sol_Ksacap

    Sol_Ksacap Миша

    Blog Posts:
    0
    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 исправит ситуацию, да.
     
  9. dermatolog

    dermatolog Member

    Blog Posts:
    0
    Sol_Ksacap
    Не болтайте ерундой. При выставленом бите IMAGE_FILE_RELOCS_STRIPPED на всех версиях венды файл может быть загружен ТОЛЬКО по своей базе. При снятом бите IMAGE_FILE_RELOCS_STRIPPED на новых версиях винды [/b]имейдж может загружен на любую базу[/b] даже если это EXE файл.
     
  10. Sol_Ksacap

    Sol_Ksacap Миша

    Blog Posts:
    0
    dermatolog
    >верно по крайней мере для exe-шников
    >даже если это EXE файл
    "По крайней мере" в данном случае имело значение "как минимум". Но, в общем-то, оказалось, что для dll наше утверждение тоже держит правду.

    dermatolog
    Ошибаешься.
    Code (Text):
    1. 0:000> vertarget
    2. Windows Server 2008/Windows Vista Version 6001 (Service Pack 1) MP (2 procs) Free x64
    3. Product: Server, suite: Enterprise TerminalServer SingleUserTS
    4. kernel32.dll version: 6.0.6001.18000 (longhorn_rtm.080118-1840)
    5. Machine Name:
    6. Debug session time: Fri Sep 11 17:12:37.189 2009 (GMT+4)
    7. System Uptime: 1 days 13:46:14.127
    8. Process Uptime: 0 days 0:03:24.433
    9.   Kernel time: 0 days 0:00:00.015
    10.   User time: 0 days 0:00:00.000
    11.  
    12. 0:000> lmM notepad*
    13. start             end                 module name
    14. 00000000`00010000 00000000`0003f000   notepad    (pdb symbols)          ...
    15.             $$ Note actual ImageBase
    16.  
    17. 0:000> .shell -i- copy notepad.exe notepad2.exe
    18.         1 file(s) copied.
    19. .shell: Process exited
    20.             $$ Copy coz ".readmem" has a bug
    21.  
    22. 0:000> .dvalloc 1000
    23. Allocated 1000 bytes starting at 00000000`00050000
    24.  
    25. 0:000> as buff 00050000
    26.  
    27. 0:000> .readmem notepad2.exe buff L1000
    28. Reading 1000 bytes..
    29.  
    30. 0:000> r $t0=${buff}+dwo(${buff}+3c)
    31. 0:000> as pNtHeaders (@@c++((_IMAGE_NT_HEADERS64*)(@$t0)))
    32.  
    33. 0:000> ?? pNtHeaders ->OptionalHeader.ImageBase
    34. unsigned int64 0x7ffe0000
    35.             $$ Note physical, on-disk ImageBase
    36.  
    37. 0:000> ?? pNtHeaders ->FileHeader.Characteristics
    38. unsigned short 0x23
    39. 0:000> .printf "IMAGE_FILE_RELOCS_STRIPPED == %d\n", @@( pNtHeaders ->FileHeader.Characteristics ) & 1
    40. IMAGE_FILE_RELOCS_STRIPPED == 1
    Релоки не фиксятся в этом случае. И не важно, какой тип имаджа – для 32х-битного процесса можно наблюдать то же самое.
     
  11. Sol_Ksacap

    Sol_Ksacap Миша

    Blog Posts:
    0
    Upd: ну и, разумеется, без дебаггера файл тоже запускается, доходит до entry point и вскоре падает с исключением – напарывается на непофикшенные релоки.
     
  12. dermatolog

    dermatolog Member

    Blog Posts:
    0
    Sol_Ksacap
    Да и видимо не только я но, еще и WinDBG под Win7 x64 :))
    Блокнот с релоками бит IMAGE_FILE_RELOCS_STRIPPED = 0
    Code (Text):
    1. CommandLine: D:\Windows\notepad.exe
    2. Symbol search path is: *** Invalid ***
    3. ****************************************************************************
    4. * Symbol loading may be unreliable without a symbol search path.           *
    5. * Use .symfix to have the debugger choose a symbol path.                   *
    6. * After setting your symbol path, use .reload to refresh symbol locations. *
    7. ****************************************************************************
    8. Executable search path is:
    9. ModLoad: 00000000`ff1e0000 00000000`ff215000   notepad.exe
    Блокнот с релоками бит IMAGE_FILE_RELOCS_STRIPPED = 1
    Code (Text):
    1. CommandLine: D:\Test\notepad_sr.exe
    2. Symbol search path is: *** Invalid ***
    3. ****************************************************************************
    4. * Symbol loading may be unreliable without a symbol search path.           *
    5. * Use .symfix to have the debugger choose a symbol path.                   *
    6. * After setting your symbol path, use .reload to refresh symbol locations. *
    7. ****************************************************************************
    8. Executable search path is:
    9. ModLoad: 00000001`00000000 00000001`00097000   image00000001`00000000
     
  13. Sol_Ksacap

    Sol_Ksacap Миша

    Blog Posts:
    0
    dermatolog
    Ах ты ж. Вот уж не подумали бы, что в висте сменят алгоритм, а в семёрке вернут предыдущее поведение. Возможно, взглянем на это поближе через пару дней.
     
  14. l_inc

    l_inc New Member

    Blog Posts:
    0
    Sol_Ksacap
    Эм... вообще у меня на Vista SP1 тоже с выставленным этим флагом notepad не грузится по занятому адресу.
     
  15. l_inc

    l_inc New Member

    Blog Posts:
    0
    Неудачно сформулировал. В общем не грузится с флагом IMAGE_FILE_RELOCS_STRIPPED по какому-либо другому адресу, если адрес ImageBase уже занят.
     
  16. Sol_Ksacap

    Sol_Ksacap Миша

    Blog Posts:
    0
    Дизрассматривайте ^этот^ пост. Он алогичен. Время было позднее – нам показалось, что в посте у 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?
     
  17. l_inc

    l_inc New Member

    Blog Posts:
    0
    Sol_Ksacap
    Ага.
     
  18. l_inc

    l_inc New Member

    Blog Posts:
    0
    Sol_Ksacap
    Хотя я раньше думал, что эта архитектура называется x86. :)
     
  19. Sol_Ksacap

    Sol_Ksacap Миша

    Blog Posts:
    0
    Собрали тестилку. Тестилка запускается, показывает дефолтную и текущую ImageBase, а также узнаёт, применены ли релоки. Затем делает свою копию, в которой устанавливает "неправильную" ImageBase и флаг IMAGE_FILE_RELOCS_STRIPPED, запускает её. Копия детектирует, что она копия, после чего передаёт родителю информацию о своей ImageBase и о том, применены ли релоки. Родитель выводит всю инфу и удаляет потомка.
    Прошу потестить на своих системах и показать вывод. На х64 желательно тестить обе версии.

    Вывод для Vista x64 SP1:
    Code (Text):
    1. WinVer: 6.0.6001  sp1, SuiteMask: 274, x64 process: 1, wow64: 0
    2.  
    3. Current process:
    4.         IMAGE_FILE_RELOCS_STRIPPED = 0
    5.         Default ImageBase: 0000000140000000
    6.         ImageBase: 000000013F740000
    7.         Relocs applied: 1
    8.  
    9. Trying to create child process... SUCCESS
    10.  
    11. Child process:
    12.         IMAGE_FILE_RELOCS_STRIPPED = 1
    13.         Default ImageBase: 000000007FFE0000
    14.         ImageBase: 0000000000010000
    15.         Relocs applied: 0
    16.  
    17.  
    18.  
    19. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    20.  
    21.  
    22.  
    23. WinVer: 6.0.6001  sp1, SuiteMask: 274, x64 process: 0, wow64: 1
    24.  
    25. Current process:
    26.         IMAGE_FILE_RELOCS_STRIPPED = 0
    27.         Default ImageBase: 00400000
    28.         ImageBase: 00840000
    29.         Relocs applied: 1
    30.  
    31. Trying to create child process... SUCCESS
    32.  
    33. Child process:
    34.         IMAGE_FILE_RELOCS_STRIPPED = 1
    35.         Default ImageBase: 7FFE0000
    36.         ImageBase: 00010000
    37.         Relocs applied: 0
    l_inc
    >думал, что эта архитектура называется x86
    А это было такое противопоставление: х32 — x64. Лайк, некий сорт дизамбиции – тут сразу видно, что имеется в виду именно х86, а не всякая x86-64 )

    Great: аттач удалить не могу, вот ссылка на новый: http://multi-up.com/144231 (по просьбе автора)
     
  20. dermatolog

    dermatolog Member

    Blog Posts:
    0
    Sol_Ksacap
    Мой последний пост подтверждает мою же теорию. Если на висте будет работать все как ты говоришь - проги без релоков (с IMAGE_FILE_RELOCS_STRIPPED=1) будут тупо падать, т.к. не рассчитаны на загрузку по другой базе! За это МС бы уже давно повесили за яйца.
    Возможно на поведение твоего примера также влияет флаг IMAGE_FILE_LARGE_ADDRESS_AWARE - видимо он может жить отдельно от IMAGE_FILE_RELOCS_STRIPPED и грузит имейдж в верхние адреса независимо от отсутствия релоков (IMAGE_FILE_RELOCS_STRIPPED=1).