说实话我感觉64的比32的难不少..应该是我笨的关系。
其中比较逆天的是bextr
我着实找不到太多资料
最后debug了半天发现了规律
举个栗子比如这里bextr rbx,rcx,rdx
rcx = 0b100010100
rdx = 302
rbx
的值就是rcx>>2
,或者说是忽略掉低位的两位
1 | 100010100 >>2 |
然后取低位开始数3位
1 | 1000101 |
于是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 | 0x00400639 aa stosb byte [rdi], al |
思路
思路蛮简单 最终要做的就是给rdi
部分写入flag.txt,而给rdi
指向的地址具体传东西是由al
传递。
所以需要控制xlat BYTE PTR ds:[rbx]
这里给rax
低位(al
)传参的是rbx
(这里需要注意因为并没有能pop rax
清理rax
的指令,所以每次计算rbx
给al
传参都需要减去上一次al
的偏移,去掉去第一次al
默认的0xb
,后面每一次al
都是上一个字符,所以除第一次减0xb
之外每次都需要rbx - flag[上一个的位] - 0x3ef2
)
再去找rbx
就找到了bextr rbx,rcx,rdx
。
要给rbx
传参就要控制rcx
和rdx
这俩,由于会rcx
给加0x3ef2
所以直接写字符给rcx
过去会被破坏掉,指定是不行了。
于是直接从这个程序中找能用的字符所在的地址,直接拿现成的来用就ok。
exp
1 | from pwn import * |