Windows ObjectType Hook 之 OpenProcedure

1、背景

  Object Type Hook 是基于 Object Type的一种深入的 Hook,比起常用的 SSDT Hook 更为深入。

  有关 Object Type 的分析见文章 《Windows驱动开发学习记录-ObjectType Hook之ObjectType结构相关分析》。

  这里进行的 Hook 为 其中之一的 OpenProcedure。文章分两部分,分别实现 Event 对象和 Process 对象的过滤。

2、OpenProcedure 函数声明

  见文章 《Windows驱动开发学习记录-ObjectType Hook之ObjectType结构相关分析》。

  这里取 x64 环境下结构:

typedef NTSTATUS (*OB_OPEN_METHOD)(IN OB_OPEN_REASON OpenReason,IN CHAR Flag,IN PEPROCESS Process OPTIONAL,IN PVOID Object,IN OUT PACCESS_MASK GrantedAccess,IN ULONG HandleCount);

3、Event 对象过滤

3.1 实验目标

  这里实验的目标魔兽争霸3,正常情况下只能单开,如下图所示:

  这里多开即会提示已经运行的消息,使用的是大多数程序单例运行的处理逻辑,启动时创建一个命名事件,然后进行相关判断。

3.2 魔兽的IDA分析

  用 IDA 分析魔兽的 Frozen Throne.exe,如下:

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{......v4 = 0;ExitCode = 0;v5 = GetTickCount() + 25000;v19 = v5;hObject = CreateEventA(0, 0, 0, LauncherName);if (GetLastError() == 183){CloseHandle(hObject);result = 0;}else{v17 = CreateEventA(0, 0, 0, aWarcraftIiiGam);if (GetLastError() == 183){LoadStringA(hInstance, 0xCu, Buffer, 260);LoadStringA(hInstance, 0xDu, Caption, 260);MessageBoxA(0, Buffer, Caption, 0);CloseHandle(v17);result = 0;}else{......

  其中 LanucherName 和 aWarcraftIiiGam 定义如下:

.data:00408048 ; CHAR aWarcraftIiiGam[]
.data:00408048 aWarcraftIiiGam db 'Warcraft III Game Application',0
.data:00408048                                         ; DATA XREF: WinMain(x,x,x,x):loc_40105F↑o
.data:00408066                 align 4
.data:00408068 ; CHAR LauncherName[]
.data:00408068 LauncherName    db 'WARCRAFT_III_LAUNCHER',0

  可以看出逻辑是创建这两个命名事件,如果返回 183,即 当文件已存在时,无法创建该文件的情况,表示已经在运行了,然后弹出上边的对话框。

  我们这里要实现的功能就是让它在创建命名事件时不返回 183,而是直接返回拒绝访问,按以上的逻辑就可以实现魔兽的多开。

3.3 实现代码

#pragma once
#include <ntifs.h>#if DBG
#define KDPRINT(projectName, format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,\projectName "::【" __FUNCTION__  "】" ##format, \##__VA_ARGS__ ) 
#else
#define KDPRINT(format, ...)
#endiftypedef struct _OBJECT_TYPE_FLAGS {UCHAR CaseInsensitive : 1;UCHAR UnnamedObjectsOnly : 1;UCHAR UseDefaultObject : 1;UCHAR SecurityRequired : 1;UCHAR MaintainHandleCount : 1;UCHAR MaintainTypeList : 1;UCHAR SupportsObjectCallbacks : 1;UCHAR CacheAligned : 1;
}OBJECT_TYPE_FLAGS, * P_OBJECT_TYPE_FLAGS;typedef struct _OBJECT_TYPE_INITIALIZER {USHORT				wLength;OBJECT_TYPE_FLAGS	ObjectTypeFlags;ULONG				ObjcetTypeCode;ULONG				InvalidAttributes;GENERIC_MAPPING		GenericMapping;ULONG				ValidAccessMask;ULONG				RetainAccess;ULONG				PoolType;ULONG				DefaultPagedPoolCharge;ULONG				DefaultNonPagedPoolCharge;PVOID				DumpProcedure;PVOID				OpenProcedure;PVOID				CloseProcedure;PVOID				DeleteProcedure;PVOID				ParseProcedure;PVOID				SecurityProcedure;PVOID				QueryNameProcedure;PVOID				OkayToCloseProcedure;
}OBJECT_TYPE_INITIALIZER, * POBJECT_TYPE_INITIALIZER;typedef struct _OBJECT_TYPE_EX {LIST_ENTRY					TypeList;UNICODE_STRING				Name;ULONGLONG					DefaultObject;ULONG						Index;ULONG						TotalNumberOfObjects;ULONG						TotalNumberOfHandles;ULONG						HighWaterNumberOfObjects;ULONG						HighWaterNumberOfHandles;OBJECT_TYPE_INITIALIZER		TypeInfo;ULONGLONG					TypeLock;ULONG						Key;LIST_ENTRY					CallbackList;
}OBJECT_TYPE_EX, * POBJECT_TYPE_EX;typedef enum _OB_OPEN_REASON {ObCreateHandle,ObOpenHandle,ObDuplicateHandle,ObInheritHandle,ObMaxOpenReason
} OB_OPEN_REASON;typedef
NTSTATUS
(NTAPI* POPEN_PROCEDURE)(IN OB_OPEN_REASON Reason,IN CHAR cUnnamed,IN PEPROCESS Process OPTIONAL,IN PVOID ObjectBody,IN PACCESS_MASK GrantedAccess,IN ULONG HandleCount);typedef struct _OBJECT_TYPE_HOOK_INFORMATION
{POBJECT_TYPE_EX pHookedObject;POPEN_PROCEDURE pOringinalOpenProcedureAddress;
}OBJECT_TYPE_HOOK_INFORMATION, * POBJECT_TYPE_HOOK_INFORMATION;OBJECT_TYPE_HOOK_INFORMATION g_HookInfomation = { 0 };UNICODE_STRING g_usEventWarIIIOK = RTL_CONSTANT_STRING(L"*WARCRAFT_III_OK*");
UNICODE_STRING g_usEventWarIIIGameApplication = RTL_CONSTANT_STRING(L"*WARCRAFT III GAME APPLICATION*");
UNICODE_STRING g_usEventWarIIILauncher = RTL_CONSTANT_STRING(L"*WARCRAFT_III_LAUNCHER*");
PVOID GetObTypeIndexTable()
{UNICODE_STRING usObGetObjectType = RTL_CONSTANT_STRING(L"ObGetObjectType");PVOID pGetObTypeIndexTable = NULL;PVOID pObGetObjectType = (PVOID)MmGetSystemRoutineAddress(&usObGetObjectType);do{if (!pObGetObjectType){KDPRINT("【ObjectTypeHook】", "MmGetSystemRoutineAddress Failed! \r\n");break;}PUCHAR pStartAddress = (PUCHAR)pObGetObjectType;PUCHAR pTempAddress = pStartAddress;for (; pTempAddress < pStartAddress + PAGE_SIZE; pTempAddress++){if ((*(pTempAddress - 3) == 0x48) &&(*(pTempAddress - 2) == 0x8d) &&(*(pTempAddress - 1) == 0x0d) &&(*(pTempAddress + 4) == 0x48) &&(*(pTempAddress + 5) == 0x8b) &&(*(pTempAddress + 6) == 0x04) &&(*(pTempAddress + 7) == 0xc1)){LONG lOffset = *(PLONG)(pTempAddress);pGetObTypeIndexTable = pTempAddress + 4 + lOffset;break;}}} while (false);if (pGetObTypeIndexTable){KDPRINT("【ObRegisterCallback】", "Found ObTypeIndexTable Address:0x%p \r\n", pGetObTypeIndexTable);}else{KDPRINT("【ObjectTypeHook】", "ObTypeIndexTable Not Found!\r\n");}return pGetObTypeIndexTable;
}void HookObjectType(PVOID pObTypeIndexTable, PUNICODE_STRING pUsObjectTypeName, PVOID pHookFunction)
{if (pObTypeIndexTable){PUCHAR pStartAddress = ((PUCHAR)pObTypeIndexTable + 8 * 2); //从第2个开始POBJECT_TYPE_EX* pTempObjectType = (POBJECT_TYPE_EX*)(pStartAddress);ULONG ulIndex = 0;PVOID pOpenProcedureAddress = NULL;while (*pTempObjectType != NULL){KDPRINT("【ObjectTypeHook】", "Index:%02ld  Address:0x%p Name:%wZ\r\n",ulIndex,*pTempObjectType,&(*pTempObjectType)->Name);if (RtlCompareUnicodeString(&(*pTempObjectType)->Name, pUsObjectTypeName, true) == 0){KDPRINT("【ObjectTypeHook】", "Found Target, Hooking...\r\n");g_HookInfomation.pHookedObject = *pTempObjectType;g_HookInfomation.pOringinalOpenProcedureAddress =(POPEN_PROCEDURE)(*pTempObjectType)->TypeInfo.OpenProcedure;pOpenProcedureAddress  = &((*pTempObjectType)->TypeInfo.OpenProcedure);InterlockedExchangePointer((PVOID*)pOpenProcedureAddress, pHookFunction);}pTempObjectType++;ulIndex++;}}
}NTSTATUS
NTAPI
CustomEventOpen(IN OB_OPEN_REASON Reason,IN CHAR Flag,IN PEPROCESS Process OPTIONAL,IN PVOID ObjectBody,IN PACCESS_MASK GrantedAccess,IN ULONG HandleCount)
{NTSTATUS ntStatus = STATUS_SUCCESS;ULONG ulRet = 0;BOOLEAN bFilterEvent = false;if (Reason == OB_OPEN_REASON::ObCreateHandle){if (ObjectBody){POBJECT_NAME_INFORMATION pName = (POBJECT_NAME_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, 1024, 'Mut');if (pName){ntStatus = ObQueryNameString(ObjectBody, pName, 1024, &ulRet);if (NT_SUCCESS(ntStatus)){if (//FsRtlIsNameInExpression(&g_usWarIIIOK, &pName->Name, true, NULL) ||FsRtlIsNameInExpression(&g_usEventWarIIIGameApplication, &pName->Name, true, NULL) ||FsRtlIsNameInExpression(&g_usEventWarIIILauncher, &pName->Name, true, NULL)){KDPRINT("【ObjectTypeHook】", "Need Filter Event Name Is %wZ\r\n", &pName->Name);bFilterEvent = true;}}ExFreePoolWithTag(pName, 'name');}}}if (bFilterEvent){return STATUS_ACCESS_DENIED;}else{ntStatus = STATUS_SUCCESS;if (g_HookInfomation.pOringinalOpenProcedureAddress){ntStatus = g_HookInfomation.pOringinalOpenProcedureAddress(Reason, Flag, Process, ObjectBody, GrantedAccess, HandleCount);}return ntStatus;}}void UnHookObjectType()
{KDPRINT("【ObjectTypeHook】", "UnHook...\r\n");if (g_HookInfomation.pHookedObject){InterlockedExchangePointer((PVOID*)(&g_HookInfomation.pHookedObject->TypeInfo.OpenProcedure), g_HookInfomation.pOringinalOpenProcedureAddress);}
}VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{UNREFERENCED_PARAMETER(pDriverObject);KDPRINT("【ObjectTypeHook】", "CurrentProcessId : 0x%p CurrentIRQL : 0x%u \r\n",PsGetCurrentProcessId(),KeGetCurrentIrql());UnHookObjectType();
}EXTERN_C NTSTATUS  DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
{UNREFERENCED_PARAMETER(pDriverObject);UNREFERENCED_PARAMETER(pRegistryPath);NTSTATUS ntStatus = STATUS_SUCCESS;KDPRINT("【ObjectTypeHook】", " Hello Kernel World! CurrentProcessId:0x%p CurrentIRQL:0x%u\r\n",PsGetCurrentProcessId(),KeGetCurrentIrql());pDriverObject->DriverUnload = DriverUnload;UNICODE_STRING usEventName = RTL_CONSTANT_STRING(L"Event");PVOID pGetObTypeIndexTable = GetObTypeIndexTable();if (pGetObTypeIndexTable){HookObjectType(pGetObTypeIndexTable, &usEventName, CustomEventOpen);}return ntStatus;
}

  其中 GetObTypeIndexTable 是利用特征码搜索 Object Type, 详细参见《遍历Windows内核ObjectType》。

3.4 实现效果

  安装驱动效果如下:

  再打开魔兽争霸,效果如下:

4、Process 对象过滤

  实现原理同 Event 对象过滤,只不过对象换成了 Process。

  在任务管理器结束进程时要先打开目标进程,然后再结束,我这里在打开进程时直接返回失败来实现相关过滤。

4.1 实现代码


#if DBG
#define KDPRINT(projectName, format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,\projectName "::【" __FUNCTION__  "】" ##format, \##__VA_ARGS__ ) 
#else
#define KDPRINT(format, ...)
#endiftypedef struct _OBJECT_TYPE_FLAGS {UCHAR CaseInsensitive : 1;UCHAR UnnamedObjectsOnly : 1;UCHAR UseDefaultObject : 1;UCHAR SecurityRequired : 1;UCHAR MaintainHandleCount : 1;UCHAR MaintainTypeList : 1;UCHAR SupportsObjectCallbacks : 1;UCHAR CacheAligned : 1;
}OBJECT_TYPE_FLAGS, * P_OBJECT_TYPE_FLAGS;typedef struct _OBJECT_TYPE_INITIALIZER {USHORT				wLength;OBJECT_TYPE_FLAGS	ObjectTypeFlags;ULONG				ObjcetTypeCode;ULONG				InvalidAttributes;GENERIC_MAPPING		GenericMapping;ULONG				ValidAccessMask;ULONG				RetainAccess;ULONG				PoolType;ULONG				DefaultPagedPoolCharge;ULONG				DefaultNonPagedPoolCharge;PVOID				DumpProcedure;PVOID				OpenProcedure;PVOID				CloseProcedure;PVOID				DeleteProcedure;PVOID				ParseProcedure;PVOID				SecurityProcedure;PVOID				QueryNameProcedure;PVOID				OkayToCloseProcedure;
}OBJECT_TYPE_INITIALIZER, * POBJECT_TYPE_INITIALIZER;typedef struct _OBJECT_TYPE_EX {LIST_ENTRY					TypeList;UNICODE_STRING				Name;ULONGLONG					DefaultObject;ULONG						Index;ULONG						TotalNumberOfObjects;ULONG						TotalNumberOfHandles;ULONG						HighWaterNumberOfObjects;ULONG						HighWaterNumberOfHandles;OBJECT_TYPE_INITIALIZER		TypeInfo;ULONGLONG					TypeLock;ULONG						Key;LIST_ENTRY					CallbackList;
}OBJECT_TYPE_EX, * POBJECT_TYPE_EX;typedef enum _OB_OPEN_REASON {ObCreateHandle,ObOpenHandle,ObDuplicateHandle,ObInheritHandle,ObMaxOpenReason
} OB_OPEN_REASON;typedef
NTSTATUS
(NTAPI* POPEN_PROCEDURE)(IN OB_OPEN_REASON Reason,IN CHAR cUnnamed,IN PEPROCESS Process OPTIONAL,IN PVOID ObjectBody,IN PACCESS_MASK GrantedAccess,IN ULONG HandleCount);typedef struct _OBJECT_TYPE_HOOK_INFORMATION
{POBJECT_TYPE_EX pHookedObject;POPEN_PROCEDURE pOringinalOpenProcedureAddress;
}OBJECT_TYPE_HOOK_INFORMATION, * POBJECT_TYPE_HOOK_INFORMATION;OBJECT_TYPE_HOOK_INFORMATION g_HookInfomation = { 0 };PVOID GetObTypeIndexTable()
{UNICODE_STRING usObGetObjectType = RTL_CONSTANT_STRING(L"ObGetObjectType");PVOID pGetObTypeIndexTable = NULL;PVOID pObGetObjectType = (PVOID)MmGetSystemRoutineAddress(&usObGetObjectType);do{if (!pObGetObjectType){KDPRINT("【ObjectTypeHook】", "MmGetSystemRoutineAddress Failed! \r\n");break;}PUCHAR pStartAddress = (PUCHAR)pObGetObjectType;PUCHAR pTempAddress = pStartAddress;for (; pTempAddress < pStartAddress + PAGE_SIZE; pTempAddress++){if ((*(pTempAddress - 3) == 0x48) &&(*(pTempAddress - 2) == 0x8d) &&(*(pTempAddress - 1) == 0x0d) &&(*(pTempAddress + 4) == 0x48) &&(*(pTempAddress + 5) == 0x8b) &&(*(pTempAddress + 6) == 0x04) &&(*(pTempAddress + 7) == 0xc1)){LONG lOffset = *(PLONG)(pTempAddress);pGetObTypeIndexTable = pTempAddress + 4 + lOffset;break;}}} while (false);if (pGetObTypeIndexTable){KDPRINT("【ObRegisterCallback】", "Found ObTypeIndexTable Address:0x%p \r\n", pGetObTypeIndexTable);}else{KDPRINT("【ObjectTypeHook】", "ObTypeIndexTable Not Found!\r\n");}return pGetObTypeIndexTable;
}void HookObjectType(PVOID pObTypeIndexTable, PUNICODE_STRING pUsObjectTypeName, PVOID pHookFunction)
{if (pObTypeIndexTable){PUCHAR pStartAddress = ((PUCHAR)pObTypeIndexTable + 8 * 2); //从第2个开始POBJECT_TYPE_EX* pTempObjectType = (POBJECT_TYPE_EX*)(pStartAddress);ULONG ulIndex = 0;PVOID pOpenProcedureAddress = NULL;while (*pTempObjectType != NULL){KDPRINT("【ObjectTypeHook】", "Index:%02ld  Address:0x%p Name:%wZ\r\n",ulIndex,*pTempObjectType,&(*pTempObjectType)->Name);if (RtlCompareUnicodeString(&(*pTempObjectType)->Name, pUsObjectTypeName, true) == 0){KDPRINT("【ObjectTypeHook】", "Found Target, Hooking...\r\n");g_HookInfomation.pHookedObject = *pTempObjectType;g_HookInfomation.pOringinalOpenProcedureAddress =(POPEN_PROCEDURE)(*pTempObjectType)->TypeInfo.OpenProcedure;pOpenProcedureAddress = &((*pTempObjectType)->TypeInfo.OpenProcedure);InterlockedExchangePointer((PVOID*)pOpenProcedureAddress, pHookFunction);}pTempObjectType++;ulIndex++;}}
}NTSTATUS
NTAPI
CustomProcessOpen(IN OB_OPEN_REASON Reason,IN CHAR Flag,IN PEPROCESS Process OPTIONAL,IN PVOID ObjectBody,IN PACCESS_MASK GrantedAccess,IN ULONG HandleCount)
{NTSTATUS ntStatus = STATUS_SUCCESS;BOOLEAN bFilterProcess = false;if (Reason == OB_OPEN_REASON::ObOpenHandle){if (ObjectBody){POBJECT_NAME_INFORMATION pName = (POBJECT_NAME_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, 1024, 'Proc');if (pName){HANDLE hProcessId = PsGetProcessId((PEPROCESS)ObjectBody);if (hProcessId == (HANDLE)5284) // exporer.exe{KDPRINT("【ObjectTypeHook】", "Need Filter Mutex Name Is %wZ\r\n", &pName->Name);bFilterProcess = true;}ExFreePoolWithTag(pName, 'Proc');}}}if (bFilterProcess){return STATUS_ACCESS_DENIED;}else{ntStatus = STATUS_SUCCESS;if (g_HookInfomation.pOringinalOpenProcedureAddress){ntStatus = g_HookInfomation.pOringinalOpenProcedureAddress(Reason, Flag, Process, ObjectBody, GrantedAccess, HandleCount);}return ntStatus;}}void UnHookObjectType()
{KDPRINT("【ObjectTypeHook】", "UnHook...\r\n");if (g_HookInfomation.pHookedObject){InterlockedExchangePointer((PVOID*)(&g_HookInfomation.pHookedObject->TypeInfo.OpenProcedure), g_HookInfomation.pOringinalOpenProcedureAddress);}
}VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{UNREFERENCED_PARAMETER(pDriverObject);KDPRINT("【ObjectTypeHook】", "CurrentProcessId : 0x%p CurrentIRQL : 0x%u \r\n",PsGetCurrentProcessId(),KeGetCurrentIrql());UnHookObjectType();
}EXTERN_C NTSTATUS  DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
{UNREFERENCED_PARAMETER(pDriverObject);UNREFERENCED_PARAMETER(pRegistryPath);NTSTATUS ntStatus = STATUS_SUCCESS;KDPRINT("【ObjectTypeHook】", " Hello Kernel World! CurrentProcessId:0x%p CurrentIRQL:0x%u\r\n",PsGetCurrentProcessId(),KeGetCurrentIrql());pDriverObject->DriverUnload = DriverUnload;UNICODE_STRING usEventName = RTL_CONSTANT_STRING(L"Process");PVOID pGetObTypeIndexTable = GetObTypeIndexTable();if (pGetObTypeIndexTable){HookObjectType(pGetObTypeIndexTable, &usEventName, CustomProcessOpen);}return ntStatus;
}

4.2 实现效果

  在安装驱动后用任务管理器结束 explorer.exe,在测试机上 PID 为 5284,效果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/181666.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LangChain+LLM实战---ChatGPT的即时插件套件制作

英文原文&#xff1a;Instant Plugins for ChatGPT: Introducing the Wolfram ChatGPT Plugin Kit 在一分钟内构建一个新插件 几周前&#xff0c;我们与OpenAI合作发布了Wolfram插件&#xff0c;使ChatGPT可以使用Wolfram语言和Wolfram|Alpha作为工具&#xff0c;在ChatGPT内部…

插值表达式 {{}}

前言 持续学习总结输出中&#xff0c;今天分享的是插值表达式 {{}} Vue插值表达式是一种Vue的模板语法&#xff0c;我们可以在模板中动态地用插值表达式渲染出Vue提供的数据绑定到视图中。插值表达式使用双大括号{{ }}将表达式包裹起来。 1.作用&#xff1a; 利用表达式进行…

Python基础入门例程43-NP43 判断布尔值(条件语句)

最近的博文&#xff1a; Python基础入门例程42-NP42 公式计算器&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程41-NP41 二进制位运算&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程40-NP40 俱乐部的成员&#xff08;运算符&#xff09;-CSDN博客…

SurfaceFlinger的硬件Vsync深入分析-千里马android framework车机手机系统开发

背景&#xff1a; 学过或者你看过surfaceflinger相关文章同学都知道&#xff0c;vsync其实都是由surfaceflinger软件层面进行模拟的&#xff0c;但是软件模拟有可能会有误差或偏差&#xff0c;这个时候就需要有个硬件vsync帮忙校准。 故才会在surfaceflinger的systrace出现如下…

python图像处理 ——几种图像增强技术

图像处理 ——几种图像增强技术 前言一、几种图像增强技术1.直方图均衡化2.直方图适应均衡化3.灰度变换4.同态滤波5.对比拉伸6.对数变换7.幂律变换&#xff08;伽马变换&#xff09; 前言 图像增强是指通过各种算法和技术&#xff0c;改善或提高数字图像的质量、清晰度、对比度…

UI自动化概念+Web自动化测试框架

1.UI自动化测试概念:我们先明确什么是UI UI&#xff0c;即(User Interface简称UI用户界面)是系统和用户之间进行交互和信息交换的媒介 UI自动化测试: Web自动化测试和移动自动化测试都属于UI自动化测试&#xff0c;UI自动化测试就是借助自动化工具对程序UI层进行自动化的测试 …

【算法|二分查找No.4】leetcode 852. 山脉数组的峰顶索引

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

go-sync-mutex

Sync ​ Go 语言作为一个原生支持用户态进程&#xff08;Goroutine&#xff09;的语言&#xff0c;当提到并发编程、多线程编程时&#xff0c;往往都离不开锁这一概念。锁是一种并发编程中的同步原语&#xff08;Synchronization Primitives&#xff09;&#xff0c;它能保证多…

python图像处理 ——图像分块

python图像处理 ——图像分块 前言一、分块与合并1.读取原始图像2.网格划分&#xff0c;将图像划分为m*n块3.网格合并 二、代码 前言 根据图像尺寸创建一个 ( m 1 ) ( n 1 ) 个均匀的网格顶点坐标&#xff0c;对于图像块来说每个图像块的左上角和右下角可以唯一确定一个图像…

0X02

web9 阐释一波密码&#xff0c;依然没有什么 发现&#xff0c;要不扫一下&#xff0c;或者看一看可不可以去爆破密码 就先扫了看看&#xff0c;发现robots.txt 访问看看,出现不允许被访问的目录 还是继续尝试访问看看 就可以下载源码&#xff0c;看看源码 <?php $fl…

【音视频 | Ogg】RFC3533 :Ogg封装格式版本 0(The Ogg Encapsulation Format Version 0)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

双目视觉检测 KX02-SY1000型测宽仪 有效修正和消除距离变化对测量的影响

双目视觉检测的基本原理 利用相机测量宽度时&#xff0c;由于单个相机在成像时存在“近大远小”的现象&#xff0c;并且单靠摄入的图像无法知道被测物的距离&#xff0c;所以由被测物的跳动导致的被测物到工业相机之间距离变化&#xff0c;使测量精度难以提高。 因此测宽仪需…

React基础知识02

一、通过属性来传值&#xff08;props&#xff09; react中可以使用属性&#xff08;props&#xff09;可以传递给子组件&#xff0c;子组件可以使用这些属性值来控制其行为和呈现输出。 例子&#xff1a; // 1.1 父组件 import React, { useState } from react // 1.2引入子…

Rust编程基础之6大数据类型

1.Rust数据类型 在 Rust 中, 每一个值都属于某一个 数据类型&#xff08;data type&#xff09;, 这告诉 Rust 它被指定为何种数据&#xff0c;以便明确数据处理方式。我们将看到两类数据类型子集&#xff1a;标量&#xff08;scalar&#xff09;和复合&#xff08;compound&a…

多态 多继承的虚表深度剖析 (3)

&#x1f4af; 博客内容&#xff1a;多态 &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准C后端工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&#xff01; &#x1f496; 欢迎大家&#xff1a;这里是CSD…

NLP之Bert多分类实现案例(数据获取与处理)

文章目录 1. 代码解读1.1 代码展示1.2 流程介绍1.3 debug的方式逐行介绍 3. 知识点 1. 代码解读 1.1 代码展示 import json import numpy as np from tqdm import tqdmbert_model "bert-base-chinese"from transformers import AutoTokenizertokenizer AutoToken…

Open3D(C++) 最小二乘拟合平面(间接平差法)

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。 一、算法原理 1、原理概述 通过传统最小二乘法对点云数据进行平面拟合时,可将误差只归因于一个方向上,本文假设误差只存在于 Z Z

Monarch Mixer:一种性能比Transformer更强的网络架构

六年前&#xff0c;谷歌团队在arXiv上发表了革命性的论文《Attention is all you need》。作为一种优势的机器学习网络架构&#xff0c;Transformer技术迅速席卷全球。Transformer一直是现代基础模型背后的主力架构&#xff0c;并且在不同的应用程序中取得了令人印象深刻的成功…

tbh着色

在tbh中&#xff0c;着色之前&#xff0c;首先可以可以创建多个色板&#xff0c;如果不同角色颜色不一样&#xff0c;就可以创建多个色板&#xff0c;每一个色板代表的角色不同。 1、创建色板 有两种方式&#xff1a; 方法一&#xff1a;在颜色菜单中&#xff0c;点击左上角 …

SQL面试

#(1)请写出要查询员工J开头的名字其工号(EMPNO)及部门名称(DEPTNA)的 SQL语句SELECT e.emp,e.name,d.deptna FROM emp e left join dept d on d.deptno e.deptno where e.name like J%#(2)请写出要查询 Kevin 所在部门的部门代号(DEPTNO)及部门名称(DEPTNA)的 SQL 语句SELECT e…