进程链表监视进程是否被创建或者销毁

汇编写驱动(一)——光速入门 用汇编写windows驱动非常简单,只要有汇编基础和用C写驱动的能力即可。有了这两样基础,我们距离用汇编写驱动,只剩下一层窗户纸,一戳就破。一、准备软件:Radasm        为了快速入门,好的IDE是降低入门难道的有效手段。Radasm是我最为钟爱的一款软件,第一次使用过它,我就果断地将masm32删除了。   RadASM是一款著名的WIN32汇编编辑器,精通win32汇编的人对它应该不会陌生。支持MASM、TASM等多种汇编编译器,提供优秀的IDE,自带一个资源编辑器和一个调试器(OD)。拥有较 阅读详情
 
        既然可以通过进程活动链表来枚举进程,当然可以用来监视进程是否被创建或者销毁。下面的程序是KmdKit例子里的代码,我在学习的过程中已经加了详细注释。

KmdKit/examples/basic/Synchronization/SharedEvent - ProcessMon


驱动代码:

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
;通过进程活动链表取得活动进程,当一个进程被创建或者被销毁,都会提供通知。
;其中g_ProcessData这个结构如下:
;PROCESS_DATA STRUCT
;    bCreate                BOOL        ? 负责通知进程是被创建还是销毁
;    dwProcessId            DWORD        ? 进程PID
;    szProcessName        CHAR    IMAGE_FILE_PATH_LEN dup(?)    ; 进程全路径
;PROCESS_DATA ENDS
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.386
.model flat, stdcall
option casemap:none

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                  I N C L U D E   F I L E S                                        
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

include w2k/ntstatus.inc
include w2k/ntddk.inc
include w2k/ntoskrnl.inc

includelib ntoskrnl.lib

include Strings.mac

include ../common.inc
include ProcPath.asm

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                 R E A D O N L Y    D A T A                                        
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.const

CCOUNTED_UNICODE_STRING    "//Device//ProcessMon", g_usDeviceName, 4
CCOUNTED_UNICODE_STRING    "//DosDevices//ProcessMon", g_usSymbolicLinkName, 4

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                              U N I N I T I A L I Z E D  D A T A                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.data?

g_pkEventObject            PKEVENT            ?
g_dwImageFileNameOffset    DWORD            ?
g_fbNotifyRoutineSet    BOOL            ?

; We do not syncronize access to this global variable
; because system itself syncronize its procrss database
; while creation/termination the process. So only one
; thread can touch it at a time.

g_ProcessData            PROCESS_DATA    <> ;就是此结构有进程信息

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                         C O D E                                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.code

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                   DispatchCreateClose                                             
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DispatchCreateClose proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP

    mov ecx, pIrp
    mov (_IRP PTR [ecx]).IoStatus.Status, STATUS_SUCCESS
    and (_IRP PTR [ecx]).IoStatus.Information, 0

    fastcall IofCompleteRequest, ecx, IO_NO_INCREMENT

    mov eax, STATUS_SUCCESS
    ret

DispatchCreateClose endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
;通过链表获取进程信息.链表存在,则进程活动,链表被删,则进程销毁
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

ProcessNotifyRoutine proc dwParentId:DWORD, dwProcessId:DWORD, bCreate:BOOL    ; BOOLEAN

