灰鸽子分析报告

    

灰鸽子分析报告

    
    

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张图片
    
三、样本基本行为流程
    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把共享内存中一个记录键盘的控制命令置上后,才会进行键盘记录。

你可能感兴趣的:(windows,Microsoft,null,dll,Delphi,hook)