【发布时间】:2013-11-30 16:48:33
【问题描述】:
我必须为一个安全项目编写一个 shellcode。只是为了培训,我想编写一个打开一个非常简单的 MessageBox 的 shellcode。下面是整个代码的摘录(这段代码只是调用了'LoadLibrary'和'ExitProcess'函数):
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
.code
start:
jmp short GetLibrary
GetLibraryReturn:
pop ecx ;recover 'user32.dllN'
mov ebx, 758c4977h ;recover LoadLibrary PTR
push ecx ;push 'kernel.dll'
call ebx ;invoke LoadLibrary
ender:
push eax
mov eax, 758c79b0h ;ExitProcess
call eax
GetLibrary:
call GetLibraryReturn
db 'user32.dll'
db 00h
[...]
end start
如您所见,它非常简单。然而,你可以在代码的末尾,有以下说明:
db 00h
不幸的是,编译后,我在shellcode中间有一个操作码'00'。 为了解决这个问题,有一个像这样的解决方案:
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
.code
start:
jmp short GetLibrary
GetLibraryReturn:
pop ecx ;recover 'user32.dllN'
xor edx, edx ;init EDX register
mov [ecx + 10], dl ;replace 'N' by 'NULL'
mov ebx, 758c4977h ;recover LoadLibrary PTR
push ecx ;push 'kernel.dll'
call ebx ;invoke LoadLibrary
ender:
push eax
mov eax, 758c79b0h ;ExitProcess addr
call eax ;invoke 'ExitProcess'
GetLibrary:
call GetLibraryReturn
db 'user32.dllN' ;Push an additional character 'N'
end start
因此,微妙之处在于在“user32.dll”原始字符串的末尾添加另一个字符。接下来我们只需要用 NULL 替换它,将 edx 寄存器初始化为 0,并使用 8 位寄存器执行以下指令来替换“N”附加字符:
mov [ecx + 10], dl ;'10' corresponds to the 'user32.dll' string length
如您所见,这两个版本应该执行相同的操作。只是生成的代码经过修改。不幸的是,执行失败了,我不明白为什么。也许有一个关键字要添加到上面的表达式中。我尝试了几种组合,但编译失败。我真的迷路了。
非常感谢您的帮助。
【问题讨论】:
-
它失败要么是因为您正在写入代码段,要么是在堆栈段中执行代码(取决于此代码的执行方式)。如果未启用适当的权限,任何一种情况都可能导致异常。我不明白为什么最后的 0 字节很重要,因为它将与字符串中的
N处于相同的位置。 -
我不明白。在 C 语言中,如果我分配一个 11 个字符的字符串,我可以将第 10 个字符替换为另一个字符。我有许可,因为我在我分配的空间中。我认为使用 ASM 或 MASM 是一样的。你认为表达不正确吗?我应该使用另一种语法吗? 0 很重要,因为您知道它标记了字符串的结尾。否则,程序将无法运行。
-
如果你分配了你可以修改它,但你没有分配它,你在默认不可写的代码段中声明了它。
-
好的。但是“pop ecx”表达式应该提取字符串信息并将其放入 ecx 寄存器中。你认为数据仍然不可写吗?
标签: assembly x86 nasm masm masm32