装配指令转移了什么?

时间:2015-04-23 00:04:22

标签: shellcode

我遇到了一个非常有趣的事情 article演示了如何从shellcode中删除nullbyte字符。在使用的技术中,汇编指令shlshr似乎在代码中扮演着相当重要的角色。

我意识到汇编指令mov $0x3b, %raxmov $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部分吗?

无论如何,我认为这很有趣,因为我从未见过今天之前的转换操作数。提前谢谢。

1 个答案:

答案 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

给你你想要的号码。这就是它的全部内容。