vik*_*cks 3 x86 assembly machine-code shellcode
我有两个汇编代码,如下所示
file: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
Run Code Online (Sandbox Code Playgroud)
和另一个汇编代码
档案: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
Run Code Online (Sandbox Code Playgroud)
在获取这两个代码的十六进制并将其放入此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)();
}
Run Code Online (Sandbox Code Playgroud)
第一个汇编代码(b
)按预期打印'KingKong',但第二个汇编代码a
打印垃圾.像显示的那样
root@bt:~/Arena# ./a
?root@bt:~/Arena#
root@bt:~/Arena# ./b
KingKong
Run Code Online (Sandbox Code Playgroud)
由a
(第一个)生成的输出是这个?
奇怪的字符,而第二个(b
)kingkong
按预期打印.现在有人可以解释为什么第二个汇编代码工作而第一个汇编代码没有.
编辑:
从答案我看到第一个程序硬编码地址.即使是第二种方法也使用标签,例如jmp mesg
,现在这条指令不会使程序与第一种程序非常相似,它们都不是labels
用来决定位置的cos .我所知道的是,为了使代码位置独立,我们需要使用具有相对寻址方案esp
的ebp
寄存器或寄存器.不要第二个程序的jmp指令使它像第一个程序一样.
地址mesg
可能会有所不同,具体取决于程序在内存中的布局方式.
以下内容将对特定地址进行硬编码,并且无法可靠地(或根本不)工作:
mov ecx, mesg
Run Code Online (Sandbox Code Playgroud)
作为参考,第一种方法硬编码以下地址:
mov ecx, 0x804807d
Run Code Online (Sandbox Code Playgroud)
第二种方法确实有效,因为它mesg
使用call
指令的返回地址在运行时计算出地址.
换句话说,第一个版本仅在加载到特定地址时才有效,而第二个版本与位置无关.
值得注意的是,第二版中出现jmp
的call
指令和指令使用相对寻址,这意味着操作码指定到目标的距离而不是目标的地址.这使得这些指令无论在内存中的位置如何都可以工作.
如果检查操作码,您将看到jmp
编码为
e9 19 00 00 00
Run Code Online (Sandbox Code Playgroud)
(即跳转0x19,或25 10,字节向前),并call
编码为
e8 e2 ff ff ff
Run Code Online (Sandbox Code Playgroud)
其中0xffffffe2
是一个小的负数(-30).