好学IT学院:IT信息技术分享交流平台
来源:互联网  作者:本站整理  发布时间:2009-02-25  ★★★加入收藏〗〖手机版
摘要:进程文件:svchost.dll 进程名称:Trojan.W32.Agent 英文描述:svchost.dllisamodulewhichisregisteredasatrojan.ThisTrojanallowsattackerstoaccessyour…

3. Svchost代码

现在我们基本清楚svchost的原理了,但是要自己写一个DLL形式的服务,由svchost来启动,仅有上边的信息还有些问题不是很清楚。比如我们在导出的ServiceMain()函数中接收的参数是ANSI还是Unicode?我们是否需要调用RegisterServiceCtrlHandler和StartServiceCtrlDispatcher来注册服务控制及调度函数?

这些问题要通过查看svchost代码获得。下边的代码是windows 2000+ service pack 4 的svchost反汇编片段,可以看出svchost程序还是很简单的。

主函数首先调用ProcCommandLine()对命令行进行分析,获得要启动的服务组,然后调用SvcHostOptions()查询该服务组的选项和服务组的所有服务,并使用一个数据结构 svcTable 来保存这些服务及其服务的DLL,然后调用PrepareSvcTable() 函数创建 SERVICE_TABLE_ENTRY 结构,把所有处理函数SERVICE_MAIN_FUNCTION 指向自己的一个函数FuncServiceMain(),最后调用API StartServiceCtrlDispatcher() 注册这些服务的调度函数。

; ======================= Main Funcion =========================
  .text:010010B8 public start
  .text:010010B8 start proc near
  .text:010010B8 push esi
  .text:010010B9 push edi
  .text:010010BA push offset sub_1001EBA ; lpTopLevelExceptionFilter
  .text:010010BF xor edi, edi
  .text:010010C1 call ds:SetUnhandledExceptionFilter
  .text:010010C7 push 1 ; uMode
  .text:010010C9 call ds:SetErrorMode
  .text:010010CF call ds:GetProcessHeap
  .text:010010D5 push eax
  .text:010010D6 call sub_1001142
  .text:010010DB mov eax, offset dword_1003018
  .text:010010E0 push offset unk_1003000 ; lpCriticalSection
  .text:010010E5 mov dword_100301C, eax
  .text:010010EA mov dword_1003018, eax
  .text:010010EF call ds:InitializeCriticalSection
  .text:010010F5 call ds:GetCommandLineW
  .text:010010FB push eax ; lpString
  .text:010010FC call ProcCommandLine
  .text:01001101 mov esi, eax
  .text:01001103 test esi, esi
  .text:01001105 jz short lab_doservice
  .text:01001107 push esi
  .text:01001108 call SvcHostOptions
  .text:0100110D call PrepareSvcTable
  .text:01001112 mov edi, eax ; SERVICE_TABLE_ENTRY returned
  .text:01001114 test edi, edi
  .text:01001116 jz short loc_1001128
  .text:01001118 mov eax, [esi+10h]
  .text:0100111B test eax, eax
  .text:0100111D jz short loc_1001128
  .text:0100111F push dword ptr [esi+14h] ; dwCapabilities
  .text:01001122 push eax ; int
  .text:01001123 call InitializeSecurity
  .text:01001128
  .text:01001128 loc_1001128: ; CODE XREF: start+5Ej
  .text:01001128 ; start+65j
  .text:01001128 push esi ; lpMem
  .text:01001129 call HeapFreeMem
  .text:0100112E
  .text:0100112E lab_doservice: ; CODE XREF: start+4Dj
  .text:0100112E test edi, edi
  .text:01001130 jz ExitProgram
  .text:01001136 push edi ; lpServiceStartTable
  .text:01001137 call ds:StartServiceCtrlDispatcherW
  .text:0100113D jmp ExitProgram
  .text:0100113D start endp
  ; ======================= Main Funcion end ===========================

由于svchost为该组的所有服务都注册了svchost中的一个处理函数,因此每次启动任何一个服务时,服务管理器SCM都会调用FuncServiceMain() 这个函数。这个函数使用 svcTable 查询要启动的服务使用的DLL,调用DLL导出的ServiceMain()函数来启动服务,然后返回。

