首页
社区
课程
招聘
[原创]过掉DNF游戏保护,仅供学习研究。不得用于非法途径。
发表于: 2009-9-8 14:05 213646

[原创]过掉DNF游戏保护,仅供学习研究。不得用于非法途径。

2009-9-8 14:05
213646
由于我的C用的比较少,所以大部分都用的汇编,部分地方用汇编写不是很方便,所以我用的C,由于只是学习,所以内核地址我没有计算都是硬编码的。过DNF主要分为三步,也许我的思路不太正确,反正可以OD调试,下断。
程序没怎么修边幅,因为只是测试,所以一般都没有写更改内核后的恢复,不过不妨碍使用。

第一步,这也是最起码的,你必须要能够打开游戏进程和线程,能够开打进程和线程后不被检测到
第二步,能够读写进村内存
第三步,能够用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


本人初学驱动,历经一月完成。。。已经很累了,心力交瘁唉,不舍得丢了,毕竟是自己的汗水,特此发出来大家相互学习交流。仅供参考,学习谢谢。

[课程]Linux pwn 探索篇!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (156)
雪    币: 135
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
强大.. 谢谢了 正在研究这个游戏
2009-9-8 14:11
0
雪    币: 416
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
呵呵 老大很强大
2009-9-8 14:14
0
雪    币: 4580
活跃值: (992)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
果然很黄很强大
2009-9-8 14:18
0
雪    币: 159
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
还有几个Shadow SSDT hook 只需要用RU恢复一下即可,它没有检测
2009-9-8 14:18
0
雪    币: 137
活跃值: (115)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
汇编的代码能改成C++的就好了,我不会汇编
2009-9-8 14:21
0
雪    币: 159
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
你终于现身了。。。
2009-9-8 14:58
0
雪    币: 451
活跃值: (78)
能力值: ( LV12,RANK:470 )
在线值:
发帖
回帖
粉丝
8
进入第一页来膜拜大牛
2009-9-8 16:57
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
果然很强悍
汇编是真不太懂,,,还得好好学学
要是有哪位牛人给翻译成C的,那就更强悍了
2009-9-8 18:23
0
雪    币: 42
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
占第一页。膜拜一下。。继续学习去。
2009-9-8 18:30
0
雪    币: 376
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
无限拜膜Lz一月成就,收藏细细研究......
2009-9-8 20:12
0
雪    币: 179
活跃值: (26)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
12
楼主辛苦了,愿意把自己一个月的成果拿出来和大家分享,佩服!
2009-9-8 20:27
0
雪    币: 494
活跃值: (629)
能力值: ( LV9,RANK:1210 )
在线值:
发帖
回帖
粉丝
13
先收藏,有时间再学习,可惜不是C代码

我试过把KiAttachProcess整个用lde剥出来,读写进程内存是可以的。只是玩玩,没试ObOpenObjectByPointer。
2009-9-8 20:32
0
雪    币: 159
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
14
遇到DebugPort清零大家还有什么好的方法么?
2009-9-8 20:58
0
雪    币: 280
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
support!!!
2009-9-8 21:08
0
雪    币: 246
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
如果我的技术有资格膜拜楼主 如果我的精神有资格膜拜 ,让我膜拜一下吧!
2009-9-8 21:12
0
雪    币: 3187
活跃值: (2694)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
不错不错,向楼主学习了,先收藏,谢谢楼主共享
2009-9-8 21:52
0
雪    币: 688
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
楼主如何知道DNF挂接了哪个函数的?望赐教一二
2009-9-9 10:33
0
雪    币: 159
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
19
实现某个功能遇到障碍就用icesword或者RU之类的工具大致定位下,然后再用Windbg看看
2009-9-9 10:41
0
雪    币: 332
活跃值: (30)
能力值: ( LV12,RANK:460 )
在线值:
发帖
回帖
粉丝
20
偶一直在找DebugPort
2009-9-9 10:47
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
一个月就有这样的水平很强大了,我都几年了没有进步
2009-9-9 11:47
0
雪    币: 77
活跃值: (17)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
22
请教LZ个问题
LZ过NTOPENPROCESS的HOOK,用到的办法是HOOK 调用ObOpenObjectByPointer函数前几个字节,然后判断是否是DNF进程读取对吧
可是DNF的驱动保护在这个地方有代码检验,不仅仅检测他自己的代理函数地址是否正确,同时也检测ObOpenObjectByPointer调用前几个字节是否被修改,如被检测出来被修改就会弹出TP发现非法模块

这一部分是怎么过的呢?
本人新手初学驱动编程,问的问题有些菜,见谅见谅
2009-9-9 17:44
0
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
无限拜膜Lz一月成就,收藏细细研究......
2009-9-9 17:58
0
雪    币: 46
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
呵呵~~强大~~~
2009-9-9 18:49
0
雪    币: 49
活跃值: (12)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
25
LZ的代码已经没用咯。。。。。感觉是蛮久以前写的。。。现在tx都内存代码校验了。。。patch直接给蓝屏了。。。。
2009-9-9 19:30
0
游客
登录 | 注册 方可回帖
返回
//