【问题标题】:Small subtility which does not work using MASM32使用 MASM32 不起作用的小技巧
【发布时间】: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


【解决方案1】:

代码段是不可写的,所以如果你在代码段中定义了一个字符串,默认情况下你不能写入它。您要么必须在数据段中声明它,要么必须修改代码段的权限才能对其进行写入。

【讨论】:

  • 实际上我写了一个shellcode,所以我不能在.data段中存储信息。所以你的第二个提议在我的情况下应该是正确的。但是我根本看不到如何更改权限。提前感谢您的帮助。
  • 如果字符串数据从堆栈中弹出并放入ecx寄存器,信息仍然不可写?
  • 您必须将字符串复制到可写的地方(即在堆栈上),或者您不能修改它。在这种情况下,您必须准备它,因为它是事先需要的,或者您必须修改权限。随意接受答案。 pop ecx 只弹出地址,而不是字符串的位置。 ;)
  • 好的 :)。这是一个链接,vividmachines.com/shellcode/shellcode.html,它谈到了你所说的(我认为)。作者说:“嗯,在大多数 shellcode 中,其中包含的程序集具有某种自修改特性。由于我们在保护模式操作系统中工作,因此可执行映像的 .code 段是只读的。这就是为什么 shell 程序需要在尝试执行之前将自身复制到堆栈中。”我不明白如何在尝试执行之前将代码复制到堆栈中。我怎样才能做到这一点 ?非常感谢您的帮助。
  • 你一定要看VirtualProtect
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-21
  • 2014-11-20
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 2020-10-10
相关资源
最近更新 更多