需要适用于 Windows 的简单“Hello-World”、无 null 的 shellcode

发布于 2024-10-10 18:21:16 字数 164 浏览 0 评论 0原文

我想通过向控制台写入“Hello World”来测试缓冲区溢出(使用 Windows XP 32 位)。 shellcode 需要是无空的,以便通过“scanf”传递到我想要溢出的程序中。我找到了大量针对 Linux 的汇编教程,但没有针对 Windows 的。有人可以使用 NASM 指导我完成此操作吗?啊啊啊!

I would like to test a buffer-overflow by writing "Hello World" to console (using Windows XP 32-Bit). The shellcode needs to be null-free in order to be passed by "scanf" into the program I want to overflow. I've found plenty of assembly-tutorials for Linux, however none for Windows. Could someone please step me through this using NASM? Thxxx!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寂寞清仓 2024-10-17 18:21:16

汇编操作码是相同的,因此生成无空 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 的任何无空技巧,有很多技巧,但我最喜欢的(虽然很长)是使用 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

Assembly opcodes are the same, so the regular tricks to produce null-free shellcodes still apply, but the way to make system calls is different.

In Linux you make system calls with the "int 0x80" instruction, while on Windows you must use DLL libraries and do normal usermode calls to their exported functions.

For that reason, on Windows your shellcode must either:

  • Hardcode the Win32 API function addresses (most likely will only work on your machine)
  • Use a Win32 API resolver shellcode (works on every Windows version)

If you're just learning, for now it's probably easier to just hardcode the addresses you see in the debugger. To make the calls position independent you can load the addresses in registers. For example, a call to a function with 4 arguments:

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

Note that the argument are pushed in reverse order. After the CALL instruction EAX contains the return value, and the stack will be just like it was before (i.e. the function pops its own arguments). The ECX and EDX registers may contain garbage, so don't rely on them keeping their values after the call.

A direct CALL instruction won't work, because those are position dependent.

To avoid zeros in the address itself try any of the null-free tricks for x86 shellcode, there are many out there but my favorite (albeit lengthy) is encoding the values using XOR instructions:

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

You can also try NEG EAX or NOT EAX (sign inversion and bit flipping) to see if they work, it's much cheaper (two bytes each).

You can get help on the different API functions you can call here: http://msdn.microsoft.com

The most important ones you'll need are probably the following:

The first launches a command, the next two are for loading DLL files and getting the addresses of its functions.

Here's a complete tutorial on writing Windows shellcodes: http://www.codeproject.com/Articles/325776/The-Art-of-Win32-Shellcoding

傲鸠 2024-10-17 18:21:16

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

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

无论如何,要使其成为 bof 漏洞利用,请输入 aaaaa... 并不断添加 a 直到崩溃
来自缓冲区溢出错误。但要准确找出需要多少个 a 才能使其崩溃。然后,它应该告诉你那是什么内存地址。通常它应该在错误消息中告诉您。如果显示“9797[原始返回地址的其余部分]”,那么您就明白了。现在你必须使用你的调试器来找出它在哪里。使用调试器反汇编程序并查找调用 scanf 的位置。在那里设置一个断点,运行并检查堆栈。查找所有这些 97(我忘了提到是“a”的 ascii 数字。)并查看它们在哪里结束。然后删除断点并键入您发现它占用的 a 的数量(确切的数量。如果错误消息是“缓冲区溢出于 '97[原始返回地址的其余部分]”,则删除最后一个 a,输入您检查时发现的地址堆栈,然后插入您的 shellcode,如果一切顺利,您应该会看到您的 shellcode 执行

Assembly language is defined by your processor, and assembly syntax is defined by the assembler (hence, at&t, and intel syntax) The main difference (at least i think it used to be...) is that windows is real-mode (call the actual interrupts to do stuff, and you can use all the memory accessible to your computer, instead of just your program) and linux is protected mode (You only have access to memory in your program's little cubby of memory, and you have to call int 0x80 and make calls to the kernel, instead of making calls to the hardware and bios) Anyway, hello world type stuff would more-or-less be the same between linux and windows, as long as they are compatible processors.

To get the shellcode from your program you've made, just load it into your target system's
debugger (gdb for linux, and debug for windows) and in debug, type d (or was it u? Anyway, it should say if you type h (help)) and between instructions and memory will be the opcodes.
Just copy them all over to your text editor into one string, and maybe make a program that translates them all into their ascii values. Not sure how to do this in gdb tho...

Anyway, to make it into a bof exploit, enter aaaaa... and keep adding a's until it crashes
from a buffer overflow error. But find exactly how many a's it takes to crash it. Then, it should tell you what memory adress that was. Usually it should tell you in the error message. If it says '9797[rest of original return adress]' then you got it. Now u gotta use ur debugger to find out where this was. disassemble the program with your debugger and look for where scanf was called. Set a breakpoint there, run and examine the stack. Look for all those 97's (which i forgot to mention is the ascii number for 'a'.) and see where they end. Then remove breakpoint and type the amount of a's you found out it took (exactly the amount. If the error message was "buffer overflow at '97[rest of original return adress]" then remove that last a, put the adress you found examining the stack, and insert your shellcode. If all goes well, you should see your shellcode execute.

Happy hacking...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文