原理基本和前几天的ForXp版本一样,还是修改Kernel32.dll模块中的TerminateProcess函数前几个字节jmp到
自己的代码段达到Hook的目的(据说这叫Inline Hook,faint!)。但由于该死的MS把Kernel32.dll放在了
BFF70000h处(可恨呀,那里是系统内存,Ring3的应用程序没有权限修改!这就是为什么俺以前那个ForXp的程
序在Win9X下不起作用的原因。不过喜得好在Win9X下进入Ring0并不是什么难事,呵呵!)
程序下载:http://b.py99.net/zip/f?v=20073/61321259.zip
源代码如下:
.586
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include macros.asm
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
Call32 macro Selector,Offsetv
db 09ah
dd Offsetv
dw Selector
endm
.data
aKernel32 db 'Kernel32.dll',0
aUser32 db 'User32.dll',0
AddrKernel32 dd ?
aTerminateProcess db 'TerminateProcess',0
AddrTerminate dd ?
aMessageboxA db 'MessageBoxA',0
AddrMessage dd ?
aExitProcess db 'ExitProcess',0
AddrExitProcess dd ?
lpMapped
Object dd ?
;;-----------------------------------------
.code
Start:
invoke GetModuleHandle,addr aKernel32
mov AddrKernel32,eax
invoke GetProcAddress,eax,addr aTerminateProcess
mov AddrTerminate,eax
detect:
cmp word ptr[eax+5],90c3h
jz _ErrHooked
invoke GetProcAddress,AddrKernel32,addr aExitProcess
mov AddrExitProcess,eax
invoke GetModuleHandle,addr aUser32
invoke GetProcAddress,eax,addr aMessageboxA
mov AddrMessage,eax
mov eax,080000000h-1000h
Try_next:
add eax,1000h
cmp eax,(-1-1000h)
jae _ErrCantAlloc
push eax
invoke VirtualAlloc,eax,1000h,MEM_COMMIT,PAGE_EXECUTE_READWRITE
test eax,eax
xchg eax,ebx
pop eax
je Try_next
mov lpMapped
Object, eax
push offset MyProc
call ToRing0Code
cld
mov edi,lpMapped
Object mov esi,offset Addr0Proc
mov ecx,Addr0ProcLength+1
rep movsb
invoke MessageBox,0,CTXT("软件已成功运行!"),CTXT("SUCCESS"),MB_ICONWARNING
jmp Exit
_ErrCantAlloc:
invoke MessageBox,0,CTXT("不能分配内存!"),CTXT("ERROR"),0
jmp Exit
_ErrHooked:
invoke MessageBox,0,CTXT("程序已经运行过了!"),CTXT("ERROR"),MB_ICONWARNING
Exit:
invoke ExitProcess,0
;-----------------------------------------
MyProc proc
;进入Ring0了,当然要先叫一声庆祝庆祝!
pushad
mov al,0B6h
out 43h,al
mov al,04h
out 42h,al
out 42h,al
in al,61h
or al,3
out 61h,al
mov ecx,2000000h ;延时
loop $
and al,0FCh ;关声音
out 61h,al
popad
;开始对Kernel32.dll动手术了!
push esi
push edi
lea esi,AddrMessage
lea edi,bAddrMessage
movsd
lea esi,AddrTerminate
lea edi,bTerminate
movsd
lea esi,lpMapped
Object lea edi,blpMapped
Object movsd
mov esi,AddrTerminate
lea edi,OldBytes
xor ecx,ecx
mov cl,7
rep movsb
mov eax,AddrTerminate
mov byte ptr[eax],68h
m2m dword ptr[eax+1],lpMapped
Object mov word ptr[eax+5],90c3h
pop edi
pop esi
retf
MyProc endp
Addr0Proc:
push ebx
push esi
push edi
jmp next
align 4
Caution db '注意',0
Text db '有程序妄图终止其它进程',0dh,0ah
db '阻止吗?',0
bAddrMessage dd ?
bTerminate dd ?
blpMapped
Object dd ?
next:
call tmp
tmp:
pop esi
mov eax,offset tmp-offset Addr0Proc
sub esi,eax
push MB_YESNOCANCEL or MB_ICONWARNING
mov ecx, offset Caution-offset Addr0Proc
add ecx,esi
push ecx
mov ecx, offset Text-offset Addr0Proc
add ecx,esi
push ecx
push dword ptr 0
mov ecx, offset bAddrMessage-offset Addr0Proc
add ecx,esi
call dword ptr[ecx]
.if eax==IDYES
pop edi
pop esi
pop ebx
mov eax,0
ret 8
.elseif eax==IDCANCEL
mov ecx,offset Restore-offset Addr0Proc
add ecx,esi
push ecx
mov ecx,offset ToRing0Code-offset Addr0Proc
add ecx,esi
call ecx
pop edi
pop esi
pop ebx
mov eax,0
ret 8
.endif
mov ecx,offset Restore-offset Addr0Proc
add ecx,esi
push ecx
mov ecx,offset ToRing0Code-offset Addr0Proc
add ecx,esi
call ecx
mov ecx,dword ptr[esp+5*4]
mov edx,dword ptr[esp+4*4]
push ecx
push edx
mov ecx,offset bTerminate-offset Addr0Proc
add ecx,esi
mov edx,offset Back-offset Addr0Proc
add edx,esi
push edx
push dword ptr[ecx]
ret
OldBytes db 7 dup(90h)
Back:
push eax
mov ecx,offset ReChange-offset Addr0Proc
add ecx,esi
push ecx
mov ecx,offset ToRing0Code-offset Addr0Proc
add ecx,esi
call ecx
pop eax
pop edi
pop esi
pop ebx
ret 8
ReChange:
mov ecx,offset bTerminate-offset Addr0Proc
add ecx,esi
mov eax,[ecx]
mov byte ptr[eax],68h
mov ecx,offset blpMapped
Object-offset Addr0Proc
add ecx,esi
m2m dword ptr[eax+1],[ecx]
mov word ptr[eax+5],90c3h
retf
Restore:
push esi
push edi
mov edi,offset bTerminate-offset Addr0Proc
add edi,esi
mov edi,dword ptr[edi]
mov ecx,offset OldBytes-offset Addr0Proc
add esi,ecx
mov ecx,7
cld
rep movsb
pop edi
pop esi
retf
ToRing0Code proc Ring0Proc:DWORD ;生成调用门并调用Ring0子程序Ring0Proc
LOCAL Temp,Temp1
call GetLdtAddress ;取出LDT的地址,返回结果在eax中
mov ecx,[eax] ;保存LDT第一个描述符
mov [Temp],ecx ;
mov ecx,[eax+4] ;
mov [Temp1],ecx ;
mov edx,Ring0Proc ;把调用门的内容写入LDT
mov [eax],dx ;偏移量的低16位
mov word ptr [eax+2],28h ;段选择子
mov word ptr [eax+4],0ec00h ;属性
shr edx,16 ;偏移量的高16位
mov [eax+6],dx ;
push eax
Call32 7,0 ;调用 Ring0 子程序
pop ebx
mov edx,[Temp] ;恢复LDT第一个描述符
mov [ebx],edx ;
mov edx,[Temp1] ;
mov [ebx+4],edx ;
ret
ToRing0Code endp
GetLdtAddress proc ;取LDT的地址
push ebx ;先要取GDT的地址
sgdt [esp-2] ;
pop ebx ;
sldt ax ;取LDT内容
and eax,0fff8H ;屏蔽掉低3位、eax的高16位清0
add ebx,eax ;算出LDT描述符的位置
mov eax,[ebx+2] ;从描述符中取出LDT的地址
mov dl,[ebx+7] ;
shl edx,24 ;
and eax,0ffffffh ;
or eax,edx ;
ret
GetLdtAddress endp
Addr0ProcLength =$-Addr0Proc
END Start