灰鸽子分析报告
magictong 2012/2
一、样本基础信息
MD5:cf6d4d8250e4ba8b5fe87fa4eb940ea8
大小: 300,703 字节
文件名:999.v
壳信息:NsPack
解壳后信息:Borland Delphi 6.0 - 7.0
其它:(无)
调试运行环境:XPSP3
调试工具:OD IDA PEID XurTr
二、总结
1、本样本是一个非常复杂的,功能非常齐全的远控木马程序。样本通过全局钩子的方式Hook一些常见的枚举文件,注册表,服务,进程的API,使得ring3层完全不可见,达到有效的隐藏自己的目的。命令接收端支持的命令非常齐全,通过远程控制几乎可以做到计算机使用者直接操作计算机效果。
2、由于本样本是使用delphi写成,分析时时间比较长,有些细节还没有完全搞清楚,譬如delphi框架的函数调用序列等等,这些需要对delphi程序本身的编写有一定的深入了解。
3、通过对这个样本的分析,对delphi样本的一些特点和分析方式有了一定的了解。
4、样本释放的文件。
GServerd.exe(自身拷贝)
GServerd.dll(由GServerd.exe释放)
GServerdkey.dll(GServerd.dll释放)
5、下面的图是GServerd.exe的资源情况,通过对样本的分析,我们可以知道样本自身没释放GServerdkey.dll,但是它有这个资源,说明这个样本是一个可以配置的远控服务端。
三、样本基本行为流程
1、样本运行后,作为两种情况运行,如果是普通情形下则会拷贝自身到system32下,名称修改为GServerd.exe,然后创建一个名为PigeonServer的 服务,并且启动服务,然后进行自删除。
2、如果样本作为服务程序运行,则会从资源中释放文件GServerd0.dll到临时目录下,然后创建一块共享内存用于通信,在服务子程中首先关闭IE 的连接向导,关闭IE的默认浏览器检测,然后启动一个隐藏窗口的IE进程,通过远程线程注入的方式,让这个IE进程去加载刚刚释放的GServerd0.dll 。
3、GServerd.dll其实这个DLL是完成主要功能也是最复杂的DLL,但是因为没有灰鸽子的客户端,因此无法进行真实的动态调试操作,但是也可以通过静态分析获知,这个DLL支持哪些远控操作。这个dll是一个典型的使用delphi的窗口框架程序来写作的。不过,这个DLL具体怎么去联客户端的没有分析出来(就是怎么知道客户端要链接它,因为它自己是服务器,要弄明白,需要弄清楚delphi窗口框架程序的调用序列)。这个DLL首先是释放名为GetKey的PE资源文件(如果没有的话),释放的文件实际就是GServerdKey.dll。设置GServerdKey.dll属性隐藏,系统和只读。然后进行网络初始化,进入网络命令循环,会等待客户端的连接,然后对客户端发送的命令进行解析,执行相应的命令。
4、GServerdKey.dll这个DLL实际上会被所有拥有消息循环的ring3进程加载,它的工作原理是通过样本服务进程启动一个隐藏窗口的IE进程之后,注入一个远程线程给这个IE进程,然后IE进程会加载这个DLL(GServerdKey.dll),调用这个DLL的导出函数CreateObject,导出函数里面会设置两个消息钩子,这样所有的拥有消息循环的进程就会加载这个dll,然后在这个dll的DllMain里面会进行APIHOOK操作。而钩子函数里面则进行键盘记录操作。Hook的API主要有FindNextFileA FindNextFileW EnumServicesStatusA EnumServicesStatusW RegEnumKeyExA RegEnumKeyExW和一些native API包括NtQuerySystemInformation,RtlGetNativeSystemInformation,ZwQuerySystemInformation。除了样本服务进程启动的IE进程外,其他的进程还需要inlinehook两个API,即NtTerminateProcesee和ZwTerminateProcesee。通过HOOK这些API,使得样本释放的文件,创建的服务,启动的IE进程,创建的一些敏感注册表键值在ring3层不可见。使得创建的无窗口ie进程不能被轻易在ring3层杀掉。
四、细节分析
--------------------------------------------------
[File1]【GServerd.exe】就是样本自身
--------------------------------------------------
作为非服务运行流程:
1、释放资源的函数入口。
1314B714 . 6A 0A PUSH 0A ; /ResourceType = RT_RCDATA
1314B716 . 50 PUSH EAX ; |ResourceName
1314B717 . A1 60E61413 MOV EAX,DWORD PTR DS:[1314E660] ; |
1314B71C . 50 PUSH EAX ; |hModule => 13140000 (GrayUnPa)
1314B71D . E8 1A9BFFFF CALL JMP.&kernel32.FindResourceA> ; \FindResourceA
2、判断是不是VER_PLATFORM_WIN32_NT:
1314A650 >/$ 81C4 6CFFFFFF ADD ESP,-94 ; IsPlatformWin32Nt
1314A656 |. C70424 940000>MOV DWORD PTR SS:[ESP],94
1314A65D |. 54 PUSH ESP ; /pVersionInformation
1314A65E |. E8 69ACFFFF CALL JMP.&kernel32.GetVersionExA> ; \GetVersionExA
1314A663 |. 837C24 10 02 CMP DWORD PTR SS:[ESP+10],2
1314A668 |. 0F94C0 SETE AL
1314A66B |. 81C4 94000000 ADD ESP,94
1314A671 \. C3 RETN
3、创建一个名位GServerd.exe的mutex,如果已经存在则直接退出
0012FF68 00000000 |Arg1 = 00000000
0012FF6C FFFFFFFF |Arg2 = FFFFFFFF
0012FF70 008D1C48 \Arg3 = 008D1C48 ASCII "GServerd.exe"
4、拷贝自身到system32目录,改名为GServerd.exe,并设置属性为只度,隐藏和系统
1314CBA9 . E8 FA74FFFF CALL GrayUnPa.LStrToPChar>
1314CBAE . 50 PUSH EAX ; |ExistingFileName
1314CBAF . E8 E885FFFF CALL JMP.&kernel32.CopyFileA> ; \CopyFileA
0012FF5C 008D1C7C |ExistingFileName = "C:\Documents and Settings\Administrator\桌面\huigezi\GrayUnPack.exe"
0012FF60 008D1C24 |NewFileName = "C:\WINDOWS\GServerd.exe"
0012FF64 00000000 \FailIfExists = FALSE
0012FF50 008D1C24 |FileName = "C:\WINDOWS\GServerd.exe"
0012FF54 00000007 \FileAttributes = READONLY|HIDDEN|SYSTEM
5、判断系统是否是nt(bp 1314CBD7),如果是则去创建下面的服务。否是使用WinExec启动进程并写入自启动。
HKEY_CURRENT_USER\\SoftWare\\Microsoft\\Windows\\CurrentVersion\\Run
6、创建服务PigeonServer(下面是服务的创建参数)。
0012FEE8 00147768 |hManager = 00147768
0012FEEC 008D1AD4 |ServiceName = "PigeonServer"
0012FEF0 008D1AB8 |DisplayName = "PigeonServer"
0012FEF4 000F01FF |DesiredAccess = SERVICE_ALL_ACCESS
0012FEF8 00000110 |ServiceType = SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS
0012FEFC 00000002 |StartType = SERVICE_AUTO_START
0012FF00 00000000 |ErrorControl = SERVICE_ERROR_IGNORE
0012FF04 008D1C24 |BinaryPathName = "C:\WINDOWS\GServerd.exe"
0012FF08 00000000 |LoadOrderGroup = NULL
0012FF0C 00000000 |pTagId = NULL
0012FF10 00000000 |pDependencies = NULL
0012FF14 00000000 |ServiceStartName = NULL
0012FF18 00000000 \Password = NULL
7、启动服务PigeonServer。
8、进行自删除(下面是进行自删除的bat文件)。
:try
del "C:\Documents and Settings\Administrator\桌面\huigezi\GrayUnPack.exe"
if exist "C:\Documents and Settings\Administrator\桌面\huigezi\GrayUnPack.exe" goto try
del %0
exit
下面是创建自删除进程的参数:
0012FD00 00000000 |ModuleFileName = NULL
0012FD04 008D1D34 |CommandLine = "C:\WINDOWS\unsetup.bat"
0012FD08 00000000 |pProcessSecurity = NULL
0012FD0C 00000000 |pThreadSecurity = NULL
0012FD10 00000000 |InheritHandles = FALSE
0012FD14 00000040 |CreationFlags = IDLE_PRIORITY_CLASS
0012FD18 00000000 |pEnvironment = NULL
0012FD1C 00000000 |CurrentDir = NULL
0012FD20 0012FD48 |pStartupInfo = 0012FD48
0012FD24 0012FD8C \pProcessInfo = 0012FD8C
作为服务运行流程:
下面主要看以服务启动后,干了些什么事情。可以通过修改流程直接调试服务的子程(bp 1314caf3 jz bp 1314cc89 sub_13149B24)。
1、先删除C:\WINDOWS\GServerd.DLL,然后从资源MAinDLL里面创建GServerd0.DLL文件到临时目录(这个0是计算出来的,如果已经有GServerd0.DLL,则创建GServerd1.DLL,以此类推)。
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\GServerd0.DLL
1314C86F |. B9 4CE91413 MOV ECX,GrayUnPa.1314E94C
1314C874 |. B8 3CC91413 MOV EAX,GrayUnPa.1314C93C ; ASCII "MAinDLL"
1314C879 |. BA 01000000 MOV EDX,1
1314C87E |. E8 71EEFFFF CALL GrayUnPa.CreateFileFromRes>
0012FF0C 008D1DB8 |FileName = "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\GServerd0.DLL"
0012FF10 C0000000 |Access = GENERIC_READ|GENERIC_WRITE
0012FF14 00000003 |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
0012FF18 00000000 |pSecurity = NULL
0012FF1C 00000002 |Mode = CREATE_ALWAYS
0012FF20 00000020 |Attributes = ARCHIVE
0012FF24 00000000 \hTemplateFile = NULL
2、设置GServerd0.DLL属性为只读,隐藏和系统
0012FF40 008D1DB8 |FileName = "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\GServerd0.DLL"
0012FF44 00000007 \FileAttributes = READONLY|HIDDEN|SYSTEM
3、创建一块0x800字节的共享内存,共享内存的名字通过临时文件名和20050101组合计算出来,计算函数在13149B24(bp 13149B24),这块共享内存用于后续启动的一个无窗口IE进程和全局钩子模块进行通信。
0012FF40 FFFFFFFF |hFile = FFFFFFFF
0012FF44 00000000 |pSecurity = NULL
0012FF48 00000004 |Protection = PAGE_READWRITE
0012FF4C 00000000 |MaximumSizeHigh = 0
0012FF50 00000800 |MaximumSizeLow = 800
0012FF54 008D1EB8 \MapName = "27EF4F2D80A025A52FB252A1B0A4EE8C67A6D8040041A7EE7411BD1E9E5BE6A400A67120BFFF6CD9242BAE2EC61CB10F"
4、启动PigeonServer服务,service_main函数的地址是ServiceMain_1314C298。在service函数里面创建了一个线程:
hthread = CreateThread(0, 0, (DWORD (__stdcall *)(LPVOID))ServiceThreadProc, 0, 0, &ThreadId);
hthreadTmp = hthread;
WaitForSingleObject(hthread, 0xFFFFFFFFu);
线程函数行为:
5、在HKEY_CURRENT_USER下的Software\Microsoft\Internet Connection Wizard,属性Completed写入2进制数据01 00 00 00(关闭IE的连接向导)。
0012FE3C 80000001 |hKey = HKEY_CURRENT_USER
0012FE40 1314BB50 |Subkey = "Software\Microsoft\Internet Connection Wizard"
0012FE44 00000000 |Reserved = 0
0012FE48 00000000 |Class = NULL
0012FE4C 00000000 |Options = REG_OPTION_NON_VOLATILE
0012FE50 000F003F |Access = KEY_ALL_ACCESS
0012FE54 00000000 |pSecurity = NULL
0012FE58 0012FE60 |pHandle = 0012FE60
0012FE5C 0012FE64 \pDisposition = 0012FE64
1314A1E9 . 6A 04 PUSH 4 ; /BufSize = 4
1314A1EB . 8D45 D8 LEA EAX,DWORD PTR SS:[EBP-28] ; |
1314A1EE . 50 PUSH EAX ; |Buffer
1314A1EF . 6A 03 PUSH 3 ; |ValueType = REG_BINARY
1314A1F1 . 6A 00 PUSH 0 ; |Reserved = 0
1314A1F3 . 57 PUSH EDI ; |ValueName
1314A1F4 . 53 PUSH EBX ; |hKey
1314A1F5 . E8 8AAFFFFF CALL JMP.&ADVAPI32.RegSetValueExA> ; \RegSetValueExA
1314A1FA > 53 PUSH EBX ; /hKey = 00000044 (window)
1314A1FB . E8 64AFFFFF CALL JMP.&ADVAPI32.RegCloseKey> ; \RegCloseKey
6、在HKEY_CURRENT_USER下的Software\Microsoft\Internet Explorer\Main,属性Check_Associations写入字符串数据no(这个键值的是设置IE是否自动检测自己是默认浏览器,设置为no之后就不检测,因为等下要启动IE进程)。
1314BA58 |. 68 80BB1413 PUSH GrayUnPa.1314BB80 ; ASCII "no"
1314BA5D |. 6A 01 PUSH 1
1314BA5F |. B9 84BB1413 MOV ECX,GrayUnPa.1314BB84 ; ASCII "Check_Associations"
1314BA64 |. BA 98BB1413 MOV EDX,GrayUnPa.1314BB98 ; ASCII "Software\Microsoft\Internet Explorer\Main"
7、用窗口隐藏方式启动IE进程
0012FEA4 00000000 |ModuleFileName = NULL
0012FEA8 008D1F8C |CommandLine = ""C:\Program Files\Internet Explorer\IEXPLORE.EXE" about:blank"
0012FEAC 00000000 |pProcessSecurity = NULL
0012FEB0 00000000 |pThreadSecurity = NULL
0012FEB4 00000000 |InheritHandles = FALSE
0012FEB8 00000028 |CreationFlags = DETACHED_PROCESS|NORMAL_PRIORITY_CLASS
0012FEBC 00000000 |pEnvironment = NULL
0012FEC0 00000000 |CurrentDir = NULL
0012FEC4 0012FEF0 |pStartupInfo = 0012FEF0
0012FEC8 0012FEE0 \pProcessInfo = 0012FEE0
8、给上面创建的IE线程创建一个远程线程,线程函数是LoadLibraryA,线程参数是C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\GServerd0.DLL。
9、如果启动IE失败的话,直接打开EXPLORE.EXE,让EXPLORE.EXE去启动远程线程,线程函数和线程参数同上。
10、服务程序退出,剩下的事情交给IE进程里面的GServerd0.DLL。
void __stdcall ServiceThreadProc()
{
int v0; // ST04_4@6
if ( (unsigned __int8)CreateIEProc2RemoteThread_1314B9F4() )
Sleep(5000u);
if ( (unsigned __int8)IsPlatformWin32Nt_1314A650() && byte_1314E96B )
{
if ( byte_1314E96C )
{
v0 = *MK_FP(__FS__, 0);
*MK_FP(__FS__, 0) = &v0;
sub_1314AFCC(0, dword_1314E970);
*MK_FP(__FS__, 0) = v0;
}
else
{
while ( GetMessageA(&Msg, 0, 0, 0) )
Sleep(8u);
}
}
else
{
ExitProcess_0(0);
}
}
--------------------------------------------------
[File1]【GServerd.dll】
--------------------------------------------------
其实这个DLL是完成主要功能也是最复杂的DLL,但是因为没有灰鸽子的客户端,因此无法进行真实的动态调试操作,但是也可以通过静态分析获知,这个DLL支持哪些远控操作。这个dll是一个典型的使用delphi的窗口框架程序来写作的。不过,这个DLL具体怎么去联客户端的没有分析出来(就是怎么知道客户端要链接它,因为它自己是服务器,要弄明白,需要弄清楚delphi窗口框架程序的调用序列)。
静态分析时,要注意两点:
1、注意一些全局对象的构造函数(他们在初始化时就已经被调用了),很多全局变量也是在构造函数里面初始化的。
2、注意delphi的框架的特点,就这个dll来讲,建议从字符串和函数入手,能够比较快的找到关键点。
【DllMain流程】
0、创建了一个线程,线程函数里面创建了一个delphi的窗口,然后就走入了窗口的消息循环。
int __stdcall MyThreadFunction_131C590C(LPVOID a1)
{
sub_13190AEC();
Forms__TApplication__CreateForm();
return Forms__TApplication__Run();
}
1、FromCreate(_TServer_FormCreate)函数里面首先是释放名为GetKey的PE资源文件(如果没有的话),释放的文件实际就是GServerdKey.dll。设置GServerdKey.dll属性隐藏,系统和只读。
2、调用GServerdKey.dll的导出CreateObject函数(设置消息钩子,进行各种隐藏)。
3、打开之前原始样本里面创建的共享内存,对共享内存的内容进行初始化,包括自身ie进程的PID。
4、对网络进行初始化。
5、然后会进入窗口消息循环,对网络进行设置之后,在收到网络命令时,会调用这里面最大的(所谓最大就是很长的一个函数)函数(131C16C4::_TServer_DirSocketRead),这个函数对收到的网络命令进行解析,调用相应的命令处理函数进行网络消息处理(这下面应该是一大部分支持的操作,你可以想象这个玩意可以做什么事情了,很多命令我下面可能就一句话,但是实际上很多操作命令在设计上都是非常精细的)。
能够处理的命令有以下一些:
a、枚举所有磁盘类型信息(1319DD40)。
b、获得特定文件的时间信息。
c、获得指定进程路径信息(1319E51C)。
d、结束指定的进程。
e、运行指定的进程,并且截获进程的输出信息(1319EEC4)。
f、获得磁盘的描述信息。
g、给指定的窗口发送消息(131BE564)。
h、获取注册表,计算机名等信息。
i、获得剪切板信息(1319D6D0)。
j、枚举窗口,获取窗口名窗口类型等等信息,控制窗口的隐藏和显示(131C08C8)。
k、强制进行GServerdKey.dll释放,并调用CreateObject导出函数(1319C310)。
l、广播一个消息,通知系统(真贴心)。
m、删除文件。
n、启动服务,删除服务,更改服务,停止服务等等操作(由不同的命令控制)。
o、枚举网络共享,打开网络共享,删除网络共享(由不同的命令控制)。
p、设置指定文件的属性(1319DA28)。
r、设置指定的注册表信息,删除注册表。
s、创建线程,模拟鼠标点击。
t、创建线程,模拟键盘击键。
u、打开指定的文件。
v、重启机器。
w、……
--------------------------------------------------
[File3]【GServerdKey.dll】
--------------------------------------------------
这个DLL实际上会被所有拥有消息循环的ring3进程加载,它的工作原理是通过样本服务进程启动一个隐藏窗口的IE进程之后,注入一个远程线程给这个IE进程,然后IE进程会加载这个DLL(GServerdKey.dll),调用这个DLL的导出函数CreateObject,导出函数里面会设置两个消息钩子,这样所有的拥有消息循环的进程就会加载这个dll,然后在这个dll的DllMain里面会进行APIHOOK操作。而钩子函数里面则进行键盘记录操作。
挂钩函数可以先通过XueTr看一个大概:
挂钩对象 挂钩位置 钩子类型 挂钩处当前值 挂钩处原始值
len(5) ntdll.dll->NtQuerySystemInformation 0x7C92D910->0x00A2AEE8[C:\WINDOWS\GServerdKey.DLL] inline E9 D3 D5 0F 84 B8 AD 00 00 00
len(5) ntdll.dll->NtTerminateProcess 0x7C92DE50->0x00A2AE8C[C:\WINDOWS\GServerdKey.DLL] inline E9 37 D0 0F 84 B8 01 01 00 00
len(5) ntdll.dll->RtlGetNativeSystemInformation 0x7C92D910->0x00A2AEE8[C:\WINDOWS\GServerdKey.DLL] inline E9 D3 D5 0F 84 B8 AD 00 00 00
len(5) ntdll.dll->ZwQuerySystemInformation 0x7C92D910->0x00A2AEE8[C:\WINDOWS\GServerdKey.DLL] inline E9 D3 D5 0F 84 B8 AD 00 00 00
len(5) ntdll.dll->ZwTerminateProcess 0x7C92DE50->0x00A2AE8C[C:\WINDOWS\GServerdKey.DLL] inline E9 37 D0 0F 84 B8 01 01 00 00
[*]len(5) kernel32.dll->FindNextFileA 0x7C834EC9->0x00A2B220[C:\WINDOWS\GServerdKey.DLL] inline E9 52 63 1F 84 8B FF 55 8B EC
[*]len(5) kernel32.dll->FindNextFileW 0x7C80EFCA->0x00A2B2D8[C:\WINDOWS\GServerdKey.DLL] inline E9 09 C3 21 84 6A 2C 68 C8 F0
[*]len(5) ADVAPI32.dll->EnumServicesStatusA 0x77DC6B17->0x00A2AFB8[C:\WINDOWS\GServerdKey.DLL] inline E9 9C 44 C6 88 6A 34 68 98 6B
[*]len(5) ADVAPI32.dll->EnumServicesStatusW 0x77E07D09->0x00A2B0EC[C:\WINDOWS\GServerdKey.DLL] inline E9 DE 33 C2 88 8B FF 55 8B EC
[*]len(5) ADVAPI32.dll->RegEnumKeyExA 0x77DB5196->0x00A2AC94[C:\WINDOWS\GServerdKey.DLL] inline E9 F9 5A C7 88 8B FF 55 8B EC
[*]len(5) ADVAPI32.dll->RegEnumKeyExW 0x77DA7BC9->0x00A2AD90[C:\WINDOWS\GServerdKey.DLL] inline E9 C2 31 C8 88 8B FF 55 8B EC
[*]SHELL32.dll->SHLWAPI.dll:[Ordinal:486] 0x77F4C297->0x77FA01E6[C:\WINDOWS\system32\SHLWAPI.dll] Iat E6 01 FA 77 97 C2 F4 77
搞清楚2个数据结构:
pbase(共享内存基地址)到1276字节处存放的是一些通信用的字符串,具体是什么没有详细分析。
pbase(共享内存基地址) + 1276字节之后的4个字节存放的是启动的隐藏窗口的IE进程的PID。
pbase(共享内存基地址) + 1280字节之后的4个字节存放的是一个控制命令。
HOOK类基本结构(翻译成C++):
class CHookClass:
{
void* pVirtualP; // 你可以认为是虚表指针
HANDLE dwCurProcessHandle; // 当前进程的句柄
BYTE bIsHook; // 是否已经HOOK了
BYTE[5] byOpCodeSrc; // (inlineHOOK前)修改前指令
BYTE JMPOpcode // E9指令
DWORD dwJMPOffset; // 相对跳转的距离
// ……
// 未知
// ……
DWORD dwOrgAPIAddress // 需要hook的API的地址
DWORD dwNewFuncAddress // 新函数地址
}
【DllMain流程】
1、打开共享内存,保存共享内存基地址,获取一些共享数据(启动的IE的PID等等)。
2、进行API的inlinehook操作。Hook的API主要有FindNextFileA FindNextFileW EnumServicesStatusA EnumServicesStatusW RegEnumKeyExA RegEnumKeyExW和一些native API包括NtQuerySystemInformation,RtlGetNativeSystemInformation,ZwQuerySystemInformation。
3、除了样本服务进程启动的IE进程外,其他的进程还需要inlinehook两个API,即NtTerminateProcesee和ZwTerminateProcesee。
4、GServerdKey.dll被卸载时,恢复这些API的inline钩子。
【hook的api函数的流程】
hook的函数可以分为5组:
1、FindNextFileA FindNextFileW
把这个函数Hook之后,使得一些文件浏览程序,譬如explorer等等无法看到GServerdKey.dll,GServerd.exe和GServerd.DLL文件,做法很简单,在hook函数里面,首先恢复hook,再调用一次源函数,譬如FindNextFileA,如果发现枚举到的是上面的三个文件任何之一,则再调用FindNextFileA,直到不是上面三个文件之一,然后再次hook,退出hook函数,返回FindNextFileA的数据给调用者。这样一些文件浏览的工具在ring3层就无法枚举到这三个文件了。
2、EnumServicesStatusA EnumServicesStatusW(NewEnumServicesStatusW_40B0EC)
这两个API hook之后,是让灰鸽子创建的服务无法在RING3层被枚举到。原理与1有点区别,也是先恢复hook,调用一次源API,譬如EnumServicesStatusA,因为这个API只调用一次,返回所有的系统服务信息,因此在hook函数里面修改了返回数据,把灰鸽子创建的服务信息从返回数据里面直接抹掉了。
3、RegEnumKeyExA RegEnumKeyExW
这两个API hook之后,是让灰鸽子创建的某些注册表在RING3层无法被枚举到。原理同1。
4、NtTerminateProcesee ZwTerminateProcesee
这两个API hook之后,是让灰鸽子创建的隐藏窗口IE进程无法在ring3层被杀掉,保护这个IE进程。
5、NtQuerySystemInformation RtlGetNativeSystemInformation ZwQuerySystemInformation
挂钩这个API的目的是让进程无法被查询到(表象是一些ring3层的进程查看工具无法看到那个无窗口的IE进程)。
【CreateObject导出函数】
这个函数安装两个两个消息钩子(WH_GETMESSAGE和WH_CALLWNDPROC消息钩子),这两个钩子配合之后,基本上可以监视一个窗口的所有消息(包括非队列消息和队列消息),不过这里主要用来监视键盘消息。
1、这两个消息钩子的钩子函数极其相似就不分开说明,只说明一个消息钩子子程的流程。
2、排除密码框。
3、如果不是密码框,则钩子函数中对键盘消息进行记录,特别处理WM_IME_COMPOSITION消息,通过对ImmGetContext,ImmGetCompositionStringA,ImmReleaseContext等等API的配合调用,获得一些特殊字符进行记录。(这种方法需要对输入法开发有一定了解,可以参考http://www.chinaaspx.com/archive/VC/9502.htm)这里需要注意的是,并不是一直进行键盘记录的,它是由Gserverd.dll里面控制的,当灰鸽子的客户端要求服务端进行键盘记录时,会通过网络通知Gserverd.dll,然后Gserverd.dll把共享内存中一个记录键盘的控制命令置上后,才会进行键盘记录。