; ====================== FuncServiceMain() ===========================
  .text:01001504 FuncServiceMain proc near ; DATA XREF: PrepareSvcTable+44o
  .text:01001504
  .text:01001504 arg_0 = dword ptr 8
  .text:01001504 arg_4 = dword ptr 0Ch
  .text:01001504
  .text:01001504 push ecx
  .text:01001505 mov eax, [esp+arg_4]
  .text:01001509 push ebx
  .text:0100150A push ebp
  .text:0100150B push esi
  .text:0100150C mov ebx, offset unk_1003000
  .text:01001511 push edi
  .text:01001512 mov edi, [eax]
  .text:01001514 push ebx
  .text:01001515 xor ebp, ebp
  .text:01001517 call ds:EnterCriticalSection
  .text:0100151D xor esi, esi
  .text:0100151F cmp dwGroupSize, esi
  .text:01001525 jbe short loc_1001566
  .text:01001527 and [esp+10h], esi
  .text:0100152B
  .text:0100152B loc_100152B: ; CODE XREF: FuncServiceMain+4Aj
  .text:0100152B mov eax, svcTable
  .text:01001530 mov ecx, [esp+10h]
  .text:01001534 push dword ptr [eax+ecx]
  .text:01001537 push edi
  .text:01001538 call ds:lstrcmpiW
  .text:0100153E test eax, eax
  .text:01001540 jz short StartThis
  .text:01001542 add dword ptr [esp+10h], 0Ch
  .text:01001547 inc esi
  .text:01001548 cmp esi, dwGroupSize
  .text:0100154E jb short loc_100152B
  .text:01001550 jmp short loc_1001566
  .text:01001552 ; =================================================
  .text:01001552
  .text:01001552 StartThis: ; CODE XREF: FuncServiceMain+3Cj
  .text:01001552 mov ecx, svcTable
  .text:01001558 lea eax, [esi+esi*2]
  .text:0100155B lea eax, [ecx+eax*4]
  .text:0100155E push eax
  .text:0100155F call GetDLLServiceMain
  .text:01001564 mov ebp, eax ; dll ServiceMain Function address
  .text:01001566
  .text:01001566 loc_1001566: ; CODE XREF: FuncServiceMain+21j
  .text:01001566 ; FuncServiceMain+4Cj
  .text:01001566 push ebx
  .text:01001567 call ds:LeaveCriticalSection
  .text:0100156D test ebp, ebp
  .text:0100156F jz short loc_100157B
  .text:01001571 push [esp+10h+arg_4]
  .text:01001575 push [esp+14h+arg_0]
  .text:01001579 call ebp
  .text:0100157B
  .text:0100157B loc_100157B: ; CODE XREF: FuncServiceMain+6Bj
  .text:0100157B pop edi
  .text:0100157C pop esi
  .text:0100157D pop ebp
  .text:0100157E pop ebx
  .text:0100157F pop ecx
  .text:01001580 retn 8
  .text:01001580 FuncServiceMain endp ; sp = -8
  ; ==================== FuncServiceMain() end ========================

由于svchost已经调用了StartServiceCtrlDispatcher来服务调度函数,因此我们在实现DLL实现时就不用了,这主要是因为一个进程只能调用一次StartServiceCtrlDispatcher API。但是需要用 RegisterServiceCtrlHandler 来注册响应控制请求的函数。最后我们的DLL接收的都是unicode字符串。

由于这种服务启动后由svchost加载,不增加新的进程,只是svchost的一个DLL,而且一般进行审计时都不会去HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionSvchost 检查服务组是否变化,就算去检查,也不一定能发现异常,因此如果添加一个这样的DLL后门,伪装的好,是比较隐蔽的。

揭秘金山网盾破钓鱼骗局的四大核心技术
  一款大小不到2M,安装后占用系统资源仅为1M的免费软件,金山网盾在推出一周后,安装量迅速超过千万,并得到了大量网友的热烈追捧,成为…
  • 好学考试H5触屏版开放内测
  • 好学触屏公众号虎力全开、杨帆起航!