이번에는 저번에 두개로 했던 것들과 strcat 함수를 곁들여 컴파일해 디버깅을 해보도록 하겠습니다.
다음부터는 버퍼 오버플로우와 관련된 함수를 주제로 디버깅 연습을 해갈 생각입니다.
[gate@localhost tmp]$ cat t3.c
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
char buffer[40];
printf("%d ", argc);
printf("%s ", argv[0]);
printf("%s ", argv[1]);
printf("%s ", argv[2]);
printf("%s\n", argv[3]);
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
strcat(argv[2], argv[3]);
printf("%s\n", argv[2]);
return 0;
}
[gate@localhost tmp]$ ./t3 1 2 3 4
5 ./t3 1 2 3
1 // Argv[1] == Buffer
23 // Argv[2] + Argv[3]
[gate@localhost tmp]$ gdb -q t3
(gdb) disas main
Dump of assembler code for function main:
0x8048440 <main>: push %ebp
0x8048441 <main+1>: mov %esp,%ebp // 프롤로그
0x8048443 <main+3>: sub $0x28,%esp // 변수 40바이트 선언
0x8048446 <main+6>: mov 0x8(%ebp),%eax // EAX 에 (EBP+8) 값 복사 - (EBP+8) == Argc
0x8048449 <main+9>: push %eax // EAX 푸시
0x804844a <main+10>: push $0x8048560 // 0x8048560 푸시 - %d
0x804844f <main+15>: call 0x8048364 <printf>
// printf("%d ", argc);
0x8048454 <main+20>: add $0x8,%esp // ESP + 8
0x8048457 <main+23>: mov 0xc(%ebp),%eax // EAX 에 (EBP+12) 값 복사 - (EBP+12) == Argv[0]
0x804845a <main+26>: mov (%eax),%edx // EDX 에 EAX 값 복사
0x804845c <main+28>: push %edx // EDX 푸시
0x804845d <main+29>: push $0x8048565 // 0x8048565 푸시 - %s
0x8048462 <main+34>: call 0x8048364 <printf>
// printf("%s ", argv[0]);
0x8048467 <main+39>: add $0x8,%esp // ESP + 8
0x804846a <main+42>: mov 0xc(%ebp),%eax // EAX 에 (EBP+12) 값 복사 - Argv[0]
0x804846d <main+45>: add $0x4,%eax // EAX + 4 - Argv[0] + 4 == Argv[1]
0x8048470 <main+48>: mov (%eax),%edx // EDX 에 EAX 값 복사
0x8048472 <main+50>: push %edx // EDX 푸시
0x8048473 <main+51>: push $0x8048565 // 0x8048565 푸시
0x8048478 <main+56>: call 0x8048364 <printf>
// printf("%s ", argv[1]);
0x804847d <main+61>: add $0x8,%esp
0x8048480 <main+64>: mov 0xc(%ebp),%eax // EAX 에 (EBP+12) 값 복사 - Argv[0]
0x8048483 <main+67>: add $0x8,%eax // Argv[0] + 8 == Argv[2]
0x8048486 <main+70>: mov (%eax),%edx
0x8048488 <main+72>: push %edx
0x8048489 <main+73>: push $0x8048565
0x804848e <main+78>: call 0x8048364 <printf>
// printf("%s ", argv[2]);
0x8048493 <main+83>: add $0x8,%esp
0x8048496 <main+86>: mov 0xc(%ebp),%eax // EAX 에 (EBP+12) 값 복사 - Argv[0]
0x8048499 <main+89>: add $0xc,%eax // Argv[0] + 12 == Argv[3]
0x804849c <main+92>: mov (%eax),%edx
0x804849e <main+94>: push %edx
0x804849f <main+95>: push $0x804856a
0x80484a4 <main+100>: call 0x8048364 <printf>
// printf("%s ", argv[3]);
0x80484a9 <main+105>: add $0x8,%esp // ESP + 8
0x80484ac <main+108>: mov 0xc(%ebp),%eax // EAX 에 (EBP+12) 값 복사 - Argv[0]
0x80484af <main+111>: add $0x4,%eax // EAX + 4 == Argv[1]
0x80484b2 <main+114>: mov (%eax),%edx // EDX 에 EAX 값 복사
0x80484b4 <main+116>: push %edx // EDX 푸시
0x80484b5 <main+117>: lea 0xffffffd8(%ebp),%eax // EAX 에 (EBP-40) 주소 값 복사 - Buffer
0x80484b8 <main+120>: push %eax // EAX 푸시
0x80484b9 <main+121>: call 0x8048374 <strcpy>
// strcpy(buffer, argv[1]);
EAX , EDX
0x80484be <main+126>: add $0x8,%esp
0x80484c1 <main+129>: lea 0xffffffd8(%ebp),%eax // EAX 에 (EBP-40) 주소값 복사 - Buffer
0x80484c4 <main+132>: push %eax // EAX 푸시
0x80484c5 <main+133>: push $0x804856a // 0x804856a 푸시 - %s\n
0x80484ca <main+138>: call 0x8048364 <printf>
0x80484cf <main+143>: add $0x8,%esp // ESP + 8
0x80484d2 <main+146>: mov 0xc(%ebp),%eax // EAX 에 (EBP+12) 값 복사 - Argv[0]
0x80484d5 <main+149>: add $0xc,%eax // EAX + 12 == Argv[3]
0x80484d8 <main+152>: mov (%eax),%edx // EDX 에 EAX 값 복사
0x80484da <main+154>: push %edx // EDX(1) 푸시
0x80484db <main+155>: mov 0xc(%ebp),%eax // EAX 에 (EBP+12) 값 복사 - Argv[0]
0x80484de <main+158>: add $0x8,%eax // EAX + 8 == Argv[2]
0x80484e1 <main+161>: mov (%eax),%edx // EDX 에 EAX 값 복사
0x80484e3 <main+163>: push %edx // EDX(2) 푸시
0x80484e4 <main+164>: call 0x8048354 <strcat>
// strcat(argv[2], argv[3]);
EDX(2), EDX(1)
0x80484e9 <main+169>: add $0x8,%esp
0x80484ec <main+172>: mov 0xc(%ebp),%eax // EAX 에 (EBP+12) 값 복사 - Argv[0]
0x80484ef <main+175>: add $0x8,%eax // EAX + 8 == Argv[2]
0x80484f2 <main+178>: mov (%eax),%edx
0x80484f4 <main+180>: push %edx
0x80484f5 <main+181>: push $0x804856a
0x80484fa <main+186>: call 0x8048364 <printf>
// printf("%s\n", argv[2]);
0x80484ff <main+191>: add $0x8,%esp
0x8048502 <main+194>: xor %eax,%eax // EAX 초기화
0x8048504 <main+196>: jmp 0x8048506 <main+198>
0x8048506 <main+198>: leave
0x8048507 <main+199>: ret // 에필로그
/* 생략 */
End of assembler dump.
메모리 구조를 확인해봅시다.
BUFFER (40Byte) | SFP (기준) | RET | Argc | Argv[0] - Argv[1] - Argv[2] - Argv[3] |
EBP-40 EBP EBP+4 EBP+8 +12 +16 +20 +24
그래서 인자를 확인할떄는 먼저 Argv[0] 으로 (EBP+12) 이동 한 후 4 씩 늘려가지만
Buffer 을 참조해야할때는 (EBP-40) 의 주소 값을 복사하는겁니다.
Strcat 함수를 디버깅 해보았는데 그다지 어렵지 않았고 매우 쉬웠습니다.
다만 인자를 거꾸로 참조한다는것만 알아두면 될것같습니다. 그런데 인자를 거꾸로 넣는건 함수는
원래 다그렇습니다. cdcel 방식 때문에 그렇다는데 자세한 설명은 다음기회로 미루겠습니다.
'스터디 > system' 카테고리의 다른 글
리눅스 심볼릭링크와 하드링크 (0) | 2011.08.21 |
---|---|
리눅스 GDB 어셈블리어 AT&T 문법을 intel 문법으로 바꾸는 방법 //AT&T -> INTEL (0) | 2011.08.20 |
[GDB-Analysis] GDB 바이너리 디버깅 2 (0) | 2011.08.17 |
[GDB-Analysis] GDB 바이너리 디버깅 1 (1) | 2011.08.17 |
[IDA-Analysis] Binary Wargames Level1 (0) | 2011.08.17 |