我想通过将“Hello World”写入控制台(使用Windows XP 32位)来测试缓冲区溢出。 shellcode需要为null,以便通过“scanf”传递到我想要溢出的程序中。我已经找到了很多适用于Linux的汇编教程,但是没有适用于Windows的汇编教程。有人可以使用NASM来指导我吗? Thxxx!
答案 0 :(得分:2)
程序集操作码是相同的,因此生成无空shellcode的常规技巧仍然适用,但进行系统调用的方式不同。
在Linux中,您使用“int 0x80”指令进行系统调用,而在Windows上,您必须使用DLL库并对其导出的函数执行普通的用户模式调用。
因此,在Windows上,您的shellcode必须:
如果您只是在学习,那么现在可能更容易对您在调试器中看到的地址进行硬编码。要使呼叫位置独立,您可以在寄存器中加载地址。例如,调用具有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
答案 1 :(得分:0)
汇编语言由处理器定义,汇编语法由汇编程序定义(因此,在& t和intel语法中)主要区别(至少我认为它曾经是......)是windows是实模式(调用实际的中断做东西,你可以使用你的计算机可访问的所有内存,而不仅仅是你的程序)和linux是保护模式(你只能访问程序的小内存中的内存,并且你必须调用int 0x80并调用内核,而不是调用硬件和BIOS)无论如何,hello world类型的东西在linux和windows之间或多或少是相同的,只要它们是兼容的处理器。
要从您的程序中获取shellcode,只需将其加载到目标系统中即可 调试器(用于linux的gdb,用于windows的调试)和在调试中,键入d(或者是它?无论如何,它应该说如果键入h(help))并且指令和内存之间将是操作码。 只需将它们全部复制到文本编辑器中,然后创建一个程序,将它们全部转换为ascii值。不确定如何在gdb中执行此操作...
无论如何,为了使它成为一个bof漏洞,输入aaaaa ...并继续添加一个直到它崩溃 从缓冲区溢出错误。但要确切地知道崩溃它需要多少。然后,它应该告诉你那是什么记忆地址。通常它应该在错误消息中告诉你。如果它说'9797 [其他原始返回地址]'那么你得到它。现在你必须使用你的调试器来找出它的位置。用调试器反汇编程序并查找scanf的调用位置。在那里设置断点,运行并检查堆栈。寻找所有那些97(我忘了提到的是'a'的ascii数字。)并看看它们的结束位置。然后删除断点并输入你发现的数量(确切的数量。如果错误信息是“缓冲区溢出'97 [原始返回地址的其余部分]”然后删除最后一个,把你发现检查的地址堆栈,并插入你的shellcode。如果一切顺利,你应该看到你的shellcode执行。
快乐的黑客......