이번에는 버퍼 오버플로우 취약점으로 자주 등장하는 strcpy 함수를 디버깅 해보겠습니다.
너무 쉬워보일수도 있겠지만 모든것들이 패턴이 있습니다. 함수가 호출되기전에 어떻게 인자를
참조하는지 이 작업은 무엇을 의미하는지, 저 또한 공부한지 별로 안됬지만 조금 알것같습니다.
이런 밑거름들을 차근차근 해나가다가 나중에는 워게임 하나를 디버깅해 취약점을 찾아낸다는지..
가능할겁니다.
[gate@localhost tmp]$ cat t2.c
int main(int argc, char *argv[])
{
char buffer[40];
strcpy(buffer, argv[1]); // argv[1] 을 buffer 에 복사합니다.
printf("%s\n", buffer); // 복사된 buffer 을 출력합니다.
}
[gate@localhost tmp]$ ./t2 buffer
buffer
고로 인자로 전달해주는 값에 따라 출력되어지는 값도 달라질겁니다.
[gate@localhost tmp]$ gdb -q t2
(gdb) disas main
Dump of assembler code for function main:
0x80483f8 <main>: push %ebp
0x80483f9 <main+1>: mov %esp,%ebp // 프롤로그
0x80483fb <main+3>: sub $0x28,%esp // 변수 40바이트 선언
0x80483fe <main+6>: mov 0xc(%ebp),%eax // EAX 에 (EBP+12) 의 값을 복사한다. - (EBP+12) == Argv[0]
0x8048401 <main+9>: add $0x4,%eax // EAX+4 - Argv[0] + 4 == Argv[1]
0x8048404 <main+12>: mov (%eax),%edx // EDX 에 EAX 의 값을 복사한다.
0x8048406 <main+14>: push %edx // EDX푸시
0x8048407 <main+15>: lea 0xffffffd8(%ebp),%eax // EAX 에 (EBP-40) 의 값을 복사한다.
0x804840a <main+18>: push %eax // EAX 푸시
0x804840b <main+19>: call 0x8048340 <strcpy>
/*
strcpy(buffer, argv[1]); 호출작업입니다.
Argv[1] 을 푸시하기위해 EAX(Argv[0]) 에 +4 를 하고 EDX 에 옮긴 후 푸시했으며
Buffer 를 인자로 가져오기 위해 (EBP-40) 주소 값(Buffer 의 주소값) 을 참조합니다.
아마 EBP 는 현재 아무런 움직임을 가지지 않았으며 꼭대기에 그대로 있나봅니다.
*/
0x8048410 <main+24>: add $0x8,%esp // ESP + 8
0x8048413 <main+27>: lea 0xffffffd8(%ebp),%eax // EAX 에 (EBP-40) 주소 값을 복사합니다.
0x8048416 <main+30>: push %eax // EAX 를 푸시합니다.
0x8048417 <main+31>: push $0x8048480 // "%s\n" 을 푸시합니다.
// 0x8048480 <_IO_stdin_used+4>: "%s\n"
0x804841c <main+36>: call 0x8048330 <printf>
// printf("%s\n", buffer);
0x8048421 <main+41>: add $0x8,%esp
0x8048424 <main+44>: leave
0x8048425 <main+45>: ret
/* 생략 */
End of assembler dump.
(gdb) b *main+19
Breakpoint 2 at 0x804840b
(gdb) r aaaa
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/gate/xodnr/tmp/t2 aaaa
Breakpoint 2, 0x804840b in main ()
(gdb) x/s $edx
0xbffffcaf: "aaaa" // 우리가 입력해주었던 Argv[1] 이 존재합니다
두 번째로 Buffer 의 주소값을 참조하는 과정입니다.
(gdb) b *main+19
Breakpoint 5 at 0x804840b
(gdb) r aaaa
The program being debugged has been started already.
Start it from the beginning? (y or n)
Please answer y or n.
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/gate/xodnr/tmp/t2 aaaa
Breakpoint 4, 0x804840a in main ()
(gdb) x/s $ebp-40
0xbffffb40: "hûÿ¿p©"
(gdb) x/s $eax
0xbffffb40: "hûÿ¿p©" // 서로 같습니다.
이로써 이번 문제의 분석과정은 끝났습니다.
복사해야할 것을 먼저 푸시하고 붙여줘야되는곳을 푸시했습니다.
소스가 짧아서 그런건지 매우 쉬웠습니다.
'스터디 > system' 카테고리의 다른 글
리눅스 GDB 어셈블리어 AT&T 문법을 intel 문법으로 바꾸는 방법 //AT&T -> INTEL (0) | 2011.08.20 |
---|---|
[GDB-Analysis] GDB 바이너리 디버깅 3 (0) | 2011.08.18 |
[GDB-Analysis] GDB 바이너리 디버깅 1 (1) | 2011.08.17 |
[IDA-Analysis] Binary Wargames Level1 (0) | 2011.08.17 |
메모리 기본 구조 STACK_EBP (0) | 2011.08.15 |