在待整理路径所在内存地址000C0F50处4字节上设内存访问断点:
按F9运行,会中断3次,前两次分别是检查待整理路径的第一个字符和调用wcslen函数,第三次是在调用wcscat函数。分析第三次传入栈中两个参数:
第一个是strDestination,指向一段以【\x5c\x00】开头的内存空间;第二个是strSource,指向上述待整理路径前两字节【\x5c\x00】后的内容。
程序把待整理路径全部复制到strDestination,即0x001572F6处。在此4字节设断点,类型选择"Hardware, on access"DWord。
复制路径到缓冲区
F9继续运行,第4次中断在0x77BD4010 ,内存里显示这里将src的前两个字符复制到了dest的【\x5C\x00】后面,这是由于这两个字节设了断点的原因:
第5次中断在0x71C44B1C,位于wcscat函数内,内存显示已将src复制到dest,如图:
第一次路径规范化
按F9运行,中断多次后停在内存0x77bd4d36处,通过栈可知此处属于wcscpy函数。此处调用该函数进行第一次路径规范化。如图:
当前参数src值为0x00EC6E0,指向【..*】;参数 strDestination 值为0x00ECF4DC,指向temp中的第一个字符【\】。 显然,这次路径规范化即把待整理路径中第一个字符【\】和第一个【..\】相对路径之间的内容抛弃。
而此时wcscpy源地址src在edx寄存器中,指向【..*】;目的地址dest在ecx寄存器中,指向待整理路径第一个字符【\】,如图:
所以,这次字符串复制操作就是去掉第一个表示父目录的相对路径,即待整理路径temp中的第一个【\】和第一个【..\】之间的内容成为无用路径被抛弃。操作完成后,temp中的路径字符形如【..*】。
第一次规范化后,待整理路径形如:
\..\***
由于还有【..\】,还需要进行一次规范化,而这第二次规范化正是玄机所在。
第二次路径规范化
由于每次路径规范化都会调用wcscpy函数,接下来删除0x00ECF4DC的硬件断点,直接在wcscpy函数的入口地址0x77BD4D28处下断点。
F9运行后中断在wcscpy函数入口0x77BD4D28处,调用wcscpy函数传入的参数:
esp [esp] * 注释 *
00ECF4AC 00ECF494 目的地址,指向的内存区域值为\x5c\x00,即【\】
00ECF4B0 00ECF4E2 源地址,指向第二个相对路径【\..\】的最后一个斜杠
正常情况下,这次规范化处理会和第一次执行同样的操作,去除第二个相对路径【..\】,从而完成第二次的路径规范化。但这里出现了一个意外的情况,temp的首地址是0x00ECF4DC,而此次字符串复制操作的目的地址dest却在0x00ECF494,在temp之前,如图:
同时注意到,栈指针ESP值为0x00ECF4A8,该地址指向wcscpy函数的返回地址0x71C52FD4。ESP到复制目的dest地址0x00ECF494只有0x14字节,于是,函数wcscpy如果继续执行,将用源字符串src覆盖wcscpy函数的返回地址。论文网
执行到retn命令,可以看到返回地址变成了0x0100129E,该地址的指令为:
00100129E FFD6 call esi
执行 call esi(ES=0x00F0F4DE)指令,正好将EIP指向复制尽量的字符串中构造好的第8字节空指令,接着是【\xeb\x62】(jmp 0x62),此jmp指令跳过中间的随机字符串,指向经过编码的Shellcode,如图:
所以这里是由于内存0x00F0F494处的一个【\】(0x5C),使得出现在处理父母了相对路径【..\】时往前溢出了待处理路径,从而将字符串覆盖到函数wcscpy返回地址的位置,跳转到shellcode造成远程代码执行。