为什么带有jmp指令的shellcode工作,为什么标签不能在C包装器内工作?

时间:2013-08-08 07:26:07

标签: assembly x86 shellcode machine-code

我有两个汇编代码,如下面的

文件:a.asm

section .text
global _start
_start: mov eax, 4
        mov ebx, 1
        mov ecx, mesg
        mov edx, 10
        int 0x80
        mov eax, 1
        int 0x80
mesg    db      "KingKong",0xa

和另一个汇编代码

file:b.asm

section .text
global _start

_start: jmp mesg

prgm:   mov eax, 4
        mov ebx, 1
        pop ecx
        mov edx, 10
        int 0x80
        mov eax,1
        int 0x80
mesg:   call prgm
        db "KingKong",0xa

获取这两个代码的十六进制并将其放入此C包装器

之后
char *b = "\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\x7d\x80\x04\x08\xba\x0a\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xcd\x80\x4b\x69\x6e\x67\x4b\x6f\x6e\x67\x0a";

char *b = "\xe9\x19\x00\x00\x00\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\x59\xba\x0a\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xcd\x80\xe8\xe2\xff\xff\xff\x4b\x69\x6e\x67\x4b\x6f\x6e\x67\x0a";
int main()
{
        (*(int (*)(void))a)();
}

第一个汇编代码(b)按预期打印'KingKong',但第二个汇编代码a打印垃圾。像显示的那样

root@bt:~/Arena# ./a
�root@bt:~/Arena#
root@bt:~/Arena# ./b
KingKong

a(第一个)生成的输出是这个奇怪的字符,而第二个(b)按预期打印kingkong。 现在有人可以解释为什么第二个汇编代码工作而第一个汇编代码没有。

修改 从答案我看到第一个程序硬编码地址。即使第二种方法使用标签,如jmp mesg,现在这条指令不会使程序与第一种程序非常相似,并不是它们都使用labels来确定位置。我所知道的是,为了使代码位置独立,我们需要使用espebp寄存器和相对寻址方案。第二个程序的jmp指令不会像第一个程序那样使用它。

1 个答案:

答案 0 :(得分:7)

mesg的地址可能会有所不同,具体取决于您的计划在内存中的布局方式。

以下内容将对特定地址进行硬编码,并且无法可靠地(或根本不)使用:

    mov ecx, mesg

作为参考,第一种方法硬编码以下地址:

    mov ecx, 0x804807d

第二种方法确实有效,因为它使用mesg指令的返回地址在运行时计算出call的地址。

换句话说,第一个版本只有在特定地址加载时才有效,而第二个版本只有position-independent

值得注意的是,第二版中出现的jmpcall指令使用相对寻址,这意味着操作码指定距离< / em>到目标而不是目标的地址。这使得这些指令无论在内存中的位置如何都可以正常工作。

如果检查操作码,您会看到jmp编码为

e9 19 00 00 00

(即跳转0x19,或25 10 ,字节向前),call编码为

e8 e2 ff ff ff

其中0xffffffe2是一个小的负数(-30)。