2015-04-23 71 views
1

我遇到了一个非常有趣的 article,演示了如何从shellcode中删除空字节字符。在使用的技术中,汇编指令shlshr似乎在代码中占据相当重要的位置。汇编指令转换是做什么的?

我意识到组装指令mov $0x3b, %raxmov $59, %rax每个实际上都会生成机器码指令48 c7 c0 3b 00 00 00。因此,为了解决这个问题,作者改用mov $0x1111113b, %rax来填充寄存器中的系统调用号码,该号码生成代替48 c7 c0 3b 11 11 11的机器代码,该代码成功地删除了空字节。

不幸的是,代码仍然不会执行,因为系统调用将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

移位是一种有损操作 - 如果位移到寄存器外,它们就会消失。 (有时候其中一个存储在进位标志中,但在这里并不重要。)请参阅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

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