进程与线程(八)进程保护(1) && 驱动逆向初步

INIT:00010D85                 public start
INIT:00010D85 start           proc near
INIT:00010D85                 mov     edi, edi
INIT:00010D87                 push    ebp
INIT:00010D88                 mov     ebp, esp
……………………略去
INIT:00010DC1                 mov     dword_10C90, eax
INIT:00010DC6                 pop     ebp
INIT:00010DC7                 jmp     DriverEntry ; 一般最后一个Jmp就是跳到DriverEntry
INIT:00010DC7 start           endp

IDA可以帮我们做很多事,很多东西不用我们自己去猜,一看就明白的东西我就略过了

.text:0001088E ; int __stdcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING pRegistryPath)
.text:0001088E DriverEntry     proc near               ; CODE XREF: start+42 j
.text:0001088E
.text:0001088E DeviceObject    = dword ptr -4
.text:0001088E DriverObject    = dword ptr  8
.text:0001088E pRegistryPath   = dword ptr  0Ch
.text:0001088E
.text:0001088E                 mov     edi, edi
.text:00010890                 push    ebp
.text:00010891                 mov     ebp, esp
………………………………………………………………
;略掉部分创建设备的代码
.text:000108E2 ; ---------------------------------------------------------------------------
.text:000108E2
.text:000108E2 loc_108E2:                              ; CODE XREF: DriverEntry+45 j
.text:000108E2                 mov     eax, offset DispatchCreateClose ;接下来要自己照着DriverObject的结构算一下,算出来各个派遣函数指向哪,当然在本程序中没什么用
.text:000108E7                 mov     [esi+40h], eax  ; IRP_MJ_CLOSE  
.text:000108EA                 mov     [esi+38h], eax  ; IRP_MJ_CREATE
.text:000108ED                 mov     dword ptr [esi+70h], offset DriverIOCtrl ; IRP_MJ_DEVICE_CONTROL
.text:000108F4                 mov     dword ptr [esi+34h], offset DriverUnload
.text:000108FB                 call    GetProcessNameOffset  ;从eprocess中得到文件名偏移
.text:00010900                 mov     uNameOffset, eax
.text:00010905                 call    FindPspTerminateThreadByPointer ;从PsTerminateSystemThread搜索PspTerminateThreadByPointer
.text:0001090A                 cmp     eax, ebx
.text:0001090C                 mov     PspTerminateThreadByPointer, eax
.text:00010911                 jz      short loc_10933
.text:00010913                 call    FindPspExitThread ; 跟上面那个差不多,懒得逆向了PspTerminateThreadByPointer中搜索PspExitThread
.text:00010918                 cmp     eax, ebx
.text:0001091A                 mov     PspExitThread, eax
.text:0001091F                 jz      short loc_10933
.text:00010921                 call    InlineHookPspExitThread  ;这是关键,一会儿会跟进
.text:00010926                 push    ebx             ; State
.text:00010927                 push    ebx             ; Type
.text:00010928                 push    offset Event    ; Event
.text:0001092D                 call    ds:KeInitializeEvent  ;创建事件,刚逆的时候还看不出来这是用来干什么的,后面会知道
………………略去
.text:00010939 DriverEntry     endp


InlineHookPspExitThread  如果你自己跟进去是非常郁闷的,因为它会显示成
mov     ax, word ptr unk_10CB0
mov     [edi+4], ax
mov     edi, dword_10CA4
mov     eax, dword_10C98
mov     [edi], eax
mov     ax, word ptr unk_10C9C
十几行诸如此类的代码,搞得我郁闷了很久,也不太确定这就是Inline, F5也毫无结果,只是知道push offset ff 8b,
查了查code table 发现c3是retn,于是想起retn返回栈顶的地址,Push xxxxxxxx再retn就是相当于jmp xxxxxxxx
再后来想到程序还没过滤NotePad呢 参考了以下字符串发现NotePad交叉参考为空,上下文又有一堆无意义的数字未被引用
于是恍然大悟这根本就是代码,不是数据,于是从.text:000105B4 到.text:00010677全部转换成代码,哈 豁然开朗

.text:000105B4                 db 6 dup(0CCh)
.text:000105BA ; ---------------------------------------------------------------------------
.text:000105BA
.text:000105BA OriginPspExitThread:                    ; CODE XREF: .text:0001066C p
.text:000105BA                                         ; DATA XREF: InlineHookPspExitThread+81 o
.text:000105BA                 mov     edi, edi
.text:000105BA ; ---------------------------------------------------------------------------
.text:000105BC aRrrrnotepad_exe db '烫烫烫烫烫烫悙悙notepad.exe',0
.text:000105D8 aNotepad_exe    db 'notepad.exe',0      ; DATA XREF: .text:00010649 o
.text:000105E4                 db 6 dup(0CCh)
.text:000105EA ; ---------------------------------------------------------------------------
.text:000105EA
.text:000105EA loc_105EA:                              ; DATA XREF: InlineHookPspExitThread+2A o
.text:000105EA                 mov     edi, edi
.text:000105EC                 push    ebp
.text:000105ED                 mov     ebp, esp    ;看到这个心里就有底了,标准的函数头
…………………………………………………………………………略去

