怎么感觉自己在做病毒呐?最近对于悄悄地干坏事比较感兴趣,那么我离病毒还差什么呐?自定位的代码有了,但是书写一个自定位代码无疑是个非常麻烦的事情,所以我想或许我还需要自己完成LoadLibrary做的工作,这样可以达到代码隐藏的目的,也不会破坏把软件工程奉为圭臬的我的审美观。然后是尽量隐藏自己,这个隐藏的手段太多了,慢慢来吧,加油~至于传播和破坏倒不是我特别关心的,希望不要抓我。
这里我想做的是避免FindWindow/EnumWindows/EnumChildWindows的检测,ollydebug里面有个插件叫做hideod,它就可以完成这个操作,我当时想ollydebug是比较流行的工具,大概有源代码或者手段分析之类的,就在看雪上面疯狂的搜索,居然未果。不过也得到一些启示,就是不光可以单独伺候FindWindow/EnumWindows/EnumChildWindows这三个API,还可以服侍支持这三个兄弟的底层大爷,比如获取窗口句柄数组的函数----如果有的话。OK,决定了方向就这么做下去。看看是不是能够验证我的猜想。
交待下我的系统是windows xp sp2,因为涉及到底层函数,而不是API本身,所以可能各个系统不一样,大家请注意。另外既然是笔记就会比较冗杂,大家包涵。
go on......
随便写了个调用EnumWindows的程序,然后用OllyDbg加载运行.
EnumWindows入口:
77D1CD97
>
8BFF mov edi, edi
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
77D2E581
>
8BFF mov edi, edi
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里面最关键的函数是
77D1CC87
50
push eax
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里面去了.......
难道最好的屏蔽办法是拦截中断,继续研究......