Введение в реверсинг с нуля, используя IDA PRO. Часть 48-2.

Дата публикации 20 июн 2018 | Редактировалось 24 июн 2018
1.png

LEA
EAX, DS:110H[EAX*4]

Программа умножает значение 0x2 на 4 и складывает полученное значение со значением 0x110 и затем вычитает из найденного значения HEAP_BUCKET и сохраняет результат в переменную VAR_2C.

Этот адрес, который сохраняется в переменную VAR_2C является началом таблицы LFH, так как HEAP_BUCKETS находится по смещению 0x110 и должен быть равен 8, потому что поле находится внутри таблицы BUCKETS, поэтому в переменной VAR_2C программа сохраняет значение 0x24ACF8, которое было началом таблицы LFH.

2.png

3.png

4.png

То, что программа сейчас делает, это то, что говорит нам картинка. Программа пытаясь найти адрес LFH для этой структуры BUCKET, используя переменную SIZEINDEX.

5.png

6.png

Очевидно, мы находимся в этой части, только в моём случае переменная не равна единице и программа продолжает выполнение здесь.

7.png

8.png

Программа достигает инструкции LEA, где на данный момент регистр EAX равен нулю, поскольку он получается из умножения 0x3418 на CONST_CERO и суммируется с регистром ESI, который хранит начало таблицы LFH и добавляет значение 0x310.

9.png

Мы напомним, что смещение 0x310 из LFH это _HEAP_LOCAL_DATA.

10.png

Это значение сохраняется в переменную VAR_44. Я переименую это поле в HEAP_LOCAL_DATA.

11.png

12.png

13.png

Основная идея состоит в том, что мы пытаемся найти эти структуры и увидим, можем ли мы их найти и идентифицировать.

Хорошо. Мы должны создать структуру для HEAP_LOCAL_DATA.

14.png

Я создаю структуру из 0x22 байт, хотя она наверняка будет намного больше, но пока пойдет и это.

По смещению 0x18 есть структуры. Их размер равен 0x128 байт.

[128] _HEAP_LOCAL_SEGMENT_INFO

Программа проходит через все эти 128 структур, используя SIZEINDEX как индекс, который умножается на 0x68, а затем добавляет значение, чтобы найти адрес это структуры SEGMENTINFO.

15.png

Это означает, что адрес DIRECCION3 равен HEAP_LOCAL_SEGMENT_INFO.

16.png

17.png

Поэтому мы будем создавать структуру больше чем 0x64 байта.

18.png

19.png

Хорошо. Внутри отладчика этого выглядит так.

ntdll!_HEAP_LOCAL_SEGMENT_INFO
+0x000 Hint : Ptr32 _HEAP_SUBSEGMENT

Первое поле, которое программа пытается использовать здесь, говорит, что это HINT .

20.png

И программа сохранит это значение в переменную VAR_30. Я переименовываю переменную в HINT.

21.png

Если значение HINT не равно нулю, программа ищет ACTIVESUBSEGMENT, что является следующим полем.

22.png

А если это поле равно нулю, программа переходит сюда

23.png

В любом из трех случае, программа сохраняет результат в переменной, которую мы назвали HINT, но она может быть любой из трех.

68.png

Хорошо. Мы находимся здесь.

24.png

Мы будем переименовывать переменную HINT в RESULTADO, поскольку переменная может принимать три значения.

25.png

Картинка показывает нам три варианта. Сейчас же мы находимся в HINT.

Этот результат должен был бы быть _HEAP_SUBSEGMENT.

26.png

27.png

Здесь программа говорит мне, что _HEAP_LOCAL_SEGMENT_INFO находится в памяти по адресу 0x24B0F0 и что 0x282660 это структура _HEAP_USERDATA_HEADER а по смещению 0x08 это структура INTERLOCK_SEQ.

Мы уже подходим к концу. Фууууууууууууууууууххххххххххххх.

Здесь я добавляю новую структуру.

28.png

29.png

Здесь я вижу, что программа находит с помощью инструкции LEA адрес поля _INTERLOCK_SEQ

30.png

31.png

На данный момент, я думаю что она состоит из 4 байтов.

Программа может прочитать поле как WORD или как DWORD, это сложно для имени. В моем случае, программа читает DWORD т.е. имеет значение 0x56000D (ЭТО ЗНАЧЕНИЕ ОЧЕНЬ ВАЖНО)

32.png

33.png

34.png

Я добавляю поле SEQUENCE.

35.png

Программа тестирует регистр DI который хранит поле OFFSETANDDEPTH. Это поле в моём случае равно 0xD.

36.png

Здесь программа читает поле USERBLOCKS, которое находится по смещению 0x4 структуры HEAP_SUBSEGMENT.

37.png

