·.text:00401000; Segment type: Pure code
·.text:00401000 _text segment para public 'CODE' use32
·.text:00401000 assume cs:_text
·.text:00401000;org 401000h
·.text:00401000 assume es:nothing, ss:nothing, ds:_data, fs:nothing, gs:nothing
·.text:00401000 Root proc near
·.text:00401000; Функции root расположена по адресу 0x401000
·.text:00401000 push ebp
·.text:00401000 ;… назначение процедуры root значение не имеет
·.text:00401000 ;… для ее вызова достаточно знать по какому адресу она расположена в памяти
·.text:00401000;… а расположена она по адресу 0x401000
·.text:00401001 mov ebp, esp
·.text:00401003 push offset aHelloRoot; "Hello, Root!\n"
·.text:00401008 call _printf
·.text:0040100D add esp, 4
·.text:00401010 pop ebp
·.text:00401011 retn
·.text:00401011 Root endp
·.text:00401012
·.text:00401012; --------------- S U B R O U T I N E ---------------------------------------
·.text:00401012
·.text:00401012; Attributes: bp-based frame
·.text:00401012
·.text:00401012 auth proc near; CODE XREF: main+10p
·.text:00401012
·.text:00401012 var_18 = byte ptr -18h
·.text:00401012 var_C = byte ptr -0Ch
·.text:00401012; Так IDA обозначает локальные переменные, а цифры указывают относительное
·.text:00401012; расположение от конца кадра стека.
·.text:00401012; В Момент вызова функции указатель стека указывает на адрес возврата
·.text:00401012 push ebp
·.text:00401012; В стек заносится регистр ebp, значение указателя стека уменьшается на 4
·.text:00401013 mov ebp, esp
·.text:00401013; Открывается кадр стека:
·.text:00401013; В регистр ebp заносится значение регистра указателя стека esp.
·.text:00401013; Регистр ebp будет использоваться для адресации локальных переменных относительно конца кадра стека
·.text:00401015 sub esp, 18h
·.text:00401015; Резервируется 0x18 (24 в десятичной нотации) байт под локальные переменные
·.text:00401015; Но размер двух буферов равен 10+10=20 байтам! Откуда взялись четрые лишние байта?
·.text:00401015 ; Для ускорения доступа к данным компилятор размещает начала каждого из буферов по адресам, кратным
·.text:00401015; четырем байтам, так называемое выравнивание.
·.text:00401015; Таким образом на данный момент стек выглядит так:
·.text:00401015;
·.text:00401015; Относительный адрес Содержимое ячейки
·.text:00401015; - 0x18 буфер var_18[0]
·.text:00401015; - 0x17 буфер var_18[1]
·.text:00401015; - 0x16 буфер var_18[2]
·.text:00401015; - 0x15 буфер var_18[3]
·.text:00401015; - 0x14 буфер var_18[4]
·.text:00401015; - 0x13 буфер var_18[5]
·.text:00401015; - 0x12 буфер var_18[6]
·.text:00401015; - 0x11 буфер var_18[7]
·.text:00401015; - 0x10 буфер var_18[8]
·.text:00401015; - 0x0F буфер var_18[9]
·.text:00401015; - 0x0E дырка для выравнивания
·.text:00401015; - 0x0D дырка для выравнивания
·.text:00401015; - 0x0С буфер var_С[0] 01
·.text:00401015; - 0x0B буфер var_С[1] 02
·.text:00401015; - 0x0A буфер var_С[2] 03
·.text:00401015; - 0x09 буфер var_С[3] 04
·.text:00401015; - 0x08 буфер var_С[4] 05
·.text:00401015; - 0x07 буфер var_С[5] 06
·.text:00401015; - 0x06 буфер var_С[6] 07
·.text:00401015; - 0x05 буфер var_С[7] 08
·.text:00401015; - 0x04 буфер var_С[8] 09
·.text:00401015; - 0x03 буфер var_С[9] 10
·.text:00401015; - 0x02 дырка для выравнивания 11
·.text:00401015; - 0x01 дырка для выравнивания 12
·.text:00401015; 0x00 значение регистра ebp[0] 13
·.text:00401015; + 0x01 значение регистра ebp[1] 14
·.text:00401015; + 0x02 значение регистра ebp[2] 15
·.text:00401015; + 0x03 значение регистра ebp[3] 16
·.text:00401015; + 0x04 значение регистра eip[0] (адрес возврата) 17
·.text:00401015; + 0x05 значение регистра eip[1] (адрес возврата) 18
·.text:00401015; + 0x06 значение регистра eip[2] (адрес возврата) 19
·.text:00401015; + 0x07 значение регистра eip[3] (адрес возврата) 20
·.text:00401015; Таким образом, байты с 17 до 20 (не считая нуля завершающего строку) из буфера var_c затирают
·.text:00401015: адрес возврата сохраненный в стеке. Следовательно, строка из шестнадцати символов, включая
·.text:00401015; завершающий ноль вызовет модификацию младшего байта адреса возврата.
·.text:00401015; Остается отождествить буфер var_c - что он собой представляет имя пользователя или пароль?
·.text:00401018 push offset aLogin; "Login:"
·.text:00401018; В стек заносится смещение строки “Login”, значение указателя стека уменьшается на 4
·.text:00401018; Это первый (и единственный) аргумент функции printf
·.text:0040101D call _printf
·.text:0040101D; Вывод на экран приглашения “Login:”
·.text:00401022 add esp, 4
·.text:00401022; Значение указателя стека увеличивается на четыре, чтобы избавится от занесенного в стек смещения
·.text:00401025; строки “Login”. Си-функции не очищают стек после своего завершения
·.text:00401025 lea eax, [ebp+var_C]
·.text:00401025; В регистр eax заносится смещение буфера var_c, для последующей передачи его функции gets, читающей
·.text:00401025; строку с клавиатуры.
·.text:00401025; Следовательно, буфер var_c содержит имя пользователя
·.text:00401028 push eax
·.text:00401028; Значение eax заносится в стек
·.text:00401029 call _gets
·.text:00401029; Вызов функции _gets
·.text:0040102E add esp, 4
·.text:0040102E; Удаление двойного слова из стека (для очистки аргумента функции gets)
·.text:00401031 push offset aPassw; "Passw:"
·.text:00401031; Занесение в стек строки «Passw»
·.text:00401036 call _printf
·.text:00401036; Вывод строки “Passw” на экран с помощью функции printf
·.text:0040103B add esp, 4
·.text:0040103B; Удаление двойного слова из стека
·.text:0040103E lea ecx, [ebp+var_18]
·.text:0040103E; В регистр ecx заносится смещение буфера var_18 для последующей передачи его функции gets,
·.text:0040103E; читающей строку с клавиатуры. Следовательно, буфер var_18 содержит пароль
·.text:00401041 push ecx
·.text:00401041 ; Передача аргумента функции gets
·.text:00401042 call _gets
·.text:00401042 ; Чтение пароля в буфер var_18
·.text:00401047 add esp, 4
·.text:00401047 ; Балансировка стека
·.text:0040104A push offset aGuest; "guest"
·.text:0040104A; Занесение в стек смещения строки Guest для сравнения ее с введенным паролем
·.text:0040104F lea edx, [ebp+var_18]
·.text:0040104F; В регистр edx заносится смещение буфера, содержащего введенный пароль
·.text:00401052 push edx
·.text:00401052; Сейчас в верхушке стека содержатся два значения
·.text:00401052; смещение эталонного пароля и смещения буфера, содержащего введенный пароль
·.text:00401053 call _strcmp