Simple PWN 0x21(fopen, fread, fwrite, fclose)
tags: CTF
PWN
eductf
Version: Ubuntu 20.04
Original Code
:::spoiler fopen
#include <fcntl.h>
#include <stdio.h>
int main()
{
FILE *fp;
fp = fopen("./test", "r");
fclose(fp);
return 0;
}
:::
:::spoiler fread
#include <fcntl.h>
#include <stdio.h>
int main()
{
FILE *fp;
char buf[0x10];
fp = fopen("./test", "r");
fread(buf, 0x1, 0x10, fp);
fclose(fp);
return 0;
}
:::
:::spoiler fwrite
#include <fcntl.h>
#include <stdio.h>
int main()
{
FILE *fp;
char buf[0x10] = "TEST!!";
fp = fopen("./test_write", "r");
fread(buf, 0x1, 0x10, fp);
fclose(fp);
return 0;
}
:::
:::spoiler fclose
:::
Analyze
fopen
- Flow chart
-
fopen
- main() ```baah! …
<main+26> call fopen@plt fopen@plt pwndbg> si
1
2
3
4
5
6
7
8
92. `malloc` - `iofopen.c` ```bash! <__fopen_internal+26> call malloc@plt <malloc@plt> # Size: 0x1d8 pwndbg> heap ... Allocated chunk | PREV_INUSE Addr: 0x555555559290 Size: 0x1e1 ...
:::spoiler
new_f
pwndbg> p *new_f $2 = { fp = { file = { _flags = 0, _IO_read_ptr = 0x0, _IO_read_end = 0x0, _IO_read_base = 0x0, _IO_write_base = 0x0, _IO_write_ptr = 0x0, _IO_write_end = 0x0, _IO_buf_base = 0x0, _IO_buf_end = 0x0, _IO_save_base = 0x0, _IO_backup_base = 0x0, _IO_save_end = 0x0, _markers = 0x0, _chain = 0x0, _fileno = 0, _flags2 = 0, _old_offset = 0, _cur_column = 0, _vtable_offset = 0 '\000', _shortbuf = "", _lock = 0x0, _offset = 0, _codecvt = 0x0, _wide_data = 0x0, _freeres_list = 0x0, _freeres_buf = 0x0, __pad5 = 0, _mode = 0, _unused2 = '\000' <repeats 19 times> }, vtable = 0x0 }, lock = { lock = 0, cnt = 0, owner = 0x0 }, wd = { _IO_read_ptr = 0x0, _IO_read_end = 0x0, _IO_read_base = 0x0, _IO_write_base = 0x0, _IO_write_ptr = 0x0, _IO_write_end = 0x0, _IO_buf_base = 0x0, _IO_buf_end = 0x0, _IO_save_base = 0x0, _IO_backup_base = 0x0, _IO_save_end = 0x0, _IO_state = { __count = 0, __value = { __wch = 0, __wchb = "\000\000\000" } }, _IO_last_state = { __count = 0, __value = { __wch = 0, __wchb = "\000\000\000" } }, _codecvt = { __cd_in = { step = 0x0, step_data = { __outbuf = 0x0, __outbufend = 0x0, __flags = 0, __invocation_counter = 0, __internal_use = 0, __statep = 0x0, __state = { __count = 0, __value = { __wch = 0, __wchb = "\000\000\000" } } } }, __cd_out = { step = 0x0, step_data = { __outbuf = 0x0, __outbufend = 0x0, __flags = 0, __invocation_counter = 0, __internal_use = 0, __statep = 0x0, __state = { __count = 0, __value = { __wch = 0, __wchb = "\000\000\000" } } } } }, _shortbuf = L"", _wide_vtable = 0x0 } }
:::
- Initialize -
iofopen.c
... _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd, &_IO_wfile_jumps); _IO_JUMPS (&new_f->fp) = &_IO_file_jumps; _IO_new_file_init_internal (&new_f->fp); ...
:::spoiler
_IO_file_jumps
pwndbg> p _IO_file_jumps $3 = { __dummy = 0, __dummy2 = 0, __finish = 0x7ffff7e87ff0 <_IO_new_file_finish>, __overflow = 0x7ffff7e88a00 <_IO_new_file_overflow>, __underflow = 0x7ffff7e886b0 <_IO_new_file_underflow>, __uflow = 0x7ffff7e899c0 <__GI__IO_default_uflow>, __pbackfail = 0x7ffff7e8ad40 <__GI__IO_default_pbackfail>, __xsputn = 0x7ffff7e87be0 <_IO_new_file_xsputn>, __xsgetn = 0x7ffff7e877a0 <__GI__IO_file_xsgetn>, __seekoff = 0x7ffff7e87010 <_IO_new_file_seekoff>, __seekpos = 0x7ffff7e89d60 <_IO_default_seekpos>, __setbuf = 0x7ffff7e868f0 <_IO_new_file_setbuf>, __sync = 0x7ffff7e86780 <_IO_new_file_sync>, __doallocate = 0x7ffff7e7b3b0 <__GI__IO_file_doallocate>, __read = 0x7ffff7e87bb0 <__GI__IO_file_read>, __write = 0x7ffff7e875f0 <_IO_new_file_write>, __seek = 0x7ffff7e86d70 <__GI__IO_file_seek>, __close = 0x7ffff7e868e0 <__GI__IO_file_close>, __stat = 0x7ffff7e875d0 <__GI__IO_file_stat>, __showmanyc = 0x7ffff7e8aed0 <_IO_default_showmanyc>, __imbue = 0x7ffff7e8aee0 <_IO_default_imbue> }
:::
- parse mode in
fileops.c
-_IO_new_file_fopen()
-
__GI__IO_file_fopen
-iofopen.c
```bash! …
-
<__fopen_internal+120> call __GI__IO_file_fopen <__GI__IO_file_fopen> rdi: 0x5555555592a0 ◂— 0xfbad248c rsi: 0x555555556006 ◂— 0x747365742f2e /* './test' */ rdx: 0x555555556004 ◂— 0x747365742f2e0072 /* 'r' */ rcx: 0x1
1
2
3
4
5
6
75. `_IO_file_open` - `fileops.c` ```bash! <__GI__IO_file_fopen+188> call _IO_file_open <_IO_file_open> rdi: 0x5555555592a0 ◂— 0xfbad248c rsi: 0x555555556006 ◂— 0x747365742f2e /* './test' */ rdx: 0x0 rcx: 0x1b6
1
6. `sys_open` - `open64.c` ```bash!
<_IO_file_open+33> call open64
# It'll return file number(fd) file: 0x555555556006 ◂— 0x747365742f2e /* './test' */ oflag: 0x0 # read only mode vararg: 0x1b6 ... <open64+73> syscall fd: 0xffffff9c file: 0x555555556006 ◂— 0x747365742f2e /* './test' */ oflag: 0x0 vararg: 0x0 ``` -
- Whole work flow
:::spoiler work flow
<main+26> call fopen@plt <fopen@plt> ... <__fopen_internal+26> call malloc@plt <malloc@plt> size: 0x1d8 ... <__fopen_internal+81> call _IO_no_init <_IO_no_init> ... <__fopen_internal+103> call _IO_new_file_init_internal <_IO_new_file_init_internal> rdi: 0x5555555592a0 ◂— 0xfbad0000 ... <_IO_new_file_init_internal+25> call _IO_link_in <_IO_link_in> rdi: 0x5555555592a0 ◂— 0xfbad240c rsi: 0xfbad0000 rdx: 0x0 rcx: 0x555555559390 ◂— 0x0 ... <__fopen_internal+120> call __GI__IO_file_fopen <__GI__IO_file_fopen> rdi: 0x5555555592a0 ◂— 0xfbad248c rsi: 0x555555556006 ◂— 0x747365742f2e /* './test' */ rdx: 0x555555556004 ◂— 0x747365742f2e0072 /* 'r' */ rcx: 0x1 ... <__GI__IO_file_fopen+188> call _IO_file_open <_IO_file_open> rdi: 0x5555555592a0 ◂— 0xfbad248c rsi: 0x555555556006 ◂— 0x747365742f2e /* './test' */ rdx: 0x0 rcx: 0x1b6 ... <_IO_file_open+33> call open64 <open64> # It'll return file number(fd) file: 0x555555556006 ◂— 0x747365742f2e /* './test' */ oflag: 0x0 # read only mode vararg: 0x1b6 ... <open64+73> syscall <SYS_openat> fd: 0xffffff9c file: 0x555555556006 ◂— 0x747365742f2e /* './test' */ oflag: 0x0 vararg: 0x0
::: :::spoiler
*fp
pwndbg> p *fp $4 = { _flags = -72539000, _IO_read_ptr = 0x0, _IO_read_end = 0x0, _IO_read_base = 0x0, _IO_write_base = 0x0, _IO_write_ptr = 0x0, _IO_write_end = 0x0, _IO_buf_base = 0x0, _IO_buf_end = 0x0, _IO_save_base = 0x0, _IO_backup_base = 0x0, _IO_save_end = 0x0, _markers = 0x0, _chain = 0x7ffff7fc45c0 <_IO_2_1_stderr_>, _fileno = 3, _flags2 = 0, _old_offset = 0, _cur_column = 0, _vtable_offset = 0 '\000', _shortbuf = "", _lock = 0x555555559380, _offset = -1, _codecvt = 0x0, _wide_data = 0x555555559390, _freeres_list = 0x0, _freeres_buf = 0x0, __pad5 = 0, _mode = 0, _unused2 = '\000' <repeats 19 times> }
:::
fread
- Flow chart
fwrite
- Flow chart
fclose
- Flow chart