怎么感觉自己在做病毒呐?最近对于悄悄地干坏事比较感兴趣,那么我离病毒还差什么呐?自定位的代码有了,但是书写一个自定位代码无疑是个非常麻烦的事情,所以我想或许我还需要自己完成LoadLibrary做的工作,这样可以达到代码隐藏的目的,也不会破坏把软件工程奉为圭臬的我的审美观。然后是尽量隐藏自己,这个隐藏的手段太多了,慢慢来吧,加油~至于传播和破坏倒不是我特别关心的,希望不要抓我。
这里我想做的是避免FindWindow/EnumWindows/EnumChildWindows的检测,ollydebug里面有个插件叫做hideod,它就可以完成这个操作,我当时想ollydebug是比较流行的工具,大概有源代码或者手段分析之类的,就在看雪上面疯狂的搜索,居然未果。不过也得到一些启示,就是不光可以单独伺候FindWindow/EnumWindows/EnumChildWindows这三个API,还可以服侍支持这三个兄弟的底层大爷,比如获取窗口句柄数组的函数----如果有的话。OK,决定了方向就这么做下去。看看是不是能够验证我的猜想。
交待下我的系统是windows xp sp2,因为涉及到底层函数,而不是API本身,所以可能各个系统不一样,大家请注意。另外既然是笔记就会比较冗杂,大家包涵。
go on......
随便写了个调用EnumWindows的程序,然后用OllyDbg加载运行.
EnumWindows入口:
77D1CD99 55 push ebp
77D1CD9A 8BEC mov ebp, esp
77D1CD9C 33C0 xor eax, eax
77D1CD9E 50 push eax
77D1CD9F 50 push eax
77D1CDA0 FF75 0C push dword ptr [ebp + C] ; lParam
77D1CDA3 FF75 08 push dword ptr [ebp + 8 ] ; EnumWindowsProc
77D1CDA6 50 push eax
77D1CDA7 50 push eax
77D1CDA8 E8 D0FEFFFF call 77D1CC7D
77D1CDAD 5D pop ebp
77D1CDAE C2 0800 retn 8
可以看到参数被转发到了77D1CC7D了,F7进去看看:
可以看到77D184D0这个函数的调用得到窗口句柄列表(是一个数组),这里是可以动手脚的,如果FindWindow也用到这个函数的话,那么我们就可以!@#@$$%,那下面看看FindWindow是怎么实现的.
FindWindow
77D2E583 55 push ebp
77D2E584 8BEC mov ebp, esp
77D2E586 33C0 xor eax, eax
77D2E588 50 push eax
77D2E589 FF75 0C push dword ptr [ebp + C] ; 这里传进去的是要寻找窗口的标题
77D2E58C FF75 08 push dword ptr [ebp + 8 ] ; 这里传进去的是要寻找窗口的类名
77D2E58F 50 push eax
77D2E590 50 push eax
77D2E591 E8 4CFFFFFF call 77D2E4E2
77D2E596 5D pop ebp
77D2E597 C2 0800 retn 8
77D2E4E2函数里面主要是把窗口标题以及类名转换成Unicode编码,然后这里是关键
77D2E525 FF75 18 push dword ptr [ebp + 18 ]
77D2E528 FF75 E8 push dword ptr [ebp - 18 ] ; 应该是窗口名unicode码。好像是个结构,开始是长度,然后是unicode指针
77D2E52B FF75 F8 push dword ptr [ebp - 8 ] ; 应该是类名unicode码。好像是个结构,开始是长度,然后是unicode指针
77D2E52E FF75 0C push dword ptr [ebp + C]
77D2E531 FF75 08 push dword ptr [ebp + 8 ]
77D2E534 E8 4CF7FEFF call 77D1DC85
77D1DC85 ==>
77D1DC85 B8 7A110000 mov eax, 117A
77D1DC8A BA 0003FE7F mov edx, 7FFE0300
77D1DC8F FF12 call [edx] ; ntdll.KiFastSystemCall,[edx] == 7C92EB8B
77D1DC91 C2 1400 retn 14
7C92EB8B ==>
7C92EB8B > 8BD4 mov edx, esp
7C92EB8D 0F34 sysenter
此时堆栈如下
0012E844 77D1DC91 RETURN to USER32.77D1DC91
0012E848 77D2E539 RETURN to USER32.77D2E539 from USER32.77D1DC85
0012E84C 00000000
0012E850 00000000
0012E854 0012E87C 这里指向一个结构,似乎包括unicode长度和unicode字符指针,这里指向 " ToFindClass "
0012E858 0012E86C 这里指向一个结构,似乎包括unicode长度和unicode字符指针,这里指向 " ToFindTitle "
0012E85C 00000000
0012E860 0012ECBC
0012E864 0012E8B8
0012E868 00000000
0012E86C 00180016
0012E870 00182930 UNICODE " ToFindTitle "
0012E874 0012E86C
0012E878 00000001
0012E87C 00180016
0012E880 0018EFD8 UNICODE " ToFindClass "
看来FindWindow最后是到了调用系统中断里面来,可以肯定是在这个系统中断里面完成FindWindow操作的,因为KiFastSystemCall出来以后就开始销毁之前产生的窗口标题和类名的unicode码分配的空间了.这和我以前假设的不一样,但是似乎可以根据ntdll.KiFastSystemCall的中断号来干些坏事,那么我们回头来看EnumWindows更里面是否最终调用了系统中断.
回顾一下,EnumWindows里面最关键的函数是
77D1CC88 FF75 18 push dword ptr [ebp + 18 ]
77D1CC8B C745 FC 01000000 mov dword ptr [ebp - 4 ], 1
77D1CC92 FF75 1C push dword ptr [ebp + 1C]
77D1CC95 FF75 0C push dword ptr [ebp + C]
77D1CC98 FF75 08 push dword ptr [ebp + 8 ]
77D1CC9B E8 65000000 call 77D1CD05 ; 填充窗口句柄结构,最后一个参数会保存返回的句柄数组,返回值是句柄总数
77D1CD05 ==> 里面有这么一个函数调用
77D1CD31 50 push eax
77D1CD32 57 push edi
77D1CD33 FF75 FC push dword ptr [ebp - 4 ]
77D1CD36 FF75 14 push dword ptr [ebp + 14 ]
77D1CD39 FF75 10 push dword ptr [ebp + 10 ]
77D1CD3C FF75 0C push dword ptr [ebp + C]
77D1CD3F FF75 08 push dword ptr [ebp + 8 ]
77D1CD42 E8 3C000000 call 77D1CD83 ; 最后一个参数会保存返回的句柄数组
77D1CD83 ==>
77D1CD83 B8 38110000 mov eax, 1138
77D1CD88 BA 0003FE7F mov edx, 7FFE0300
77D1CD8D FF12 call [edx] ; ntdll.KiFastSystemCall
77D1CD8F C2 1C00 retn 1C
OK,总算有点成绩了,可见使用的都是系统调用,然后我们看看EnumChildWindows.
EnumChildWindows的调试结果也类似,最好转到sysenter里面去了.......
难道最好的屏蔽办法是拦截中断,继续研究......