📄 hookprocess.cpp
字号:
#include "HookProcess.h"
#include "CommonFunc.h"
/////////////////////////////////////////////////////////////////////////////////////////
extern "C"
{
typedef NTSTATUS (*NtQuerySystemInfo)(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
NtQuerySystemInfo TrueNtQuerySystemInfo;
NTSTATUS NewNtQuerySystemInfo(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
NTSTATUS CompleteIrp( PIRP Irp, NTSTATUS status, ULONG info);
}
// Synchronization object
static wrSync sProcessWRSync;
// Process names to hide
struct _ProcInfo
{
UNICODE_STRING Name;
UNICODE_STRING User;
UNICODE_STRING Proc;
void Clear()
{
RtlFreeUnicodeString(&Name);
RtlFreeUnicodeString(&User);
RtlFreeUnicodeString(&Proc);
}
};
typedef std::vector<_ProcInfo> vProcInfo;
static vProcInfo sProcInfo;
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS AddProcessName(WCHAR* pBuf,ULONG buf_size,ULONG out_buf_size,PULONG BytesTxd)
/*++
Routine Description:
Add process name to hide list
Arguments:
WCHAR* pBuf - input/output buffer
ULONG buf_size - input buffer size
ULONG out_buf_size - max output buf size
PULONG BytesTxd - size of information writed in output buffer
Return Value:
NTSTATUS code.
--*/
{
DbgPrint("-HideDriver- Add Process Name - Input string: %ws\n",pBuf);
if(out_buf_size< 2 || buf_size==0)
return STATUS_BUFFER_TOO_SMALL;
UNICODE_STRING Name;
UNICODE_STRING User;
UNICODE_STRING Proc;
if(!PackadgeParser(pBuf,&Name,&User,&Proc))
{
*pBuf=HOOK_FAIL_PARAMETER;
*BytesTxd = 2;
RtlFreeUnicodeString(&Name);
RtlFreeUnicodeString(&User);
RtlFreeUnicodeString(&Proc);
return STATUS_SUCCESS;
}
sProcessWRSync.WaitToWrite();
sProcInfo.push_back(_ProcInfo());
size_t nIndex = sProcInfo.size() - 1;
sProcInfo[nIndex].Name = Name;
sProcInfo[nIndex].User = User;
sProcInfo[nIndex].Proc = Proc;
sProcessWRSync.Done();
*pBuf=HOOK_SUCCESS;
*BytesTxd = 2;
return STATUS_SUCCESS;
}
NTSTATUS DelProcessName(WCHAR* pBuf,ULONG buf_size,ULONG out_buf_size,PULONG BytesTxd)
/*++
Routine Description:
Delete process name from hide list
Arguments:
WCHAR* pBuf - input/output buffer
ULONG buf_size - input buffer size
ULONG out_buf_size - max output buf size
PULONG BytesTxd - size of information writed in output buffer
Return Value:
NTSTATUS code.
--*/
{
DbgPrint("-HideDriver- Del Process Name - Input string: %ws\n",pBuf);
if(out_buf_size< 2 || buf_size==0)
return STATUS_BUFFER_TOO_SMALL;
UNICODE_STRING myUStr;
RtlInitUnicodeString(&myUStr,pBuf);
sProcessWRSync.WaitToWrite();
vProcInfo::iterator it = sProcInfo.begin();
while(sProcInfo.end() != it)
{
if(RtlEqualUnicodeString(&myUStr,&(*it).Name,FALSE))
{
// Clenup buffers
(*it).Clear();
// Delete from array
sProcInfo.erase(it);
sProcessWRSync.Done();
*pBuf=HOOK_SUCCESS;
*BytesTxd = 2;
return STATUS_SUCCESS;
}
++it;
}
sProcessWRSync.Done();
*pBuf= HOOK_FAIL_PARAMETER;
*BytesTxd = 2;
return STATUS_SUCCESS;
}
NTSTATUS ClearProcessNames(WCHAR* pBuf,ULONG buf_size,ULONG out_buf_size,PULONG BytesTxd)
/*++
Routine Description:
Delete process name from hide list.
Arguments:
WCHAR* pBuf - input/output buffer
ULONG buf_size - input buffer size
ULONG out_buf_size - max output buf size
PULONG BytesTxd - size of information writed in output buffer
Return Value:
NTSTATUS code.
--*/
{
DbgPrint("-HideDriver- Clear Process Names\n");
if(out_buf_size< 2)
return STATUS_BUFFER_TOO_SMALL;
sProcessWRSync.WaitToWrite();
vProcInfo::iterator it = sProcInfo.begin();
while(sProcInfo.end() != it)
{
// Cleanup buffers;
(*it).Clear();
++it;
}
sProcInfo.clear();
sProcessWRSync.Done();
*pBuf=HOOK_SUCCESS;
*BytesTxd = 2;
return STATUS_SUCCESS;
}
NTSTATUS QueryProcessNames(WCHAR* pBuf,ULONG buf_size,ULONG out_buf_size,PULONG BytesTxd)
/*++
Routine Description:
Query all process names from hide list. List consist of:
- Process name to hide
- User name, not used now, but reserved for future implementation
- Process name to hide from
Arguments:
WCHAR* pBuf - input/output buffer
ULONG buf_size - input buffer size
ULONG out_buf_size - max output buf size
PULONG BytesTxd - size of information writed in output buffer
Return Value:
NTSTATUS code.
--*/
{
DbgPrint("-HideDriver- Query Process Names\n");
if(out_buf_size< 2 || buf_size==0)
return STATUS_BUFFER_TOO_SMALL;
sProcessWRSync.WaitToRead();
ULONG nIndex=0;
vProcInfo::iterator it = sProcInfo.begin();
while(sProcInfo.end() != it)
{
size_t Name_size = (*it).Name.Length;
size_t User_size = (*it).User.Length;
size_t Proc_size = (*it).Proc.Length;
size_t Total_size = Name_size+User_size+Proc_size;
if((Total_size + nIndex) > out_buf_size)
{
sProcessWRSync.Done();
*pBuf = HOOK_FAIL_PARAMETER;
*BytesTxd = 2;
return STATUS_BUFFER_TOO_SMALL;
}
// Process Name
memcpy((char*)pBuf + nIndex,(*it).Name.Buffer,Name_size);
nIndex+=Name_size;
memcpy((char*)pBuf + nIndex,L";",2);
nIndex+=2;
// Access User Name
memcpy((char*)pBuf + nIndex,(*it).User.Buffer,User_size);
nIndex+=User_size;
memcpy((char*)pBuf + nIndex,L";",2);
nIndex+=2;
// Access Process Name
memcpy((char*)pBuf + nIndex,(*it).Proc.Buffer,Proc_size);
nIndex+=Proc_size;
memcpy((char*)pBuf + nIndex,L";",2);
nIndex+=2;
// Packet end
memcpy((char*)pBuf + nIndex,L"\n",2);
nIndex+=2;
++it;
}
sProcessWRSync.Done();
memcpy((char*)pBuf + nIndex,L"\0",2);
nIndex+=2;
*BytesTxd = nIndex;
return STATUS_SUCCESS;
}
NTSTATUS HookProcessIrpRoutine(PIRP pIrp)
/*++
Routine Description:
Dispatch IOCTL's from user:
IOCTL_ADD_PROCESS_NAME - Add process name to hide list
IOCTL_DEL_PROCESS_NAME - Delete process name from hide list
IOCTL_CLEAR_PROCESS_NAME - Erase all process names from hide list
IOCTL_QUERY_PROCESS_NAME - Query all process names from hide list
Arguments:
RIRP - irp packet with information about call
Return Value:
NTSTATUS code.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
ULONG BytesTxd =0; // Number of transmitted,received bytes
PIO_STACK_LOCATION IrpStack=IoGetCurrentIrpStackLocation(pIrp);
// Getting the IOCTL code
ULONG ControlCode =
IrpStack->Parameters.DeviceIoControl.IoControlCode;
// Getting the exchange method
ULONG method = ControlCode & 0x03;
if(method!=METHOD_BUFFERED)
return CompleteIrp(pIrp,STATUS_INVALID_PARAMETER,BytesTxd);
// input buffer size
ULONG InputLength =
IrpStack->Parameters.DeviceIoControl.InputBufferLength;
// output buffer size
ULONG OutputLength =
IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
// if there is no buffer generate the error
if( OutputLength < 1 || InputLength < 1)
return CompleteIrp(pIrp,STATUS_INVALID_PARAMETER,BytesTxd);
WCHAR *buff;
buff = (PWCHAR)pIrp->AssociatedIrp.SystemBuffer;
switch( ControlCode)
{
case IOCTL_ADD_PROCESS_NAME:
status = AddProcessName(buff,InputLength,OutputLength,&BytesTxd); break;
case IOCTL_DEL_PROCESS_NAME:
status = DelProcessName(buff,InputLength,OutputLength,&BytesTxd); break;
case IOCTL_CLEAR_PROCESS_NAME:
status = ClearProcessNames(buff,InputLength,OutputLength,&BytesTxd); break;
case IOCTL_QUERY_PROCESS_NAME:
status = QueryProcessNames(buff,InputLength,OutputLength,&BytesTxd); break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
}
return CompleteIrp(pIrp,status,BytesTxd);
}
void HookProcessInit(HookMng& refHookMng,QueryMng& refQueryMng)
/*++
Routine Description:
Perform initializing of objects needed for process hiding.
Insert hook in SSDT and register dispatcher for IOCTL's
Arguments:
HookMng - needed to add hook of specific function on SSDT
QueryMng - need to add response of IOCTL needed to receive information from user
Return Value:
nothing
--*/
{
UNICODE_STRING funcUnicodeStr_process;
RtlInitUnicodeString(&funcUnicodeStr_process,L"ZwQuerySystemInformation");
//
std::auto_ptr<Hook> pNewHook(
CreateHook( NewNtQuerySystemInfo,
&funcUnicodeStr_process));
TrueNtQuerySystemInfo = (NtQuerySystemInfo)pNewHook->mpTrueFuncPtr;
if(!refHookMng.QueueHook(*pNewHook))
DbgPrint("Hook installing error2\n");
//
refQueryMng.AddRoutine(IOCTL_ADD_PROCESS_NAME,&HookProcessIrpRoutine);
refQueryMng.AddRoutine(IOCTL_DEL_PROCESS_NAME,&HookProcessIrpRoutine);
refQueryMng.AddRoutine(IOCTL_CLEAR_PROCESS_NAME,&HookProcessIrpRoutine);
refQueryMng.AddRoutine(IOCTL_QUERY_PROCESS_NAME,&HookProcessIrpRoutine);
}
void HookProcessExit()
/*++
Routine Description:
Perform cleanup of objects needed for process hiding.
Arguments:
none
Return Value:
nothing
--*/
{
sProcessWRSync.WaitToWrite();
vProcInfo::iterator it = sProcInfo.begin();
while(sProcInfo.end() != it)
{
// Cleanup buffers;
(*it).Clear();
++it;
}
sProcInfo.clear();
sProcessWRSync.Done();
}
bool CheckProcess(UNICODE_STRING* pProcessName)
/*++
Routine Description:
Function check process name to make decision about hiding it
Arguments:
Name of process to check
Return Value:
true - if process need to hide
false - if process do not need to hide
--*/
{
sProcessWRSync.WaitToRead();
vProcInfo::iterator it = sProcInfo.begin();
for(;sProcInfo.end() != it;++it)
{
if(!ApplyMask(&(*it).Name,pProcessName))
continue;
if(!CheckProcessAccess(&(*it).Proc))
continue;
//if(!CheckUserAccess(&(*it).User))
// continue;
sProcessWRSync.Done();
return true;
}
sProcessWRSync.Done();
return false;
}
NTSTATUS NewNtQuerySystemInfo(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
)
/*++
Routine Description:
Function call every time when NtQuerySystemInformation function call in the system.
For hiding process we need to change SystemInformation structure.
Arguments:
SystemInformationClass - One of the values enumerated in SYSTEM_INFORMATION_CLASS,
which indicate the kind of system information to be retrieved.
SystemInformation - A pointer to a buffer that receives the requested information.
SystemInformationLength - The size of the buffer pointed to by the SystemInformation parameter, in bytes.
Return Value:
NT status code.
--*/
{
NTSTATUS status=TrueNtQuerySystemInfo(SystemInformationClass, SystemInformation,
SystemInformationLength, ReturnLength);
if(!NT_SUCCESS(status))return status;
if( SystemInformationClass == SystemProcessesAndThreadsInformation )
{
// convert buffer to SYSTEM_PROCESSES_INFORMATION
SYSTEM_PROCESSES_INFORMATION* pSystemInfo=static_cast<SYSTEM_PROCESSES_INFORMATION*>(SystemInformation);
ULONG PreviousDelta=0;
// The loop for enumerating process
while( pSystemInfo->NextEntryDelta != 0 )
{
// go to the next process ( idle is always the first process )
PreviousDelta = pSystemInfo->NextEntryDelta;
pSystemInfo = (SYSTEM_PROCESSES_INFORMATION*)(((PUCHAR)pSystemInfo)+PreviousDelta);
// check if the current process need to hide
if( CheckProcess(&(pSystemInfo->ProcessName)) )
{
// go to the previous process
ULONG curentDelta=pSystemInfo->NextEntryDelta;
pSystemInfo =
(SYSTEM_PROCESSES_INFORMATION*)(((PUCHAR)pSystemInfo)-PreviousDelta);
// if the process is last:
if(curentDelta == 0 )
PreviousDelta=0;
pSystemInfo->NextEntryDelta = PreviousDelta + curentDelta;
} // if(CheckProcessName(pSystemInfo->ProcessName))
}//while(pSystemInfo->NextEntryDelta != 0)
}// if(SystemInformationClass == SystemProcessesAndThreadsInformation)
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -