汇编指令移位有什么作用?
What Does Assembly Instruction Shift Do?
我遇到了一个很有趣的
article 演示了如何从 shellcode 中删除空字节字符。在使用的技术中,汇编指令 shl
和 shr
似乎在代码中占据了相当重要的作用。
我意识到汇编指令 mov [=13=]x3b, %rax
和 mov , %rax
实际上都生成了机器码指令 48 c7 c0 3b 00 00 00
。因此,为了解决这个问题,作者改为使用 mov [=16=]x1111113b, %rax
用系统调用号填充寄存器,而不是生成机器代码 48 c7 c0 3b 11 11 11
,从而成功删除空字节。
不幸的是,代码仍然没有执行,因为系统调用将 3b 11 11 11
视为非法指令,或者这会导致代码出现段错误。所以作者随后所做的就是使用命令
来回移动 %rax
56 个字节
shl [=10=]x38, %rax
shr [=10=]x38, %rax
这次转变后,代码完美执行。我想知道的是移位指令如何解决 48 c7 c0 3b 11 11 11
问题,并以某种方式使 %rax
正确且可系统调用。我知道 shl/shr
向左和向右移动位,这意味着向左移动将位向上移动到更高的位,向右移动使它们再次降低,因为二进制是从右到左读取的。但是,这到底是如何改变代码并使其可执行的呢?来回移动本质上不会改变任何东西,将移位的位准确地放回它们开始时的位置吗?
我唯一的理论是移开位会留下零。但我仍然看不出如何将 %rax
向前移动然后向后移动来修复解决方案,因为它不会带回 11 11 11
部分吗?
无论如何,我认为这很有趣,因为我在今天之前从未见过移位操作数。提前致谢。
移位是一种有损操作 - 如果位被移出寄存器,它们就会消失。 (有时其中之一存储在进位标志中,但这在这里并不重要。)参见 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
给你你想要的号码。仅此而已。
我遇到了一个很有趣的
article 演示了如何从 shellcode 中删除空字节字符。在使用的技术中,汇编指令 shl
和 shr
似乎在代码中占据了相当重要的作用。
我意识到汇编指令 mov [=13=]x3b, %rax
和 mov , %rax
实际上都生成了机器码指令 48 c7 c0 3b 00 00 00
。因此,为了解决这个问题,作者改为使用 mov [=16=]x1111113b, %rax
用系统调用号填充寄存器,而不是生成机器代码 48 c7 c0 3b 11 11 11
,从而成功删除空字节。
不幸的是,代码仍然没有执行,因为系统调用将 3b 11 11 11
视为非法指令,或者这会导致代码出现段错误。所以作者随后所做的就是使用命令
%rax
56 个字节
shl [=10=]x38, %rax
shr [=10=]x38, %rax
这次转变后,代码完美执行。我想知道的是移位指令如何解决 48 c7 c0 3b 11 11 11
问题,并以某种方式使 %rax
正确且可系统调用。我知道 shl/shr
向左和向右移动位,这意味着向左移动将位向上移动到更高的位,向右移动使它们再次降低,因为二进制是从右到左读取的。但是,这到底是如何改变代码并使其可执行的呢?来回移动本质上不会改变任何东西,将移位的位准确地放回它们开始时的位置吗?
我唯一的理论是移开位会留下零。但我仍然看不出如何将 %rax
向前移动然后向后移动来修复解决方案,因为它不会带回 11 11 11
部分吗?
无论如何,我认为这很有趣,因为我在今天之前从未见过移位操作数。提前致谢。
移位是一种有损操作 - 如果位被移出寄存器,它们就会消失。 (有时其中之一存储在进位标志中,但这在这里并不重要。)参见 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
给你你想要的号码。仅此而已。