上面的转换还是有点问题,别着急,一会儿弄
再看刚才的代码,这回就很清楚了

; void __cdecl InlineHookPspExitThread()
InlineHookPspExitThread proc near
mov     edi, edi
push    esi
push    edi
mov     edi, PspExitThread
mov     eax, [edi]
mov     OriginCode_1_, eax ; 保存10字节
mov     eax, [edi+4]
mov     OriginCode_2_, eax
mov     ax, [edi+8]
mov     orgincode_3_, ax
mov     byte ptr PushMyAddrCode, 68h
mov     edi, offset MyPspExitThread ; hook函数地址
mov     PushMyAddrCode+1, edi ; ...
mov     RETNcode, 0C3h
mov     Nopx4Code, 90909090h
mov     byte ptr PushPspAdd10, 68h
mov     edi, PspExitThread
add     edi, 0Ah
mov     PushPspAdd10+1, edi ; push &(PspExitThread + 0Ah)
mov     RETNcode1, 0C3h
mov     esi, offset SpinLock
mov     ecx, esi        ; SpinLock
call    ds:KfAcquireSpinLock
mov     byte_10CB8, al
mov     eax, cr0
and     eax, 0FFFEFFFFh
mov     cr0, eax
cli
mov     edi, offset OriginPspExitThread
mov     eax, OriginCode_1_
mov     [edi], eax
mov     eax, OriginCode_2_
mov     [edi+4], eax
mov     ax, orgincode_3_
mov     [edi+8], ax
add     edi, 0Ah
mov     eax, PushPspAdd10
mov     [edi], eax      ; 写入原始10字节 然后Pushpsp+10
mov     ax, word ptr RETN_0
mov     [edi+4], ax
mov     edi, PspExitThread
mov     eax, PushMyAddrCode
mov     [edi], eax
mov     ax, word ptr rETN_0
mov     [edi+4], ax
mov     eax, Nopx4Code  ; 剩余字节nop掉
mov     [edi+6], eax
sti
mov     eax, cr0
or      eax, 10000h
mov     cr0, eax
mov     dl, byte_10CB8
pop     edi
mov     ecx, esi
pop     esi
jmp     ds:KfReleaseSpinLock
InlineHookPspExitThread endp

下面看原始那段转换的代码

