破解DNF的驱动保护实现不掉线(转)
. A% o3 _3 G, Y7 e& ^保护得比较没有意思,强度也不高.可能隐藏性稍好一些.
! K. g% ]5 O5 ?; v6 g用IDA反汇编TesSafe.sys可以看到:
' `. t6 y# X" P2 P这个驱动一加载,ExAllocPoolWithTag分配了一块内存,然后将一个函数写进这块内存,接着做好保护,然后PsCreateSystemThread()创建的线程调用ZwUnloadDriver将驱动卸载。虽
/ C* P' f/ B$ N& x7 U2 f5 n然驱动被卸载了,但是ExAllocPoolWithTag分配的内存仍然在起作用。
) _5 l6 e+ ^ Q* f1 s具体来看它如何进行保护:
# F8 z/ C4 f$ r在一个函数里,有这么些代码: 5 {; @( k" B% _; d
TesSafe.sys:
* T$ P1 G5 X% l5 K3 H.text:00011356 mov edi, edi , C# ^: a- [) m, q4 J% d' ]; u
.text:00011358 push ebp " J- ~4 T; c# S+ m0 y( X; `
.text:00011359 mov ebp, esp 7 b6 j' Y5 ]- J$ p" z
.text:0001135B sub esp, 5Ch
, W: T4 I4 [! m" `.text:0001135E mov eax, BugCheckParameter2 # L, v3 `: V7 F* }
.text:00011363 push ebx5 _8 J* ^4 F8 l9 [4 Q
.text:00011364 push esi
! I) Z/ _) V- j" i, r: V& J4 m.text:00011365 push edi * Y! u% q* ~6 m6 U$ M' H
.text:00011366 push 0Bh
0 Q0 d9 z$ N0 x/ |3 @9 n. X: n% t.text:00011368 pop ecx
B V6 \( ^! }% r$ F.text:00011369 mov [ebp+var_4], eax 4 d6 \6 a4 V( E( }
.text:0001136C xor eax, eax : H+ F2 x4 |' {6 I+ p. u
.text:0001136E mov esi, offset aObopenobjectby
9 J; b E- @- ~) q# }"ObOpenObjectByPointer"
; g0 E. T% J- r.text:00011373 lea edi, [ebp+SourceString]
( L) K1 D9 c5 k.text:00011376 rep movsd
' @5 y/ H; _5 r. L: }, B.text:00011378 xor ebx, ebx / B2 O$ {% _1 x# i' B
mov [ebp+SystemRoutineName.Length]
0 W3 H( o; s0 \8 b.text:0001137E lea edi,
w# C* Q6 O0 W W/ w {[ebp+SystemRoutineName.MaximumLength] m% g9 B) i, z& X; q* C+ i
.text:00011381 stosd $ f2 D @: ]7 v- a
.text:00011382 stosw
3 {" @5 f& A3 H# S.text:00011384 push 7
3 I& x8 D1 c, {! x7 ].text:00011386 pop ecx _* f1 [' M4 D( O, L0 x" ?7 l
.text:00011387 mov esi, offset aNtopenprocess ; 3 n% m+ f) I' d% v3 ?3 I2 `
"NtOpenProcess"
5 F" q8 Y6 U7 A9 s.text:0001138C lea edi, [ebp+var_20] 8 B$ f; F( k$ B: o' @4 q- }
.text:0001138F rep movsd 4 s9 d- G. A k% C
.text:00011391 mov esi, ds:RtlInitUnicodeString : C: u. x0 W! ~! c: w p" R/ A7 B
.text:00011397 xor eax, eax
3 k+ L3 _9 T& P& L- F( L.text:00011399 mov [ebp+DestinationString.Length], " ^1 F& C) b5 [. c/ X
.text:0001139D lea edi, ( I/ y7 _6 t6 ?' k. i
[ebp+DestinationString.MaximumLength] )
+ y: I( @' Y. U# N# f3 D" A) u.text:000113A0 stosd 5 Q8 f6 K: f* g& N- [9 ]0 X- b
.text:000113A1 stosw ' }) |' I3 K! z
.text:000113A3 lea eax, [ebp+SourceString] - h( E0 K3 f+ g% j1 _
.text:000113A6 push eax ; SourceString
D4 o4 o) K. P( v+ j.text:000113A7 lea eax, [ebp+SystemRoutineName] # l2 i5 c4 }- D( X) K+ Y
.text:000113AA push eax ; DestinationString
- f5 C1 ?6 p, ^9 H$ X' V& s.text:000113AB call esi ; RtlInitUnicodeString 3 B% G+ i% ]: C$ G" ^ e$ {% i
.text:000113AD mov edi, ds:MmGetSystemRoutineAddress
9 o: Y8 r* ?2 ^) v.text:000113B3 lea eax, [ebp+SystemRoutineName]
; ~; {1 a+ b/ a+ v.text:000113B6 push eax ; SystemRoutineName
7 ^2 |. {( _7 k; K* N- }0 p.text:000113B7 call edi ; MmGetSystemRoutineAddress ) I7 u8 z0 {% t4 y
.text:000113B9 test eax, eax 9 o) @9 L1 ^5 o( T
.text:000113BB mov dword_132A0, eax
6 U I! c( K9 j( ~3 ]* D.text:000113C0 jz short loc_1142D
/ b7 |% \$ x J1 x.text:000113C2 lea eax, [ebp+var_20] 2 W* l$ I" P$ _8 H
.text:000113C5 push eax ; SourceString
* W" O/ p3 G* o% u v' X$ e1 N% b.text:000113C6 lea eax, [ebp+DestinationString]
6 E' m p; {: K' l8 x+ D/ c8 @, l.text:000113C9 push eax ; DestinationString - V( q; l4 G4 x" d, h
.text:000113CA call esi ; RtlInitUnicodeString
# z* ]. o- d! B& ^1 _.text:000113CC lea eax, [ebp+DestinationString] : e- E; ^# d) a
.text:000113CF push eax ; SystemRoutineName
~: L1 i( [7 |8 e. P.text:000113D0 call edi ; MmGetSystemRoutineAddress
" h7 v3 x( I b.text:000113D2 mov ecx, eax ) v0 {6 V) ^3 i" z. h) ~
.text:000113D4 test ecx, ecx
; v- V! S3 _- Y3 P.text:000113D6 mov dword_132A8, ecx
- {- q* p% w* ^: x8 i.text:000113DC jz short loc_1142D + H/ o7 ]) U3 Z- y3 G* G( j
.text:000113DE cmp dword_13050,
& Z4 U0 o# W; B.text:000113E5 jnz short loc_11437 7 K" o M( w/ P" G3 X3 `
.text:000113E7 mov al, [ecx] ! [: c( Z) C( p' w. U" d6 ^4 ^
.text:000113E9 cmp al, 0C2h // 这是RET返回指令的机器码" T, j% o6 k. T! c' a6 _! ?+ |
.text:000113EB jz short loc_1142D ' @0 G: p- I9 ]; T: p/ D1 _9 G
.text:000113ED mov esi, 100h '
) i/ B2 k% Z9 A! P.text:000113F2
7 P1 e4 S& d( ].text:000113F2 loc_113F2: ; CODE XREF:
! r. R, {+ }. F; X$ |* l7 Hsub_11356+BDj" d! B% g1 n" Q7 c1 e0 K' M
.text:000113F2 cmp ebx, esi
. t" K. y" {0 ^6 o2 e4 z$ r.text:000113F4 jnb short loc_11424) ]. }5 ^: h/ h
.text:000113F6 cmp al, 0E8h // JMP 机器码。
$ H/ m8 F, n( [" F w.text:000113F8 jz short loc_11417 u
7 |7 z) D- o3 u) \( z.text:000113FA call sub_11DA4
% r3 p8 ?8 t% E+ H.text:000113FF mov ecx, dword_132A8
P$ E3 s2 j% h0 |' A2 d.text:00011405 add ecx, eax 3 L0 u* U6 \; {/ {+ N# D
.text:00011407 add ebx, eax 3 ?( h ^8 [! `* Z% u0 p7 v9 V" P
.text:00011409 mov dword_132A8, ecx 4 q; ^) b2 k$ V; x
.text:0001140F mov al, [ecx]
8 r1 w5 H5 ^5 h" @$ b7 C.text:00011411 cmp al, 0C2h $ Q# M& R* U1 k. \5 j X/ |
.text:00011413 jnz short loc_113F2 ! r6 b& M6 F( W1 T8 B! x7 Y
.text:00011415 jmp short loc_114242 O% C- O/ \ k8 [$ E
先是得到了ObOpenObjectByPointer的地址,然后在NtOpenProcess中搜索0xe8 ,也就是跳转指令,直到遇见RET为止。
# P/ E* I2 X6 G0 Q$ L4 j一但得到0xe8,比较后面的四个字节,如果转换后为ObOpenObjectByPointer的地址,就把这个地址用自己*****函数的地址转换后替换掉,达到保护自己的目的。
$ Y! \3 c! a; m f& p, j: e用WinDbg看了看,果然在我的机器上:0x80570e41这个在NtOpenProcess中的区域被TesSafe.sys修改,原来这里是:80570e41 e87c8dffff call nt!ObOpenObjectByPointer (80569bc2)
) r0 x+ o/ c! T9 c J# S系统通过ObOpenObjectByPointer来通过EPROCESS得到Handle返回给调用者。TENCENT在这里下了一个跳转:(TesSafe.sys加载后。)80570e41 e826542a78 call f881626c : I( L4 A8 `: D
很明显,系统执行到这里就会调用0x6881626c的函数,也就是TesSafe.sys的! E% s! o6 k0 y0 H+ \
ObOpenObjectByPointer*****函数。这样,Client.exe就会在这里被过滤掉,从而让R3程序无法得到QQT的句柄,从而保护进程。% P9 O5 ]& l- \$ T: V6 @
5 ?2 A5 q& Q% T& O' V" O! I+ G, d6 j6 l+ Z& i2 H3 D' v1 h! ]
本人转来的,希望对高手有用,卜懂的也来顶下,卜要让贴子沉下去,沉了高手见卜到了,我们就没挂用了