获取Windows 系统的内核变量

WinDbg x64内核之寻找KdVersionBlock 😀 Win 10 x64 内核之 寻找KdVersionBlock一、_KPCR二、_DBGKD_GET_VERSION64总结 找这个的目的是什么的就不说了。 提示:以下是本篇文章正文内容,下面案例可供参考 一、_KPCR 由于Windows需要支持多个CPU, 因此Windows内核中为此定义了一套以处理器控制区(Processor Control Region)即KPCR为枢纽的数据结构, 使每个CPU都有个KPCR. 其中KPCR这个结构中有一个域KPRCB(Kernel Processo. 阅读详情

关键字:PsLoadedModuleList、PsActiveProcessHead、NtSystemDebugControl
        PsNtosImageBase、KdVersionBlock、KdDebuggerDataBlock、内核变量

 

    PsLoadedModuleList等重要内核变量并未被ntoskrnl.exe导出,也没有公开的函
数可以获取。而这些内核变量对于Rootkit、Anti-Rootkit 以及内核溢出的利用等都
是至关重要的。

    下面我们以PsLoadedModuleList、PsActiveProcessHead 等为例,介绍得到这些
变量的方法。

    对于Windows NT 4.0和Windows 2000,尚没有“温柔”的办法可以获取这些变量,
比较理想的办法也就是特征代码搜索,这种方法虽然暴力,但通常都很有效,一般也
不会出问题;对于Windows XP和Windows 2003,我们找到了一些更加优雅的选择。

    下面首先介绍特征代码搜索的方法。

[DWORD KernelBase]

    要进行特征代码搜索,首先要定位ntoskrnl.exe在内核的加载地址KernelBase。
这个地址可以通过ZwQuerySystemInformation Class 10的SystemModuleInformation
来得到。参考资源[1]中给出了相关代码。事实上,KernelBase 这个值对同一操作系
统来说非常固定,可以作为常量来用:

Windows NT:  0x80100000
Windows 2000:0x80400000
Windows XP:  0x804d1000
Windows 2003: 0x804e0000

    Windows NT 4.0 ntoskrnl.exe 的OptionalHeader->ImageBase = 0x80100000,
ntldr 也会按照这个值来加载内核,但是从Windows 2000开始就不是这样了。可能基
于这个历史原因,各系统的*(DWORD *)PsNtosImageBase始终初始化为0x80100000。

    另外,内核变量PsNtosImageBase、KdpNtosImageBase等也指向KernelBase:

KernelBase = *(DWORD *)PsNtosImageBase
KernelBase = *(DWORD *)KdpNtosImageBase

[LIST_ENTRY PsLoadedModuleList]

    PsLoadedModuleList这个全局变量指向一个保存着所加载驱动信息的双向链表。
通过它可以枚举系统中所有的驱动模块。

    虽然很多内核函数都用到了PsLoadedModuleList,但是大部分并没有被导出,而
从基址开始搜会很花时间。对于Windows 2000来说,从下面这个地方入手是个好主意:

nt!MmGetSystemRoutineAddress+0x66:
804f0ed0 8b35f0e84680     mov     esi,[nt!PsLoadedModuleList (8046e8f0)]
804f0ed6 81fef0e84680     cmp     esi,0x8046e8f0

流程如下:
1、ImageBase = LoadLibraryA("ntoskrnl.exe")
2、GetProcAddress(ImageBase,"MmGetSystemRoutineAddress")
3、搜索特征代码:
*(WORD *)(MmGetSystemRoutineAddress + i) = 0x358b && /
*(WORD *)(MmGetSystemRoutineAddress + i + 6) = 0xfe81
&&
*(DWORD *)(MmGetSystemRoutineAddress + i + 2) == /
*(DWORD *)(MmGetSystemRoutineAddress + i + 8)
4、定位内核中的地址:
PsLoadedModuleList = /
*(DWORD *)(MmGetSystemRoutineAddress + i + 2) + (KernelBase - ImageBase)

    从SP0到SP4,i值并不相同,但是肯定不大于0x100。

    对Windows NT来说,就没这么好运气了,没有理想的可用于定位的API,只能从头
开始搜索。下面这段代码至少对SP1~SP6a的来说都具有很好的稳定性和唯一性:
801CEB1C: 8B 4D 08           mov       ecx,dword ptr [ebp+8]
801CEB1F: 89 01              mov       dword ptr [ecx],eax
801CEB21: 8B 45 0C           mov       eax,dword ptr [ebp+0Ch]
801CEB24: 89 10              mov       dword ptr [eax],edx
801CEB26: 8B 36              mov       esi,dword ptr [esi]
801CEB28: 81 FE 70 0B 15 80  cmp       esi,80150B70h  //PsLoadedModuleList

    如果是用驱动做这件事情,就不必暴力搜索了,fuzen_op(fuzen_op@yahoo.com)
在FU_Rootkit2.0(参考资源[2])中使用了一段比较巧妙的代码:

DWORD FindPsLoadedModuleList (IN PDRIVER_OBJECT DriverObject)
{
    PMODULE_ENTRY pm_current;
    if (DriverObject == NULL)
        return 0;

    pm_current = *((PMODULE_ENTRY*)((DWORD)DriverObject + 0x14));
    if (pm_current == NULL)
        return 0;

    gul_PsLoadedModuleList = pm_current;

    while ((PMODULE_ENTRY)pm_current->le_mod.Flink != gul_PsLoadedModuleList)
    {
        if ((pm_current->unk1 == 0x00000000) && /
        (pm_current->driver_Path.Length == 0))
        {
            return (DWORD) pm_current;
        }
        pm_current = (MODULE_ENTRY*)pm_current->le_mod.Flink;
    }

    return 0;
}

[LIST_ENTRY PsActiveProcessHead]

    理论上PsActiveProcessHead 也可以用搜索代码的方法来取,但是还有更简单的
方法。

    ntoskrnl.exe导出的PsInitialSystemProcess 是一个PEPROCESS,指向system进
程的EPROCESS。这个EPROCESS的结构成员EPROCESS.ActiveProcessLinks.Blink 就是
PsActiveProcessHead:

kd> dt _EPROCESS ActiveProcessLinks.Blink poi(PsInitialSystemProcess)
   +0x0a0 ActiveProcessLinks  :  [ 0x81356900 - 0x8046e728 ]
      +0x004 Blink               : 0x8046e728  [ 0x81a2fb00 - 0xff5a4ce0 ]
kd> ? PsActiveProcessHead
Evaluate expression: -2142836952 = 8046e728

    EPROCESS这个结构在不同的操作系统上各不相同,需要分别对待。

[struct _KDDEBUGGER_DATA64 KdDebuggerDataBlock]

    Windows 2000 开始,系统引入了变量KdDebuggerDataBlock。其中包含了大量的
内核变量。如果能够获取到的话,可以解决许多问题。遗憾的是,Windows NT上没有
这个变量。WinDBG SDK的wdbgexts.h中包含了它的结构:
    typedef struct _KDDEBUGGER_DATA64
因为比较长,这里就不引用了。

    从对5.0.2195.6902版本ntoskrnl.exe 的逆向工程结果来看,只有两个函数使用
了该变量,并且,两个函数都未导出,且代码前后没有明显特征,无法靠直接搜索代
码来获取。

    但是,我们发现,ntoskrnl.exe导出了KdEnableDebugger,KdEnableDebugger会
调用KdInitSystem,而KdInitSystem 中引用了KdDebuggerDataBlock:

n < 100

Windows 2000:

KdEnableDebugger + n:
6A 00                 push    0
6A 00                 push    0
C6 05 28 41 48 00 01  mov     _PoHiberInProgress, 1
E8 1C DC 10 00        call    _KdInitSystem@8 ; KdInitSystem(x,x)

KdInitSystem + n:
68 70 02 00 00        push    270h      // sizeof(KdDebuggerDataBlock)
B9 50 D1 54 00        mov     ecx, offset _KdpDebuggerDataListHead
68 D8 FA 46 00        push    offset KdDebuggerDataBlock
8B 40 18              mov     eax, [eax+18h]
68 4B 44 42 47        push    4742444Bh // "KDBG",可以用作搜索的定位标志
A3 3C D1 54 00        mov     ds:_KdpNtosImageBase, eax
89 0D 54 D1 54 00     mov     ds:dword_54D154, ecx
89 0D 50 D1 54 00     mov     ds:_KdpDebuggerDataListHead, ecx

Windows XP

KdEnableDebugger + n:
6A 00                 push    0
6A 00                 push    0
C6 05 8C 98 47 00 01  mov     _PoHiberInProgress, 1
E8 2B 17 13 00        call    _KdInitSystem@8 ; KdInitSystem(x,x)

KdInitSystem + n:
68 90 02 00 00        push    290h
68 E0 9D 46 00        push    offset KdDebuggerDataBlock
BE 74 96 59 00        mov     esi, offset _KdpDebuggerDataListHead
68 4B 44 42 47        push    4742444Bh
89 35 78 96 59 00     mov     ds:dword_599678, esi
89 35 74 96 59 00     mov     ds:_KdpDebuggerDataListHead, esi

Windows 2003

KdEnableDebugger + n:
56                    push    esi
56                    push    esi
C6 05 0C 08 49 00 01  mov     PoHiberInProgres, 1
E8 CB AD 15 00        call    _KdInitSystem@8 ; KdInitSystem(x,x)

KdInitSystem + n:
68 18 03 00 00        push    318h
68 D0 A3 47 00        push    offset KdDebuggerDataBlock
BE 18 10 5D 00        mov     esi, offset _KdpDebuggerDataListHead
68 4B 44 42 47        push    4742444Bh
89 35 1C 10 5D 00     mov     ds:dword_5D101C, esi
89 35 18 10 5D 00     mov     ds:_KdpDebuggerDataListHead, esi

    可以看出,上面代码特征的唯一性很好。用于搜索是没有问题的。我在上面同时
列出了三个系统的代码,仅仅只是为了比较,事实上,对Windows XP和Windows 2003
是完全没有必要采取如此暴力手段的。

 

    下面介绍针对Windows XP和Windows 2003的方法。

[struct _DBGKD_GET_VERSION64 KdVersionBlock]

    Opc0de和Edgar Barbosa在参考资源[3]中提到,Windows XP和Windows 2003引入
的一个新内核变量:KdVersionBlock,其结构中包含了PsLoadedModuleList。

    WinDBG SDK的wdbgexts.h中有KdVersionBlock的结构:

typedef struct _DBGKD_GET_VERSION64 {
    USHORT  MajorVersion;
    USHORT  MinorVersion;
    USHORT  ProtocolVersion;
    USHORT  Flags;
    USHORT  MachineType;
    UCHAR   MaxPacketType;
    UCHAR   MaxStateChange;
    UCHAR   MaxManipulate;
    UCHAR   Simulation;
    USHORT  Unused[1];
    ULONG64 KernBase;
    ULONG64 PsLoadedModuleList;
    ULONG64 DebuggerDataList;

} DBGKD_GET_VERSION64, *PDBGKD_GET_VERSION64;

KdVersionBlock是KPCR的一个成员:

lkd> dt _kpcr ffdff000
nt!_KPCR
   +0x000 NtTib            : _NT_TIB
   +0x000 Used_ExceptionList : 0xf717dbcc
   +0x004 Used_StackBase   : (null)
   +0x008 PerfGlobalGroupMask : (null)
   +0x00c TssCopy          : 0x80042000
   +0x010 ContextSwitches  : 0x1f8b07a
   +0x014 SetMemberCopy    : 1
   +0x018 Used_Self        : 0x7ffde000
   +0x01c SelfPcr          : 0xffdff000
   +0x020 Prcb             : 0xffdff120
   +0x024 Irql             : 0x2 ''
   +0x028 IRR              : 0
   +0x02c IrrActive        : 0
   +0x030 IDR              : 0xffff24e0
   +0x034 KdVersionBlock   : 0x8055a3a8     <--
   +0x038 IDT              : 0x8003f400
   +0x03c GDT              : 0x8003f000
   +0x040 TSS              : 0x80042000
   +0x044 MajorVersion     : 1
   +0x046 MinorVersion     : 1
   +0x048 SetMember        : 1
   +0x04c StallScaleFactor : 0x64
   +0x050 SpareUnused      : 0 ''
   +0x051 Number           : 0 ''
   +0x052 Spare0           : 0 ''
   +0x053 SecondLevelCacheAssociativity : 0x8 ''
   +0x054 VdmAlert         : 0
   +0x058 KernelReserved   : [14] 0
   +0x090 SecondLevelCacheSize : 0x80000
   +0x094 HalReserved      : [16] 0
   +0x0d4 InterruptMode    : 0
   +0x0d8 Spare1           : 0 ''
   +0x0dc KernelReserved2  : [17] 0
   +0x120 PrcbData         : _KPRCB

Windows 2000和NT的KPCR是没有这个成员的:

kd> dt _kpcr ffdff000
nt!_KPCR
   +0x000 NtTib            : _NT_TIB
   +0x01c SelfPcr          : 0xffdff000
   +0x020 Prcb             : 0xffdff120
   +0x024 Irql             : 0 ''
   +0x028 IRR              : 0
   +0x02c IrrActive        : 0
   +0x030 IDR              : 0xffffffff
   +0x034 Reserved2        : 0              <--
   +0x038 IDT              : 0x80036400
   +0x03c GDT              : 0x80036000
   +0x040 TSS              : 0x802a4000
   +0x044 MajorVersion     : 1
   +0x046 MinorVersion     : 1
   +0x048 SetMember        : 1
   +0x04c StallScaleFactor : 0x64
   +0x050 DebugActive      : 0 ''
   +0x051 Number           : 0 ''
   +0x052 VdmAlert         : 0 ''
   +0x053 Reserved         : [1]  ""
   +0x054 KernelReserved   : [15] 0
   +0x090 SecondLevelCacheSize : 0
   +0x094 HalReserved      : [16] 0
   +0x0d4 InterruptMode    : 0
   +0x0d8 Spare1           : 0 ''
   +0x0dc KernelReserved2  : [17] 0
   +0x120 PrcbData         : _KPRCB

    KPCR 在各版本Windows系统上的值都是固定的0xffdff000,这就给我们提供了另
一个获得PsLoadedModuleList的方法:

#define KPCR 0xffdff000
PsLoadedModuleList = *(DWORD *)( *(DWORD *)(KPCR+0x34)+0x18 )

    KdVersionBlock的结构成员DebuggerDataList实际就是KdpDebuggerDataListHead,
而:
KdpDebuggerDataListHead.Flink = KdDebuggerDataBlock
KdpDebuggerDataListHead.Blink = KdDebuggerDataBlock
   
    也就是说,得到KdVersionBlock也就获得了KdDebuggerDataBlock。


[利用NtSystemDebugControl获取KdVersionBlock]

    Windows XP 和Windows 2003上,kd在使用“-kl”参数本地运行的时候,即使没
有加载符号表,依然能够给出正确的PsLoadedModuleList:

Windows Server 2003 Kernel Version 3790 UP Free x86 compatible
Product: Server, suite: TerminalServer SingleUserTS
Built by: 3790.srv03_rtm.030324-2048
Kernel base = 0x804e0000 PsLoadedModuleList = 0x8056ac08

    显然,Windows 5.1 以上版本提供了获取PsLoadedModuleList和KernelBase的机
制。用WinDBG对kd进行调试(煮豆燃豆萁……)发现,dbgeng.dll调用一个未文档化
的Native API NtSystemDebugControl,获取了上文提到的 KdVersionBlock。调用过
程如下:

dbgeng!DebugClient::WaitForEvent
dbgeng!RawWaitForEvent
dbgeng!WaitForAnyTarget
dbgeng!LocalLiveKernelTargetInfo::WaitForEvent
dbgeng!LiveKernelTargetInfo::InitFromKdVersion
dbgeng!LocalLiveKernelTargetInfo::GetTargetKdVersion
ntdll!NtSystemDebugControl

    对于NtSystemDebugControl,除了BUGTRAQ ID 9694 的一个漏洞报告外,在互联
网上找不到任何相关信息。(事实上,作者报告的问题是不能称之为漏洞的,因为,
要执行这个API,必须拥有SeDebugPrivilege 特权,而正常情况下,只有管理员用户
才有该特权。关于该漏洞,见参考资源[4])。

    逆向工程的结果显示,在Windows XP和Windows 2003上,NtSystemDebugControl
的功能号7将调用内部函数KdpSysGetVersion:
; __stdcall KdpSysGetVersion(x)

arg_0           = dword ptr  0Ch

                push    esi
                push    edi
                mov     edi, [esp+arg_0]
                push    0Ah
                pop     ecx
                mov     esi, offset _KdVersionBlock
                rep movsd
                pop     edi
                pop     esi
                retn    4

    利用NtSystemDebugControl,可以非常优雅地得到KdVersionBlock:

typedef enum _DEBUG_CONTROL_CODE {
    DebugGetKdVersionBlock = 7
} DEBUG_CONTROL_CODE;

EnablePrivilege(SE_DEBUG_NAME);

ZwSystemDebugControl(
    DebugGetKdVersionBlock,
    NULL,
    0,
    &KdVersionBlock,
    sizeof(KdVersionBlock),
    NULL
    );

printf ("KernBase:           0x%.8x/n",KdVersionBlock.KernBase);
printf ("PsLoadedModuleList: 0x%.8x/n",KdVersionBlock.PsLoadedModuleList);
printf ("DebuggerDataList:   0x%.8x/n",KdVersionBlock.DebuggerDataList);

    除了获取KdVersionBlock之外,NtSystemDebugControl还有很多强大的功能,我
将在另外一篇文档中详细介绍。

    现在总结一下。
   
    对Windows 2000来说,最重要的是搜索代码,得到 KdDebuggerDataBlock,得到
了这个,实际上也就得到了PsLoadedModuleList、PsActiveProcessHead等。

    对Windows XP和Windows 2003,最佳的办法是直接利用NtSystemDebugControl得
到KdVersionBlock,然后取得KdDebuggerDataBlock。

Android内核的编译和调试 本文博客地址:http://blog.youkuaiyun.com/qq1084283172/article/details/70500488 一、Android内核源码的选择 Android手机设备内核源码的调试需要外部硬件设备的支持,调试步骤比较麻烦。相对来说,Android模拟器内核源码的调试就比较简单了,这里... 阅读详情

相关推荐

11、Windows 系统中的同步机制:从内核对象到用户模式抽象

本文深入探讨了Windows系统中的同步机制,涵盖从内核对象到用户模式下的各种同步抽象。详细介绍了Win32和.NET Framework中的常见同步原语,包括CRITICAL_SECTION、CLR锁、SRWL、ReaderWriterLockSlim、条件变量等,分析了它们的原理、使用方法及性能特点。旨在帮助开发者理解并合理运用这些机制,以构建高效、稳定的并发程序。

bert9linguist的博客 70

Win64 Driver开发问题记录(二)

Win64 driver开发中遇到的第二个问题是如何通过SSDT表引用系统服务内核函数。 MS在64系统中引入了全新的PatchGuard技术,使得原本在32位下可轻易hook的SSDT表在64位系统中无法再patch(会引发BSOD). 当然,目前我并非是要hook SSDT表,而是需要使用到SSDT表中的一个未导出的系统服务内核函数。在32位driver中可以通过extern "C

nevil的专栏 3623

从零构建物联网数据中台:MQTT协议、Node.js服务、MongoDB与InfluxDB双存储及React可视化实战

本文详细介绍了从零构建物联网数据中台的完整实战方案。通过采用MQTT协议作为设备通信标准,结合Node.js搭建高并发数据处理服务,并创新性地使用MongoDB与InfluxDB双存储架构分别管理设备元数据与海量时序数据,最后利用React构建了实时数据可视化控制台。该架构有效解决了物联网项目中数据异构、查询性能低下等核心痛点,为构建高效、可扩展的物联网平台提供了清晰路径。

weixin_28432777的博客 292

(转载)获取Windows 系统的内核变量

获取Windows 系统的内核变量转自:http://www.xfocus.net创建时间:2004-08-05文章属性:原创文章提交:tombkeeper (t0mbkeeper_at_hotmail.com)获取Windows 系统的内核变量作  者:于旸邮  件:tombkeeper[0x40]nsfocus[0x2e]com        tombkeeper[0x40]xfocus[0x

Kendiv's Box 2050

安卓集成华为HMS Scankit实现自定义扫码功能

实现扫码功能 使用的是集成华为扫描的SDK,UI界面借鉴的是谷歌官方的Zxing项目中的自定义view,两者结合实现。 先上效果图: 先在项目根级别(build.gradle)当中配置HMS Core SDK的Maven仓地址。 // 配置HMS Core SDK的Maven仓地址。 maven {url 'https://developer.huawei.com/repo/'} // 配置HMS Core SDK的Maven仓地址。 maven {url 'https://developer.huaw

qq_47625961的博客 5513

笔记——Oracle19c

Oracle阅读笔记

weixin_63819458的博客 1352

利用PsLoadModuleList 杖举驱动模块

PsLoadedModuleList是系统的一个全局变量,它指向一个保存着所加载驱动信息的双向链表。通过它可以枚举系统中所有的驱动模块。 这个双向链表的结构如下: kd> dt _LIST_ENTRY nt!_LIST_ENTRY +0x000 Flink : Ptr32 _LIST_ENTRY      //指向后一个链表 +0x0...

weixin_30439031的博客 604

Python异步协程爬虫优化:解决aiohttp中ServerDisconnectedError的高效策略

本文深入探讨了在Python异步协程爬虫中使用aiohttp时,如何高效解决常见的ServerDisconnectedError问题。核心策略包括全局复用ClientSession、精细配置TCPConnector连接池、实施请求重试与速率限制,从而构建稳定、高效的异步爬虫架构,有效避免服务器断开连接错误。

pz890123的博客 862

驱动中获取PsActiveProcessHead变量地址的五种方法

PsActiveProcessHead的定义: 在windows系统中,所有的活动进程都是连在一起的,构成一个双链表,表头是全局变量PsActiveProcessHead,当一个进程被创建时,其ActiveProcessList域将被作为节点加入到此链表中;当进程被删除时,则从此链表中移除,如果windows需要枚举所有的进程,直接操纵此链表即可。 方法一:从Kd...

weixin_33949359的博客 302

从零构建Carsim线控转向仿真:模型搭建、算法集成与整车联动实战

本文详细介绍了从零开始基于Carsim和Simulink搭建线控转向仿真模型的完整实战流程。内容涵盖RWA前轮执行器动力学建模与PID控制、卡尔曼滤波器估算齿条力、HWA方向盘手感模拟算法设计,以及最终实现HWA与RWA闭环联动并进行整车仿真调试。通过分步拆解,帮助读者深入理解线控转向系统的核心原理与工程实现。

weixin_29158413的博客 251

基于强化学习方法的PID参数整定

前言 PID控制器在工业界应用非常广泛,但是PID的参数调节一般需要人工根据经验法来试。对于有经验的工程师来说,一般试几次就可以获得满足调节的参数。然而对于新手工程师却很难确定一套比较好的参数。 这里我们采用强化学习的方法来调节PID参数。 这个例子展示了如何使用双延迟深度确定性策略梯度(TD3:twin-delayed deep deterministic policy gradient)强化学习算法来调整PI控制器。整定控制器的性能与使用Control System Tuner app整定的控制器的性能

weixin_42188287的博客 2万+

Windows内核 - 调试:符号文件和Windbg的安装与环境配置

flyingstarsoul 2007-9-21            内核调试: 内核调试可以帮助我们查看内核的内部数据结构,跟踪内核中的函数,从而探查Windows的内部机理。内核调试工具有Microsoft的Windows调试工具箱、Compuware NuM

_Max 834

knowhere | 第一课:项目导论与环境搭建

摘要 本课程是Knowhere项目的第一课,重点介绍项目整体架构和开发环境搭建。Knowhere定位为AI Agent的文档记忆基础设施,通过解析多格式文档并保留结构化信息(如章节层级、表格语义等),为Agent提供可导航的文档知识。项目采用Python monorepo结构,核心包括: apps/api:FastAPI服务,处理HTTP请求和流程调用 apps/worker:Celery服务,执行文档解析等耗时任务 packages/shared-python:共享基础设施层 课程明确了各层职责边界,并推

weixin_43674738的博客 153

Windows Research Kernel (WRK) 快速入门:10分钟搭建Windows内核研究环境

Windows Research Kernel (WRK) 是微软官方发布的Windows NT内核源代码,为操作系统研究者和开发者提供了深入了解Windows内核架构的终极机会。本文将为您提供完整的Windows Research Kernel快速入门指南,帮助您在10分钟内搭建起Windows内核研究环境,开启操作系统内核探索之旅!🚀 ## 什么是Windows Research Kern

gitblog_00257的博客 409

自动识别象棋棋子的OpenCV应用

在计算机视觉领域,OpenCV是一个广泛应用的开源计算机视觉库,它提供了丰富的图像处理和分析工具。本文将介绍如何使用OpenCV实现自动识别象棋棋子的功能,并提供相应的源代码。通过以上代码,我们可以实现对棋盘图像中棋子的自动识别。需要注意的是,以上代码只是一个简单的示例,实际应用中可能需要根据具体情况进行参数调整和算法优化,以获得更好的识别效果。函数利用预处理后的图像,寻找图像中的轮廓,并根据轮廓的面积筛选出可能的棋子轮廓,最后在原图像中提取棋子区域。在主程序中,我们读取输入图像,并调用。

WzisTypescript的博客 908

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

windows的dmp文件使用

windows出现蓝屏后都会产生dmp文件,它记录windows蓝屏时的内存信息。 1、快速定位引起崩溃的文件 dmp文件的查看用Debugging Tools for Windows (x86)及windbg工具,从下面地址下载 http://msdn.microsoft.com/en-us/windows/hardware/gg463009.aspx 下载安装后,启动 Debuggin

东子的博客 1万+

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Windows驱动签名绕过终极指南:3步快速禁用DSE的完整方案

Windows x64系统的驱动签名强制执行(Driver Signature Enforcement,简称DSE)是微软为了保护内核安全而设计的核心机制,但对于驱动程序开发者、安全研究人员和系统管理员来说,这常常成为一个技术障碍。今天我们要介绍的DSEFix项目,正是解决这一问题的专业工具,它提供了快速、有效的Windows驱动签名绕过方案,让你能够轻松安装和测试未签名驱动程序。 ## 🔍

gitblog_00559的博客 808

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Windows 11 上使用安卓应用

安装谷歌 Google Play、亚马逊 应用商店、以及安装安卓APK就像Windows安装软件一样容易! 系统要求:Windows 11(企业版、专业版、家庭版均可) 内存要求:最小8G,不然无法运行 主板BIOS:开启CPU的虚拟化......

树欲静而风不止 4092

终极指南:如何绕过Windows驱动签名强制验证(DSEFix完整教程)

你是否遇到过Windows系统提示"驱动程序未签名"而无法安装硬件的困扰?DSEFix(Driver Signature Enforcement Fix)是一款专为解决Windows x64系统驱动签名验证问题而设计的开源工具。本文将详细介绍这款强大的Windows驱动签名强制绕过工具的使用方法、工作原理以及注意事项,帮助你在几分钟内解决驱动签名问题! ## 为什么需要DSEFix?Window

gitblog_00217的博客 332
上一篇: 从socket中读取一行语句
下一篇: 数据压缩技术简史
普通网友
博客等级 码龄22年 1万+粉丝 3156原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值