;@echo off
;goto make
.386
.model flat, stdcall
option casemap:none
include .\masm32\include\ntddk.inc
include .\masm32\include\ntstatus.inc
include .\masm32\include\ntoskrnl.inc
includelib .\masm32\lib\ntoskrnl.lib
include .\masm32\Macros\Strings.mac
.const
CCOUNTED_UNICODE_STRING "\\Device\\myhook", g_DeviceName, 4
COUNTED_UNICODE_STRING "\\??\\myhook", g_LinkName, 4
;18///////////////////////////////////////////////////////////////////
.data?
SERVICE_DESCRIPTOR_TABLE STRUCT
ServiceTableBase DWORD ?
ServiceCounterTableBase DWORD ?
NumberOfService DWORD ?
ParamTableBase DWORD ?
SERVICE_DESCRIPTOR_TABLE ends
;30///////////////////////////////////////////////////////////////////
.data
ssdtaddr dd 0
oldreadaddr dd 0
readpush dd 0
readjmpaddr dd 0
oldwriteaddr dd 0
writepush dd 0
writejmpaddr dd 0
ntopenprcaddr dd 0
ntopentrdaddr dd 0
KiAttachProcessaddr dd 0
ObOpenObjectByPointeraddr dd 0
CCOUNTED_UNICODE_STRING "NtOpenProcess", g_ProcessAddr, 4
CCOUNTED_UNICODE_STRING "NtOpenThread", g_ThreadAddr, 4
CCOUNTED_UNICODE_STRING "KeAttachProcess",g_KeAttachAddr, 4
CCOUNTED_UNICODE_STRING "ObOpenObjectByPointer",g_PointerAddr, 4 ;56///////////////////////////////////////////////////////////////////
.code
;///////////////////////////////////////////////////////////////////
MyNtReadVirtualMemory proc
;写好自己的nt!readvirtualmemory前几段代码直接跳到被hook代码后面
push 1ch
push readpush
jmp readjmpaddr
;readjmpaddr在后面记录下被hook了的代码后的地址
MyNtReadVirtualMemory endp
;///////////////////////////////////////////////////////////////////
MyNtWriteVirtualMemory proc ;同上
push 1ch
push writepush
jmp writejmpaddr
MyNtWriteVirtualMemory endp
;/////////////////////////////////////////////////////////////////
MyOpenProcess proc
;这里TX直接把call ObOpenObjectByPointer改为自己的地址
;我们就要在他前面hook,让代码走我们的线路跳过TX的call
pushad
;这里的pushad,popad 里面可以写一些检测代码,比如,
;如果是TX的代码要检测这里可以让他去运行他自己的call
;这里好像没有检测,所以没有写代码
popad push dword ptr [ebp-38h]
push dword ptr [ebp-24h]
mov eax,ntopenprcaddr
add eax,0bh
push eax
;这里要注意,这里的ntopenprcaddr是call ObOpenObjectByPointer后面
;的代码的地址,这个一定要写进去,因为我们是直接jmp进ObOpenObjectByPointer
jmp ObOpenObjectByPointeraddr MyOpenProcess endp
;这里就相当于是一个call 但这里为什么不用call ObOpenObjectByPointer
;只不过是少写几行代码也可以这样写
;push dword ptr [ebp-38h] 这两行代码是直接拷贝
;push dword ptr [ebp-24h] ntopenprocess里的代码
;call ObOpenObjectByPointer
;push ntopenprcaddr
;ret
这里一个push 和ret 也就是把下一个代码地址写入esp返回,
;这里大家可以练习一下,刚开绐我这里也不太明白怎么写,蓝屏N次
;后来在ring3下写了几次代码试验出来的,哈哈,菜鸟,只能这样,
;//////////////////////////////////////////////////////////////////
MyOpenTread proc ;这里同上
pushad
popad
push dword ptr [ebp-34h]
push dword ptr [ebp-20h]
mov eax,ntopentrdaddr
add eax,0bh
push eax
jmp ObOpenObjectByPointeraddr
MyOpenTread endp
;/////////////////////////////////////////////////////////////////
Findcodeaddr proc code1:dword,code2:word,prcaddr:dword
;这里是通过特征码搜索地址,因为不同的系统各地址不同,所以只能
;这样,试过xpsp2,xpsp3通过,别的系统没测试
mov edx,prcaddr
mov ecx,1000h
.while ecx
sub ecx,1h
add edx,1h
mov ebx,dword ptr [edx]
xor eax,eax
mov ax,word ptr [edx+4h]
.break .if ebx==code1 && ax==code2
.endw
mov eax,edx
ret
Findcodeaddr endp
;////////////////////////////////////////////////////////////////
myhook proc
pushad
invoke MmGetSystemRoutineAddress,addr g_ProcessAddr
invoke Findcodeaddr,0ffc875ffh,0dc75h,eax
;通过windbg找到被hook地址前面的特征码找地址
mov ntopenprcaddr,eax
invoke MmGetSystemRoutineAddress,addr g_ThreadAddr
invoke Findcodeaddr,0ffcc75ffh,0e075h,eax
mov ntopentrdaddr,eax
invoke MmGetSystemRoutineAddress,addr g_PointerAddr ;ObOpenObjectByPointer
mov ObOpenObjectByPointeraddr,eax
invoke MmGetSystemRoutineAddress,addr g_KeAttachAddr
;这个KiAttachProcess没导出函数就通过KeAttachProcess
invoke Findcodeaddr,570875ffh,0e856h,eax
;来找了,大鸟们说是第一个E8 call我也就这样找了
add eax,6h
mov ebx,dword ptr [eax]
add ebx,eax
add ebx,4h
mov KiAttachProcessaddr,ebx
mov eax,offset KeServiceDescriptorTable
;这里找SSDT,ntwritevirtualmemory,ntreadvirtualmemory
mov eax,[eax] ;address of KeServiceDescriptorTable
assume eax : ptr SERVICE_DESCRIPTOR_TABLE
;这两个函数在SSDT的位置找出这两个地址,等下改成我们的
mov ebx,[eax].ServiceTableBase
;地址,这就是SSDT hook,当时搞定这个心里乐得不行,
mov ssdtaddr,ebx
;偶菜鸟也能HOOk系统函数了,
mov eax,ssdtaddr
add eax,2e8h ;0xBA * 4 ntreadvirtualmemoryaddr
mov eax,DWORD PTR [eax]
mov oldreadaddr,eax
mov ebx,DWORD PTR [eax+3h]
mov readpush,ebx
add eax,7h
mov readjmpaddr,eax
mov eax,ssdtaddr
add eax,454h ;0x115*4 ntwritevirtualmemoryaddr
mov eax,DWORD PTR [eax]
mov oldwriteaddr,eax
mov ebx,DWORD PTR [eax+3h]
mov writepush,ebx
add eax,7h
mov writejmpaddr,eax
;这里我就不说了,大鸟们说得很清楚了,改写代码的时候不被中断
;要是代码没改完中断了,嘿嘿,蓝瓶的,好喝
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
mov eax,ssdtaddr
mov DWORD ptr [eax+2e8h],offset MyNtReadVirtualMemory
mov DWORD ptr [eax+454h],offset MyNtWriteVirtualMemory
mov ebx,ntopenprcaddr
mov BYTE ptr [ebx],0e9h
mov eax,offset MyOpenProcess
sub eax,ebx
sub eax,5h
mov DWORD ptr [ebx+1h],eax
mov ebx,ntopentrdaddr
mov BYTE ptr [ebx],0e9h
mov eax,offset MyOpenTread
sub eax,ebx
sub eax,5h
mov DWORD ptr [ebx+1h],eax
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
popad
mov eax,1h
ret
myhook endp
;/////////////////////////////////////////////////////////////////
DriverUnload proc pDriverObject:PDRIVER_OBJECT
;驱动卸载,把自己hook找码改回
pushad
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
mov eax,ssdtaddr
mov ebx,DWORD ptr [oldreadaddr]
mov DWORD ptr [eax+2e8h],ebx
mov ebx,DWORD ptr [oldwriteaddr]
mov DWORD ptr [eax+454h],ebx
mov eax,ntopenprcaddr
mov dword PTR [eax],0ffc875ffh
mov WORD ptr [eax+4h],0dc75h
mov eax,ntopentrdaddr
mov dword PTR [eax],0ffcc75ffh
mov WORD ptr [eax+4h],0e075h
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
invoke IoDeleteSymbolicLink, addr g_LinkName
mov eax, pDriverObject
invoke IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject
popad
ret
DriverUnload endp
;////////////////////////////////////////////////////////////////////
MyCreate proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
;这里的做用是当我们的程序加载驱动后,
;可以检测游戏是否运行,等,还有一个对付TX debug清0
;在程序中用CreateFile调用此函数
mov esi, pIrp
assume esi:ptr _IRP
mov [esi].IoStatus.Status, STATUS_UNSUCCESSFUL
and [esi].IoStatus.Information, 0
pushad
mov ebx,KiAttachProcessaddr
mov eax,dword ptr [ebx]
.if eax==8b55ff8bh
mov eax,STATUS_UNSUCCESSFUL
popad
ret
;本人对TX hook KiAttachProcess的代码检测,
;如果这里代码改动则游戏已运行, .endif
add ebx,1h
mov eax,dword ptr [ebx]
sub eax,53bh ;这里就是大鸟找出来的debug清0的地址通过
mov ebx,dword ptr [eax] ;ebx此地址为bc改为70 ;TX hook KiAttachProcess的地址加偏移找到
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
mov dword ptr [ebx],70h ;去除debugport 清0
mov eax,KiAttachProcessaddr
mov dword ptr [eax],8b55ff8bh
mov dword ptr [eax+4],5d8b53ech
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
popad
mov [esi].IoStatus.Status, STATUS_SUCCESS
ret
MyCreate endp
;////////////////////////////////////////////////////////////////////
MyClose proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
;关闭CreateFile函数调用
mov esi, pIrp
assume esi:ptr _IRP
mov [esi].IoStatus.Status,STATUS_UNSUCCESSFUL
and [esi].IoStatus.Information, 0
mov [esi].IoStatus.Status,STATUS_SUCCESS
ret
MyClose endp
;////////////////////////////////////////////////////////////////////
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING ;驱动入口,这里大家学习下驱动编程
local status:NTSTATUS
local pDeviceObject:PDEVICE_OBJECT
invoke myhook
.if eax == 0
mov eax,STATUS_UNSUCCESSFUL
ret
.endif
mov status,STATUS_UNSUCCESSFUL
invoke IoCreateDevice,pDriverObject,0,addr g_DeviceName,FILE_DEVICE_UNKNOWN,0,FALSE,addr pDeviceObject
.if eax == STATUS_SUCCESS
invoke IoCreateSymbolicLink,addr g_LinkName,addr g_DeviceName
.if eax == STATUS_SUCCESS
mov eax, pDriverObject
assume eax:ptr DRIVER_OBJECT
mov [eax].MajorFunction[IRP_MJ_CREATE*(sizeof PVOID)],offset MyCreate
mov [eax].MajorFunction[IRP_MJ_CLOSE*(sizeof PVOID)],offset MyClose
mov [eax].DriverUnload,offset DriverUnload
assume eax:nothing
mov status, STATUS_SUCCESS
.else
invoke IoDeleteDevice, pDeviceObject
.endif
.endif
mov eax,status
.if eax == STATUS_SUCCESS
.endif
ret
DriverEntry endp
end DriverEntry
:make
set drv=mydrv
\masm32\bin\ml /nologo /c /coff %drv%.bat
\masm32\bin\link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native /ignore:4078 %drv%.obj
del %drv%.obj
move %drv%.sys ..
echo.
Pause 代码保存为bat 文件,直接运行即可,
本人菜鸟只能拿大鸟们的成果在这里组合一个,代码写得烂,有什么地方可优化的地方,
高手优化过发我一份,哈哈,
菜鸟学习一个多月的成果,此驱动可通过OD加载DNF进行调试
能送一张邀请卡最好不过,哈哈
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)