Программа сравнивает регистр EDX который хранит LOCALINFO высчитанный с помощью указателя HEAP_SUBSEGMENT.LOCALINFO и они должны быть одинаковыми.

Поскольку значения одинаковые, программа идет к этому блоку.

38.png

39.png

Хорошо. Я не собираюсь просчитывать все эти значения, но очевидно, что то, что программа делает, это получает первый свободный блок запрошенного размера из значений структуры _INTERLOCK_SEQ, и когда программа покинет этот блок, она сохранит его здесь.

40.png

Регистр ECX здесь равен значению 282918 и если я посмотрю список блоков с размером 0x10 с помощью команды.

!heap -flt s 0x10

В выводе блоки находятся здесь

41.png

И это первое значение из этих LFH, потому что предыдущие размеры 0x10, которые говорят что они FREE(СВОБОДНЫЕ), имеют другую LFH младшего адреса, возможно, соответствующей другой куче.

42.png

Здесь по адресу чанка 0x282918 без заголовка, вычитается 8, и остается адрес полного блока с заголовком 0x282910.

43.png

Структура, которую мы ещё не добавили называется структурой LFH. Сейчас я сделаю это.

44.png

45.png

Теперь используется поле 0x24, которое должно найти базовый адрес КУЧИ по адресу 0x240000. Полученное значение помещается в регистр ESI.

46.png

BLOCKUNITS
был равен 0x3 в инструкции SHL EAX, 3

Это похоже на умножение 8 поэтому

47.png

И это то значение, что осталось в поле USERSIZE

48.png

И это значение программа сравнивает со значением 0x3F . Поскольку оно меньше, программа идёт сюда.

49.png

Здесь программа пишет в заголовок чанка LFH. Мы не сделали структуру.

50.png

51.png

52.png

Программа перезаписывает 7 байт, меняя его со значения 0x80 на 0x88.

53.png

54.png

Сейчас блок обозначен как занятый. Если мы посмотрим следующий свободный блок по адресу 282928

55.png

Свободные блоки - это блоки со значение 0x80 , а занятые со значением 0x88.

56.png

Вопрос состоит в том, что значение, которое находится в структуре INTERLOCK_SEQ и которое определяет следующий блок для доставки находится в по адресу 0x282A78 (по смещению 0x8 от начала структуры HEAP_SUBSEGMENT)

До этого значение было равно 56000D.

57.png

А сейчас значение равно 59000C.

58.png

59.png

Расстояние между началом чанка, в который я могу написать, который решает, кто следующий….

60.png

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

61.png

Это значение 0x282660 USERBLOCKS, помещается в регистр ESI.

62.png
63.png

Это означает, что в следующий раз, когда запрашивается размер 0x010, программа поместит в EDI значение 0x59000C если оно не перезаписано.

Программа помещает значение в регистр EAX и затем исполняет инструкцию SHR EAX,0xD

2
в 0xD степени = 8192 десятичных байт, т.е. 0x2000 в шестнадцатеричной системе

Другими словами, это эквивалентно значению 0x59000С делённому на значение 0x2000, что даёт мне результат 0x2C8

64.png

К этому значению программа применяет инструкцию AND c параметром 0x7FFF8

65.png

Затем программа добавляет регистр ESI, который равен 0x282660

66.png

И это даём мне результат 0x282928, что является следующим свободным

67.png

Это означает, что если есть переполнение, мы можем перезаписать эти данные переписав значение внутри структуры INTERLOCK_SEQ и программа предоставит мне предыдущий блок, про который мы расскажем в следующей части.

=======================================================
Автор текста: Рикардо Нарваха - Ricardo Narvaja (@ricnar456)
Перевод на русский с испанского: Яша_Добрый_Хакер(Ростовский фанат Нарвахи).
Исправление ошибок и неточностей - репетитор и носитель испанского языка.

Перевод специально для форума системного и низкоуровневого программирования — WASM.IN
24.06.2018
Версия 1.0

5 5.288
yashechka

yashechka
Ростовский фанат Нарвахи

Регистрация:
2 янв 2012
Публикаций:
90

Комментарии


      1. yashechka 24 июн 2018
      2. yashechka 24 июн 2018
        [​IMG]
      3. yashechka 24 июн 2018
        Не совсем удачный перевод, но даже репетитор разводит руками, говоря, что ей трудно понять, что Рик хотел сказать, со своим аргентиским наречием. Также все усугубляет, то что она не связана с программированием. Поэтому она переводит для меня дословно. Также он придумывает слова, которых нет. Произодные от английскийcого -PUSHEA, PIVOTEANDO. В любом случае, на 90 % здесь все правильно, может даже на 95 ))
      4. yashechka 21 июн 2018
        Jeje
      5. LastNoob 21 июн 2018
        Хехе, вот эту главу я точно осилю)
        yashechka нравится это.