local peProcess:PVOID                ; PEPROCESS
local fbDereference:BOOL
local us:UNICODE_STRING
local as:ANSI_STRING

    push eax                        ; reserve DWORD on stack
    invoke PsLookupProcessByProcessId, dwProcessId, esp ;得进程链表EPROCESS
    pop peProcess                    ; -> EPROCESS
    .if eax == STATUS_SUCCESS
        mov fbDereference, TRUE        ; PsLookupProcessByProcessId references process object
    .else
        ; PsLookupProcessByProcessId fails (on w2k only) with STATUS_INVALID_PARAMETER
        ; if called in the very same process context.
        ; So if we are here it maight mean (on w2k) we are in process context being terminated.
        invoke IoGetCurrentProcess
        mov peProcess, eax
        and fbDereference, FALSE    ; IoGetCurrentProcess doesn't references process object
    .endif

    mov eax, dwProcessId
    mov g_ProcessData.dwProcessId, eax ;保存其PID

    mov eax, bCreate
    mov g_ProcessData.bCreate, eax ;进程是否有活动?

    invoke memset, addr g_ProcessData.szProcessName, 0, IMAGE_FILE_PATH_LEN

    invoke GetImageFilePath, peProcess, addr us
    .if eax == STATUS_SUCCESS

        lea eax, g_ProcessData.szProcessName
        mov as.Buffer,eax ;保存有进程名的eax填充as.Buffer
        mov as.MaximumLength,    IMAGE_FILE_PATH_LEN
        and as._Length,            0

        invoke RtlUnicodeStringToAnsiString, addr as, addr us, FALSE

        invoke ExFreePool, us.Buffer        ; Free memory allocated by GetImageFilePath
    .else

        ; 如果我们获取进程全路径失败的话
        ; 只能在进程链表用进程名。
        ;也就是说GetImageFilePath函数调用失败,那么我们只能从活动链表获取

        mov eax, g_dwImageFileNameOffset
        .if eax != 0
            add eax, peProcess
            invoke memcpy, addr g_ProcessData.szProcessName, eax, 16
        .endif

    .endif

    .if fbDereference
        fastcall ObfDereferenceObject, peProcess
    .endif

    ; Notify user-mode client.

    invoke KeSetEvent, g_pkEventObject, 0, FALSE ;异步的唤醒睡眠的线程

    ret

ProcessNotifyRoutine endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
;这个函数应该是在进程创建或者被销毁的时候,提供通知。
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DispatchControl proc uses esi edi pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP

