我遇到了一个非常有趣的事情
article演示了如何从shellcode中删除nullbyte字符。在使用的技术中,汇编指令shl
和shr
似乎在代码中扮演着相当重要的角色。
我意识到汇编指令mov $0x3b, %rax
和mov $59, %rax
每个都实际生成了机器代码指令48 c7 c0 3b 00 00 00
。因此,为了解决这个问题,作者改为使用mov $0x1111113b, %rax
用系统调用号填充寄存器,系统调用号生成机器代码48 c7 c0 3b 11 11 11
,成功删除了空字节。
不幸的是,代码仍然没有执行,因为syscall将3b 11 11 11
视为非法指令,否则会导致代码出错。那么作者接着做的是使用命令
%rax
56个字节
shl $0x38, %rax
shr $0x38, %rax
在此转变之后,代码执行完美。我想知道的是移位指令如何修复48 c7 c0 3b 11 11 11
问题,并以某种方式使%rax
正确和系统调用。我知道shl/shr
向左和向右移位,这意味着向左移位会将位向上移动到更高位,向右移位会使位置再次降低,因为二进制从右向左读取。但这如何改变代码并使其可执行?不是来回移动本质上没有改变任何东西,把移位的位置准确地放回到它们在开头的位置?
我唯一的理论是,将位移掉会留下零。但是我仍然没有看到如何转移%rax
然后修复解决方案,因为它不会带回11 11 11
部分吗?
无论如何,我认为这很有趣,因为我从未见过今天之前的转换操作数。提前谢谢。
答案 0 :(得分:1)
移位是一种有损操作 - 如果位移出寄存器,它们就会消失。 (有时其中一个存储在进位标志中,但这里并不重要。)请参阅http://en.wikibooks.org/wiki/X86_Assembly/Shift_and_Rotate#Logical_Shift_Instructions。
左移(shl)操作执行此操作:
0x000000001111113b<< 0x38 = 0x3b00000000000000
0x111111部分将占用64,65,66等位,但%rax是64位寄存器,因此这些位消失。然后,逻辑右移(shr)操作执行此操作:
0x3b00000000000000>> 0x38 = 0x000000000000003b
给你你想要的号码。这就是它的全部内容。