#include "ntddk.h" YLzx<~E4a
#define ThreadLength 0x190 rcC<Zat,|
#define ProcessLength 0x184 O4V.11FnW
#define DeviceLink L"\\Device\\DNFCracker" yU-e3O7L
#define SymbolicLink L"\\DosDevices\\DNFCracker"
HTS%^<u
#define IOCTL_RESTORE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, 0x886, METHOD_BUFFERED, FILE_ANY_ACCESS) j;-1J
_e5
:lPb.UCY
zU gE~[1]
#define BYTE unsigned char 8L:ji,"
#define FAILED_TO_OBTAIN_FUNCTION_ADDRESSES -1 4;?0lvDD
typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY { b2OQtSr a
HANDLE Section; PE3vQH=t~
PVOID MappedBase; %&w3;d;c
PVOID Base; O Hb[qX\
ULONG Size; Rld!,t
ULONG Flags; [
f1 (`<
USHORT LoadOrderIndex; `Nb[G)Xh
USHORT InitOrderIndex;
[1]+#lM
USHORT LoadCount; 4{rZppm
USHORT PathLength; 7BK0}sxO
CHAR ImageName[256]; ZjQ |
Wx
} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY; h?BFvbAt
%S*{9
hm/
|[1]Lf"6^@yh
typedef struct _SYSTEM_MODULE_INFORMATION { :U3kW8;UMP
ULONG Count; c
#Sa]n
SYSTEM_MODULE_INFORMATION_ENTRY Module[1]; jV>raCK_
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; w$z}r
Po__-xN>Q
zr+zhpp
NTSTATUS ZwQuerySystemInformation(ULONG systemInformationClass, s:/8[[1](A
PVOID systemInformation, s.N7qO^:E
ULONG systemInformationLength, C&*oI =6
PULONG returnLength); 2ORNi,_I
x(etb<!jd
?D coX+8 7
UCHAR* PsGetProcessImageFileName(IN PEPROCESS Process ); 4C<j dv_J
~$:|VHl
P&9Gga^I
typedef NTSTATUS (* NTOPENTHREAD)( Co (.:z
~
OUT PHANDLE ThreadHandle, HJX?T9;w
IN ACCESS_MASK DesiredAccess,
I[1]r`eL
IN POBJECT_ATTRIBUTES ObjectAttributes, lE;Ewg
IN OPTIONAL PCLIENT_ID ClientId -8eoNzut
); e,F1Xi #d
typedef NTSTATUS (* NTOPENPROCESS)( [1]ORyE`h
OUT PHANDLE ProcessHandle, S{PJUA u[1]
IN ACCESS_MASK DesiredAccess, C[1]8[&S&<_<
IN POBJECT_ATTRIBUTES ObjectAttributes, ^
B(V4-|
IN PCLIENT_ID ClientId G
e-CY
); Rv#]I#O
typedef struct _SERVICE_DESCRIPTOR_TABLE c_-drS
{ NLUT#!Gr
PVOID ServiceTableBase; [1];i Fz?d3;
PULONG ServiceCounterTableBase; m@"QDMHk.
ULONG NumberOfService; W=#:.Xj[
ULONG ParamTableBase; 19O,a#{KHf
} B8B; y^b>i
SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE; :YXX
8|[1]>
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable; u+'tfFds&
iVB86XZ`
`S6x<J&T\/
#define NAKED _declspec(naked) ^W c@oa
`
|K.mP4CKY
2 $?C7(kW
#pragma pack(1) fb{`` ,nO
typedef struct _TOP5CODE {B[=?6tQ
{ =bHD#o|R
UCHAR instruction; kKA[1]P"'v
ULONG address; |2[1]abmuR0
}TOP5CODE,*PTOP5CODE; '7+4` E
#pragma pack( ) \~fONB Y
i(iX
D
typedef struct _ServiceDescriptorTable { BaSZ71>9]r
PVOID ServiceTableBase; $4/yZaVb
PVOID ServiceCounterTable; S,Xnzrz
unsigned int NumberOfServices; %d?cP}V?
PVOID ParamTableBase; 89o/F+_b
}*PServiceDescriptorTable; Kac' ;1
![1]"\80LP
ULONG MyGetFunAddress( IN PCWSTR FunctionName) UPG9)a?F
{ >[_f 3;P
UNICODE_STRING UniCodeFunctionName; n p\[1]TlUc
RtlInitUnicodeString( &UniCodeFunctionName, FunctionName ); jpO7'ivG
return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName ); ZuS0DPS`L
} !*oi!ysU;O
g7O qX \
ULONG myGetCurrentAddress(IN ULONG index) mg*qiScfW
{ xHz[t6;4;
ULONG SSDT_Cur_Addr; (]Y 5eM
__asm (Q.waI
{ STxKE %l
push ebx >g+?Oebgw
push eax D"ND+*Q [X
mov ebx,KeServiceDescriptorTable HN&Z2v
mov ebx,[ebx] ~%SH3$
mov eax,index XgL
L!5`
shl eax,2 ; 9# Z@]p
add ebx,eax Axe8n1*y
mov ebx,[ebx] iy14mh\ ~
mov SSDT_Cur_Addr,ebx X&0 uI*r
pop eax dv.(7Y7.x
pop ebx {a4z2"\A
} i1>- QDYnJ
($}`R xj1@
return SSDT_Cur_Addr; \>7^f 3m
} F@<CsgKB-
tb$LriN
VOID WPOFF() m"o ;L3
{ <K8?\n^i~c
__asm D?0zhU
{ <j5NFJ9
cli /6h(6 *JI
mov eax,cr0 -*m+(
7G\
and eax,not 10000h ^",ACWF4Sk
mov cr0,eax e{v=MxO=S
} cdG |m[
}
$.GOZqMs
* ?H.oP[1]
VOID WPON() e`v`XSA[p
{ `zE
}1M%y
__asm ^4`Px/&
{ v
Ms$ceq
mov eax,cr0 zA!0l*H
or eax,10000h
'
^F?Gc
mov cr0,eax O=dJi9;`#_
sti f}@jFhr'<
} zKsz*xv6b
} H_ez'yy
}[1]oKG}wgY
!grVR157P
NTSTATUS MyEnumKernelModule(IN CHAR* str,OUT ULONG *moduleadd,OUT ULONG *modulesie) ?%T[^D&9$,
{ C{q:_M;
NTSTATUS status = STATUS_SUCCESS; T1r3=Y[1]4
ULONG n = 0; ?"KC-u|
ULONG i = 0; W[1](?Uu
@^
PSYSTEM_MODULE_INFORMATION_ENTRY module = NULL; X[1]K5<Tg
PVOID pbuftmp = NULL; 1 `7<2w
ANSI_STRING ModuleName1,ModuleName2; $\"9<o|h
BOOLEAN tlgstst= FALSE; w?Hem5E
[
*Z`Kc
status = ZwQuerySystemInformation(11, &n, 0, &n);
/2m?15c+
N<L`c/
pbuftmp = ExAllocatePool(NonPagedPool, n); \Fe_rh
p<v.Q
status = ZwQuerySystemInformation(11, pbuftmp, n, NULL); 4W#E`9 6u
#?DjCzz\
module = (PSYSTEM_MODULE_INFORMATION_ENTRY)((PULONG )pbuftmp + 1 ); "aF8[1]l<1xn
"W#t;;9Wz
RtlInitAnsiString(&ModuleName1,str); ]}Ug
S+g>$
// =q"eU=9
n = *((PULONG)pbuftmp ); !4rPv\
for ( i = 0; i < n; i++ ) 4{qB
X?
{ %o}(sSh
S
RtlInitAnsiString(&ModuleName2,(PCSZ)&module.ImageName); b%t+,0s|
if (RtlCompareString(&ModuleName1,&ModuleName2,TRUE) == 0) &l}?v@@+_
{ LjdYsai-
DbgPrint("MyEnumKernelModule:%s:%0X \n",ModuleName2.Buffer,module.Base); ,5|d3d[1]JS
*moduleadd = (ULONG)module.Base; 5v^L9!`@%v
*modulesie = module.Size; &&L"&Rc
tlgstst = TRUE; @1R8 -aa-r
break; QT#6'>&7-b
} <3hA!$[1]o~
} J Lb6C 52
ExFreePool(pbuftmp); >m?_v5K
if (tlgstst == FALSE) 2@vj!U8
{ TD04/ ISHT
return FAILED_TO_OBTAIN_FUNCTION_ADDRESSES; Q1>zg,?r
} _eLVBG35z
return status; M+[1]s
j}
} Xz;b,C&*t
]2+g&ox4'
BOOLEAN MatchByte(BYTE bSrc, BYTE bDest) :G'xi2?bs
{ J-J3=JG
if ( bDest == 'X' || bDest == 'x' ) { U <tc4^
return TRUE; w1B<0'#
else if ( bSrc == 'X' || bSrc == 'x' ) $<e +r$1
return TRUE; BV9*s
else da*9(?!OV
return bSrc == bDest; Rlw?9$/D!Z
} ItK
xQz#i-v?
X}apxSd"
BYTE *FindBytePattern(BYTE *pPattern, size_t length, BYTE *pRangeBegin, BYTE *pRangeEnd) `=!p$hg($
{ L_*L`!vQA"
BYTE *pIter = pRangeBegin; 8Nvr
93T,
BYTE *pPatternIter = NULL; 1hNEkpL^a
BYTE *pMatcher = NULL; v:P!(`sF
EHWv3
sR-
|p'i,.(c_W
if ( NULL == pPattern ) return NULL; luF#OPC
if ( NULL == pRangeBegin ) return NULL; P7 8uq
if ( NULL == pRangeEnd ) return NULL; W}k[slqZA
if ( pRangeEnd - pRangeBegin <= 0 ) return NULL; w?;b7?i
gCwt0
)
o@@w^##
while ( pIter < pRangeEnd ) { 'WnpwY
pPatternIter = pPattern; `g?
8tq
pMatcher = pIter; 1?
]J;9p
while ( MatchByte(*pPatternIter, *pMatcher) ) { 7?]!
Ecr"
pPatternIter++; Ds G !S*
pMatcher++; `NoCH[$!+
} =KW|#]RB^
-s?D:+Te
*U2Ck<"]
if ( pPatternIter - pPattern == length ) zlN+edgY#,
{ t3M0La&
return pIter; I@c0N*[1](
} Cb< ~i
else `o
an,wq+
{ ),z,LU Y
f
pPatternIter = pPattern; hiT9H5 6 >
pIter++; )8
\Z=uC
} N_|YOw6
} .Pqj6Ko9
mfUKHX5
s-y'<(ll
return NULL; a'c
9XG}
} ye9QTK6$,
oM m/?!Dc
#{.pQi})
BYTE *g_pTesSafeAddress = NULL; {"
Y]/6
ULONG g_TesSafeSize = 0; H 7 o$
O
NTSTATUS GetTesSafeAddress(BYTE **ppAddress, ULONG *pSize) P1vF{
e
{ "
>v_uq a
NTSTATUS status = STATUS_UNSUCCESSFUL; a'(lVZA;
if ( g_pTesSafeAddress == NULL ) jnx+wcd
{ uugzIV)
status = MyEnumKernelModule("\\??\\c:\\windows\\system32\\tessafe.sys", &(ULONG)g_pTesSafeAddress, &g_TesSafeSize); -#:Y+"'
if (!NT_SUCCESS(status)) kY0g }o'<
{ %t?(, *;
DbgPrint("TesSafe is not loaded yet\n"); _j|n}7a
return status; 1L(Nfkh
} ?`BED6$`G9
} ;nHo%
`Zt
else )yz9? ?]a
{
^y;OHo
*ppAddress = g_pTesSafeAddress; G$cq
*pSize = g_TesSafeSize; D q_{
?O
} LU 5 `!0m
n=Z[w
5
return STATUS_SUCCESS; Rqd
%#v
} hr 6LB&d_
n?ZH2dI \0
#
uDBF
VOID Hook(); v"?PhO/{=
VOID Unhook(); ]$` s}BN
NTOPENTHREAD OldThread; ,:Ix s^-
NTOPENPROCESS OldProcess; wW)&Px n
ULONG AddrRead, AddrWrite; ,uD*FSp>
ULONG OrgRead[2], OrgWrite[2]; QW"6]
ULONG OrgKdDD[2]; F|3Fv
xA
UCHAR MyThread[ThreadLength], MyProcess[ProcessLength]; 7=ga_2
MZ+IorZl
NTSTATUS My_RecoveryHook_NtReadAndWriteMemory() 4uE5h~0Z
{ xo"4mbTV
BYTE Push1Ch[2] = {0x6a,0x1c}; N?<@o2{
//BYTE PushAdd[5] = {0x68,0x12,0x34,0x56,0x78}; $@f3=NJ4k
BYTE PushAdd_ReadMemory[5] = {0x68,0xd8,0xa4,0x4d,0x80}; an5kR_=
BYTE PushAdd_WriteMemory[5] = {0x68,0xf0,0xa4,0x4d,0x80}; a0j.\g??
KIRQL Irql; _q 9
lr8hx
BYTE *NtReadVirtualMemoryAddress = NULL; /gy:#-2Gy
BYTE *NtWriteVirtualMemoryAddress = NULL; Da[X HUk
g~sNY|%
NtReadVirtualMemoryAddress = (BYTE*)myGetCurrentAddress(0xBA); i&G`ah>
if (NtReadVirtualMemoryAddress == NULL) $0C
/S5b
{ $aI MQ[(
KdPrint(("Failed to get address of NtReadVirtualMemory! \n")); 3 a[(GW _
return FAILED_TO_OBTAIN_FUNCTION_ADDRESSES; -&$%m)wN
} B148wh#r
NtWriteVirtualMemoryAddress = (BYTE*)myGetCurrentAddress(0x115); snNg:
rT L
if (NtWriteVirtualMemoryAddress == NULL) C`<} nx1
{ !! #ale[1]&
KdPrint(("Failed to get address of NtWriteVirtualMemory! \n")); ~:b~f]lO
return FAILED_TO_OBTAIN_FUNCTION_ADDRESSES; 0J[1]-ux"kfI
} @Iatlz*W
%4^/.) Q
iDxg?AV f*
WPOFF(); `?7n
[1],(
Irql=KeRaiseIrqlToDpcLevel(); G7JZP T
RtlCopyMemory(NtReadVirtualMemoryAddress,Push1Ch,2); ebVfny$D
RtlCopyMemory(NtReadVirtualMemoryAddress+2,PushAdd_ReadMemory,5); U}
Fk %Jj
78#ud15Ml
RtlCopyMemory(NtWriteVirtualMemoryAddress,Push1Ch,2); Om{ML,d
RtlCopyMemory(NtWriteVirtualMemoryAddress+2,PushAdd_WriteMemory,5); @V u[Tg}J
KeLowerIrql(Irql); j zp
%.4/j
WPON(); h*%1Jkxu
P=z':4,M}
return STATUS_SUCCESS; v1r
Gq
} M#|xj <p
PEPROCESS processEPROCESS = NULL; AkC\CdmA
ANSI_STRING p_str1,p_str2; dGN*K}5
BYTE *ObOpenObjectByPointerAddress = NULL; Wc[)mYOSuO
BYTE *p_OpenProcess_TpHookAddress = NULL; A":x<9
BYTE *p_OpenThread_TpHookAddress = NULL; ;pq4El_
BYTE *p_OpenProcess_ReturnAddress = NULL; $dVjxo
BYTE *p_OpenThread_ReturnAddress = NULL; C ^'}{K
BYTE *p_MyHookAddress = NULL; " [1]8v
#define DNF_EXE "DNF.exe" BZsxf'eN'
wu3ZS
LY
//NtOpenThread用到的全局变量[为了方便堆栈平衡的处理使用全局变量] w}?
\Q
,
PEPROCESS threadEPROCESS = NULL; //保存访问者的EPROCESS *
{Vyt5
ANSI_STRING t_str1,t_str2; //保存进程名称 $@X,J2&
R8_qZ;t:z
+{
&g|V
////////////////////////////////////////////////////////////////////// $onliW|
// 名称: Nakd_NtOpenThread 6 AY%o nY
// 功能: My_RecoveryHook_NtOpenThread的中继函数 <@P0sd
// 参数: XT\;2etVL
// 返回: uPpP
"
)
////////////////////////////////////////////////////////////////////// 9;jfg|x1[
static NAKED VOID Nakd_NtOpenThread() ^
gy(
~u
{ *
| '
k
//获得调用者的EPROCESS ,b/0_?Q
threadEPROCESS = IoGetCurrentProcess(); t{[1] 'QMX
//将调用者的进程名保存到str1中 /*[a>B4-q
RtlInitAnsiString(&t_str1,(PCSZ)((ULONG)threadEPROCESS+0x174)); q /#O :Q
//将我们要比对的进程名放入str2 Z`[j;=[
RtlInitAnsiString(&t_str2,DNF_EXE); zx^)Qb/EL6
if (RtlCompareString(&t_str1,&t_str2,TRUE) == 0) {\?k9%2V*+
{ g&"Nr aQM9
//说明是DNF进程访问了这里 )]>9\(
__asm #[1]ws6z`mt
{ wM><D?rQ
push dword ptr [ebp-34h] {T$;BoR#O
push dword ptr [ebp-20h] A!NT 2YdHZ
push p_OpenThread_ReturnAddress E3`KO'v%
mov eax,p_OpenThread_TpHookAddress 1~j.jv$
jmp eax NKd):>d%
} -"<eq0
} U5Rzfm4
else ;DGp7f#9
{ DK:d'
zb
__asm =uD2j9!"7
{ i`E]gJ$
push dword ptr [ebp-34h] 2-2
' c?%
push dword ptr [ebp-20h] u6I# D [1]_
push p_OpenThread_ReturnAddress _oR6^#5#
mov eax,ObOpenObjectByPointerAddress (RGl, x:
jmp eax G.L4
l|%W
} NmK%k jCx
} /K'Kx
} #[J..i/h
`lr\V;o!
l@## Ex9
////////////////////////////////////////////////////////////////////// BC&Et62*
// 名称: My_RecoveryHook_NtOpenProcess vw3%u+Z&?
// 功能: 解除游戏保护对NtOpenProcess的HOOK _Tev503
// 参数: N/]TZu~k z
// 返回: 状态 ))u$j4 V
////////////////////////////////////////////////////////////////////// :N(L7&<
NTSTATUS My_RecoveryHook_NtOpenThread() dA )7d77
{ HH8a"Hq)
BYTE *NtOpenThreadAddress = NULL; //NtOpenProcess的地址 1 BVi?vEG
BYTE *p = NULL; //临时 Ws}u4t
TOP5CODE *top5code = NULL; //保存5字节内容 vP? "MG
BYTE JmpAddress[6] = {0xE9,0,0,0,0,0x90}; (eG#JVsm9
BYTE *pHookAddress = NULL; w ~Es,@
// 从805c2724这个位置开始,也就是NtOpenThread + 0x202的位置 Fpl<2eBg4
BYTE bHookPattern[] = { 0x50,0xff,0x75,0xd0,0xff,0x35,'x','x','x','x',0x56,0x8d,0x85,0x4c,0xff,0xff,0xff,0x50,0xff,0x75,0xcc,0xff,0x75,0xe0,0xe8,'x','x','x','x',0x8b,0xf8,0x8d,0x85,0x4c,0xff,0xff,0xff,0x50, }; j =[Td
KIRQL Irql; Ch^Al 2)=
int i = 0; c7'I'~
/tx_I(6F?|
kQwBrb 4
//获取NtOpenProcess的地址 B u*ge~
NtOpenThreadAddress = (BYTE*)MyGetFunAddress(L"NtOpenThread"); !Vv$
if (NtOpenThreadAddress == NULL) E.4`aJ@>d
{ zEpc
JHI%
KdPrint(("NtOpenProcess地址获取失败\n")); 67')n
EQ9
return FAILED_TO_OBTAIN_FUNCTION_ADDRESSES; @va
)j
} YjoN: z`b
//获取ObOpenObjectByPointer的地址 pX*Oc6.0mu
ObOpenObjectByPointerAddress = (BYTE*)MyGetFunAddress(L"ObOpenObjectByPointer"); f [1]LxFF
if (ObOpenObjectByPointerAddress == NULL) +mYD DlvI
{ +^{yJp.H#
KdPrint(("ObOpenObjectByPointer地址获取失败\n")); #p6#,PZ
return FAILED_TO_OBTAIN_FUNCTION_ADDRESSES; tAPqbi$a
} $:t;WXc.<
q_ykB8Ensa
*(ULONG *)(JmpAddress+1)=(ULONG)Nakd_NtOpenThread - (ULONG)p - 5; v](7c2;
S?6 `4&0'
Jx[IHE
//将p指向NtOpenProcess函数开始处 LTm2B_+
p = NtOpenThreadAddress; ~ub Gx
pHookAddress = FindBytePattern( =O<Ul~JRK
bHookPattern, sizeof(bHookPattern), NtOpenThreadAddress, NtOpenThreadAddress + 1024); /q ;MihK
if ( NULL == pHookAddress ) oL2|@WNj,
return STATUS_UNSUCCESSFUL; Sdy\s5
p = pHookAddress + 0x18; 7xb z)FI
f.!)O@HzH
"~jt0pp
//将top5code指向 p 的当前处 \`Db|D?oy
//用以取出 call [地址] 这5字节里面的地址 HcXyU/>D
top5code = (TOP5CODE*)p; KDhr.P.~
p_OpenThread_TpHookAddress = (BYTE*)((ULONG)p+5+top5code->address); s/ib j@h
(f,D$mX
j{?,nJd
Q
//找到我们写入自定义函数的地址 N 3 i ,_
p_MyHookAddress = p-6; K'+GK S7.
[1]#/Y t4n
~[1]@S5*(&8
//保存调用ObOpenObjectByPointer函数以后的返回地址 M;V (Tf
p_OpenThread_ReturnAddress = p+5; US A!N
br*L|s\P\9
]1>U@oK
//将一条JMP Nakd_NtOpenProcess写入到数组中 V[1]'sp6:3*\
*(ULONG *)(JmpAddress+1)=(ULONG)Nakd_NtOpenThread - ((ULONG)p_MyHookAddress+5); *|h-iA+9
cVv+,l4 V0
M)C. bo{p
WPOFF(); //清除CR0 Pf5RlpL:p
//提升IRQL中断级 .<} (J#vC
Irql=KeRaiseIrqlToDpcLevel(); w-*$gk]
//写入 -e_ IDE
RtlCopyMemory(p_MyHookAddress,JmpAddress,sizeof(JmpAddress)); 4 :RL[;
//恢复Irql 5<\&7P3y
KeLowerIrql(Irql); N>!RKf:ir
WPON(); //恢复CR0 4vKp341B
+a_eNl,
[1]Cy-q9uT
m
return STATUS_SUCCESS; ikf!7-,
} :=WiT_M
d%VG@./xq
u~FXO[b
static NAKED VOID Nakd_NtOpenProcess() a]XQM$T$
{ &m2 FEQ
Lj
processEPROCESS = IoGetCurrentProcess(); |:Gz9u+
RtlInitAnsiString(&p_str1,(PCSZ)((ULONG)processEPROCESS+0x174)); +ptVAg+
RtlInitAnsiString(&p_str2,DNF_EXE); l6Wa~ E
if (RtlCompareString(&p_str1,&p_str2,TRUE) == 0) [1]dYV'?<
{ spter35b[
__asm .O! JI"?
{ Z]f_? @0
push dword ptr [ebp-38h] r?mXxid
push dword ptr [ebp-24h] nI4Kuz`dF
push p_OpenProcess_ReturnAddress Y/cnj n
mov eax,p_OpenProcess_TpHookAddress ` b a}
6D
jmp eax >xQgCOi
} B
1dVHz#
} BUT{}2+K
else ~/Gx~P]
{ ^Xv[1]_y+
__asm XF
pII4 5
{ YjaEKM8?*
push dword ptr [ebp-38h] |iN!V3#S
push dword ptr [ebp-24h] b[&A,ZPh$@
push p_OpenProcess_ReturnAddress d%1T v1={
mov eax,ObOpenObjectByPointerAddress `o~ dQb/k+
jmp eax *J^l [1]r"%c
} _<tWy+.[1]
} g'2'K
} #[ZF'
9x
<T]BSQk
?i-1lppI
NTSTATUS My_RecoveryHook_NtOpenProcess() lmmB=F?
{ A4 ;EtW+
F
BYTE *NtOpenProcessAddress = NULL; <?dzfD;
BYTE *p = NULL; +[1]; / ]'
TOP5CODE *top5code = NULL; "},0Cs
BYTE JmpAddress[6] = {0xE9,0,0,0,0,0x90}; 5:3%RTLG
BYTE *pHookAddress = NULL; &?T7|f!y
// 从805c24a2这个位置开始,也就是NtOpenProcess + 0x20c的位置 Fh[1]2[1]$,$ 2
BYTE bHookPattern[] = { 0x50,0xff,0x75,0xcc,0xff, 0x35,'x','x','x','x',0x56,0x8d,0x85,0x48,0xff,0xff,0xff,0x50,0xff,0x75,0xc8,0xff,0x75,0xdc,0xe8,'x','x','x','x',0x8b,0xf8,0x8d,0x85,0x48,0xff,0xff,0xff,0x50 };
g
z{~\0y
KIRQL Irql;
i%~^3?/K
int i; Kob
i!
|%wgux`z
NtOpenProcessAddress = (BYTE*)MyGetFunAddress(L"NtOpenProcess"); +rT[1]%C&ze
if (NtOpenProcessAddress == NULL) )- 2sk@y
{ 4J#F;#iA
KdPrint(("Failed to get address of NtOpenProcess\n")); )SkJgz
vC
return FAILED_TO_OBTAIN_FUNCTION_ADDRESSES; Eqx2.?S
} q_0So[1]}
>[,ywRJ#_}
d! BQ%a
ObOpenObjectByPointerAddress = (BYTE*)MyGetFunAddress(L"ObOpenObjectByPointer");
Vjv~RNGF
if (ObOpenObjectByPointerAddress == NULL) ^
,P# <,D,
{ $0uh8RB
KdPrint(("Failed to get address of ObOpenObjectByPointer\n")); [ " n+2;
return FAILED_TO_OBTAIN_FUNCTION_ADDRESSES; Iq76JJuCb
} &m=G
kK
Z&f@)j
xiWP^dIF
p = NtOpenProcessAddress; {6_M$"e.
pHookAddress = FindBytePattern( F&tU^(7<
bHookPattern, sizeof(bHookPattern), NtOpenProcessAddress, NtOpenProcessAddress + 1024); >9WJa5{
if ( NULL == pHookAddress ) _T96.~Q
return STATUS_UNSUCCESSFUL; u-8b,$@Z>'
p = pHookAddress + 0x18; `Z#0kp
Xk_
?S*Cvr+=4
p)u?x)w=
top5code = (TOP5CODE*)p; t
!=qt*
p_OpenProcess_TpHookAddress = (BYTE*)((ULONG)p+5+top5code->address); C`J>Gm
N$!aP/[1][1]b
p_MyHookAddress = p-6; ; ,vGw <|o
p_OpenProcess_ReturnAddress = p+5; bp[wr
2l4*6rYa(
*(ULONG *)(JmpAddress+1)=(ULONG)Nakd_NtOpenProcess - (ULONG)p_MyHookAddress - 5; ~E8L,h~
W0I)< S
WPOFF(); A2 r\=for
Irql=KeRaiseIrqlToDpcLevel(); f@j)t%mh
RtlCopyMemory(p_MyHookAddress, JmpAddress, sizeof(JmpAddress)); O x),jc[/
KeLowerIrql(Irql); 1_jd1 UT
WPON(); nI es}n:
V0/PjD,jP
return STATUS_SUCCESS; rRQKW_9mB
} 1iJaj
E*Z# fa
9 WO|g[Y3
ULONG uNtSetContextThreadAddress; k d9<&.y{
ULONG uNtGetContextThreadAddress; =j~vL`d2]
ULONG TenNtSetContextThread, (MGYX_rD
TenNtGetContextThread; /wX5>^
static NAKED NTSTATUS Nakd_NtGetThreadContext(HANDLE hThread, PCONTEXT pContext) TY
`t3
{ p9-s'F|@i
__asm P;U(2;9 N
{ *hIjVKTu79
jmp dword ptr[TenNtGetContextThread] ?0x
=ascP
} U}R (
} P[%nD cB
F #)@ c
static NAKED NTSTATUS Nakd_NtSetThreadContext(HANDLE hThread, PCONTEXT pContext) t`")Re_j
{ 1d 1 ~`B
__asm w2) @o >w
{ &&ZX
<wOM
jmp dword ptr[TenNtSetContextThread] F [1]EA t6
} l.xKv$uOGR
} Wi@YJ
$'n?V=4
zG)vmysJf
NTSTATUS MyNtGetThreadContext(HANDLE hThread, PCONTEXT pContext) l?B=5*0
{ OCELG~
const char *pszName = (const char*)PsGetProcessImageFileName(PsGetCurrentProcess()); oFKTBH:[1]I
HANDLE hCallingThread = PsGetCurrentThreadId(); PsM8J
)|6OPR@(#/
"hnvND4=
KdPrint(("[MyNtGetThreadContext] pszName: %s, hThread:%x, hCallingThread: %d\n", pszName)); LKBh{X0%(
if ( _stricmp(pszName, DNF_EXE) ) * !9
=?
{ Nw '$r
NTSTATUS result = Nakd_NtGetThreadContext(hThread, pContext); 0),fY(D2T
// KdPrint(("[MyNtGetThreadContext] result: %d\n", result)); J7HY(7
Nx
return result; Fj46~#ZZ
} m'-QVZ{(M%
return STATUS_SUCCESS; .{-X1tJ7
} ZiPz~G0[^
Dutc[1]#?bT
yxi&80$
NTSTATUS MyNtSetThreadContext(HANDLE hThread, PCONTEXT pContext) CjEzsjqe<I
{ :!^NjO[1]
const char *pszName = (const char*)PsGetProcessImageFileName(PsGetCurrentProcess()); [+L!c}
#
KdPrint(("[MyNtGetThreadContext] pszName: %s, hThread:%x, hCallingThread: %d\n", pszName)); qHv
U4v
% K,cGgp^)
{9[1]* l
if ( _stricmp(pszName, DNF_EXE) ) uw/N`u?
{ ?vFtv}@\
NTSTATUS result = Nakd_NtSetThreadContext(hThread, pContext); ttls
.~DG
// KdPrint(("[MyNtSetThreadContext] result: %d\n", result)); /
N#
=Tol
return result; 9{e/ V)
} yo8mfH_,
if ( pContext->Dr7 == 0x101 ) ]~~G<Yh:=
{ RF ;[:[*W
return Nakd_NtSetThreadContext(hThread, pContext); lEw;X
78?+
} zhbSiw
return STATUS_SUCCESS; ( P=WKZMPN
}
?HAo=[1]t
mnBT?Z/ZjS
U#bm
MH
NTSTATUS My_Recovery_HardwareBreakpoint() 1k^$:'
{ |i~-,:/-Y
KIRQL Irql; <lNNT6[/r
uNtSetContextThreadAddress = (ULONG)KeServiceDescriptorTable->ServiceTableBase+0xD5 * 4; `(gQw~|z
uNtGetContextThreadAddress = (ULONG)KeServiceDescriptorTable->ServiceTableBase+0x55 * 4; f$9|qfW'$
G 9V[1]2(P
TenNtSetContextThread = *(ULONG*)uNtSetContextThreadAddress; X y`2ux+>/
TenNtGetContextThread = *(ULONG*)uNtGetContextThreadAddress; s diWQ
?v
3a BE[
KdPrint(("TenNtSetContextThread:%0X\n",TenNtSetContextThread)); zb4
{nzX=
KdPrint(("TenNtGetContextThread:%0X\n",TenNtGetContextThread)); )_n(u3'
p
|NY.N
KdPrint(("Process:%0X \n",(ULONG)p_MyHookAddress)); /hmDeP o}
KdPrint(("Thread:%0X \n",(ULONG)p_MyHookAddress)); KATf9-
Sz
+ !" Y C
WPOFF(); 3 {hUp81>
Irql=KeRaiseIrqlToDpcLevel(); MxUbx+_N?
^i2>Ax&T
*(ULONG*)uNtGetContextThreadAddress = (ULONG)MyNtGetThreadContext; n qx0#_K-E
*(ULONG*)uNtSetContextThreadAddress = (ULONG)MyNtSetThreadContext; 7=yjd)Iy9m
L+T'TC:
KeLowerIrql(Irql); :SW vH-]
WPON(); oM?^vJ3
<P ?gP1_zi
return STATUS_UNSUCCESSFUL; Y2tBFeWY
}
*JZ9'|v_H
;&f(7 Q+T_
BzH0"xq^
NTSTATUS DispatchIoCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) ?(Tin80=r
{ X[dH*PV
ULONG ioControlCode; R]Z#VnL@qz
ULONG inBufLength, outBufLength; Nu3IYS5&
d0|{/4IWw;
NTSTATUS status = STATUS_SUCCESS; |+JO]J#bc
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
`#85r{c$:
QmGK! H>3
inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; iRcac[uV
outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; xXI WEZA
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; {iq^CH[1]AVK
g`C"t3~%S
switch (ioControlCode)
&U=_:]/
{ p[%~d$J
Uq
default: r8N)]Hs ZH
DbgPrint("Unknown IOCTL: 0x%X (%04X)", `*
yOc6i]
ioControlCode, IoGetFunctionCodeFromCtlCode(ioControlCode)); U UtS me
status = STATUS_INVALID_PARAMETER; yg
?m6(+
Irp->IoStatus.Information = 0; *Sbc 8Y
} H15!QxD#
$:-C9N29
Irp->IoStatus.Status = status; x 0vW9*&
IoCompleteRequest(Irp, IO_NO_INCREMENT); p&`I#6{
return status; A]o3 MoSt
} |\"%Dy[m
+:c}LCI9<
X C390t
NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) -w[1]NhbV2
{ 4`r-*Lx
Irp->IoStatus.Status = STATUS_SUCCESS; eR3MU]zF
Irp->IoStatus.Information = 0; gKPqU@$*
IoCompleteRequest(Irp, IO_NO_INCREMENT); z^
%`sUgP
return Irp->IoStatus.Status; [{ A5?BE -
} 5(Xq58nhxI
f-}_
@
XKVdtG
VOID OnUnload(IN PDRIVER_OBJECT DriverObject) 4'`*Sce
}
{ ]
}_O
he]X
UNICODE_STRING usLink; -PiZvg
e
9v}
v
Cg
DbgPrint("DNF Cracker Unloaded!"); !/e8x;_
<>=abgg
RtlInitUnicodeString(&usLink, SymbolicLink); 93Q x+oK]
IoDeleteSymbolicLink(&usLink); ]5eZLXM
IoDeleteDevice(DriverObject->DeviceObject); k
jR-p=}
} #w[1])D m
l
(R{z
3[/u&
TJ(vq]|&
VOID My_RecoveryHook_AntiRestart() N*>&XJ#
{ Pill |4c<
KIRQL Irql; 6C*4' P9>
NTSTATUS status = STATUS_UNSUCCESSFUL; f
<2<8xS
BYTE *pTesSafeAddress = NULL; y
vKKE
ULONG lTesSafeSize = 0; dw< b}2
BYTE *pHookAddress = NULL; -- |L?-2k,
BYTE JUMP[1] = {0xeb}; =:v5` :
BYTE RET[1]={0xC3}; iJ~e8l0CA
BYTE *RestartCheckFunction1HookPoint, `v1~nNoY
*RestartCheckFunction2HookPoint, L@LT*M
*RestartFunctionHookPoint = 0; #jR1ti)p
cP(is!
1jQlwT(:
if ( !NT_SUCCESS(GetTesSafeAddress(&pTesSafeAddress, &lTesSafeSize)) ) %(n
^re uP
{ +h?
z7ZY^
return; } {m.\O
} UG<`m]
8 n)3'ok
/2e,
,)4g
RestartCheckFunction1HookPoint = pTesSafeAddress + 0x5f72; //insert ret at begin qz[1]/d6-0"
RestartCheckFunction2HookPoint = pTesSafeAddress + 0x41e0; // insert ret at begin >4eZ%</D5
RestartFunctionHookPoint = pTesSafeAddress + 0x163c; //restart function. insert ret at begin. H?
<c eK'e
ds?UY[X-<6
~`Xu 6[1]+1o
WPOFF(); &C7HG^;W9
Irql=KeRaiseIrqlToDpcLevel(); i7(\i2_P
Kw ^tvRt'*
RtlCopyMemory(RestartCheckFunction1HookPoint, RET, sizeof(RET)); t.E3Fh!o
RtlCopyMemory(RestartCheckFunction2HookPoint, RET, sizeof(RET)); =C.WM*='
RtlCopyMemory(RestartFunctionHookPoint, RET, sizeof(RET)); GcYT<pwN6
[1]*=ymK*
&,B 91H*#
KeLowerIrql(Irql); v/
B
:n
WPON(); Y2,\WKa
} 8fwM)DKS
^."HD?(
W^^}-9
NTSTATUS ModifyKiAttachProcessHook() Z/ypWoV(
{ S?AEV [1] "
KIRQL Irql; 4{r_EV[(
NTSTATUS status = STATUS_UNSUCCESSFUL; nBVknyMFNF
BYTE *pTesSafeAddress = NULL; zjrr*iw
ULONG lTesSafeSize = 0; 3[jk}2R';p
BYTE *pHookAddress = NULL; z4nVsgQ$??
BYTE bHookPattern[] = { 0x8b, 0xff, 0x55, 0x8b, 0xec, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, 0x60, 0x9c, 0xb8, 'x', 'x', 'x', 'x', 0x33, 0xc9, 0x41, 0xf0, 0x0f, 0xc1, 0x08, 0xff, 0x15, 0x4c, 'x', 'x', 'x', 0x89, 0x45, 0xfc, 0x8b, 0x45, 0xfc, 0x3b, 0x05, 0xe0, 'x', 'x', 'x', 0x75, 0x05, 0xe9, 0xc0, 0x00, 0x00, 0x00, 0x6a, 0x10, 0xff, 0x75, 0xfc, 0xe8, 0x76, 0xfb, 0xff, 0xff, 0x0f, 0xb6, 0xc0, 0x85, 0xc0, 0x74, 0x05, 0xe9, 0xaa, 0x00, 0x00, 0x00, 0x6a, 0x10, 0xff, 0x75, 0x0c, 0xe8, 0x20, 0xfc, 0xff, 0xff, 0x0f, 0xb6, 0xc0, 0x85, 0xc0, 0x75, 0x05, 0xe9, 0x94, 0x00, 0x00, 0x00, 0x8b, 0x45, 0x00, 0x8b, 0x40, 0x04, 0x89, 0x45, 0xf8, 0x83, 0x3d, 0x58, 'x', 'x', 'x', 'x', 0x74, 0x1d, 0x8b, 0x45, 0xf8, 0x3b, 0x05, 0x58, 'x', 'x', 'x', 0x72, 0x12 }; ]
cv|
A^
BYTE bReplaces[] = { 0xe9, 0xec, 0x00, 0x00, 0x00 }; YTc o;5/
fV;&)7
d&
j{nkus[1]2
if ( !NT_SUCCESS(GetTesSafeAddress(&pTesSafeAddress, &lTesSafeSize)) ) y{eZ?rX|
{ 8elT/Wl
return STATUS_UNSUCCESSFUL; ~%Ws"1
} $Q:5KNF+p
o4kNDXP#S
r[$Qtj Q
pHookAddress = FindBytePattern( A&5$eGe9
bHookPattern, sizeof(bHookPattern), pTesSafeAddress, pTesSafeAddress + lTesSafeSize); 'FBvAk6
if ( NULL == pHookAddress ) ZU[1]yM:$
return STATUS_UNSUCCESSFUL; p Nu13o~
H[x9 7r
@D"1}CW
WPOFF(); nWZrB s _
Irql=KeRaiseIrqlToDpcLevel(); %!rsu-W:Y
$zCUQthL@
// eb b0f834cd e9 bi^LpyEn
// ed b0f834ce 000000ec t9pPG{1
RtlCopyMemory(pHookAddress + 0xd, bReplaces, sizeof(bReplaces)); o7 !@WOeZ3
(([1]dG<
"<O?KO 3K
KeLowerIrql(Irql); 5o
~Z>?
WPON(); P6=|C;[
|J}~a
8?o
\+Cp?<Hv+
return status; *gT TI;:
} mU&J,C
*pW
swcV/
d7G'+B1
BOOLEAN UnHookTesSafeHooks() $K G?d>wx
{ [w4z)!
BYTE *pTesSafeAddress = NULL; $4M3j%S[1]
ULONG lTesSafeSize = 0; uuC/F_='B
?,,iQG' *
L'6zs:i
return NT_SUCCESS(GetTesSafeAddress(&pTesSafeAddress, &lTesSafeSize)); WMC6 dD_6e
} IWQ8e$N?
5s|gKM
EagI?)W!s[
VOID HookNtNFuncs() ~.Gk:M
{ qy]-
YJZ
if ( UnHookTesSafeHooks() ) X3 >(K
1
{ doa$ ;=wg
My_RecoveryHook_AntiRestart(); 2,fB$5+
ModifyKiAttachProcessHook(); St3~Y{aI|
My_RecoveryHook_NtReadAndWriteMemory(); (+@.L7>m+t
My_RecoveryHook_NtOpenProcess(); oa4}GN[1]H
My_RecoveryHook_NtOpenThread(); r3-3*_[1]
My_Recovery_HardwareBreakpoint(); 'K!kJ9oqe
} oMVwId f
} tX?_eN
pA2U+Q@
C[1]/ bttd
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) HT&0i,`
{ =~h54/#[I
NTSTATUS status; jz)H?UuD?Y
PDEVICE_OBJECT DvcObj; Q@8[ql1l
UNICODE_STRING usDevice, usLink; _=8+_OEk
PLIST_ENTRY pLE = (PLIST_ENTRY)DriverObject->DriverSection; 1@WGbORc*
-db+Y:xUZ
0 OBk d
pLE->Flink->Blink = pLE->Blink; "YL-!
P
pLE->Blink->Flink = pLE->Flink;
1 XG-O
f
Dd?!Mt
DriverObject->DriverUnload = OnUnload; !A!\S/x4
zqh{=&Tjx
}k?j6hnQ
RtlInitUnicodeString(&usDevice, DeviceLink); "b 0cj
status = IoCreateDevice(DriverObject, 0, &usDevice, FILE_DEVICE_UNKNOWN, 0, TRUE, &DvcObj); -Q
6pV<i
if (!NT_SUCCESS(status))
qR qy
{ Ct)MvZ
DbgPrint("Failed to create device!\n"); &r%*_pX
return status; prtxE&-
} &._!)al
Zjg\jo
*
Xoscc?
RtlInitUnicodeString(&usLink, SymbolicLink); zXZ'nJ5OGG
status = IoCreateSymbolicLink(&usLink, &usDevice); |A0$XU
{
if (!NT_SUCCESS(status)) LUck>l\l
{ oDP((I2-
IoDeleteDevice(DriverObject->DeviceObject); iIaT1i4t.
DbgPrint("Failed to create symbolic link!\n"); _}OJPahw
return status; -Zg @D(pF
} _AYC|R|
~9r!m5ws
U}w+`ZLN
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = #we>75l{+R
DriverObject->MajorFunction[IRP_MJ_CREATE] = HDVl5X`j'
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose; sD
8 m<
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoCtrl;
kt{C?7qpD
;Q=GJ5`B
D2</^]3Su
HookNtNFuncs(); rS )b1nPA
DbgPrint("DNF Cracker Loaded!"); {^2W>
^
return STATUS_SUCCESS; MJ*]fC3/
} 5m^Hi} S _
第二篇:dnf过驱动源码asm
class CDlgMain : public CDialog
{
// Construction
public:
LRESULT OnUpdateData(WPARAM wParam,LPARAM lParam);
static DWORD WINAPI ThreadShowSignMsgProc(LPVOID lpParam);
CDlgMain(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CDlgMain)
enum { IDD = IDD_DIALOG_MAIN };
CString m_strLog;
CString m_TimeInfo;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDlgMain)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CDlgMain)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
第一步,这也是最起码的,你必须要能够打开游戏进程和线程,能够开打进程和线程后不被检测到
第二步,能够读写进村内存
第三步,能够用OD附加游戏进程
第四步,能够下硬件断点而不被检测
跳过NtReadVirtualMemory,NtWriteVirtualMemory函数头的钩子
代码:
#include<ntddk.h>
typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE; //由于KeServiceDescriptorTable只有一项,这里就简单点了
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;//KeServiceDescriptorTable为导出函数
/////////////////////////////////////
VOID Hook();
VOID Unhook();
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);
//////////////////////////////////////
ULONG JmpAddress;//跳转到NtOpenProcess里的地址
ULONG JmpAddress1;//跳转到NtOpenProcess里的地址
ULONG OldServiceAddress;//原来NtOpenProcess的服务地址
ULONG OldServiceAddress1;//原来NtOpenProcess的服务地址
//////////////////////////////////////
__declspec(naked) NTSTATUS __stdcall MyNtReadVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress,
PVOID Buffer,
ULONG NumberOfBytesToRead,
PULONG NumberOfBytesReaded)
{
//跳过去
__asm
{
push 0x1c
push 804eb560h //共十个字节
jmp [JmpAddress]
}
}
__declspec(naked) NTSTATUS __stdcall MyNtWriteVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress,
PVOID Buffer,
ULONG NumberOfBytesToWrite,
PULONG NumberOfBytesReaded)
{
//跳过去
__asm
{
push 0x1c
push 804eb560h //共十个字节
jmp [JmpAddress1]
}
}
///////////////////////////////////////////////////
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = OnUnload;
DbgPrint("Unhooker load");
Hook();
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint("Unhooker unload!");
Unhook();
}
/////////////////////////////////////////////////////
VOID Hook()
{
ULONG Address, Address1;
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0xBA * 4;//0x7A为NtOpenProcess服务ID
Address1 = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x115 * 4;//0x7A为NtOpenProcess服务ID
DbgPrint("Address:0x%08X",Address);
OldServiceAddress = *(ULONG*)Address;//保存原来NtOpenProcess的地址
OldServiceAddress1 = *(ULONG*)Address1;//保存原来NtOpenProcess的地址
DbgPrint("OldServiceAddress:0x%08X",OldServiceAddress);
DbgPrint("OldServiceAddress1:0x%08X",OldServiceAddress1);
DbgPrint("MyNtOpenProcess:0x%08X",MyNtReadVirtualMemory);
DbgPrint("MyNtOpenProcess:0x%08X",MyNtWriteVirtualMemory);
JmpAddress = (ULONG)0x805b528a + 7; //跳转到NtOpenProcess函数头+10的地方,这样在其前面写的JMP都失效了
JmpAddress1 = (ULONG)0x805b5394 + 7;
DbgPrint("JmpAddress:0x%08X",JmpAddress);
DbgPrint("JmpAddress1:0x%08X",JmpAddress1);
__asm
{ //去掉内存保护
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
*((ULONG*)Address) = (ULONG)MyNtReadVirtualMemory;//HOOK SSDT
*((ULONG*)Address1) = (ULONG)MyNtWriteVirtualMemory;
__asm
{ //恢复内存保护
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}
//////////////////////////////////////////////////////
VOID Unhook()
{
ULONG Address, Address1;
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0xBA * 4;//查找SSDT Address1 = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x115 * 4;
__asm{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
*((ULONG*)Address) = (ULONG)OldServiceAddress;//还原SSDT
*((ULONG*)Address1) = (ULONG)OldServiceAddress1;//还原SSDT
__asm{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
DbgPrint("Unhook");
}
由于它不断对DebugPort清零,所以要修改调试相关函数,使得所有的访问DebugPort的地方全部访问EPROCESS中的ExitTime字节,这样它怎么清零都无效了,也检测不到 代码:
.386
.model flat, stdcall
option casemap:none
include dnf_hook.inc
.const
Dspdo_1 equ 80643db6h
Dmpp_1 equ 80642d5eh
Dmpp_2 equ 80642d64h
Dct_1 equ 806445d3h
Dqm_1 equ 80643089h
Kde_1 equ 804ff5fdh
Dfe_1 equ 80644340h
Pcp_1 equ 805d1a0dh
Mcp_1 equ 805b0c06h
Mcp_2 equ 805b0d7fh
Dmvos_1 equ 8064497fh
Dumvos_1 equ 80644a45h
Pet_1 equ 805d32f8h
Det_1 equ 8064486ch
Dep_1 equ 806448e6h
.code
;还原自己的Hook
DriverUnload proc pDriverObject:PDRIVER_OBJECT
ret
DriverUnload endp
ModifyFuncAboutDbg proc addrOdFunc, cmd_1, cmd_2
pushad
mov ebx, addrOdFunc
mov eax, cmd_1
mov DWORD ptr [ebx], eax
mov eax, cmd_2
mov DWORD ptr [ebx + 4], eax
popad
ret
ModifyFuncAboutDbg endp
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
invoke ModifyFuncAboutDbg, Dspdo_1, 90784789h, 0fde89090h
invoke ModifyFuncAboutDbg, Dmpp_1, 90787e39h, 950f9090h
invoke ModifyFuncAboutDbg, Dct_1, 90785e39h, 840f9090h
invoke ModifyFuncAboutDbg, Dqm_1, 9078408bh, 45899090h
invoke ModifyFuncAboutDbg, Kde_1, 90787839h, 13749090h
invoke ModifyFuncAboutDbg, Dfe_1, 9078418bh, 0d2329090h
invoke ModifyFuncAboutDbg, Pcp_1, 90784389h, 45f69090h
invoke ModifyFuncAboutDbg, Mcp_1, 90785e39h, 950f9090h
invoke ModifyFuncAboutDbg, Mcp_2, 90784a89h, 5e399090h
invoke ModifyFuncAboutDbg, Dmvos_1, 9078498bh, 0cb3b9090h
invoke ModifyFuncAboutDbg, Dumvos_1, 00787983h, 74909090h
invoke ModifyFuncAboutDbg, Pet_1, 00787f83h, 74909090h
invoke ModifyFuncAboutDbg, Det_1, 9078498bh, 0c9859090h
invoke ModifyFuncAboutDbg, Dep_1, 9078498bh, 0c9859090h
;invoke ModifyFuncAboutDbg, Dmpp_2, 8bc0950fh, 8b90c032h
mov eax, pDriverObject
assume eax : ptr DRIVER_OBJECT
mov [eax].DriverUnload, offset DriverUnload
assume eax : nothing
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
mov eax, STATUS_SUCCESS
ret
DriverEntry endp
end DriverEntry
绕过NtOpenProcess,NtOpenThread,KiAttachProcess
以及最重要的,不能让它检测到有硬件断点,所以要对CONTEXT做一些伪装,把真实的DR0~DR7的数据存放到别的地方,OD访问的时候返回正确的数据,如果是DNF要获取上下文,就稍微做下手脚
代码:
.386
.model flat, stdcall
option casemap:none
include dnf_hook.inc
.const
NtOpenProcessHookAddr equ 805cc626h
NtOpenProcessRetAddr equ 805cc631h
NtOpenProcessNoChange equ 805cc62ch
NtOpenThreadHookAddr equ 805cc8a8h
NtOpenThreadRetAddr equ 805cc8b3h
NtOpenThreadNoChange equ 805cc8aeh
KiAttachProcessAddr equ 804f9a08h
KiAttachProcessRetAddr equ 804f9a0fh
ObOpenObjectByPointerAddr equ 805bcc78h
NtGetContextThreadAddr equ 805d2551h;805c76a3h NtGetContextThreadRetAddr equ 805c76a7h;805d2555h
.data
nameOffset dd ?
threadCxtLink dd 0
tmpLink dd ?
.code
GetProcessName proc
invoke PsGetCurrentProcess
mov ebx, eax
add ebx, nameOffset
invoke DbgPrint, $CTA0("\n")
push ebx
invoke DbgPrint, ebx
pop ebx
invoke strncmp, $CTA0("DNF.exe"), ebx, 6 push eax
invoke DbgPrint, $CTA0("\n")
pop eax
ret
GetProcessName endp
HookCode proc
;执行被覆盖的代码
push dword ptr [ebp-38h]
push dword ptr [ebp-24h]
;判断是否dnf的进程
invoke GetProcessName
.if !eax ;如果是DNF自己的进程,那么跳转回去执行它的Hook代码
pushad
invoke DbgPrint, $CTA0("\nNotUnHook\n")
popad
mov eax, NtOpenProcessNoChange;805c13e6h
jmp eax
.else ;如果不是DNF自己的进程,那么直接调用ObOpenObjectByPointer,再返回到后面
pushad
invoke DbgPrint, $CTA0("\nUnHook\n")
popad
mov eax, ObOpenObjectByPointerAddr;805b13f0h
call eax
mov ebx, NtOpenProcessRetAddr;805c13ebh
jmp ebx
.endif
HookCode endp
;获取系统名称偏移
GetNameOffset proc epe
local tmpOffset
pushad
mov ebx, epe
invoke strlen, $CTA0("System")
xor ecx, ecx
@@:
push eax
push ecx
invoke strncmp, $CTA0("System"), ebx, eax
pop ecx
.if !eax
pop eax
mov tmpOffset, ecx
popad
mov eax, tmpOffset
ret
.elseif
pop eax
inc ebx
inc ecx
cmp ecx, 4096
je @F
jmp @B
.endif
@@:
popad
mov eax, -1
ret
GetNameOffset endp
Hook proc
pushad
;头5字节跳转
mov eax, offset HookCode
sub eax, NtOpenProcessHookAddr;805c13e0h;805c13edh
sub eax, 5
mov ebx, NtOpenProcessHookAddr;805c13e0h;805c13edh
mov cl, 0E9h
mov BYTE PTR [ebx], cl
mov DWORD PTR [ebx + 1], eax
popad
ret
Hook endp
HookThreadCode proc
;执行被覆盖的代码
push dword ptr [ebp-34h]
push dword ptr [ebp-20h]
;判断是否dnf的进程
invoke GetProcessName
.if !eax ;如果是DNF自己的进程,那么跳转回去执行它的Hook代码
pushad
invoke DbgPrint, $CTA0("\nNotUnHook\n")
popad
mov eax, NtOpenThreadNoChange;805c13e6h
jmp eax
.else ;如果不是DNF自己的进程,那么直接调用ObOpenObjectByPointer,再返回到后面
pushad
invoke DbgPrint, $CTA0("\nUnHook\n")
popad
mov eax, ObOpenObjectByPointerAddr;805b13f0h call eax
mov ebx, NtOpenThreadRetAddr;805c13ebh jmp ebx
.endif
HookThreadCode endp
HookThread proc
pushad
;头5字节跳转
mov eax, offset HookThreadCode
sub eax, NtOpenThreadHookAddr;805c13e0h;805c13edh sub eax, 5
mov ebx, NtOpenThreadHookAddr;805c13e0h;805c13edh mov cl, 0E9h
mov BYTE PTR [ebx], cl
mov DWORD PTR [ebx + 1], eax
popad
ret
HookThread endp
HookDbg proc
mov edi, edi
push ebp
mov ebp, esp
push ebx
push esi
mov esi, KiAttachProcessRetAddr
jmp esi
HookDbg endp
Dbg proc
pushad
;头5字节跳转
mov eax, offset HookDbg
sub eax, KiAttachProcessAddr;805c13e0h;805c13edh sub eax, 5
mov ebx, KiAttachProcessAddr;805c13e0h;805c13edh mov cl, 0E9h
mov BYTE PTR [ebx], cl
mov DWORD PTR [ebx + 1], eax
popad
ret
Dbg endp
;还原自己的Hook
DriverUnload proc pDriverObject:PDRIVER_OBJECT cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
;还原进程处理
mov eax, 0ffc875ffh
mov ebx, 805cc656h
mov DWORD ptr [ebx], eax
mov eax, 43e8dc75h
mov DWORD ptr [ebx + 4], eax
;还原线程处理
mov eax, 0ffcc75ffh
mov ebx, 805cc8d8h
mov DWORD ptr [ebx], eax
mov eax, 0c1e8e075h
mov DWORD ptr [ebx + 4], eax
;还原调试处理
mov eax, 08b55ff8bh
mov ebx, 804f9a08h
mov DWORD ptr [ebx], eax
mov eax, 08b5653ech
mov DWORD ptr [ebx + 4], eax
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
ret
DriverUnload endp
;显示LinkTable的信息
ShowLinkTableInfo proc ptrLT
pushad
invoke DbgPrint, $CTA0("\nThe LinkTable Info:\n")
mov ebx, ptrLT
mov eax, (LinkTable ptr [ebx]).ThreadHandle
invoke DbgPrint, $CTA0("ThreadHandle:%0X\n"), eax
mov ebx, ptrLT
mov eax, (LinkTable ptr [ebx]).Dr0Seg
invoke DbgPrint, $CTA0("Dr0Seg:%0X\n"), eax
mov ebx, ptrLT
mov eax, (LinkTable ptr [ebx]).Dr1Seg
invoke DbgPrint, $CTA0("Dr1Seg:%0X\n"), eax
mov ebx, ptrLT
mov eax, (LinkTable ptr [ebx]).Dr2Seg
invoke DbgPrint, $CTA0("Dr2Seg:%0X\n"), eax
mov ebx, ptrLT
mov eax, (LinkTable ptr [ebx]).Dr3Seg
invoke DbgPrint, $CTA0("Dr3Seg:%0X\n"), eax
mov ebx, ptrLT
mov eax, (LinkTable ptr [ebx]).Dr6Seg
invoke DbgPrint, $CTA0("Dr6Seg:%0X\n"), eax
mov ebx, ptrLT
mov eax, (LinkTable ptr [ebx]).Dr7Seg
invoke DbgPrint, $CTA0("Dr7Seg:%0X\n"), eax
mov ebx, ptrLT
mov eax, (LinkTable ptr [ebx]).LinkPtr
invoke DbgPrint, $CTA0("LinkPtr:%0X\n"), eax
mov ebx, ptrLT
mov eax, (LinkTable ptr [ebx]).NextLinkPtr
invoke DbgPrint, $CTA0("NextLinkPtr:%0X\n"), eax
popad
ret
ShowLinkTableInfo endp
;判断该线程是否存在
;如果不存在则返回0,存在则返回指向该链表的指针,1代表链表为空 ExsitsLinkTable proc pHandle
pushad
mov eax, threadCxtLink
.if !eax ;链表为空
pushad
invoke DbgPrint, $CTA0("\nLinkTable Is Null.\n") popad
popad
mov eax, 1
ret
.endif
@@:
mov ebx, (LinkTable ptr [eax]).ThreadHandle cmp ebx, pHandle ;如果匹配已经存在
je @F
mov eax, (LinkTable ptr [eax]).NextLinkPtr
.if !eax ;已经到达末尾,没有找到匹配
pushad
invoke DbgPrint, $CTA0("\pHandle Is Not Found.\n") popad
popad
xor eax, eax
ret
.endif
jmp @B
@@:
pushad
invoke DbgPrint, $CTA0("\npHandle Is Exsits.\n") popad
invoke ShowLinkTableInfo, eax
;返回链表指针
mov tmpLink, eax
popad
mov eax, tmpLink
ret
ExsitsLinkTable endp
;拷贝Context到LinkTable中
CopyContextToLinkTable proc ptrContext, ptrLT pushad
mov ebx, ptrContext
mov edx, ptrLT
mov ecx, 4
@@:
mov eax, DWORD ptr [ebx + ecx]
mov DWORD ptr [edx + ecx], eax
add ecx, 4
cmp ecx, 18h
jbe @B
popad
ret
CopyContextToLinkTable endp
;添加LinkTable表
AddLinkTable proc pHandle, ptrContext
pushad
invoke ExsitsLinkTable, pHandle
.if eax > 1
;已经存在只需要更新dr寄存器即可
invoke CopyContextToLinkTable, eax, ptrContext .else
push eax
invoke ExAllocatePool, 1, size LinkTable .if eax
;申请内存成功
mov ebx, eax
pop eax
;置地一个元素
mov ecx, pHandle
mov (LinkTable ptr [ebx]).ThreadHandle, ecx ;拷贝dr寄存器的值
invoke CopyContextToLinkTable, ptrContext, ebx ;置另外两个元素
mov (LinkTable ptr [ebx]).LinkPtr, ebx mov (LinkTable ptr [ebx]).NextLinkPtr, 0 invoke ShowLinkTableInfo, ebx
;把新的链表项添加到链表中
.if eax == 1
;如果链表为空,直接加在表头
mov threadCxtLink, ebx
.else
;如果链表不为空则加到末尾
mov eax, threadCxtLink
@@:
;指向下一个元素
mov ecx, (LinkTable ptr [eax]).NextLinkPtr test ecx, ecx
je @F
mov eax, ecx
jmp @B
@@:
mov (LinkTable ptr [eax]).NextLinkPtr, ebx
.endif
.else
;申请内存失败
pop eax
pushad
invoke DbgPrint, $CTA0("\nAlloc Memory Faild.\n") popad
jmp @F
.endif
.endif
@@:
popad
ret
AddLinkTable endp
;判断进程是否过虑进程
;如果是需要过虑的进程返回值为1,否则返回0
IsFilterProcess proc
pushad
;获取当前进程名
invoke PsGetCurrentProcess
mov ebx, eax
add ebx, nameOffset
invoke DbgPrint, $CTA0("\n%s: Call NtGetContextThread \n"), ebx invoke strncmp, $CTA0("DNF.exe"), ebx, 7
test eax, eax
jne @F
popad
mov eax, 1
ret
@@:
popad
xor eax, eax
ret
IsFilterProcess endp
;显示Context的调试寄存器
ShowDrRegInfo proc ptrContext
pushad
invoke DbgPrint, $CTA0("\nThe Context Info:\n")
mov ebx, ptrContext
mov eax, DWORD ptr [ebx + 4]
invoke DbgPrint, $CTA0("Dr0:%0X\n"), eax
mov ebx, ptrContext
mov eax, DWORD ptr [ebx + 8]
invoke DbgPrint, $CTA0("Dr1:%0X\n"), eax
mov ebx, ptrContext
mov eax, DWORD ptr [ebx + 0ch]
invoke DbgPrint, $CTA0("Dr2:%0X\n"), eax
mov ebx, ptrContext
mov eax, DWORD ptr [ebx + 10h]
invoke DbgPrint, $CTA0("Dr3:%0X\n"), eax
mov ebx, ptrContext
mov eax, DWORD ptr [ebx + 14h]
invoke DbgPrint, $CTA0("Dr6:%0X\n"), eax
mov ebx, ptrContext
mov eax, DWORD ptr [ebx + 18h]
invoke DbgPrint, $CTA0("Dr7:%0X\n"), eax popad
ret
ShowDrRegInfo endp
;恢复被隐藏的dr寄存器
RecoveryDrReg proc ptrContext, pHandle pushad
;定位到LinkTable
mov ebx, threadCxtLink
NEXT:
test ebx, ebx
jne @F ;如果没有遍历完
popad
ret
@@:
mov eax, (LinkTable ptr [ebx]).ThreadHandle cmp eax, pHandle
je @F ;如果找到匹配项
mov ebx, (LinkTable ptr [ebx]).NextLinkPtr jmp NEXT
@@:
;拷贝完毕后立即结束
invoke CopyContextToLinkTable, ebx, ptrContext
xor ebx, ebx
jmp NEXT
RecoveryDrReg endp
;清空Context的dr寄存器
ClearDrReg proc ptrContext
pushad
mov ebx, ptrContext
mov ecx, 4
@@:
mov DWORD ptr [ebx + ecx], 0
add ecx, 4
cmp ecx, 18h
jbe @B
pushad
invoke DbgPrint, $CTA0("\n-------------ClearDrReg-------------\n") popad
invoke ShowDrRegInfo, ptrContext
popad
ret
ClearDrReg endp
;NtGetContextThread钩子代码
NtGetContextThreadHookCode proc
;ebx存放CONTEXT指针
mov ebx, DWORD ptr [ebp + 10h]
;线程句柄
mov edx, DWORD ptr [ebp + 0ch]
pushad
invoke ShowDrRegInfo, ebx
invoke IsFilterProcess
.if eax ;如果是DNF.exe
invoke AddLinkTable, edx, ebx
invoke ClearDrReg, ebx
.else ;如果不是DNF.exe
invoke RecoveryDrReg, ebx, edx
.endif
invoke ShowDrRegInfo, ebx
;执行被覆盖的代码
popad
mov eax, esi
pop esi
leave
ret
NtGetContextThreadHookCode endp
;NtGetContextThread加跳转
HookNtGetContextThread proc
pushad
;头5字节跳转
mov eax, offset NtGetContextThreadHookCode
sub eax, NtGetContextThreadAddr;805c13e0h;805c13edh
sub eax, 5
mov ebx, NtGetContextThreadAddr;805c13e0h;805c13edh
mov cl, 0E9h
mov BYTE PTR [ebx], cl
mov DWORD PTR [ebx + 1], eax
popad
ret
HookNtGetContextThread endp
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING invoke DbgPrint, $CTA0("Begin")
invoke PsGetCurrentProcess
invoke GetNameOffset, eax
mov nameOffset, eax
cmp eax, -1
je @F
mov nameOffset, eax
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
call Hook
call HookThread
call Dbg
call HookNtGetContextThread
mov eax, pDriverObject
assume eax : ptr DRIVER_OBJECT
mov [eax].DriverUnload, offset DriverUnload
assume eax : nothing
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
invoke DbgPrint, $CTA0("End")
@@:
mov eax, STATUS_SUCCESS
ret
DriverEntry endp
end DriverEntry
// Record tags in .udd files.
#define MI_SIGNATURE 0x00646F4DL // Module info signature
#define MI_VERSION 0x7265560AL // OllyDbg version
#define MI_FILENAME 0x6C69460AL // Record with full name of executable #define MI_FILESIZE 0x7A69530AL // Record with file size
#define MI_TIMESTAMP 0x7473540AL // Record with timestamp file data #define MI_SFXENTRY 0x6566530AL // Real entry of SFX-able module #define MI_PATCH 0x7461500AL // Record with patch data
#define MI_USER 0x0073550AL // Record with user-defined label/comment #define MI_PROCDATA 0x6372500AL // Record with procedure data
#define MI_SWDATA 0x6977530AL // Record with switch data
#define MI_CALLFINT 0x6966430AL // Record with internal call
#define MI_CALLFMOD 0x6D66430AL // Record with intermodular call #define MI_CALLFABS 0x6166430AL // Record with absolute call
#define MI_INT3BREAK 0x7470420AL // Record with breakpoint data
#define MI_INT3BRKC 0x6370420AL // Record with checked breakpoint data #define MI_HDWRBREAK 0x7262480AL // Record with hardware breakpoint data #define MI_JDDATA 0x74644A0AL // Record with all module jump data #define MI_ANALYSIS 0x616E410AL // Record with analysis data
#define MI_ANALPACK 0x636E410AL // Record with compressed analysis data #define MI_AHINT 0x7468410AL // Record with analysis hint data #define MI_TRACE 0x6172540AL // Record with trace data
#define MI_TRACEPACK 0x6372540AL // Record with compressed trace data #define MI_CODECRC 0x7263430AL // Record with CRC of code for analysis #define MI_SAVEAREA 0x6176530AL // Record with general-purpose save area #define MI_END 0x646E450AL // End of module info data
// Tags reserved for 3rd-party plugins.
#define MI_WINJUG 0x67754A0AL // WindowJuggler by EsseEmme #define MI_WINJU1 0x31754A0AL
#define MI_WINJU2 0x32754A0AL
#define MI_WINJU3 0x33754A0AL
#define MI_APPST 0x73614F0AL // OllyAppStarter by Homunculus
// Prototypes for plugin callback functions.
extc int _export cdecl ODBG_Plugindata(char shortname[32]);
extc int _export cdecl ODBG_Plugininit(int ollydbgversion,HWND hw, ulong *features);
extc void _export cdecl ODBG_Pluginmainloop(DEBUG_EVENT *debugevent); extc void _export cdecl ODBG_Pluginsaveudd(t_module *pmod,int ismainmodule); extc int _export cdecl ODBG_Pluginuddrecord(t_module *pmod,int ismainmodule, ulong tag,ulong size,void *data);
extc int _export cdecl ODBG_Pluginmenu(int origin,char data[4096],void *item); extc void _export cdecl ODBG_Pluginaction(int origin,int action,void *item); extc int _export cdecl ODBG_Pluginshortcut(
int origin,int ctrl,int alt,int shift,int key,
void *item);
extc void _export cdecl ODBG_Pluginreset(void);
extc int _export cdecl ODBG_Pluginclose(void);
extc void _export cdecl ODBG_Plugindestroy(void);
extc int _export cdecl ODBG_Paused(int reason,t_reg *reg);
extc int _export cdecl ODBG_Pausedex(int reasonex,int dummy,t_reg *reg, DEBUG_EVENT *debugevent);
extc int _export cdecl ODBG_Plugincmd(int reason,t_reg *reg,char *cmd);