-
-
360保险箱进程保护分析(续)
-
发表于: 2010-3-23 21:11 9395
-
分析版本:360保险箱v3.0正式版(2010.1.1下载)
分析工具:syser debugger、ida
使用平台:XP sp2虚拟机
续上文:http://bbs.pediy.com/showthread.php?t=108378
3、代理服务分析
在上文调用系统服务处设置条件断点:bpx 8053E636 if eax==115(115系统服务号),即可跟入
NtWriteVirtualMemory对应的代理服务:(Syser代码,对应IDA的函数sub_125c4)
FAB6D5C4 MOV EDI,EDI
FAB6D5C6 PUSH EBP
FAB6D5C7 MOV EBP,ESP
FAB6D5C9 SUB ESP,000000AC
FAB6D5CF PUSH ESI
FAB6D5D0 MOV [EBP-2C],EDX
FAB6D5D3 MOV [EBP-28],ESI
FAB6D5D6 MOV EAX,[EBP+0C]
FAB6D5D9 MOV [EBP-20],EAX
FAB6D5DC MOV EAX,[EBP+10]
FAB6D5DF AND [EBP-10],+00
FAB6D5E3 MOV [EBP-1C],EAX
FAB6D5E6 MOV EAX,[EBP+14]
FAB6D5E9 MOV [EBP-18],EAX
FAB6D5EC MOV EAX,[EBP+18]
FAB6D5EF MOV [EBP-14],EAX
FAB6D5F2 MOV EAX,[EBP+08]
FAB6D5F5 MOV [EBP-24],EAX
--------------------入口参数检查 ---------------------------------------------------
FAB6D5F8 LEA EAX,[EBP-0C] //出口参数检查记数
FAB6D5FB PUSH EAX
FAB6D5FC LEA EAX,[EBP+FFFFFF54] //出口参数指针
FAB6D602 PUSH EAX
FAB6D603 LEA EAX,[EBP-6C] //用于检查出口参数的函数指针
FAB6D606 PUSH EAX
FAB6D607 LEA EAX,[EBP-24] //calc进程句柄
FAB6D60A PUSH EAX
FAB6D60B PUAH +1A //过滤函数索引
FAB6D60D CALL FAB6BC0A //入口参数检查
FAB6D612 CMP EAX,C0000503
FAB6D617 MOV [EBP-8],EAX
FAB6D61A JNZ FABD623 //如检查成功
FAB6D61C XOR EAX,EAX
FAB6D61E JMP FAB6D6EB
FAB6D623 TEST EAX,EAX
FAB6D625 JL FAB6D6EB //如被拦截
FAB6D62B MOV EAX,[FAB74070]
FAB6D630 MOV ESI,EAX
FAB6D632 TEST AH,10
FAB6D635 MOV EAX,[FAB740E4] //代理服务表基址
FAB6D63A JZ FAB6D66B //如果是SSDT服务序号
---------------------取原始服务地址(for SSDTShadow)---------------------------
FAB6D63C AND ESI,00000FFF
FAB6D642 PUSH [EAX+ESI*4+00001F4C]
FAB6D649 CALL MmIsAddressValid //检查代理服务表中原服务地址有效性
FAB6D64F TEST AL,AL
FAB6D651 JZ FAB6D661 //如无效
FAB6D653 MOV EAX,[EAB740E4]
FAB6D658 MOV EAX,[EAX+ESI*4+00001F4C] //取代理服务表中原服务地址
FAB6D65F JMP FAB6D68F
FAB6D661 MOV EAX,[FAB73F24]
FAB6D666 MOV EAX,[EAX+ESI*4] //取原始SSDTShadow中服务地址
FAB6D669 JMP FAB6D68F
--------------------取原始服务地址(for SSDT)------------------------------------
FAB6D66B SHL ESI,02
FAB6D66E PUSH [ESI+EAX+04]
FAB6D672 CALL MmIsAddressValid //检查代理服务表中原服务地址有效性
FAB6D678 TEST AL,AL
FAB6D67A JZ FAB6D687 //如无效
FAB6D67C MOV EAX,[FAB740E4]
FAB6D681 MOV EAX,[ESI+EAX+04] //取代理服务表中原服务地址
FAB6D685 JMP FAB6D68F
FAB6D687 MOV EAX,[FAB73F2C]
FAB6D68C MOV EAX,[ESI+EAX] //取原始SSDT中服务地址
------------------- 调用取到的原始服务地址 --------------------------------------
FAB6D68F MOV [EBP-04],EAX
FAB6D692 MOV EDX,[EBP-2C]
FAB6D695 MOV ESI,[EBP-28]
FAB6D698 PUSH [EBP+18]
FAB6D69B PUSH [EBP+14]
FAB6D69E PUSH [EBP+10]
FAB6D6A1 PUSH [EBP+0C]
FAB6D6A4 PUSH [EBP+08]
FAB6D6A7 CALL [EBP-04] //调用取到的服务地址
FAB6D6AA MOV [EBP-08],EAX
------------------- 出口参数检查 ------------------------------------------------
FAB6D6AD XOR ESI,ESI
FAB6D6AF CMP [EBP-0C],ESI
FAB6D6B2 JNA FAB6D6E8 //如不需出口参数检查
FAB6D6B4 MOV EAX,[EBP+ESI*4-6C] // 用于检查出口参数的函数指针
FAB6D6B8 TEST EAX,EAX
FAB6D6BA MOV ECX,[EBP+ESI*4+FFFFFF54] //出口参数指针
FAB6D6C1 MOV [EBP+08],EAX
FAB6D6C4 MOV [EBP+0C],ECX
FAB6D6C7 JZ FAB6D6E2
FAB6D6C9 PUSH [EBP+0C]
FAB6D6CC PUSH [EBP-08] //调用原始服务的返回值
FAB6D6CF LEA EAX,[EBP-24]
FAB6D6D2 PUSH EAX
FAB6D6D3 PUSH +1A //过滤函数索引
FAB6D6D5 CALL [EBP+08] //出口参数检查
FAB6D6D8 MOV [EBP+10],EAX
FAB6D6DB MOV EAX,[EBP+10]
FAB6D6DE TEST EAX,EAX
FAB6D6E0 JL FAB6D6EB
FAB6D6E2 INC ESI
FAB6D6E3 CMP ESI,[EBP-0C] //是否检查完毕
FAB6D6E6 JC FAB6D6B4 //继续检查
FAB6D6E8 MOV EAX,[EBP-08]
FAB6D6EB POP ESI
FAB6D6EC LEAVE
FAB6D6ED RET 0014
该函数首先检查传入的用户态参数,如果无需拦截则执行原始服务例程序,并根据返回的相关
参数决定是否对出口参数做检查。
继续跟入入口参数检查函数FAB6D60D CALL FAB6BC0A :(Syser代码,对应IDA函数
sub_10c0a)
FAB6BC0A MOV EDI,EDI
FAB6BC0C PUSH EBP
FAB6BC0D MOV EBP,ESP
FAB6BC0F SUB ESP,+0C
FAB6BC12 AND [EBP-04],+00
FAB6BC16 CMP [EBP+08],4B //过滤函数索引值范围
FAB6BC1A PUSH EBX
FAB6BC1B PUSH ESI
FAB6BC1C PUSH EDI
FAB6BC1D JNC FAB6BC92 //如果过滤函数索引越限
FAB6BC1F MOV ESI,[FAB73F34] //过滤规则表基址
FAB6BC25 TEST ESI,ESI
FAB6BC27 JZ FAB6BC8A //如过滤规则表不存在
FAB6BC29 MOV EDI,[EBP+14]
FAB6BC2C MOV EBX,[EBP+10]
FAB6BC2F SUB EBX,EDI
FAB6BC31 CMP [ESI+08],+00 //过滤规则表中过滤函数是否存在
FAB6BC35 JZ FAB6BC83 //如不存在
FAB6BC37 MOV EAX,[EBP+8] //传入的过滤函数索引
FAB6BC3A MOV EAX,[ESI+EAX*4+0C] //取规则表中对应索引的过滤函数地址
FAB6BC3E TEST EAX,EAX
FAB6BC40 MOV [EBP-08],EAX
FAB6BC43 JZ FAB6BC83 //如该过滤函数不存在
FAB6BC45 AND [EBP+14],+00
FAB6BC49 AND [EBP+10],+00
FAB6BC4D LEA EAX,[EBP+10] //出口参数检查函数指针数组
FAB6BC50 PUSH EAX
FAB6BC51 LEA EAX,[EBP+14] //出口参数指针数组
FAB6BC54 PUSH EAX
FAB6BC55 PUSH [EBP+0C] //calc进程句柄
FAB6BC58 PUSH [EBP+08] //过滤函数索引
FAB6BC5B CALL [EBP-08] //调用索引到的过滤函数
FAB6BC5E MOV [EBP-0C],EAX
FAB6BC61 MOV EAX,[EBP-0C]
FAB6BC64 TEST EAX,EAX
FAB6BC66 JL FAB6BC94
FAB6BC68 MOV EAX,[EBP+14]
FAB6BC6B TEST EAX,EAX
FAB6BC6D JZ FAB6BC83 //出口参数指针存在
FAB6BC6F CMP [EBP-04],+10 //出口参数指针最多16个
FAB6BC73 JNC FAB6BC83
FAB6BC75 INC [EBP-04]
FAB6BC78 MOV [EBX+EDI],EAX
FAB6BC7B MOV EAX,[EBP+10] //出口参数检查指针
FAB6BC7E MOV [EDI],EAX
FAB6BC80 ADD EDI,+04
FAB6BC83 MOV ESI,[ESI+04]
FAB6BC86 TEST ESI,ESI
FAB6BC88 JNZ FAB6BC31
FAB6BC8A MOV EAX,[EBP+18]
FAB6BC8D MOV ECX,[EBP-04] //出口参数检查指针的数量
FAB6BC90 MOV [EAX],ECX
FAB6BC92 XOR EAX,EAX
FAB6BC94 POP EDI
FAB6BC95 POP ESI
FAB6BC96 POP EBX
FAB6BC97 LEAVE
FAB6BC98 RET 0014
该函数调用索引值对应的过滤函数(见前文过滤规则表数据结构),返回用于做出口参数检查
的函数指针的地址及指针个数。
4、过滤函数分析
继续跟入过滤函数FAB6BC5B CALL [EBP-08],此时代码已经进入驱动safeboxkrnl.sys。
(Syser代码,IDA对应的函数sub_141c8)
FACDF1C8 MOV EDI,EDI
FACDF1CA PUSH EBP
FACDF1CB MOV EBP,ESP
FACDF1CD PUSH -01
FACDF1CF PUSH FACE3180
FACDF1D4 PUSH FACE29E2
FACDF1D9 MOV EAX,FS[00000000]
FACDF1DF PUSH EAX
FACDF1E0 MOV FS:[0],ESP
FACDF1E7 PUSH ECX
FACDF1E8 PUSH ECX
FACDF1E9 SUB ESP,0454
FACDF1EF MOV EAX,[FACE3CD4]
FACDF1F7 MOV [EBP-34],EAX
FACDF1F7 PUSH EBX
FACDF1F8 PUSH ESI
FACDF1F9 PUSH EDI
FACDF1FA MOV [EBP-18],ESP
FACDF1FD AND [EBP-24],+00
FACDF201 MOV [EBP-2C],01 //放行标志位
FACDF208 AND [EBP-28],+00 //向R3询问标志位
FACDF20C AND [EBP-20],+00 //进程对象的PEPROCESS指针
FACDF210 CALL ExGetPreviousMode //调用来自用户态还是内核心态
FACDF216 MOVSX EAX,AL
FACDF219 TEST EAX,EAX
FACDF21B JNZ FACDF224
FACDF21D XOR EAX,EAX
FACDF21F JMP FACDF402
FACDF224 MOV EAX,[EBP+0C] //calc进程句柄
FACDF227 CMP [EAX],-01 //句柄是否为空
FACDF22A JNZ FACDF233
FACDF22C XOR EAX,EAX
FACDF22E JMP FACDF402
FACDF233 AND [EBP-04],+00
FACDF237 CALL PsGetCurrentProcessID //得到当前进程 ID
FACDF23C MOV [EBP+FFFFB9C],EAX
FACDF242 CMP [FACE53E0],+00
FACDF249 JZ FACDF294
FACDF24B MOV EAX,[EBP+FFFFFB9C]
FACDF251 OR EAX,+03
FACDF254 XOR EAX,+03
FACDF257 MOV ECX,[FACE53E4]
FACDF25D MOV ECX,[ECX+14]
FACDF260 MOV ECX,[ECX+18]
FACDF263 OR ECX,+03
FACDF266 XOR ECX,+03
FACDF269 CMP EAX,ECX //是否保险箱自身进程
FACDF26B JZ FACDF28F
FACDF26D MOV EAX,[EBP+FFFFFB9C]
FACDF273 OR EAX,+03
FACDF276 XOR EAX,+03
FACDF279 MOV ECX,[FACE53E4]
FACDF27F MOV ECX,[ECX+14]
FACDF282 MOV ECX,[ECX+14]
FACDF285 OR ECX,+03
FACDF288 XOR ECX,+03
FACDF28B CMP EAX,ECX //是否保险箱自身进程
FACDF28D JNZ FACDF294
FACDF28F JMP FACDF3B3
FACDF294 MOV [EBP+FFFFFBA8],01
FACDF29E CALL PsGetCurrentProcessID //得到当前进程 ID
FACDF2A3 MOV [EBP+FFFFFBAC],EAX
FACDF2A9 PUSH 0104
FACDF2AE LEA EAX,[EBP+FFFFFDC0]
FACDF2B4 PUSH EAX
FACDF2B5 LEA EAX,[EBP+FFFFFBA8]
FACDF2BB PUSH EAX
FACDF2BC CALL FACDDAD6 //当前进程是否为保险箱保护对象
FACDF2C1 MOV [EBP-24],EAX
FACDF2C4 CMP [EBP-24],+00
FACDF2C8 JZ FACDF2D6 //如果非保护进程
FACDF2CA MOV [EBP-2C],01 //如果是保护进程则放行标志置位
FACDF2D1 JMP FACDF3B3
FACDF2D6 PUSH +00
FACDF2D8 LEA EAX,[EBP-20] //OUT参数:引用对象的PEPROCESS指针
FACDF2DB PUSH EAX
FACDF2DC PUSH +00
FACDF2DE PUSH +00
FACDF2E0 PUSH +01
FACDF2E2 MOV EAX,[EBP+0C] //calc进程句柄
FACDF2E5 PUSH [EAX]
FACDF2E7 CALL ObReferenceObjectByHandle //根据calc句柄获得引用的进程对象
FACDF2ED MOV [EBP-30],EAX
FACDF2F0 CMP [EBP-30],+00
FACDF2F4 JNL FACDF2FB
FACDF2F6 JMP FACDF3B3
FACDF2FB CALL IoGetCurrentProcess //得到当前进程对象
FACDF301 CMP [EBP-20],EAX //当前进程对象是否为calc进程对象
FACDF304 JNZ FACDF30B
FACDF306 JMP FACDF3B3
FACDF30B LEA EAX,[EBP+FFFFFBA0]
FACDF311 PUSH EAX
FACDF312 PUSH [EBP-20]
FACDF315 CALL FACDCF86 //根据进程对象的PEPROCESS指针得到calc进程的PID
FACDF31A MOVZX EAX,AL
FACDF31D TEST EAX,EAX
FACDF31F JNZ FACDF326
FACDF321 JMP FACDF3B3
FACDF326 MOV EAX,[EBP+FFFFFBA0]
FACDF32C MOV [EBP+FFFFFBAC],EAX
FACDF332 PUSH 0104
FACDF337 LEA EAX,[EBP+FFFFFDC0]
FACDF33D PUSH EAX
FACDF33E LEA EAX,[EBP+FFFFFBA8]
FACDF344 PUSH EAX
FACDF345 CALL FACDDAD6 //calc进程是否为保险箱设置的保护对象
FACDF34A MOV [EBP-24],EAX
FACDF34D CMP [EBP-24],+00
FACDF351 JZ FACDF3AC
FACDF353 CALL FACDD6DE //检查当前进程是否在放行或拦截列表中
FACDF358 MOV [EBP+FFFFFB98],EAX
FACDF35E MOV EAX,[EBP+FFFFFB98]
FACDF364 MOV [EBP+FFFFFB94],EAX
FACDF36A CMP [EBP+FFFFFB94],+00
FACDF371 JZ FACDF387 //不在放行和拦截列表中
FACDF373 CMP [EBP+FFFFFB94],+01
FACDF37A JZ FACDF3A3 //在放行列表中
FACDF37C CMP [EBP+FFFFFB94],+02
FACDF383 JZ FACDF39D //在拦截列表中
FACDF385 JMP FACDF3AA
FACDF387 AND [EBP-2C],+00 //标志:拦截
FACDF38B MOV [EBP-28],01 //询问标志置位
FACDF392 MOV EAX,[EBP+FFFFFBAC]
FACDF398 MOV [EBP-1C],EAX //保存calc进程PID
FACDF39B JMP FACDF3AA
FACDF39D AND [EBP-2C],00 //标志:拦截
FACDF3A1 JMP FACDF3AA
FACDF3A3 MOV [EBP-2C],01 //标志:放行
FACDF3AA JMP FACDF3B3
FACDF3AC MOV [EBP-2C],01
FACDF3B3 OR [EBP-04],-01
FACDF3B7 JMP FACDF3C4
FACDF3B9 XOR EAX,EAX
FACDF3BB INC EAX
FACDF3BC RET
FACDF3BD MOV ESP,[EBP-18]
FACDF3C0 OR [EBP-04],-01
FACDF3C4 CMP [EBP-20],+00
FACDF3C8 JZ FACDF3D7 //calc进程的PEPROCESS指针如果为空
FACDF3CA MOV ECX,[EBP-20]
FACDF3CD CALL ObfDereferenceObject //释放对象
FACDF3D3 AND [EBP-20],+00
FACDF3D7 CMP [EBP-28],+00
FACDF3DB JZ FACDF3F3
FACDF3DD PUSH +00
FACDF3DF LEA EAX,[EBP+FFFFFDC0]
FACDF3E5 PUSH EAX
FACDF3E6 PUSH [EBP-1C] //calc 进程 PID
FACDF3E9 PUSH +04
FACDF3EB CALL FACDDF84 //向R3传递消息,询问“放行”或“禁止”
FACDF3F0 MOV [EBP-2C],EAX
FACDF3F3 CMP [EBP-2C],+00
FACDF3F7 JZ FACDF3FD
FACDF3F9 XOR EAX.EAX //放行返回0
FACDF3FB JMP FACDF402
FACDF3FD MOV EAX,C0000001 //需要拦截,返回负值
FACDF402 MOV ECX,[EBP-10]
FACDF405 MOV FS:[0],ECX
FACDF40C MOV ECX,[EBP-34]
FACDF40F CALL FACE29CE
FACDF414 POP EDI
FACDF415 POP ESI
FACDF416 POP EBX
FACDF417 LEAVE
FACDF418 RET 0010
本例中当前进程是指注入器进程。从注释中可以整理出该函数的基本逻辑:
A、 如果当前进程是保险箱进程则放行。
B、 如果当前进程是保险箱保护对象则放行。
C、 如果当前进程打开的进程是保险箱保护对象,则检查当前进程文件是否在保险
箱设置的放行或拦截列表中:如在放行列表中则放行,如在拦截列表中则拦截,如
不在这两个表中则向R3传递询问消息,由用户手动选择放行或拦截。
当跟踪代码到FACDF371处,可以知道注入器进程并未在拦截或放行列表中,进
而FACDF3EB处的向R3发送询问消息的函数得以执行,桌面弹出选择对话框,当用户
手动选择“禁止”后,会导致代理服务FAB6D6A7处原始系统服务例程无法得到调用,
进而注入失败,达到保护目的。
四、总结
对于被保护进程的恶意控制总要调用到相关的系统服务,这些系统服务例程被重新
设计成代理服务,并以一张代理服务表的形式通过新的调度函数(见F997C811)完成
索引,供系统调用。可见,保险箱架构的枢纽正是这个位于系统内核KiFastCallEntry
函数内hook代码中的调度函数。而代理服务的本质则是通过入口、出口参数的检查完
成对进程破坏行为的过滤。
究竟有多少代理服务被创建呢,看看IDA加载的hookport.sys中代理服务表建立函
数sub_1832c就知道了,此处不再列举。同样地,打开 safeboxkrnl.sys 的函数
sub_15bca,我们可以看到有多少代理服务调用过的入口参数过滤函数被创建。
赞赏
- 360保险箱进程保护分析(续) 9396
- 360保险箱进程保护分析 23859
- 求职 3636
- [原创]360保险箱反注入分析 24269
- [推荐]找工作。。。 3981