text:000105BA OriginPspExitThread:                    ; CODE XREF: .text:0001066C p
.text:000105BA                                         ; DATA XREF: InlineHookPspExitThread+81 o
.text:000105BA                 mov     edi, edi
.text:000105BA ; ---------------------------------------------------------------------------
.text:000105BC                 db 0CCh
.text:000105BD                 db 0CCh ; ?
.text:000105BE                 db 0CCh ; ?
.text:000105BF                 db 0CCh ; ?
.text:000105C0                 db 0CCh ; ?
.text:000105C1                 db 0CCh ; ?
.text:000105C2                 db 0CCh ; ?            ; 原始十字节 push xxxxxxxx retn 0
.text:000105C3                 db 0CCh ; ?            ; 。
.text:000105C4                 db 0CCh ; ?
.text:000105C5                 db 0CCh ; ?
.text:000105C6                 db 0CCh ; ?
.text:000105C7                 db 0CCh ; ?
.text:000105C8                 db  90h ; ?
.text:000105C9                 db  90h ; ?
.text:000105CA                 db  90h ; ?
.text:000105CB                 db  90h ; ?
.text:000105CC NotePad         db  6Eh ; n             ; DATA XREF: .text:00010638 o
.text:000105CD                 db  6Fh ; o
.text:000105CE                 db  74h ; t
.text:000105CF                 db  65h ; e
.text:000105D0                 db  70h ; p
.text:000105D1                 db  61h ; a
.text:000105D2                 db  64h ; d
.text:000105D3                 db  2Eh ; .
.text:000105D4                 db  65h ; e
.text:000105D5                 db  78h ; x
.text:000105D6                 db  65h ; e
.text:000105D7                 db    0
.text:000105D8 aNotepad_exe    db 'notepad.exe',0      ; DATA XREF: .text:00010649 o
.text:000105E4                 db 0CCh
.text:000105E5                 db 0CCh ; ?
.text:000105E6                 db 0CCh ; ?
.text:000105E7                 db 0CCh ; ?
.text:000105E8                 db 0CCh ; ?
.text:000105E9                 db 0CCh ; ?
.text:000105EA ; ---------------------------------------------------------------------------
.text:000105EA
.text:000105EA MyPspExitThread:                        ; DATA XREF: InlineHookPspExitThread+2A o
.text:000105EA                 mov     edi, edi
.text:000105EC                 push    ebp
.text:000105ED                 mov     ebp, esp
.text:000105EF                 push    ebx
.text:000105F0                 push    esi
.text:000105F1                 push    edi
.text:000105F2                 push    10h
.text:000105F4                 call    ds:IoGetCurrentProcess
.text:000105FA                 add     eax, uNameOffset
.text:00010600                 mov     esi, ds:strncpy
.text:00010606                 push    eax
.text:00010607                 mov     edi, offset CurrentEXEname
.text:0001060C                 push    edi
.text:0001060D                 call    esi ; strncpy   ; 当前进程名
.text:0001060F                 add     esp, 0Ch
.text:00010612                 push    10h
.text:00010614                 call    KeGetCurrentThread
.text:00010619                 push    eax
.text:0001061A                 call    ds:IoThreadToProcess
.text:00010620                 add     eax, uNameOffset
.text:00010626                 mov     ebx, 10CF4h
.text:0001062B                 push    eax
.text:0001062C                 push    ebx
.text:0001062D                 call    esi ; strncpy
.text:0001062F                 mov     esi, ds:_strnicmp ; 比较名字
.text:00010635                 push    0Ch
.text:00010637                 push    edi
.text:00010638                 push    offset NotePad
.text:0001063D                 call    esi ; _strnicmp
.text:0001063F                 add     esp, 18h
.text:00010642                 test    eax, eax
.text:00010644                 jz      short loc_10657
.text:00010646                 push    0Ch
.text:00010648                 push    ebx
.text:00010649                 push    offset aNotepad_exe ; "notepad.exe"
.text:0001064E                 call    esi ; _strnicmp
.text:00010650                 add     esp, 0Ch
.text:00010653                 test    eax, eax
.text:00010655                 jnz     short loc_10669
.text:00010657
.text:00010657 loc_10657:                              ; CODE XREF: .text:00010644 j
.text:00010657                 xor     eax, eax        ; 如果匹配 那么就等待object
.text:00010659                 push    eax
.text:0001065A                 push    1
.text:0001065C                 push    eax
.text:0001065D                 push    eax
.text:0001065E                 push    offset Event
.text:0001065E ; ---------------------------------------------------------------------------
.text:00010663                 db 0FFh
.text:00010664                 db 15h
.text:00010665                 dd offset KeWaitForSingleObject
.text:00010669 ; ---------------------------------------------------------------------------
.text:00010669
.text:00010669 loc_10669:                              ; CODE XREF: .text:00010655 j
.text:00010669                 push    dword ptr [ebp+8]
.text:0001066C                 call    OriginPspExitThread

也就是防杀,进程保护其实没什么意思,对于病毒,与其防止别人杀你进程,倒不如在R3下迅速处理完自己的工作然后撤退,没理由让exe长驻。盗号木马的话倒是要长期监视,但也没必要保护进程。要保护进程的大多是安全产品,也没必要做的太底层,不稳定了就得不偿失。防住R3层面的就可以了,然后再保护住自己窗口,句柄,最最重要的就是截住加载驱动的接口,如果用户愿意让驱动加载那出什么事就不怪你了。
大概说下结束进程的流程,结束进程似乎没有创建进程那么繁琐。
R3:
TerminateProcess→NtTerminateProcess→sysenter
R0:
ZwTerminateProcess→SSDT→NtTerminateProcess→PspTerminateThreadByPointer→KeInitializeApc→PspExitThread
大概是这样,古老的方法也挺多,R0下SSDT Hook NtOpenProcess NtTerminateProcess;Hook ObReferenceObjectByHandle;Hook PspTerminateThreadByPointer,Hook Ke(i)InitializeApc先进的可能也有,我还没来得及逆…
Hook  PspExitThread的不多,原因自然是太低层太不稳定,而且由于是以APC的形式插入线程,Hook之后也不是很方便。花了点时间逆了 diyhack的进程挑战赛的驱动,(一年以前的东西了。。不过那会儿本小菜正在高三的水深火热之中,毛都不懂),这个驱动就是Hook  PspExitThread,其实没什么东西,文件也小到2.5k。功能就是防止结束notepad,首先扔到IDA里,第一次逆向驱动,所以就多逆了很多,把整体驱动框架都逆向了出来,以后只要逆向自己感兴趣的部分就好了,顺便记录下第一次逆向驱动的全过程。
IDA加载后找到函数参考的start函数就是程序开始的位置了


为什么比较了两次文件名?分别用了KeGetCurrentThread  IoGetCurrentProcess ?这么做是为了防止别人DKOM 把线程所属指向别的进程然后结束掉
到此也就大概明白了,其实是在PsExitThread中无限等待事件触发,只到UnHook时触发才恢复。

IDA很方便,但是静态分析弊端也很大,但是在动态分析没效果的情况下就需要有一点耐性去在大脑里模拟程序的运行了。

其实这种挑战挺有意思的,算是锻炼思维,无聊的解决方法就很多,有点意思的算是MJ说的搜索data里的event然后唤醒线程
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值