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

Дата публикации 13 июн 2019 | Редактировалось 4 июл 2019
Мы видим, что есть две разные операции и SEND. Мы должны изучить обе операции, чтобы увидеть, какая из них работает и почему.

1.png


В этом компиляторе резервируются 4 QWORDS над пространством переменных, так что дочерняя функция хранит аргументы, которые передаются через регистры.

2.png

Таким образом, поскольку дочерняя функция имеет 5 аргументов, 5-й будет VAR_248.

Я переименую переменную в CONST_0, так как программа пишет туда ноль.

3.png

Давайте сначала проанализируем операцию 0x22222222.

4.png

Другие 4 аргумента такие.

__INT64 __USERCALL OP_0X22222222@<RAX>(INT LEVEL_MENOR_O_IGUAL_QUE_0X200 @<ECX>, CHAR * P_BUF_512_TERCER_RECV@<RDX>, INT BYTES_RECIBIDOS_3ER_RECV@<R8D>, INT OFFSET_VALOR_NEGATIVO@<R9D>);

Здесь распространяются аргументы.

5.png

Дело в том, что это рекурсивная функция, одинаковая в каждом вызове.

6.png

Мы видим, что когда функция повторяется, аргументы совпадают, только уменьшается уровень. Мы видели, что он не может быть больше или равен 0x200, поэтому, если вы передадите 0x200, будете повторяться то же самое 0x200 раз, уменьшая уровень в каждом вызове.

Другими словами, функция будет продолжать повторяться только уменьшая уровень и больше ничего не будет делать.

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

7.png

Это всё будет повторяться, ничего не делая, пока уровень не уменьшится и не достигнет нуля.

8.png

В этом случае программа перейдёт к этому блоку, где вы перепишите с помощью OK на некоторую часть стека выше BUFFER_512_TERCER_RECV, так как указатель на него добавляет отрицательное смещение.

Мы видим, что OK - это строка из 2 байтов и конечного нуля.

9.png

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

10.png

Дело в том, что после того, как программа достигнете уровня до нуля и выполнит функцию strcpy, вы выйдете из функции и вернетесь сюда.

11.png

И пройдет через возврат каждого уровня, в противоположном направлении, оставляя каждую функцию по тому же адресу.

Дело в том, что переменная CONST_0 всегда будет равна 0 и программа не будет переходить к функции STRNCAT, которая будет пропущена, до уровня 0X1FF, который был выполнен первым и который имеет переменную CONST_0, и которую мы перезаписали с помощью OK, поэтому существует только один раз перейти к функции STRNCAT.

12.png

Этот уровень будет 0x200, так как это максимальный уровень и он будет счетчиком STRNCAT, поэтому вы должны попытаться отправить максимально возможное значение, в данном случае 0x200, чтобы объединить много данных.

13.png

SOURCE - это указатель на пакет, отправленный RECV ему в третьем параметре, который будет скопирован после строки OK, поэтому я могу перейти к переменным в стеке, которые находятся ниже CONST_0, включая очень ценную переменную, такую как размер SEND.

14.png

Если я перезапишу этот размер с большим значением, чем у меня, я мог бы получить утечку из стека, включая COOKIE, и адрес возврата, который позволит мне в следующем пакете отправить длину, поскольку исполняемый файл имеет ASLR.

Прежде чем мы начнем делать скрипт, я должен изучить другую функцию OP_0X11111111, чтобы увидеть, что произойдет, если я выберу её вместо OP_0X22222222.

15.png

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

__INT64 __USERCALL OP_0X11111111@<RAX>(INT LEVEL_MENOR_O_IGUAL_QUE_0X200 @<ECX>, CHAR * P_BUF_512_TERCER_RECV@<RDX>, INT BYTES_RECIBIDOS_3ER_RECV@<R8D>, INT OFFSET_VALOR_NEGATIVO@<R9D>);

Здесь распространяются значения.

16.png

Мы видим, что так же, как в OP_0X22222222 программа будет повторять ту же функцию, только изменяя уровень, который уменьшается. В то время как он будет повторяться до 0x200 раз в зависимости от уровня, который мы установили, и по мере его снижения счетчик достигнет ноль. Когда он это сделает, программа перейдет к STRCPY.

17.png

Здесь программа достигает функции STRCPY с уровнем равным 0.

18.png

В этом случае программа не добавляет отрицательное смещение к DESTINO, поэтому программа будет писать только OK в начале третьего буфера пакета.

Также следует отметить, что строка OK не совпадает с функцией 0x22222222, она имеет длину пять символов и имеет три точки после “OK…”.

Здесь есть обе строки.

19.png

20.png

Затем, возвращаясь к адресу возврата при каждом повторения, программа переходит к функции STRNCAT.

21.png

22.png

DESTINATION будет буфером THIRD_RECV, где в начале будет “OK…” куда я копирую в функцию strcpy, но после того, как эта строка заканчивается, это будет зависеть от того, что мы указываем в SOURCE, который будет тем же указателем плюс отрицательное смещение. Другими словами, мы можем добавить данные из верхней части буфера и вставить их в конце.

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

Также может случиться утечка, так как строка, которая будет в DEST в буфере, будет маленькой (для строки "OK ...", которую я копирую, будет только 5 байтов, и она заканчивается нулем, что сделает ее зависимой от того, что находится над буфером, например, адрес возврата повторений, хотя не COOKIE, он не будет выше буфера.

Мы также помним, что в случае функции OP_0X22222222 программа только один раз прибыла бы в функцию STRNCAT. В случае OP_0X11111111 необходимо помнить, что когда она уменьшается и достигает уровня 0, программа идет в функцию STRCPY и оттуда, поскольку она не зависит ни от каких CONST_0 во всех выходах всех уровней программа переходит в функцию STRNCAT.

23.png

Кроме того, поскольку количество, которое копирует в COUNT, является значением текущего уровня, и оно будет уменьшено, скопировано на уровень 1 будет только 1 байт. Далее, когда программа выйдет из LEVEL2_COPIARA и так далее, до последнего уровня, который скопирует 0x1ff и затем уже перейдет к отцовской функции.

Очевидно, что скопируется это количество байтов если нет нулей, потому что копируются строки, если уровень равен 0x150, и есть ноль, копируюся только из SOURCE в ноль, а не в полный размер.

Хорошо. Таким образом, существует много возможностей. Мы можем сделать утечку данных на первом этапе и получить COOKIE и адреса исполняемых файлов, которые позволят нам переполнить во втором пакете и выполнить ROP и записать флаг, чтобы избежать утечки средств и запустить CALC.

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

0 3.859
yashechka

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

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