【问题标题】:Simple "Hello-World", null-free shellcode for Windows needed需要简单的“Hello-World”,适用于 Windows 的无空 shellcode
【发布时间】:2011-01-09 11:49:11
【问题描述】:

我想通过将“Hello World”写入控制台(使用 Windows XP 32 位)来测试缓冲区溢出。 shellcode 必须是无空的,才能通过“scanf”传递到我想要溢出的程序中。我发现了很多适用于 Linux 的汇编教程,但没有找到适用于 Windows 的。有人可以使用 NASM 引导我完成这个吗?哇!

【问题讨论】:

  • 好吧,linux 和 windows 的程序集操作码是相同的,这些教程中的内容也应该适用于 windows。
  • 程序集操作码相同,但系统调用不同。有关更多详细信息,请参阅下面的答案。 :)

标签: windows assembly nasm shellcode


【解决方案1】:

汇编操作码是相同的,因此生成无空 shellcode 的常规技巧仍然适用,但进行系统调用的方式不同。

在 Linux 中,您使用“int 0x80”指令进行系统调用,而在 Windows 中,您必须使用 DLL 库并对其导出的函数进行正常的用户模式调用。

因此,在 Windows 上,您的 shellcode 必须:

  • 硬编码 Win32 API 函数地址(很可能只在您的机器上工作)
  • 使用 Win32 API 解析器 shellcode(适用于每个 Windows 版本)

如果您只是在学习,那么现在对您在调试器中看到的地址进行硬编码可能会更容易。要使调用位置独立,您可以将地址加载到寄存器中。例如,调用具有 4 个参数的函数:

PUSH 4                  ; argument #4 to the function
PUSH 3                  ; argument #3 to the function
PUSH 2                  ; argument #2 to the function
PUSH 1                  ; argument #1 to the function
MOV EAX, 0xDEADBEEF     ; put the address of the function to call
CALL EAX

请注意,参数以相反的顺序推送。在 CALL 指令 EAX 包含返回值之后,堆栈将与之前一样(即函数弹出自己的参数)。 ECX 和 EDX 寄存器可能包含垃圾,所以不要依赖它们在调用后保持它们的值。

直接的 CALL 指令不起作用,因为它们是位置相关的。

为避免地址本身出现零,请尝试使用 x86 shellcode 的任何无 null 技巧,有很多技巧,但我最喜欢(虽然很长)是使用 XOR 指令对值进行编码:

MOV EAX, 0xDEADBEEF ^ 0xFFFFFFFF   ; your value xor'ed against an arbitrary mask
XOR EAX, 0xFFFFFFFF                ; the arbitrary mask

您也可以尝试 NEG EAX 或 NOT EAX(符号反转和位翻转),看看它们是否有效,它便宜得多(每个两个字节)。

您可以在此处获取有关可以调用的不同 API 函数的帮助:http://msdn.microsoft.com

您需要的最重要的可能如下:

第一个启动命令,后两个用于加载DLL文件并获取其函数的地址。

这是编写 Windows shellcode 的完整教程:http://www.codeproject.com/Articles/325776/The-Art-of-Win32-Shellcoding

【讨论】:

    【解决方案2】:

    汇编语言由你的处理器定义,汇编语法由汇编器定义(因此,at&t 和 intel 语法)主要区别(至少我认为它曾经是......)是 windows 是真实的-模式(调用实际的中断来做事情,你可以使用你的计算机可以访问的所有内存,而不仅仅是你的程序)并且 linux 是保护模式(你只能访问你程序的小内存中的内存,并且你必须调用 int 0x80 并调用内核,而不是调用硬件和 bios)无论如何,只要它们是兼容的处理器,hello world 类型的东西在 linux 和 windows 之间或多或少是相同的。

    要从您制作的程序中获取 shellcode,只需将其加载到目标系统的 调试器(用于 linux 的 gdb,用于 Windows 的调试)并在调试中键入 d(或者是 u?无论如何,它应该说如果您键入 h(帮助))并且指令和内存之间将是操作码。 只需将它们全部复制到您的文本编辑器中成为一个字符串,然后编写一个程序将它们全部转换为它们的 ascii 值。不知道如何在 gdb 中执行此操作...

    无论如何,要使其成为 bof 漏洞利用,请输入 aaaaa... 并继续添加 a's 直到它崩溃 从缓冲区溢出错误。但是要准确找出崩溃它需要多少个a。然后,它应该告诉你那是什么内存地址。通常它应该在错误消息中告诉你。如果上面写着“9797 [其余的原始退货地址]”,那么你明白了。现在你必须使用你的调试器来找出它在哪里。使用调试器反汇编程序并查找调用 scanf 的位置。在那里设置一个断点,运行并检查堆栈。查找所有那些 97(我忘了提到的是 'a' 的 ascii 编号。)并查看它们的结束位置。然后删除断点并输入你发现它占用的 a 的数量(确切的数量。如果错误消息是“缓冲区溢出在 '97 [rest of original return address]”然后删除最后一个 a,把你发现检查的地址堆栈,然后插入你的 shellcode。如果一切顺利,你应该会看到你的 shellcode 执行。

    黑客攻击愉快...

    【讨论】:

    • 这个回复有几个问题。 1) Windows 不是实模式。 2) Windows 和 Linux hello world 代码完全不同,因为 Windows 不是 POSIX。 3)最好用谷歌搜索答案,而不是相信你的记忆。 4) 关于如何利用 bof 的解释相当混乱、不完整,并且与问题无关。
    猜你喜欢
    • 1970-01-01
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    • 2019-01-14
    相关资源
    最近更新 更多