house of emma
前言
看完了kiwi,现在来看看emma,这两个手法的思路大差不差。但是emma有一道湖湘杯的例题,学习起来会方便很多
原理
源码
核心同样是kiwi当中的那个断言,但是修改的思路转变了。在kiwi中是修改虚表中某个函数指针,在emma中则是修改vtable的地址。这个地址是–_IO_cookie_jumps
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| struct _IO_cookie_file { struct _IO_FILE_plus __fp; void *__cookie; cookie_io_functions_t __io_functions; };
typedef struct _IO_cookie_io_functions_t { cookie_read_function_t *read; cookie_write_function_t *write; cookie_seek_function_t *seek; cookie_close_function_t *close; } cookie_io_functions_t;
static ssize_t _IO_cookie_read (FILE *fp, void *buf, ssize_t size) { struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp; cookie_read_function_t *read_cb = cfile->__io_functions.read; #ifdef PTR_DEMANGLE PTR_DEMANGLE (read_cb); #endif
if (read_cb == NULL) return -1;
return read_cb (cfile->__cookie, buf, size); }
static ssize_t _IO_cookie_write (FILE *fp, const void *buf, ssize_t size) { struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp; cookie_write_function_t *write_cb = cfile->__io_functions.write; #ifdef PTR_DEMANGLE PTR_DEMANGLE (write_cb); #endif
if (write_cb == NULL) { fp->_flags |= _IO_ERR_SEEN; return 0; }
ssize_t n = write_cb (cfile->__cookie, buf, size); if (n < size) fp->_flags |= _IO_ERR_SEEN;
return n; }
static off64_t _IO_cookie_seek (FILE *fp, off64_t offset, int dir) { struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp; cookie_seek_function_t *seek_cb = cfile->__io_functions.seek; #ifdef PTR_DEMANGLE PTR_DEMANGLE (seek_cb); #endif
return ((seek_cb == NULL || (seek_cb (cfile->__cookie, &offset, dir) == -1) || offset == (off64_t) -1) ? _IO_pos_BAD : offset); }
static int _IO_cookie_close (FILE *fp) { struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp; cookie_close_function_t *close_cb = cfile->__io_functions.close; #ifdef PTR_DEMANGLE PTR_DEMANGLE (close_cb); #endif
if (close_cb == NULL) return 0;
return close_cb (cfile->__cookie); }
|
在emma的利用中,主要就是利用_IO_cookie_read,而在这个函数的开始几行,是对rax 加密,然后call rax,加密是另一个操作数是fs:[0x30],这个指针可以利用large bin attack 修改.
如果题目开启沙箱禁用了execve,那就需要setcontext中的gadget了
利用思路
- 利用
largebins attack等手段,修改掉stderr,然后伪造fake io
- 利用
setcontext+61控制程序的执行流.
- 如果程序没有开启沙箱的话,可以考虑用
system来get shell
例子
湖湘杯-2021-house of emma