过dnf驱动

时间:2024.4.20

#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{rZp­pm  
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{P­JUA 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.m­P4CKY  
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 );    ZuS0­DPS`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|d3­d[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#,  
{ t3M0L­a&  
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  
{ uugz­IV)  
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字节内容 v­P? "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'
9­x  
<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*6­rYa(  
    *(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 d­9<&.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] ?0­x
=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?+  
} zhbSi­w
  
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  
c­P(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  
} 8f­wM)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();   P­6=|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|g­KM  
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!kJ9o­qe  
} 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(p­F  
    } _A­YC|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);

更多相关推荐:
dnf心得1

第一条开贴继续奉献给大家大家一切从0开始哈哈队伍里等级高的人最好不要刷低过个人等级5级以上的图虚弱的时候进图比满血进图出随机深渊的几率大很多建议进图刷次图出来在进去如果没有深渊那么直接出去虚弱在进图没有在出去如...

dnf刷图经验心得

很多人都喜欢师傅带为什么呢因为师父可以带你去比你等级高的地图那里经验多但是高太多了经验却又减少了甚至到了一个图刷下来只有一丁点经验而且没有COF我在这里介绍的不是说某个图某个怪经验获得是多少因为这个没意义我想在...

dnf强化心得

Dnf强化心得6丢进去回到了5继续把5丢进去回到了4再丢一个10的碎了然后把11的丢进去上12了6丢进去回到了5继续把5丢进去回到了4再丢一个8的碎了然后把9的丢进去上10了11的还在研究中下面介绍统一的上9和...

dnf剑豪加点心得

剑豪加点心得技巧加点方案职业女鬼剑gt流浪武士gt剑豪等级85SP全部10770已用10365剩余405TP全部36已用35剩余1QP全部3974已用0剩余3974通用技能后跳Lv1受身蹲伏Lv1基础精通Lv1...

dnf深渊装备掉落表

dnf深渊装备掉落表龙人之塔gtgt适合等级lv14Lv17学者护腕人偶玄关gtgt适合等级lv16lv1914粉旋炎手炮石巨人塔gtgt适合等级lv18Lv21城主宫殿gtgt适合等级v21Lv24暗黑玄廊g...

dnf卡深渊 文档

卡深渊第一种卡非常进去了先别挑战深渊先点到勇士然后再点挑战深渊点到勇士等一下等到倒计时到2秒的时候回成然后再进游戏挑战深渊直接王者进入百分之85几率如果没有果断人长丑了第二种进图不点开启深渊来回点勇士级王者级一...

dnf深渊必备_doc

卡深渊第一种卡非常进去了先别挑战深渊先点到勇士然后再点挑战深渊点到勇士等一下等到倒计时到2秒的时候回成然后再进游戏挑战深渊直接王者进入百分之85几率如果没有果断人长丑了第二种进图不点开启深渊来回点勇士级王者级一...

dnf深渊顺序

APC顺序是大枪魔道崩拳火女APC顺序是漫游召唤格斗狮子王APC顺序是魔道大枪铁甲阿米力火女APC顺序是双毒王鬼泣大叔最后大叔掉的粉双剑APC顺序是双大枪崩拳首先要注意一下三条一进深渊之前要进人少的频道这样开出...

dnf深渊 文档

那么暂且忽略不计组队遇的深渊只说用卷开的深渊首先注意以下3条1进深渊之前切忌换个线挑那种人少的线最好这样开出非常困难的深渊几率会提高很多2不要连续进深渊综上所述只有非常困难的深渊才有较高几率出SS和粉困难的深渊...

dnf刷深渊技巧

我也是一个DNF爱好者不怕说出来丢人我只会玩DNF这个网游其他一概不会现在刷图我都刷得吐血了没意思啊想去PK又木有技术只有当小白鼠的份后来在朋友们的影响下开始玩深渊模式前期真的很郁闷的说几千万游戏币砸进去屁都木...

dnf时空之门深渊怎么开

dnf时空之门深渊怎么开dnf新版本更新之后开启深渊的任务随着一些任务的更新被淹没在一堆任务中不少玩家为了开启深渊只好将手上的任务全部清一遍需要花费很长时间dnf时空之门深渊怎么开哪个任务是开启时空之门深渊的开...

dnf附魔师怎么赚钱 大转移后轻松满级-欢乐园游戏

dnf附魔师怎么赚钱大转移后轻松满级曾经附魔师以难冲烧钱闻名附魔冲满之后想要赚钱却还行但是现在的附魔200W就冲满了下面小编就为大家介绍下DNF11级附魔师怎么赚钱dnf副职如何赚钱首先我们要确定现在的附魔师能...

dnf心得(4篇)