Вопрос по структуре PE-файла

Тема в разделе "WASM.RESEARCH", создана пользователем GRRRLPower, 17 авг 2010.

  1. GRRRLPower

    GRRRLPower New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2010
    Сообщения:
    46
    Я новичок, изучаю понемногу формат PE-файлов, пишу простейший дампер PE-файлов. С "правильными" PE, созданными по стандарту, всё ОК, но тут я наткнулся на упакованный (вроде бы как upack'ом), и начались вопросы.

    Во-первых, DATA_DIRECTORY странным образом искажена:

    [​IMG]


    Адреса и размеры почти всех элементов DATA_DIRECTORY выходят далеко за пределы секций (в именах секций, кстати, тоже непонятно что):

    Код (Text):
    1. Section name: PSяХ«лзГ
    2. Section read: [executable] [readable] [writeable] [RVA: 00001000 RVA+RawSize: 000011F0, RAW address: 00000010]
    3. Section name:
    4. Section read: [executable] [readable] [writeable] [RVA: 00012000 RVA+RawSize: 00017404, RAW address: 00000200]
    5. Section name: FA
    6. Section read: [executable] [readable] [writeable] [RVA: 0001A000 RVA+RawSize: 0001A1F0, RAW address: 00000010]
    (а у первой и последней секций еще и адреса совпадают физические.)

    Единственная попадающая внутрь последней секции таблица импорта (в DATA_DIRECTORY элемент 1) тоже искажена:

    [​IMG]

    Тут вообще ни один из адресов не является правильным.

    Отсюда три вопроса:
    1. Как вообще работать с таким exe?
    2. Имеет ли он таблицу импорта?
    2. Получается, системному загрузчику можно скармливать всё что угодно, и это будет загружаться и работать?

    Ссылка на сам exe: http://www.sendspace.com/file/hoxejc
     
  2. izl3sa

    izl3sa New Member

    Публикаций:
    0
    Регистрация:
    22 апр 2010
    Сообщения:
    164
    Адрес:
    Spb
    1. Как и со всеми.
    2. да
    3. Нет, не все. Если вы не заметили, все, что имеет невалидные адреса не парсится загрузчиком, кроме фиксапов, но выставлен флаг, указывающий, что фиксапы отрезаны. Остальное вполне валидно.

    Про секции - один и тот же физический оффсет может отображатся на различные виртуальные адреса, но не наоборот. Имена пофик, они не важны (ну кроме ресурсов, но там отдельная песня)

    По импорту, скорее всего вы не правильно преобразовываете к оффсету. Дайте код.
     
  3. Flint_ta

    Flint_ta New Member

    Публикаций:
    0
    Регистрация:
    25 май 2008
    Сообщения:
    312
    1. upack не совсем тот пакер которые нужен для новичков ) PE заголовок там собран таким образом что оставлены нетронутыми только самые важные поля. Остальные поля являются частью кода.
    Как видно файловое смещение секции кода = 00000010h, а файловое выравнивание 00000200h, смещение меньше чем выравнивание, поэтому загрузчик проигнорирует это смещение и спроецирует в первую секцию данные начиная с начала файла. Точка входа (00001018h) минус виртуальное выравнивание (00001000h) = 0000018h. Получается по смещение 18h от начала файла начинается исполняемый код, также "являющийся" и данными PE заголовка ).
    Также обрати внимание на размер опционального заголовка.
    2. Таблицу импорта он имеет
    3. Не все что угодно, а только то что допустимо.
     
  4. GRRRLPower

    GRRRLPower New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2010
    Сообщения:
    46
    Мне тут подсказали вот такое: https://cracklab.ru/f/index.php?action=vthread&topic=4611&forum=1&page=-1
    Здесь, видимо и есть это самое - RAW offset у первой и третьей секций меньше File Alignment, поэтому он выравнивается вниз и получается просто 0. Но как это обработать, я пока не могу понять.

    Код страшный, вот он: http://pastebin.com/EBK20hUJ
    CreateDump(const char * output, const char* input) - создает дамп PE файла по пути input и пишет лог в output.
    VirtualToPhysical - конвертирует rva в raw.
    Там GUI, но основные функции на него не опираются.

    Раньше был вариант не с чтением PE-файла от начала до конца и преобразованием RVA в RAW offset, а с загрузкой PE по секциям в память, как делает системный загрузчик, но он тоже с этим exe не справляется.

    ------
    Flint_ta, спасибо, это я в теории понял (первая ссылка в этом посте об этом же вроде и говорит). Неплохо бы еще понять, как в таком файле найти таблицу импорта. Даже PE Tools не справляется.
     
  5. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    GRRRLPower
    Совет:
    Рекомендую отображение значений в подсказывающих хинтах впредь включать в Hex виде, а то не очень-то удобно смотреть ;) По одной простой причине, сис.программеру, тем более опытному быстрее сообразить на цифрах подобные :
    0x401000, 0x78900000, etc чем в их десятичном. Ну и если он увидет 0xCCCCCCC или другое подобное дебаг-значение, то сразу же может тебе дать ответ )
     
  6. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    Интересно, все-таки, прояснить вопрос по таблице импорта..
    С учетом сказанного Flint_ta в #3 таблица импорта начинатся по адресу(в файле) 0х1ее, имеет размер 20 байт, т.е. запись об одном экспортируемом файле (kernel32.dll).
    Но поля этой структуры мало поддаются осмыслению:
    -Указатель на массив с адресами названий имп-х функций(1 копия) 0х0
    -Указатель на строку с именем dll - 0х2 (ну это еще можно переварить..)
    -Указатель на массив с адресами названий имп-х функций(2 копия) 0х003511е8

    Вот последнюю цифру не могу переварить - по идее должно быть 0х000001е8(0х00011е8)...
    Flint_ta - может объясните?
     
  7. GRRRLPower

    GRRRLPower New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2010
    Сообщения:
    46
    EvilsInterrupt, спасибо за совет, включил)

    Это вообще забавно, получается, что RVA Name может вести вообще мимо существующих секций. Интересно, для чего еще такие значения допустимы?

    Тоже не могу понять.
     
  8. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    GRRRLPower
    1) Истинный размер образа это ALIGN_UP(SizeOfImage, SectionAlignment), таким образом если в хидере "пофиксать", то AddressOfEntryPoint может быть больше чем SizeOfImage !!!
    2) Истинное начало секции это ALIGN_DOWN( PointerToRawData, FileAlignment ) /// ALIGN_DOWN( VirtualAddress, SectionAlignment);
    3) Размер секции весьма хитрое значение, его надо:
    VS = ALIGN( VirtualSize, SectionAlignment )
    RS = ALIGN( SizeOfRawData , FileAlignment )
    len = MIN(VS, RS)
    + учесть размер файла ну или образа
    4) офсет первой секции есть: 4 + sizeof(image_file_header) + pe->fileheader.SizeOfRawData

    С импортом возиться надо тогда, когда все пункты выше оттестированы и п.3 особенно !!!
     
  9. Bazhan

    Bazhan Андрей

    Публикаций:
    0
    Регистрация:
    8 янв 2008
    Сообщения:
    71
    Адрес:
    Украина
    загруженная в память секция (остальная часть страницы памяти обнулена)

    [​IMG]


    обнулим байт для получения корректной таблицы импорта

    [​IMG]
    [​IMG]
     
  10. GRRRLPower

    GRRRLPower New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2010
    Сообщения:
    46
    EvilsInterrupt, благодарю за подробное пояснение всего, что стоит учесть, второй пункт я уже учел, а для четвертого есть макрос IMAGE_FIRST_SECTION.

    Насчет первого:
    Думаю, что в хедере это значение менять нельзя, оно должно быть строго равно виртуальному адресу последней секции плюс ее выровненный размер, иначе PE не загрузится.

    Насчет третьего не совсем понял, о каком размере идет речь - в памяти или в образе на диске. Этот вопрос хорошо Крис Касперски осветил:
    Bazhan - не совсем понятно, зачем обнулять байт по указанному адресу? Там же, по спецификации, уже должен лежать RVA? Секции перекрываться не могут в памяти, поясните пожалуйста, как там может оказаться ноль?
     
  11. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    >>Думаю, что в хедере это значение менять нельзя, оно должно быть строго равно виртуальному адресу последней секции плюс ее выровненный размер, иначе PE не загрузится.
    Были прецеденты! Файл грузился, а размер не был выровнен ;) Выравнивай!
     
  12. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    Ну Bazhan объяснил: "загруженная в память секция (остальная часть страницы памяти обнулена)"
    Подробнее: оперирования с полями из таблицы импорта происходит после загрузки(проецирования) секций в память процесса. В нашем случае размер проецирования составляет 0x200 байт, а последующие байты (35 00..) спроецированы не будут и на их месте будут нули - и ...
    Указатель на массив с адресами названий имп-х функций(2 копия) будет 0х000011е8

    Непонятно другое:
    Указатель на таблицу импорта равен 0х0001а1ее - значит она располагается в 3 секции, которая проецируется с адреса 0х0001а000(без базы) ... и по-идее должно быть:
    -Указатель на строку с именем dll - 0х0001а002
    -Указатель на массив с адресами названий имп-х функций(2 копия) 0х001а11е8

    но лежит
    -Указатель на строку с именем dll - 0х00000002
    -Указатель на массив с адресами названий имп-х функций(2 копия) 0х000011е8

    -вообще, загадка... :)
     
  13. GRRRLPower

    GRRRLPower New Member

    Публикаций:
    0
    Регистрация:
    17 авг 2010
    Сообщения:
    46
    Спасибо, теперь понятно стало. Как Flint_ta говорил, upack действительно непростая штука)
     
  14. Bazhan

    Bazhan Андрей

    Публикаций:
    0
    Регистрация:
    8 янв 2008
    Сообщения:
    71
    Адрес:
    Украина
    под отладчиком
    Код (Text):
    1. kd> !dh 400000
    2.  
    3. File Type: EXECUTABLE IMAGE
    4. FILE HEADER VALUES
    5.      14C machine (i386)
    6.        3 number of sections
    7. 4011B0BE time date stamp Sat Jan 24 01:39:42 2004
    8.  
    9. FF50AD00 file pointer to symbol table
    10. 7CEB3476 number of symbols
    11.      148 size of optional header
    12.      10F characteristics
    13.             Relocations stripped
    14.             Executable
    15.             Line numbers stripped
    16.             Symbols stripped
    17.             32 bit word machine
    18.  
    19. OPTIONAL HEADER VALUES
    20.      10B magic #
    21.   76.111 linker version
    22. 694C6461 size of code
    23. 72617262 size of initialized data
    24.     4179 size of uninitialized data
    25.     1018 address of entry point
    26.       10 base of code
    27.          ----- new -----
    28. 00400000 image base
    29.     1000 section alignment
    30.      200 file alignment
    31.        2 subsystem (Windows GUI)
    32.     4.00 operating system version
    33.     0.57 image version
    34.     4.00 subsystem version
    35.    1B000 size of image
    36.      200 size of headers
    37.        0 checksum
    38. 00100000 size of stack reserve
    39. 00001000 size of stack commit
    40. 00100000 size of heap reserve
    41. 00001000 size of heap commit
    42.        0  DLL characteristics
    43.        0 [       0] address [size] of Export Directory
    44.    1A1EE [      14] address [size] of Import Directory
    45.        0 [       0] address [size] of Resource Directory
    46. AD3876FF [BE3E8B50] address [size] of Exception Directory
    47.   41A0F0 [F359276A] address [size] of Security Directory
    48.  476FFA5 [8BFFC883] address [size] of Base Relocation Directory
    49. 1CEBABDF [       0] address [size] of Debug Directory
    50. 50746547 [41636F72] address [size] of Description Directory
    51. 65726464 [    7373] address [size] of Special Directory
    52.        0 [       0] address [size] of Thread Storage Directory
    53. B140AB40 [C1ABF304] address [size] of Load Configuration Directory
    54.  7B50AE0 [7E8BABF3] address [size] of Bound Import Directory
    55. E951570C [   161FF] address [size] of Import Address Table Directory
    56. E3E21056 [E0D304B1] address [size] of Delay Import Directory
    57. 538DE803 [55C03318] address [size] of COR20 Header Directory
    58. E0D35140 [FF91EA8B] address [size] of Reserved Directory
    59.  
    60.  
    61. SECTION HEADER #1
    62. PSÿÕ«ëçà name
    63.    11000 virtual size
    64.     1000 virtual address
    65.      1F0 size of raw data
    66.       10 file pointer to raw data
    67.   412000 file pointer to relocation table
    68.   4172A7 file pointer to line numbers
    69.        3 number of relocations
    70.        0 number of line numbers
    71. E0000060 flags
    72.          Code
    73.          Initialized Data
    74.          (no align specified)
    75.          Execute Read Write
    76.  
    77. SECTION HEADER #2
    78.          name
    79.     8000 virtual size
    80.    12000 virtual address
    81.     5404 size of raw data
    82.      200 file pointer to raw data
    83.   401000 file pointer to relocation table
    84.   410FFF file pointer to line numbers
    85.     7404 number of relocations
    86.       41 number of line numbers
    87. E0000060 flags
    88.          Code
    89.          Initialized Data
    90.          (no align specified)
    91.          Execute Read Write
    92.  
    93. SECTION HEADER #3
    94.      FA name
    95.     1000 virtual size
    96.    1A000 virtual address
    97.      1F0 size of raw data
    98.       10 file pointer to raw data
    99.   417274 file pointer to relocation table
    100.   417277 file pointer to line numbers
    101.     7286 number of relocations
    102.       41 number of line numbers
    103. E0000060 flags
    104.          Code
    105.          Initialized Data
    106.          (no align specified)
    107.          Execute Read Write
    108.  
    109. //
    110. //секция где находится таблица импорта
    111. //
    112.  
    113. kd> db 41a000 L250
    114. 0041a000  4d 5a 4b 45 52 4e 45 4c-33 32 2e 44 4c 4c 00 00  MZKERNEL32.DLL..
    115. 0041a010  50 45 00 00 4c 01 03 00-be b0 11 40 00 ad 50 ff  PE..L......@..P.
    116. 0041a020  76 34 eb 7c 48 01 0f 01-0b 01 4c 6f 61 64 4c 69  v4.|H.....LoadLi
    117. 0041a030  62 72 61 72 79 41 00 00-18 10 00 00 10 00 00 00  braryA..........
    118. 0041a040  00 50 00 00 00 00 40 00-00 10 00 00 00 02 00 00  .P....@.........
    119. 0041a050  04 00 00 00 00 00 39 00-04 00 00 00 00 00 00 00  ......9.........
    120. 0041a060  00 b0 01 00 00 02 00 00-00 00 00 00 02 00 00 00  ................
    121. 0041a070  00 00 10 00 00 10 00 00-00 00 10 00 00 10 00 00  ................
    122. 0041a080  00 00 00 00 0a 00 00 00-00 00 00 00 00 00 00 00  ................
    123. 0041a090  ee a1 01 00 14 00 00 00-00 00 00 00 00 00 00 00  ................
    124. 0041a0a0  ff 76 38 ad 50 8b 3e be-f0 a0 41 00 6a 27 59 f3  .v8.P.>...A.j'Y.
    125. 0041a0b0  a5 ff 76 04 83 c8 ff 8b-df ab eb 1c 00 00 00 00  ..v.............
    126. 0041a0c0  47 65 74 50 72 6f 63 41-64 64 72 65 73 73 00 00  GetProcAddress..
    127. 0041a0d0  00 00 00 00 00 00 00 00-40 ab 40 b1 04 f3 ab c1  ........@.@.....
    128. 0041a0e0  e0 0a b5 07 f3 ab 8b 7e-0c 57 51 e9 ff 61 01 00  .......~.WQ..a..
    129. 0041a0f0  56 10 e2 e3 b1 04 d3 e0-03 e8 8d 53 18 33 c0 55  V..........S.3.U
    130. 0041a100  40 51 d3 e0 8b ea 91 ff-56 4c 99 59 d1 e8 13 d2  @Q......VL.Y....
    131. 0041a110  e2 fa 5d 03 ea 45 59 89-6b 08 56 8b f7 2b f5 f3  ..]..EY.k.V..+..
    132. 0041a120  a4 ac 5e b1 80 aa 3b 7e-34 0f 82 ac fe ff ff 58  ..^...;~4......X
    133. 0041a130  5f 59 e3 1b 8a 07 47 04-18 3c 02 73 f7 8b 07 3c  _Y....G..<.s...<
    134. 0041a140  00 75 f3 b0 00 0f c8 03-46 38 2b c7 ab e2 e5 5e  .u......F8+....^
    135. 0041a150  5d 59 46 ad 85 c0 74 1f-51 56 97 ff d1 93 ac 84  ]YF...t.QV......
    136. 0041a160  c0 75 fb 38 06 74 ea 8b-c6 79 05 46 33 c0 66 ad  .u.8.t...y.F3.f.
    137. 0041a170  50 53 ff d5 ab eb e7 c3-00 10 01 00 00 10 00 00  PS..............
    138. 0041a180  f0 01 00 00 10 00 00 00-00 20 41 00 a7 72 41 00  ......... A..rA.
    139. 0041a190  03 00 00 00 60 00 00 e0-00 10 40 00 dc 72 41 00  ....`.....@..rA.
    140. 0041a1a0  00 80 00 00 00 20 01 00-04 54 00 00 00 02 00 00  ..... ...T......
    141. 0041a1b0  00 10 40 00 ff 0f 41 00-04 74 41 00 60 00 00 e0  ..@...A..tA.`...
    142. 0041a1c0  46 12 41 00 fc 0f 40 00-00 10 00 00 00 a0 01 00  F.A...@.........
    143. 0041a1d0  f0 01 00 00 10 00 00 00-74 72 41 00 77 72 41 00  ........trA.wrA.
    144. 0041a1e0  86 72 41 00 60 00 00 e0-28 00 00 00 be 00 00 00  .rA.`...(.......
    145. 0041a1f0  00 00 00 00 00 00 00 00-00 00 02 00 00 00 e8 11  ................
    146. 0041a200  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
    147. 0041a210  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
    148. 0041a220  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
    149. 0041a230  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
    150. 0041a240  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
    151.  
    152. //
    153. //IMAGE_IMPORT_DESCRIPTOR
    154. //
    155.  
    156. kd> dd 400000+1a1ee
    157. 0041a1ee  00000000 00000000 00000000 00000002
    158. 0041a1fe  000011e8 00000000 00000000 00000000
    159. 0041a20e  00000000 00000000 00000000 00000000
    160. 0041a21e  00000000 00000000 00000000 00000000
    161. 0041a22e  00000000 00000000 00000000 00000000
    162. 0041a23e  00000000 00000000 00000000 00000000
    163. 0041a24e  00000000 00000000 00000000 00000000
    164. 0041a25e  00000000 00000000 00000000 00000000
    165.  
    166. //
    167. //Import address table
    168. //
    169.  
    170. kd> dps 400000+11e8
    171. 004011e8  6591de40 kernel32!LoadLibraryA
    172. 004011ec  6591e8c0 kernel32!GetProcAddress
    173. 004011f0  00000000
    174.  
    175. kd> da 400000 + 2
    176. 00400002  "KERNEL32.DLL"
     
  15. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    Bazhan
    Вот спасибо, теперь все понятно...
    Код (Text):
    1. //
    2. //Import address table
    3. //
    4. kd> dps 400000+11e8
    - адрес указывает в другую секцию (обычно все эти структуры лежат в одной секции)

    чего-то я сам не догадался загрузить и сдампить память - все в голове считал...