7.3.3 黑白结合,LSA漏洞的分析利用

“一气呵成!不知不觉中就把漏洞找了出来,”宇强感叹道。

“呵呵!最后来一个高难度的吧!LSA的远程溢出漏洞分析利用。这就需要黑白法结合了。”

“首先看看本地溢出,这个比较简单,图7-40里的代码就可引发本地溢出。”

“其功能是从系统Netapi32.dll中找到DsRolepEncryptPasswordStart函数,然后执行该函数,函数的第一个参数过长,就会溢出,溢出效果么?呵呵,弹出一个出错对话框,倒计时1分钟后就重启。”

“哦!和震荡波的效果一样啊!”

“只能等它重启,没有办法了吗?”

“大家在运行程序里输入 shutdown –a ,可以终止系统关机。Shutdown命令的帮助如图7-41。”

“因为可以直接用DsRolepEncryptPasswordStart函数引发本地异常,所以本地漏洞利用比较简单,大家用Ollydbg加载lsass.exe进程,然后填充buf用定位大法,就可轻松实现定位和利用!大家都应该很清楚了吧,这个作为寒假作业,大家自己跟入分析一下。”

大家纷纷埋头记下来。

“好了,我们来看看感兴趣的——远程利用!”

“我们刚才用的Netapi32.dll中的DsRoleUpgradeDownlevelServer函数是个客户端函数,我们给它的超长参数会在服务端函数LSASRV.dll中的DsRolerUpgradeDownlevelServer?处理!注意,函数名只相差一个‘r’。大家下去亲自跟踪一下就清楚了。”

“服务端函数不会判断请求是哪儿来的,但微软实现时就固定好了客户端函数只向本机发请求。所以我们发请求,默认给本机,本机LSASRV.dll中的服务器函数处理就会出现问题重启。”

“好,现在我们的目标就是要给远程机器发送请求!但刚才说了,微软在实现代码时就固定了只能向本机发请求,那怎么办呢?”

“是啊!不好办啊!”台下说道。

“其实,平时我们使用修改后的东西也多了;要注册码,我们就破解注册码;要过期,我们就破解过期补丁。所以,我们也把比尔盖茨实现好的客户端代码改一下,不仅向本机发请求,也能向远程主机发请求。”

“真正的黑客精神,就是不断的深入研究技术,大胆创新,发扬共享精神。”

“我们用IDA反编译NetApi32.dll。好,结束后,用名字找到DsRoleUpgradeDownlevelServer()的地方。如图7-42。”

“好,从函数开始的地方,往下走一点点,代码如下:”

.text:7513D5F7 8D 45 CC lea eax, [ebp+var_34]
.text:7513D5FA 50 push eax
.text:7513D5FB 6A 00 push 0
.text:7513D5FD E8 0F 05 00 00 call _DsRolepEncryptPasswordStart@24 ;

“在IDA中,默认是不显示机器码的,在‘Options→General→Disassembly’页面中,有Number of opcode bytes,默认是0,我们把它改成6或8就行了。如图7-43。”

“根据eEye的文档,那里就是我们要修改的地方!_DsRolepEncryptPasswordStart函数的第一个参数就是主机。微软用的是0,即为空,表示把请求发给本机。我们要把它改成远程主机的地址就OK了。”

“ShellCode的是DsRoleUpgradeDownlevelServer的参数传来的;那么远程主机的地址也从那里传来吧!用DsRoleUpgradeDownlevelServer函数的第九个参数传主机地址;然后作为第一个参数给DsRolepEncryptPasswordStart。”

“因为前面第九个参数已经给了[ebp+var+34]了,我们把[ebp+var+34]的内容压入就行了。”

“明白了思路,现在改写代码。注意,改写时要保证字节个数和原来的相同,参数也要压足。除了保证第一个参数压的是[ebp+var+34]外,其他的乱压也可以,所以我们就这样吧:”

  50 push eax
  8B 45 CC mov eax, [ebp+var_34]
  50 push eax
  90 nop

