diff --git a/Anti-Rootkit/ARK.cpp b/Anti-Rootkit/ARK.cpp index 05cd370..90b80c7 100644 --- a/Anti-Rootkit/ARK.cpp +++ b/Anti-Rootkit/ARK.cpp @@ -543,6 +543,7 @@ NTSTATUS AntiRootkitDeviceControl(PDEVICE_OBJECT, PIRP Irp) { break; } + case IOCTL_ARK_ENUM_THREAD_NOTIFY: case IOCTL_ARK_ENUM_PROCESS_NOTIFY: { if (Irp->AssociatedIrp.SystemBuffer == nullptr) { @@ -565,6 +566,34 @@ NTSTATUS AntiRootkitDeviceControl(PDEVICE_OBJECT, PIRP Irp) { len = sizeof(void*) * info->Count; break; } + + case IOCTL_ARK_GET_THREAD_NOTIFY_COUNT: + { + if (Irp->AssociatedIrp.SystemBuffer == nullptr) { + status = STATUS_INVALID_PARAMETER; + break; + } + if (dic.InputBufferLength < sizeof(ThreadNotifyCountData)) { + status = STATUS_INVALID_BUFFER_SIZE; + break; + } + if (dic.OutputBufferLength < sizeof(ULONG)) { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + auto info = (ThreadNotifyCountData*)Irp->AssociatedIrp.SystemBuffer; + ULONG count = 0; + if (info->pCount) { + count = *info->pCount; + } + if (info->pNonSystemCount) { + count += *info->pNonSystemCount; + } + *(ULONG*)Irp->AssociatedIrp.SystemBuffer = count; + status = STATUS_SUCCESS; + len = sizeof(count); + break; + } } Irp->IoStatus.Status = status; diff --git a/Anti-Rootkit/AntiRootkit.h b/Anti-Rootkit/AntiRootkit.h index 11203fa..5c30ba7 100644 --- a/Anti-Rootkit/AntiRootkit.h +++ b/Anti-Rootkit/AntiRootkit.h @@ -44,7 +44,7 @@ Typical drivers just use FILE_ANY_ACCESS and deal with the actual request in the // 回调驱动 链接器 命令行 + -----> /integritycheck #define ANTI_ROOTKIT_DEVICE 0x8000 -#define DRIVER_CURRENT_VERSION 0x11 +#define DRIVER_CURRENT_VERSION 0x12 // 用MDL锁定用户内存 // METHOD_OUT_DIRECT in: Irp->AssociatedIrp.SystemBuffer out: Irp->MdlAddress write @@ -64,6 +64,10 @@ Typical drivers just use FILE_ANY_ACCESS and deal with the actual request in the #define IOCTL_ARK_GET_SHADOW_SERVICE_LIMIT CTL_CODE(ANTI_ROOTKIT_DEVICE,0x80A,METHOD_BUFFERED,FILE_ANY_ACCESS) #define IOCTL_ARK_ENUM_PROCESS_NOTIFY CTL_CODE(ANTI_ROOTKIT_DEVICE,0x80B,METHOD_BUFFERED,FILE_ANY_ACCESS) #define IOCTL_ARK_GET_PROCESS_NOTIFY_COUNT CTL_CODE(ANTI_ROOTKIT_DEVICE,0x80C,METHOD_BUFFERED,FILE_ANY_ACCESS) +#define IOCTL_ARK_GET_THREAD_NOTIFY_COUNT CTL_CODE(ANTI_ROOTKIT_DEVICE,0x80D,METHOD_BUFFERED,FILE_ANY_ACCESS) +#define IOCTL_ARK_ENUM_THREAD_NOTIFY CTL_CODE(ANTI_ROOTKIT_DEVICE,0x80E,METHOD_BUFFERED,FILE_ANY_ACCESS) + + @@ -112,4 +116,9 @@ struct NotifyInfo { struct KernelCallbackInfo { ULONG Count; void* Address[ANYSIZE_ARRAY]; +}; + +struct ThreadNotifyCountData { + PULONG pCount; + PULONG pNonSystemCount; }; \ No newline at end of file diff --git a/PdbParser/SymbolHandler.cpp b/PdbParser/SymbolHandler.cpp index 80b037d..ff419c9 100644 --- a/PdbParser/SymbolHandler.cpp +++ b/PdbParser/SymbolHandler.cpp @@ -173,4 +173,12 @@ std::unique_ptr SymbolHandler::CreateForProcess(DWORD pid, PCSTR if (!hProcess) return nullptr; return std::make_unique(hProcess, searchPath); +} + +ULONG SymbolHandler::GetStructSize(std::string name) { + auto symbol = std::make_unique(); + auto info = symbol->GetSymbolInfo(); + SymGetTypeFromName(m_hProcess, _address, name.c_str(), info); + + return info->Size; } \ No newline at end of file diff --git a/PdbParser/SymbolHandler.h b/PdbParser/SymbolHandler.h index a8cd776..86fe5f0 100644 --- a/PdbParser/SymbolHandler.h +++ b/PdbParser/SymbolHandler.h @@ -187,6 +187,9 @@ public: DWORD GetStructMemberOffset(std::string name,std::string memberName); DWORD64 LoadKernelModule(DWORD64 address); + ULONG GetStructSize(std::string name); + + private: BOOL Callback(ULONG code, ULONG64 data); diff --git a/WinArk/KernelHookView.cpp b/WinArk/KernelHookView.cpp index e72d9f6..54615c0 100644 --- a/WinArk/KernelHookView.cpp +++ b/WinArk/KernelHookView.cpp @@ -155,8 +155,8 @@ LRESULT CKernelHookView::OnTcnSelChange(int, LPNMHDR hdr, BOOL&) { void CKernelHookView::InitKernelNotifyTable() { BarDesc bars[] = { {20,"回调函数地址",0}, - {20,"回调类型",0}, - {50,"所在模块",0}, + {15,"回调类型",0}, + {115,"所在模块",0}, {25,"文件厂商",0} }; diff --git a/WinArk/KernelNotifyTable.cpp b/WinArk/KernelNotifyTable.cpp index c9e14c5..99948e9 100644 --- a/WinArk/KernelNotifyTable.cpp +++ b/WinArk/KernelNotifyTable.cpp @@ -155,31 +155,64 @@ void CKernelNotifyTable::Refresh() { info.pRoutine = (void*)symbol->GetSymbolInfo()->Address; ULONG offset = handler.GetStructMemberOffset("_OBJECT_TYPE", "CallbackList"); + if (count > 0) { + wil::unique_virtualalloc_ptr<> buffer(::VirtualAlloc(nullptr, count * sizeof(void*), MEM_COMMIT, PAGE_READWRITE)); - wil::unique_virtualalloc_ptr<> buffer(::VirtualAlloc(nullptr, count * sizeof(void*), MEM_COMMIT, PAGE_READWRITE)); - - KernelCallbackInfo* p = (KernelCallbackInfo*)buffer.get(); - p->Count = count; - DriverHelper::EnumProcessNotify(&info, p); + KernelCallbackInfo* p = (KernelCallbackInfo*)buffer.get(); + p->Count = count; + DriverHelper::EnumProcessNotify(&info, p); - m_Table.data.info.clear(); - m_Table.data.n = 0; - for (int i = 0; i < count; i++) { - CallbackInfo info; - info.Routine = p->Address[i]; - info.Type = CallbackType::CreateProcessNotify; - info.Module = Helpers::GetModuleByAddress((ULONG_PTR)info.Routine); - std::wstring path(info.Module.begin(), info.Module.end()); - info.Company = GetCompanyName(path); - m_Table.data.info.push_back(std::move(info)); + m_Table.data.info.clear(); + m_Table.data.n = 0; + for (int i = 0; i < count; i++) { + CallbackInfo info; + info.Routine = p->Address[i]; + info.Type = CallbackType::CreateProcessNotify; + info.Module = Helpers::GetModuleByAddress((ULONG_PTR)info.Routine); + std::wstring path(info.Module.begin(), info.Module.end()); + info.Company = GetCompanyName(path); + m_Table.data.info.push_back(std::move(info)); + } } + + + count = 0; + ThreadNotifyCountData threadData; + symbol = handler.GetSymbolFromName("PspCreateThreadNotifyRoutineCount"); + threadData.pCount = (PULONG)symbol->GetSymbolInfo()->Address; + symbol = handler.GetSymbolFromName("PspCreateThreadNotifyRoutineNonSystemCount"); + threadData.pNonSystemCount = (PULONG)symbol->GetSymbolInfo()->Address; + count = DriverHelper::GetThreadNotifyCount(&threadData); + if (count > 0) { + info.Count = count; + symbol = handler.GetSymbolFromName("PspCreateThreadNotifyRoutine"); + info.pRoutine = (void*)symbol->GetSymbolInfo()->Address; + wil::unique_virtualalloc_ptr<> buffer(::VirtualAlloc(nullptr, count * sizeof(void*), MEM_COMMIT, PAGE_READWRITE)); + KernelCallbackInfo* p = (KernelCallbackInfo*)buffer.get(); + p->Count = count; + DriverHelper::EnumThreadNotify(&info, p); + for (int i = 0; i < count; i++) { + CallbackInfo info; + info.Routine = p->Address[i]; + info.Type = CallbackType::CreateThreadNotify; + info.Module = Helpers::GetModuleByAddress((ULONG_PTR)info.Routine); + std::wstring path(info.Module.begin(), info.Module.end()); + info.Company = GetCompanyName(path); + m_Table.data.info.push_back(std::move(info)); + } + } + + m_Table.data.n = m_Table.data.info.size(); } std::wstring CKernelNotifyTable::GetCompanyName(std::wstring path) { BYTE buffer[1 << 12]; WCHAR* companyName = nullptr; - if (::GetFileVersionInfo(path.c_str(), 0, sizeof(buffer), buffer)) { + CString filePath = path.c_str(); + if (filePath.Mid(1, 2) == "??") + filePath = filePath.Mid(4); + if (::GetFileVersionInfo(filePath, 0, sizeof(buffer), buffer)) { WORD* langAndCodePage; UINT len; if (::VerQueryValue(buffer, L"\\VarFileInfo\\Translation", (void**)&langAndCodePage, &len)) { @@ -190,6 +223,6 @@ std::wstring CKernelNotifyTable::GetCompanyName(std::wstring path) { return companyName; } } - return companyName; + return L""; } diff --git a/WinSysCore/DriverHelper.cpp b/WinSysCore/DriverHelper.cpp index 5776144..8e0f014 100644 --- a/WinSysCore/DriverHelper.cpp +++ b/WinSysCore/DriverHelper.cpp @@ -301,6 +301,17 @@ ULONG DriverHelper::GetProcessNotifyCount(ProcessNotifyCountData *pData) { return count; } +ULONG DriverHelper::GetThreadNotifyCount(ThreadNotifyCountData* pData) { + if (!OpenDevice()) + return 0; + + ULONG count = 0; + DWORD bytes; + ::DeviceIoControl(_hDevice, IOCTL_ARK_GET_THREAD_NOTIFY_COUNT, pData, sizeof(ThreadNotifyCountData), + &count, sizeof(count), &bytes, nullptr); + return count; +} + bool DriverHelper::EnumProcessNotify(NotifyInfo* pNotifyInfo, KernelCallbackInfo* pCallbackInfo) { if (!OpenDevice()) return false; @@ -310,4 +321,15 @@ bool DriverHelper::EnumProcessNotify(NotifyInfo* pNotifyInfo, KernelCallbackInfo ::DeviceIoControl(_hDevice, IOCTL_ARK_ENUM_PROCESS_NOTIFY, pNotifyInfo, sizeof(NotifyInfo), pCallbackInfo, size, &bytes, nullptr); return true; +} + +bool DriverHelper::EnumThreadNotify(NotifyInfo* pNotifyInfo, KernelCallbackInfo* pCallbackInfo) { + if (!OpenDevice()) + return false; + + DWORD bytes; + DWORD size = pCallbackInfo->Count * sizeof(pCallbackInfo->Address); + ::DeviceIoControl(_hDevice, IOCTL_ARK_ENUM_THREAD_NOTIFY, pNotifyInfo, sizeof(NotifyInfo), + pCallbackInfo, size, &bytes, nullptr); + return true; } \ No newline at end of file diff --git a/WinSysCore/DriverHelper.h b/WinSysCore/DriverHelper.h index d1d36b1..fbf38ff 100644 --- a/WinSysCore/DriverHelper.h +++ b/WinSysCore/DriverHelper.h @@ -23,7 +23,10 @@ struct DriverHelper final { static PULONG GetShadowServiceTable(); static ULONG GetShadowServiceLimit(); static ULONG GetProcessNotifyCount(ProcessNotifyCountData* pData); + static ULONG GetThreadNotifyCount(ThreadNotifyCountData* pData); static bool EnumProcessNotify(NotifyInfo* pNotifyInfo, KernelCallbackInfo* pCallbackInfo); + static bool EnumThreadNotify(NotifyInfo* pNotifyInfo, KernelCallbackInfo* pCallbackInfo); + private: static bool OpenDevice(); diff --git a/WinSysCore/KernelModuleTracker.cpp b/WinSysCore/KernelModuleTracker.cpp index 77533e2..fd4dc58 100644 --- a/WinSysCore/KernelModuleTracker.cpp +++ b/WinSysCore/KernelModuleTracker.cpp @@ -20,6 +20,7 @@ uint32_t WinSys::KernelModuleTracker::EnumModules() { CHAR winDir[MAX_PATH]; ::GetWindowsDirectoryA(winDir, _countof(winDir)); static const std::string root("\\SystemRoot\\"); + static const std::string global("\\??\\"); for (;;) { if (p->BaseInfo.ImageBase == 0) @@ -27,6 +28,8 @@ uint32_t WinSys::KernelModuleTracker::EnumModules() { auto m = std::make_shared(); m->Flags = p->BaseInfo.Flags; m->FullPath = (const char*)p->BaseInfo.FullPathName; + if (m->FullPath.find(global) == 0) + m->FullPath = m->FullPath.substr(global.size()); if (m->FullPath.find(root) == 0) m->FullPath = winDir + m->FullPath.substr(root.size() - 1); m->ImageBase = p->BaseInfo.ImageBase;