local liDelayTime:LARGE_INTEGER

    mov esi, pIrp
    assume esi:ptr _IRP

    ; Initialize to failure.

    mov [esi].IoStatus.Status, STATUS_UNSUCCESSFUL
    and [esi].IoStatus.Information, 0

    IoGetCurrentIrpStackLocation esi ;获取当前堆栈单元
    mov edi, eax
    assume edi:ptr IO_STACK_LOCATION

    .if [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_SET_NOTIFY
        .if [edi].Parameters.DeviceIoControl.InputBufferLength >= sizeof HANDLE

            .if g_fbNotifyRoutineSet == FALSE        ; For sure

                mov edx, [esi].AssociatedIrp.SystemBuffer
                mov edx, [edx]            ; user-mode hEvent

                mov ecx, ExEventObjectType
                mov ecx, [ecx]
                mov ecx, [ecx]            ; PTR OBJECT_TYPE

                invoke ObReferenceObjectByHandle, edx, EVENT_MODIFY_STATE, ecx, /
                                        UserMode, addr g_pkEventObject, NULL
                .if eax == STATUS_SUCCESS
                
                    ;得到一个句柄对应的文件对象
                
                    invoke PsSetCreateProcessNotifyRoutine, ProcessNotifyRoutine, FALSE
                    mov [esi].IoStatus.Status, eax
               ;每当一个进程被创建(被销毁)时就往例行程序链表中添加(从例行程序链表中删除)一个驱动提供的召回例行程序
               ;也就是说,当一个进程被创建或者被销毁,此函数都要被调用
                    .if eax == STATUS_SUCCESS

                        mov g_fbNotifyRoutineSet, TRUE

                        invoke DbgPrint, /
                                $CTA0("ProcessMon: 设置通知/n")
    
                        ; Make driver nonunloadable

                        mov eax, pDeviceObject
                        mov eax, (DEVICE_OBJECT PTR [eax]).DriverObject
                        and (DRIVER_OBJECT PTR [eax]).DriverUnload, NULL

                    .else
                        invoke DbgPrint, /
                        $CTA0("ProcessMon: 不能设置通知/n")
                    .endif

                .else
                    mov [esi].IoStatus.Status, eax
                    invoke DbgPrint, /
                    $CTA0("ProcessMon: 不能设置用户对象 状态: %08X/n"), /
                    eax
                .endif
            .endif
        .else
            mov [esi].IoStatus.Status, STATUS_BUFFER_TOO_SMALL
        .endif

    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_REMOVE_NOTIFY

        ;当一个进程被删除,或创建,因回收。

        .if g_fbNotifyRoutineSet == TRUE

            invoke PsSetCreateProcessNotifyRoutine, ProcessNotifyRoutine, TRUE
            mov [esi].IoStatus.Status, eax
         ;每当一个进程被创建(被销毁)时就往例行程序链表中添加(从例行程序链表中删除)一个驱动提供的召回例行程序
         ;也就是说,当一个进程被创建或者被销毁,此函数都要被调用
         
            .if eax == STATUS_SUCCESS

                and g_fbNotifyRoutineSet, FALSE

                invoke DbgPrint, $CTA0("ProcessMon: 去除了通知/n")
                    
                ; Just for sure. It's theoreticaly possible our ProcessNotifyRoutine is now being executed.
                ; So we wait for some small amount of time (~50 ms).

                or liDelayTime.HighPart, -1
                mov liDelayTime.LowPart, -1000000
    
                invoke KeDelayExecutionThread, KernelMode, FALSE, addr liDelayTime
            ;等待知道该线程再次被CPU执行
                ;Make driver unloadable

                mov eax, pDeviceObject
                mov eax, (DEVICE_OBJECT PTR [eax]).DriverObject
                mov (DRIVER_OBJECT PTR [eax]).DriverUnload, offset DriverUnload

                .if g_pkEventObject != NULL
                    invoke ObDereferenceObject, g_pkEventObject
                    and g_pkEventObject, NULL
                    ;调用完PsLookupProcessByProcessId之后记住要调用ObDereferenceObject,否则Object还会在内存中不被释放
                .endif
            .else
                invoke DbgPrint, /
                $CTA0("ProcessMon: Couldn't remove notification/n")
            .endif
            
        .endif

    .elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_PROCESS_DATA
        .if [edi].Parameters.DeviceIoControl.OutputBufferLength >= sizeof PROCESS_DATA

            mov eax,[esi].AssociatedIrp.SystemBuffer
            invoke memcpy, eax, offset g_ProcessData, sizeof g_ProcessData
    
            mov [esi].IoStatus.Status, STATUS_SUCCESS
            mov [esi].IoStatus.Information, sizeof g_ProcessData

        .else
            mov [esi].IoStatus.Status, STATUS_BUFFER_TOO_SMALL
        .endif

    .else
        mov [esi].IoStatus.Status, STATUS_INVALID_DEVICE_REQUEST
    .endif

    ; After IoCompleteRequest returns, the IRP pointer
    ; is no longer valid and cannot safely be dereferenced.

    push [esi].IoStatus.Status
    
    assume edi:nothing
    assume esi:nothing

    fastcall IofCompleteRequest, esi, IO_NO_INCREMENT

    pop eax            ; [esi].IoStatus.Status
    ret

DispatchControl endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
;函数负责卸载驱动。如果没有,并且在驱动入口中返回的是STATUS_SUCCESS,
;那么驱动将存在内存中而不被卸载 
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DriverUnload proc pDriverObject:PDRIVER_OBJECT

    invoke IoDeleteSymbolicLink, addr g_usSymbolicLinkName
   ;删除连接设备
    mov eax, pDriverObject
    invoke IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject
   ;删除驱动设备
    ret

DriverUnload endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                              D I S C A R D A B L E   C O D E                                      
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.code INIT

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                    GetImageFileNameOffset                                         
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

GetImageFileNameOffset proc uses esi ebx

; Finds EPROCESS.ImageFileName field offset

; W2K        EPROCESS.ImageFileName = 01FCh
; WXP        EPROCESS.ImageFileName = 0174h
; WNET        EPROCESS.ImageFileName = 0154h

; Instead of hardcoding above offsets we just scan
; the EPROCESS structure of System process one page down.
; It's well-known trick.

    invoke IoGetCurrentProcess
    mov esi, eax

    xor ebx, ebx
    .while ebx < 1000h            ; one page more than enough.
        ; Case insensitive compare.
        lea eax, [esi+ebx]
        invoke _strnicmp, eax, $CTA0("system"), 6
        .break .if eax == 0
        inc ebx
    .endw

    .if eax == 0
        ; Found.
        mov eax, ebx
    .else
        ; Not found.
        xor eax, eax
    .endif

    ret

GetImageFileNameOffset endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;驱动函数入口                                               
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING

local status:NTSTATUS
local pDeviceObject:PDEVICE_OBJECT

    mov status, STATUS_DEVICE_CONFIGURATION_ERROR ;返回时需要的。

    invoke IoCreateDevice, pDriverObject, 0, addr g_usDeviceName, /
                FILE_DEVICE_UNKNOWN, 0, TRUE, addr pDeviceObject
    ;创建一个驱动设备            
    .if eax == STATUS_SUCCESS
        invoke IoCreateSymbolicLink, addr g_usSymbolicLinkName, addr g_usDeviceName
        ;设置驱动设备连接
        .if eax == STATUS_SUCCESS
            mov eax, pDriverObject
            assume eax:ptr DRIVER_OBJECT
            mov [eax].MajorFunction[IRP_MJ_Create*(sizeof PVOID)],offset DispatchCreateClose
            mov [eax].MajorFunction[IRP_MJ_CLOSE*(sizeof PVOID)],offset DispatchCreateClose
            ;上面两行代码在驱动关闭是,解除一个pIrp。比如客人退房后要收拾房间。
            mov [eax].MajorFunction[IRP_MJ_DEVICE_CONTROL*(sizeof PVOID)],    offset DispatchControl
            ;上面一行代码是驱动的执行代码。
            mov [eax].DriverUnload,offset DriverUnload
            ;上面一行代码负责驱动的卸载。
            assume eax:nothing

            and g_fbNotifyRoutineSet, FALSE
            invoke memset, addr g_ProcessData, 0, sizeof g_ProcessData
           ;初始化为0
            invoke GetImageFileNameOffset
            mov g_dwImageFileNameOffset, eax            ; it can be not found and equal to 0, btw

            mov status, STATUS_SUCCESS
        .else
            invoke IoDeleteDevice, pDeviceObject
        .endif
    .endif

    mov eax, status ;mov eax,STATUS_DEVICE_CONFIGURATION_ERROR
    ret

DriverEntry endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                                                                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

end DriverEntry


下载地址  下载 
借鉴木马机制的主动内生安全:构建深度监控与响应体系 在网络安全领域,主机安全监控与威胁检测是保障核心数字资产的关键技术。其原理在于通过部署在系统内部的代理程序,实现对进程、文件、网络连接等行为的深度监控,从而突破传统边界防护的局限。这项技术的核心价值在于能够主动发现内部威胁和高级持续性攻击,尤其适用于检测潜伏性恶意活动和异常内部行为。从应用场景来看,它广泛服务于对内部威胁敏感的组织,如金融机构和研发中心,用于内部威胁检测、APT攻击狩猎和应急响应。本文聚焦于一种借鉴木马“潜伏与控制”机制的主动防御方案,通过高隐蔽性代理和深度行为分析,构建了一套内生的安全监控 阅读详情

相关推荐

通过暴力搜索PID遍历进程并获取进程信息

背景 通常我们在内核中使用 ZwQuerySystemInformation 函数来遍历进程模块并获取进程信息,这种是通过正常的进程遍历方式,所以,有很多 Rootkit 程序会 HOOK 这个 ZwQuerySyste...

墨鱼菜鸡 613

Kmdkit的下载和安装

<br /> 2005-08-19 18:41:55  www.hackbase.com  来源:互联网在dos时代,程序可以访问所有的内存和端口,只要你想到的功能,只要付出足够的时间和精力,都可以实现。感觉自己用汇编写的程序就在dos时代,程序可以访问所有的内存和端口,只要你想到的功能,只要付出足够的时间和精力,都可以实现。感觉自己用汇编写的程序就像随时可以大闹天宫的孙悟空,发挥的空间很大,主要看你的能力。由于喜欢这种感觉,我在的dos下写过很多小程序,我写的《用hdcopy进行加密》曾在《电脑爱好者》杂

武林谣言的专栏 1429

Kmd教程1 For FASM

  KmdKit的全称是Kernel Mode Driver development Kit for assembly language programmers,即内核模式驱动程序汇编开发包。 1.Kernel Mode驱动程序基础    本教程讲述了如何在Windows NT为基础的操作系统上用Win32汇编开发KMD,包括NT4.0、2000、XP和2003等操作系统。开发Wind

xyblack技术地带 2251

Windows中进程和线程数据结构(下)

2 执行体层的进程和线程对象 执行体层进程对象的数据结构EPROCESS,第一部分 Pcb : KPROCESS 内嵌结构体 ProcessLock : 一个推锁(push lock)对象,用于保护EPROCESS中的数据成员 CreateTime : 进程的创建时间 ExitTime : 进程的退出时间 RundownProtect : 进程的停止保护锁。当一个进程到最后被销毁时,它要等到所有其他进程和线程以及释放了此锁,才可继续进行 UniqueProcessId : 进程的唯一编号.

maomao171314的专栏 1106

KmdKit windows内核程序开发包

KmdKit 是一个用Masm32汇编的内核程序开发包. 包含由汇编前辈们翻译的中文教程.

KmdKit Win32汇编开发包

Win32汇编开发包,稀有资源,包括诸多例子

GetProcessId 函数使用方法 示例

#include "stdafx.h"#include &lt;Windows.h&gt;int _tmain(int argc, _TCHAR* argv[]){        HWND h=FindWindowA(NULL,"代码注入器 郁金香灬软件 QQ:150330575——出售游戏外挂技术,教程");        printf("h=%llx \n",h);        DWORD ...

编程论坛 1万+

易语言监视新进程创建

易语言监视新进程创建监视新进程创建监视新进程创建

C# 通过进程名/进程Id 操作窗口/程序

1. 判断窗口是否存在 1 private bool IsWindowExist(IntPtr handle) 2 { 3 return (!(GetWindow(new HandleRef(this, handle), 4) != IntPtr.Zero) && IsWindowVisible(n...

weixin_33713503的博客 495

yolov5 onnx推理时报错[ONNXRuntimeError] : 2 : INVALID_ARGUMENT : Unexpected input data type.

yolov5 onnxruntime 推理报错

zjulkw的博客 1223

Ansys 19 Mechanical 流体密封分析

start point是一个特殊的概念,在仿真中ansys将从start point开始搜索会发生流体渗漏的点,可以简单理解为从start point开始,向四周逐个节点比较节点上的接触压紧力与流体压力,如果流体压力大于压紧力,则发生渗漏。事实上此处的最后一个参数是指定start point类型的,为1代表这是一个“open”的start point。在通常情况下,如果不人为指定start point,程序会自动寻找指定流体压力面的“边界”,对于二维情况,就是曲线的两个端点,对于三维情况就是曲面的边线。

Dio980的博客 1537

虚拟键盘驱动 MASM+KmdKit

下载 源自VC版,一些过滤模拟功能没有弄好,但是不影响在设备管理器中模拟出虚拟键盘,用于单价多用户环境非常方便。 .386.model flat, stdcalloption casemap:noneinclude w2k/ntstatus.incinclude w2k/ntddk.incinclude w2k/ntoskrnl.incinclude w2k/ntddkbd.i

mergerly的专栏 2774

ArcGIS小白必看:如何用3D Analyst工具将二维点线秒变三维模型(附详细步骤)

本文为ArcGIS初学者提供了利用3D Analyst工具将二维点、线数据快速转换为三维模型的完整指南。详细讲解了基于属性字段和数字高程模型(DEM)两种核心方法,并附上从数据准备、工具操作到三维场景可视化与问题排查的详细步骤,帮助用户轻松实现从平面到立体的空间数据建模。

nft7creator的博客 141

内核枚举进程总结

我知道的有三种方法 这里的第三种和第二种是一样的 隐藏进程也可以在这么做手脚 但需要注意多线程,在操作前,理应加锁 可以参考这篇文章 http://blog.youkuaiyun.com/zfdyq0/article/details/41813747 1.暴力枚举进程 通过PsLookupProcessByProcessId获得EPROCESS 第一个参数我们使用循环 填入0~6553

zhuhuibeishadiao 3770

DPO(Direct Preference Optimization)直接偏好优化

本文介绍了DPO(直接偏好优化)方法,该方法通过简化传统的RLHF(基于人类反馈的强化学习)流程,直接利用人类偏好数据进行模型优化。DPO的核心思想是跳过奖励模型训练和强化学习交互步骤,通过数学推导将优化目标转化为仅与策略概率分布相关的形式。推导表明最优策略与奖励模型之间存在显式关系,从而可以构建直接优化策略的损失函数。与RLHF相比,DPO简化了训练流程,提高了工程实现稳定性,同时保持了同等效果。

TeenLucifer的博客 1956

基于Python的船舶AIS数据爬取与分析:从数据采集到可视化实战

本文详细介绍了如何使用Python构建一个完整的船舶AIS数据爬取与分析系统。文章从AIS系统的基本原理讲起,逐步深入到数据采集、存储、清洗、分析和可视化的全流程。我们将使用最新的Python技术栈,包括aiohttp异步爬虫、MongoDB存储、Pandas数据处理以及Pydeck三维可视化等。本文提供了完整的代码实现,并探讨了在实际应用中可能遇到的问题及其解决方案。关键词:AIS数据、Python爬虫、异步IO、数据可视化、海事分析。

2201_76125261的博客 812

通过PID获取进程全路径

/* NTKERNELAPI NTSTATUS PsLookupProcessByProcessId( IN HANDLE ProcessId, OUT PEPROCESS *Process ); NTSTATUS IoQueryFileDosDeviceName( IN PFILE_OBJECT FileObject, OUT POBJECT_NAME_INF...

kernweak的博客 1520

71.qt quick-可伸展菜单-抽屉栏示例 通用QML界面(一键换肤)

特点: 支持动态添加item、删除item、自适应界面 附带添加删除、展开等动画 同时支持qwidget、qml加载 支持number提示(比如消息数量等) 侧边抽屉栏支持动画伸展 支持换肤、拖拽、最大化等

抵抗时间扭曲,坚持做一件有意义的事 5286

Kmd教程1-内核模式驱动程序基础

1.Kernel Mode驱动程序基础 1.1 KMD结构概述 1.1.1 主要组成部分     根据地址空间、代码权限和职责的不同,Windows NT内部划分为两个截然不同的部分。     地址空间的享用方式也非常容易理解,整个32位系统的4GB内容被划分为两个相等的部分,用户模式(user-mode)的进程使用的地址空间被映射到低 位的2GB上(地址范围00000000 - 7FFF

chinaplus的专栏 3505

华为MetaERP国资委语境下的 DRP(全域数字化资源管理平台/Digitalized Resource-management Platform)与传统 ERP(以 SAP、Oracle 为代表)的

【摘要】国资委推动的DRP(全域数字化资源管理平台)正在重构央国企数智化转型路径,其本质是通过"ERP管交易+DRP管管控"的双层架构实现升维替代。与传统ERP相比,DRP具有三大突破:采用国产分布式数据库实现全级次穿透监管、构建数据中台打破信息孤岛、以实时分析替代事后报表。当前政策明确2026-2030年分阶段建设目标,这将重塑产业格局——倒逼传统ERP厂商转型,为云原生/AI/信创企业创造新机遇。需注意DRP并非简单替代ERP,而是通过治理模式变革实现"交易系统做薄、管控中

金牌架构师 289

STM32入门教程:智能储物柜控制

在这个例子中,我们将使用一个4x4的储物柜,共有16个储物格。我们了解了硬件准备、储物柜电路设计、STM32的基本配置、储物柜控制代码的编写以及测试和调试等方面的知识。根据我们的电路设计,我们需要将一些引脚配置为输出,并将其他引脚配置为输入。在本教程中,我们将使用STM32微控制器来实现一个基本的智能储物柜控制系统。在主函数中,我们将不断循环读取传感器数据,并根据数据的变化来控制储物柜的开关和显示相关信息。这个函数将读取人体感应传感器、温湿度传感器和光照传感器的数据,并将数据存储到相应的变量中。

m0_75244442的博客 663

KMD驱动教程续-8

 Kmdtut 8---共享Section通讯                                       共享Section通讯董岩译8.1 结构化异常处理8.1.1 seh驱动程序源代码8.1.2 建立 SEH-frame8.1.3 异常处理8.1.4 卸载SEH-frame8.1.5 使用宏来建立/卸载SEH-frame8.2 共享Section通讯8

guokeno1--JEFF的技术博客 1523

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

KMD驱动教程续-9

Kmdtut 9---共享内存                                       共享内存董岩 译 9.1 SharingMemory驱动程序源代码9.1.1 DriverEntry函数9.1.2 DispatchControl函数9.1.3 Memory Descriptor List9.1.4 Cleanup函数9.2 SharingMemor

guokeno1--JEFF的技术博客 1591

老版QQ原生表情gif动态

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

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

上一篇: 在VC中编译、运行程序的小知识点
下一篇: Hook API监视驱动的加载_ASM
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值