“这样就把存在[ebp+var_34]中的远程主机地址作为第一个参数压入;nop是什么都不做的空指令,目的只是为了保证字节数和原来的相同。”

“好,我们调出WinHex,搜索至我们要修改的地方,作图7-44的的修改。”

“啊,诺顿报警了!这么厉害啊!”古风发现道。

“我们等会再来考虑这个问题,先把诺顿关掉,然后LoadLibrary我们改过后的ww1NetApi.dll,并把第九个参数改成远程主机的地址,即 \ip\ipc$ 的Unicode 形式。指定远程主机的IP地址,编译执行LSA1.cpp,再Telnet远程主机的1234端口。‘啪’!果然连上了我们要攻击的远程主机。”

“成功了!”大家欢呼起来。

“我们再来改进改进。首先,辛辛苦苦修改的dll会被查杀成病毒,那么就要想办法让杀毒软件不认识!”

“杀毒软件是按照文件的特征码来识别一个病毒或木马的。我们只是在正常的系统文件NetApi32.dll的基础上改变了6个字节,其他完全相同;所以杀毒软件的特征码一定是判断的这6个字节!那我们就把这六个字节稍微改一下,看它还能否识别!”

“刚才说了,90是nop,表示什么都不做的空指令,我们把它放在其它指令之间,如图7-45,和指令50 (即汇编PUSH EAX)交换一下位置。”

“然后保存为ww2NetApi.dll,让诺顿再扫描看看。呵呵!这次没报警了。其实,如果还要报警,我们可以继续修改nop位置,如还不行,还可改成 mov ebx [] ,再push ebx等。办法多得很呢!”

“不会被查杀了,看看效果啊!我们把程序改为读ww2NetApi.dll,再运行,还是成功了!如图7-46。

小知识:特征码

现在绝大多数杀毒软件都是建立在“病毒特征码”基础上的。有新病毒出现时,厂商先要获得病毒的一个样本,提取出它的特征码,用户把特征码加入到病毒库中才能查杀。如果我们测试出了杀毒软件的判断特征码,将其改成不影响功能的其他指令,就肯定不会被查杀!从这个意义上来说,反病毒的技术需要一个革命化的突破!

“在此,我们是直接物理修改了NetApi32.dll,就像破解一样,修改了物理文件。其实,我们还可在内存里动态修改,就如同内存注册机一样,动态读出内存的东西!这个交给大家下去完成吧!”

“现在我们可以说是完美的实现远程溢出了,但带有一个300k的dll,试想震荡波拖着这个dll到处跑,也太难为它了吧!所以我们就把dll也去掉,完全用一个程序实现!”

“啊?怎么实现呢?”

“源代码是微软控制的,一般人都看不到。当然,对我们菜鸟来说,即使有了源代码,也是读不懂请求是如何实现的,更不用说自己写一个请求了。”

“所以黑盒法出场了!本机向远程发起请求时,一定会通过网络的。所以,我们可把远程主机发的请求包抓下来,模拟客户端,向服务端发送这样的网络包就可以了!

“好啊,说干就干!”古风打开Ethereal(光盘有收录),再对远程主机攻击一次,然后把攻击发送的包抓下来,如图7-47。

“192.168.1.166是攻击机,192.168.1.169的被攻击的服务机。192.168.1.166先是TCP三次握手,然后建立空连接,图7-47里 NT Create Andx Request, Path:\lsarpc 那排是关键!那就是发送一定的请求,然后把我们的超长参数发过去。”

“但我们不用具体了解它的含义,只管把请求拷贝下来存在数组中,直接向远程机器发送就是了。”

“这次运行我们的LSA2.cpp,又成功了,它可是不带dll的哦!”

“哇!”

“Sniffer是很有用的,如果有溢出的exe程序,那我们就不用具体搞清楚协议、实现什么的,到时直接一抓包,发挥菜鸟吃苦精神,一句句的敲在发送数据中就可以了!而且这种方法分析微软未文档化的东西(特别是RPC相关的东西),那更是相当有用!”