rbx1中的follow

部署运行你感兴趣的模型镜像

github地址:https://github.com/robotBing/openrobot_follower.git 

视频展示地址:http://blog.jiutucao.com:9000/upload/2018/07/color_follow.mp4

1.  基本功能

1)跟随人行走

2)语音控制开始或停止

3)颜色标定

2. 跟随实现

1)代码:

#!/usr/bin/env python

import rospy

from roslib import message

from std_msgs.msg import String

from sensor_msgs import point_cloud2

from sensor_msgs.msg import PointCloud2

from geometry_msgs.msg import Twist

from math import copysign 

class Follower():

int status = 0

    def __init__(self):

        rospy.init_node("follower")

 

        rospy.on_shutdown(self.shutdown)

 

        self.goal_z = rospy.get_param("~goal_z", 0.6)

 

        self.z_threshold = rospy.get_param("~z_threshold", 0.05)

 

        self.x_threshold = rospy.get_param("~x_threshold", 0.05)

        self.z_scale = rospy.get_param("~z_scale", 1.0)     

        self.x_scale = rospy.get_param("~x_scale", 2.5)

   

        self.max_angular_speed = rospy.get_param("~max_angular_speed", 2.0)

        self.min_angular_speed = rospy.get_param("~min_angular_speed", 0.0)

        self.max_linear_speed = rospy.get_param("~max_linear_speed", 0.3)

        self.min_linear_speed = rospy.get_param("~min_linear_speed", 0.1

        self.low_down_factor = rospy.get_param("~slow_down_factor", 0.8)

        self.move_cmd = Twist()

        self.cmd_vel_pub = rospy.Publisher('/cmd_vel', Twist, queue_size=5)

        self.depth_subscriber = rospy.Subscriber('point_cloud', PointCloud2, self.set_cmd_vel, queue_size=1)

        rospy.Subscriber('/recognizer/output', String, self.speechcb)

        rospy.loginfo("Subscribing to point cloud...")

        rospy.wait_for_message('point_cloud', PointCloud2)

        rospy.loginfo("Ready to follow!"

def speechcb(self,msg):

        command = msg.data

        if command == 'stop':

               self.status = 0

        else if command == 'move' :

               self.status = 1

    def set_cmd_vel(self, msg):

        x = y = z = n = 0

        for point in point_cloud2.read_points(msg, skip_nans=True):

            pt_x = point[0]

            pt_y = point[1]

            pt_z = point[2]

            x += pt_x

            y += pt_y

            z += pt_z

            n += 1

        if n:

            x /= n

            y /= n

            z /= n

            if (abs(z - self.goal_z) > self.z_threshold):

                linear_speed = (z - self.goal_z) * self.z_scale

                self.move_cmd.linear.x = copysign(max(self.min_line

 

ar_speed,

                                        min(self.max_linear_speed, abs(linear_speed))), linear_speed)

            else:

                self.move_cmd.linear.x *= self.slow_down_factor

               

            if (abs(x) > self.x_threshold):    

                angular_speed = -x * self.x_scale

                self.move_cmd.angular.z = copysign(max(self.min_angular_speed,

                                        min(self.max_angular_speed, abs(angular_speed))), angular_speed)

            else:

                self.move_cmd.angular.z *= self.slow_down_factor

        else:

            self.move_cmd.linear.x *= self.slow_down_factor

            self.move_cmd.angular.z *= self.slow_down_factor

       if self.status == 0:

            self.cmd_vel_pub.publish(twist())

        else:

               self.cmd_vel_pub.publish(self.move_cmd)

    def shutdown(self):

        rospy.loginfo("Stopping the robot...")

        self.depth_subscriber.unregister()

        rospy.sleep(1)

        self.cmd_vel_pub.publish(Twist())

        rospy.sleep(1)     

if __name__ == '__main__':

    try:

        Follower()

        rospy.spin()

    except rospy.ROSInterruptException:

        rospy.loginfo("Follower node terminated.")

 

2)基本思路

订阅点云(pointcloud2)话题,点云数据包括图像的宽度,高度和一个个点的信息。

根据点云数据找出人的质心点,然后将质心点和图像的中间点和设定的距离点比较,

左右偏移则往/cmd_vel话题上发布左右消息,前后则发布前后消息

  3) launch文件

  <launch>

  <node pkg="nodelet" type="nodelet" name="pcl_manager" args="manager" output="screen" />

  <node pkg="nodelet" type="nodelet" name="voxel_grid_z" args="load pcl/VoxelGrid pcl_manager" output="screen">

    <remap from="~input" to="/camera/depth_registered/points" />

    <remap from="~output" to="/z_filtered" />

    <rosparam>

      filter_field_name: z

      filter_limit_min: 0.3

      filter_limit_max: 1.6

      filter_limit_negative: False

      leaf_size: 0.02

    </rosparam>

  </node>

  <node pkg="nodelet" type="nodelet" name="passthrough_x" args="load pcl/PassThrough pcl_manager" output="screen">

    <remap from="~input" to="/z_filtered" />

    <remap from="~output" to="/x_filtered" />

    <rosparam>

      filter_field_name: x

      filter_limit_min: -0.3

      filter_limit_max: 0.3

      filter_limit_negative: False

    </rosparam>

  </node>

  <node pkg="nodelet" type="nodelet" name="passthrough_y" args="load pcl/PassThrough pcl_manager" output="screen">

    <remap from="~input" to="/x_filtered" />

    <remap from="~output" to="/search_cloud" />

    <rosparam>

      filter_field_name: y

      filter_limit_min: -0.5

      filter_limit_max: -0.1

      filter_limit_negative: False

    </rosparam>

  </node>

 

  <node pkg="openrobot_follow" name="follower" type="follower2.py" output="screen">

    <remap from="point_cloud" to="search_cloud" />

    <rosparam>

       goal_z: 0.8

       z_threshold: 0.025

       x_threshold: 0.025

       z_scale: 1.0

       x_scale: 3.0

       max_angular_speed: 5.0

       min_angular_speed: 0.1

       max_linear_speed: 0.4

       min_linear_speed: 0.05

    </rosparam>

  </node>

</launch>

 

 

4)launch详解

nodelet是ros自带的节点管理系统,类似于java里的多线程

 

利用VoxelGrid算法,对pointcloud的深度信息过滤

 

然后利用passthrough算法,对x  ,y坐标过滤

 

过滤可以降低计算量,又不会影响follow结果

 

最后启动follow节点

 

remap表示话题的映射,相当于给话题改名

 

5)参数详解

filter_field_name:     选择过滤的坐标系(x,y,z)

filter_limit_min:      最短的过滤信息,即最短的检测距离

      filter_limit_max:      最大的过滤信息,即最大的检测距离

leaf_size:             算法切块的大小

goal_z:               距离目标的距离

      z_threshold:          深度偏差量

      x_threshold:          x方向偏差量,即允许人在图像的哪个范围

      z_scale:             距离权重,控制线速度

      x_scale:             x方向的权重,控制角速度

      max_angular_speed:   最大角速度

      min_angular_speed:    最小角速度

      max_linear_speed:     最大线速度

      min_linear_speed:     最小线速度

 

3.  语音实现

1)概述

利用ros自带的语音识别包pocketsphinx,订阅/input/recognizer话题,获得识别结果,然后给follow函数设置一个使能变量,在语音的回调函数里对使能变量做操作

 

2)环境配置

sudo apt-get install ros-indigo-turtlebot-bringup \

ros-indigo-turtlebot-create-desktop ros-indigo-openni-* \

ros-indigo-openni2-* ros-indigo-freenect-* ros-indigo-usb-cam \

ros-indigo-laser-* ros-indigo-hokuyo-node \

ros-indigo-audio-common gstreamer0.10-pocketsphinx \

ros-indigo-pocketsphinx ros-indigo-slam-gmapping \

ros-indigo-joystick-drivers python-rosinstall \

ros-indigo-orocos-kdl ros-indigo-python-orocos-kdl \

python-setuptools ros-indigo-dynamixel-motor-* \

libopencv-dev python-opencv ros-indigo-vision-opencv \

ros-indigo-depthimage-to-laserscan ros-indigo-arbotix-* \

ros-indigo-turtlebot-teleop ros-indigo-move-base \

ros-indigo-map-server ros-indigo-fake-localization \

ros-indigo-amcl git subversion mercurial

 

 

3)代码重写

 

#!/usr/bin/env python

import rospy

from roslib import message

from sensor_msgs import point_cloud2

from sensor_msgs.msg import PointCloud2

from geometry_msgs.msg import Twist

from std_msgs.msg import String

from math import copysig

class Follower():

    def __init__(self):

        rospy.init_node("follower")

        rospy.on_shutdown(self.shutdown)

        self.goal_z = rospy.get_param("~goal_z", 1.5)

        self.z_threshold = rospy.get_param("~z_threshold", 0.05)

        self.x_threshold = rospy.get_param("~x_threshold", 0.05)

        self.z_scale = rospy.get_param("~z_scale", 0.7) 

        self.x_scale = rospy.get_param("~x_scale", 2.2)

        self.max_angular_speed = rospy.get_param("~max_angular_speed", 2.0)

        self.min_angular_speed = rospy.get_param("~min_angular_speed", 0.0)        self.max_linear_speed = rospy.get_param("~max_linear_speed", 0.3)       

        self.min_linear_speed = rospy.get_param("~min_linear_speed", 0.1)

        self.slow_down_factor = rospy.get_param("~slow_down_factor", 0.8)

        self.move_cmd = Twist()

        self.cmd_vel_pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10)

  self.sta = 1

  self.speech_sub = rospy.Subscriber('recognizer/output',String,self.speechcb,queue_size=1)

 

        # Subscribe to the point cloud

        self.depth_subscriber = rospy.Subscriber('point_cloud', PointCloud2, self.set_cmd_vel, queue_size=10)

 

        rospy.loginfo("Subscribing to point cloud...")

       

        # Wait for the pointcloud topic to become available

        rospy.wait_for_message('point_cloud', PointCloud2)

 

        rospy.loginfo("Ready to follow!")

 

    def speechcb(self,msg):

  if msg.data == 'stop':

         self.sta=0

  elif msg.data == 'move':

         self.sta=1

       

    def set_cmd_vel(self, msg):

        # Initialize the centroid coordinates point count

        x = y = z = n = 0

       

        # Read in the x, y, z coordinates of all points in the cloud

        for point in point_cloud2.read_points(msg, skip_nans=True):

            pt_x = point[0]

            pt_y = point[1]

            pt_z = point[2]

           

            x += pt_x

            y += pt_y

            z += pt_z

            n += 1

        if n:

            x /= n

            y /= n

            z /= n

 

            if (abs(z - self.goal_z) > self.z_threshold):

   

                linear_speed = (z - self.goal_z) * self.z_scale

                self.move_cmd.linear.x = copysign(max(self.min_linear_speed,

                                        min(self.max_linear_speed, abs(linear_speed))), linear_speed)

            else:

                self.move_cmd.linear.x *= self.slow_down_factor

               

            if (abs(x) > self.x_threshold):    

                angular_speed = -x * self.x_scale

                

                self.move_cmd.angular.z = copysign(max(self.min_angular_speed,

                                        min(self.max_angular_speed, abs(angular_speed))), angular_speed)

            else:

                self.move_cmd.angular.z *= self.slow_down_factor

               

        else:

            self.move_cmd.linear.x *= self.slow_down_factor

            self.move_cmd.angular.z *= self.slow_down_factor

           

     

  if self.sta == 0:

         self.cmd_vel_pub.publish(Twist())

  else:

         self.cmd_vel_pub.publish(self.move_cmd)

       

    def shutdown(self):

        rospy.loginfo("Stopping the robot...")

       

        self.depth_subscriber.unregister()

        rospy.sleep(1)

       

        self.cmd_vel_pub.publish(Twist())

        rospy.sleep(1)     

                  

if __name__ == '__main__':

    try:

        Follower()

        rospy.spin()

    except rospy.ROSInterruptException:

        rospy.loginfo("Follower node terminated.")

 

4)Launch重写

<launch>

 

<node name="recognizer" pkg="pocketsphinx" type="recognizer.py" output="screen">

    <param name="lm" value="$(find rbx1_speech)/config/nav_commands.lm"/>

    <param name="dict" value="$(find rbx1_speech)/config/nav_commands.dic"/>

  </node>

 

  <node pkg="nodelet" type="nodelet" name="pcl_manager" args="manager" output="screen" />

 

  <!-- Run a VoxelGrid filter on the z axis -->

  <node pkg="nodelet" type="nodelet" name="voxel_grid_z" args="load pcl/VoxelGrid pcl_manager" output="screen">

    <remap from="~input" to="/kinect2/qhd/points" />

    <remap from="~output" to="/z_filtered" />

    <rosparam>

      filter_field_name: z

      filter_limit_min: 0.3

      filter_limit_max: 1.6

      filter_limit_negative: False

      leaf_size: 0.02

    </rosparam>

  </node>

 

  <!-- Run a passthrough filter on the x axis -->

  <node pkg="nodelet" type="nodelet" name="passthrough_x" args="load pcl/PassThrough pcl_manager" output="screen">

    <remap from="~input" to="/z_filtered" />

    <remap from="~output" to="/x_filtered" />

    <rosparam>

      filter_field_name: x

      filter_limit_min: -0.3

      filter_limit_max: 0.3

      filter_limit_negative: False

    </rosparam>

  </node>

 

  <!-- Run a passthrough filter on the y axis -->

  <node pkg="nodelet" type="nodelet" name="passthrough_y" args="load pcl/PassThrough pcl_manager" output="screen">

    <remap from="~input" to="/x_filtered" />

    <remap from="~output" to="/search_cloud" />

    <rosparam>

      filter_field_name: y

      filter_limit_min: -0.5

      filter_limit_max: -0.1

      filter_limit_negative: False

    </rosparam>

  </node>

 

  <node pkg="openrobot_follow" name="follower" type="follower2.py" output="screen">

    <remap from="point_cloud" to="search_cloud" />

   

    <rosparam>

       goal_z: 1.2

       z_threshold: 0.025

       x_threshold: 0.025

       z_scale: 0.6

       x_scale: 2.1

       max_angular_speed: 3.0

       min_angular_speed: 0.1

       max_linear_speed: 0.4

       min_linear_speed: 0.05

    </rosparam>

   

  </node>

</launch>

 

 

4. 颜色标定实现

1 ) 概述

 利用opencv提供的python接口,处理图像信息,利用cv_bridge将ros话题上发布的摄像头消息数据转化成为opencv可以处理的图像数据。

 

2 )代码见github项目

 

 

 

 3 ) launch

    <launch> 

  <node name="recognizer" pkg="pocketsphinx" type="recognizer.py" output="screen">

    <param name="lm" value="/home/tt/my_ws/src/openrobot_follow/speech_conf/command.lm"/>

    <param name="dict" value="/home/tt/my_ws/src/openrobot_follow/speech_conf/command.dic"/>

  </node>

  <node pkg="openrobot_follow" name="color_follower" type="color_follower.py" output="screen">

<remap from="camera_info" to="/camera/rgb/camera_info" />

  <remap from="depth_image" to="/camera/depth_registered/image_raw" />

    <rosparam>

       rate: 20

       max_z: 2.0  # How far out do we want to detect

       min_z: 0.1

       goal_z: 0.7

       z_threshold: 0.1

       x_threshold: 0.3

       z_scale: 1.0 # forward/back scale

       x_scale: 1.3 # left/right scale

       max_rotation_speed: 1.0

       min_rotation_speed: 0.1

       max_linear_speed: 0.2

       min_linear_speed: 0.02

       scale_roi: 0.9

    </rosparam>

  </node>

</launch>

4 )launch详解

rate:   消息回调速度,一般不用动,如果出现卡顿再改动

       max_z:   检测的最大距离

       min_z:   检测的最小距离

       goal_z:   保持机器和目标的距离

       z_threshold: 距离的可控区域

       x_threshold: 图像的可控区域,即在屏幕上画个矩形,让目标保持在矩形内

       z_scale:    线速度的权值

       x_scale:    角速度的权值

       max_rotation_speed: 最大角速度

       min_rotation_speed: 最小角速度

       max_linear_speed:   最大线速度

       min_linear_speed:    最小线速度

       scale_roi:    对roi话题上发布的信息的缩小范围

1.     运行底盘驱动

rosrun openrobot Node_p_chassis

 

 2 .打开摄像头驱动(实验室用的奥比中光深度摄像头)

  roslaunch astra_launch astra.launch

 3.启动camshift 发布/roi

  roslaunch openrobot_follow camshift.launch

这时候屏幕上会出现3个窗口,在有图像的窗口选择需要跟随的物体。这时候程序会计算物体的颜色,另外两个窗口其中一个会出现颜色的柱状图,另一个窗口出现颜色柱状图。物体移动绿色的框会跟着移动。尽量选中颜色鲜艳的物体。4.启动跟随

  roslaunch openrobot_follow color_follow.launch

您可能感兴趣的与本文相关的镜像

Langchain-Chatchat

Langchain-Chatchat

AI应用
Langchain

Langchain-Chatchat 是一个基于 ChatGLM 等大语言模型和 Langchain 应用框架实现的开源项目,旨在构建一个可以离线部署的本地知识库问答系统。它通过检索增强生成 (RAG) 的方法,让用户能够以自然语言与本地文件、数据库或搜索引擎进行交互,并支持多种大模型和向量数据库的集成,以及提供 WebUI 和 API 服务

上面的错误,我使用了!analyze -v 指令后 SYSTEM_SERVICE_EXCEPTION (3b) An exception happened while executing a system service routine. Arguments: Arg1: 00000000c000001d, Exception code that caused the BugCheck Arg2: ffffbf8942103b20, Address of the instruction which caused the BugCheck Arg3: ffffdf815547d070, Address of the context record for the exception that caused the BugCheck Arg4: 0000000000000000, zero. Debugging Details: ------------------ KEY_VALUES_STRING: 1 Key : Analysis.CPU.mSec Value: 3109 Key : Analysis.Elapsed.mSec Value: 15964 Key : Analysis.IO.Other.Mb Value: 0 Key : Analysis.IO.Read.Mb Value: 14 Key : Analysis.IO.Write.Mb Value: 2 Key : Analysis.Init.CPU.mSec Value: 1625 Key : Analysis.Init.Elapsed.mSec Value: 336944 Key : Analysis.Memory.CommitPeak.Mb Value: 121 Key : Analysis.Version.DbgEng Value: 10.0.27829.1001 Key : Analysis.Version.Description Value: 10.2503.24.01 amd64fre Key : Analysis.Version.Ext Value: 1.2503.24.1 Key : Bugcheck.Code.KiBugCheckData Value: 0x3b Key : Bugcheck.Code.LegacyAPI Value: 0x3b Key : Bugcheck.Code.TargetModel Value: 0x3b Key : Failure.Bucket Value: 0x3B_C000001D_HyperHideDrv!HookedNtContinue Key : Failure.Exception.IP.Address Value: 0xffffbf8942103b20 Key : Failure.Hash Value: {8e106373-5690-bf65-5b28-0541e087c782} Key : Hypervisor.Enlightenments.Value Value: 13088 Key : Hypervisor.Enlightenments.ValueHex Value: 0x3320 Key : Hypervisor.Flags.AnyHypervisorPresent Value: 1 Key : Hypervisor.Flags.ApicEnlightened Value: 0 Key : Hypervisor.Flags.ApicVirtualizationAvailable Value: 0 Key : Hypervisor.Flags.AsyncMemoryHint Value: 0 Key : Hypervisor.Flags.CoreSchedulerRequested Value: 0 Key : Hypervisor.Flags.CpuManager Value: 0 Key : Hypervisor.Flags.DeprecateAutoEoi Value: 1 Key : Hypervisor.Flags.DynamicCpuDisabled Value: 0 Key : Hypervisor.Flags.Epf Value: 0 Key : Hypervisor.Flags.ExtendedProcessorMasks Value: 0 Key : Hypervisor.Flags.HardwareMbecAvailable Value: 0 Key : Hypervisor.Flags.MaxBankNumber Value: 0 Key : Hypervisor.Flags.MemoryZeroingControl Value: 0 Key : Hypervisor.Flags.NoExtendedRangeFlush Value: 1 Key : Hypervisor.Flags.NoNonArchCoreSharing Value: 0 Key : Hypervisor.Flags.Phase0InitDone Value: 1 Key : Hypervisor.Flags.PowerSchedulerQos Value: 0 Key : Hypervisor.Flags.RootScheduler Value: 0 Key : Hypervisor.Flags.SynicAvailable Value: 1 Key : Hypervisor.Flags.UseQpcBias Value: 0 Key : Hypervisor.Flags.Value Value: 536632 Key : Hypervisor.Flags.ValueHex Value: 0x83038 Key : Hypervisor.Flags.VpAssistPage Value: 1 Key : Hypervisor.Flags.VsmAvailable Value: 0 Key : Hypervisor.RootFlags.AccessStats Value: 0 Key : Hypervisor.RootFlags.CrashdumpEnlightened Value: 0 Key : Hypervisor.RootFlags.CreateVirtualProcessor Value: 0 Key : Hypervisor.RootFlags.DisableHyperthreading Value: 0 Key : Hypervisor.RootFlags.HostTimelineSync Value: 0 Key : Hypervisor.RootFlags.HypervisorDebuggingEnabled Value: 0 Key : Hypervisor.RootFlags.IsHyperV Value: 0 Key : Hypervisor.RootFlags.LivedumpEnlightened Value: 0 Key : Hypervisor.RootFlags.MapDeviceInterrupt Value: 0 Key : Hypervisor.RootFlags.MceEnlightened Value: 0 Key : Hypervisor.RootFlags.Nested Value: 0 Key : Hypervisor.RootFlags.StartLogicalProcessor Value: 0 Key : Hypervisor.RootFlags.Value Value: 0 Key : Hypervisor.RootFlags.ValueHex Value: 0x0 Key : SecureKernel.HalpHvciEnabled Value: 0 Key : WER.OS.Branch Value: vb_release Key : WER.OS.Version Value: 10.0.19041.1 BUGCHECK_CODE: 3b BUGCHECK_P1: c000001d BUGCHECK_P2: ffffbf8942103b20 BUGCHECK_P3: ffffdf815547d070 BUGCHECK_P4: 0 FAULTING_THREAD: ffffbf8943364080 CONTEXT: ffffdf815547d070 -- (.cxr 0xffffdf815547d070) rax=ffffbf8942103b10 rbx=ffffbf8943364080 rcx=000000e265bff770 rdx=0000000000000001 rsi=0000000000000000 rdi=0000000000000000 rip=ffffbf8942103b20 rsp=ffffdf815547da78 rbp=ffffdf815547db80 r8=00000000ffffffff r9=7ffff80119936b30 r10=7ffffffffffffffc r11=0000000000336cb0 r12=0000000000000000 r13=0000000000000000 r14=0000000000000000 r15=0000000000000000 iopl=0 nv up ei ng nz ac po cy cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00010297 ffffbf89`42103b20 ff ??? Resetting default scope PROCESS_NAME: msedgewebview2.exe STACK_TEXT: ffffdf81`5547da78 fffff801`1992bc21 : ffffbf89`48c74080 fffff801`00000013 00000000`00000000 ffffdf81`5547db80 : 0xffffbf89`42103b20 ffffdf81`5547da80 fffff801`14811f05 : 000000e2`65bff770 00000000`00000001 00000000`00000001 ffffbf89`00000000 : HyperHideDrv!HookedNtContinue+0x1b1 [C:\Users\pc\Desktop\vt-debuuger-main\HyperHideDrv\HookedFunctions.cpp @ 1540] ffffdf81`5547db00 00007ff9`79badd54 : 00007ff9`79b85c28 000000e2`65bff770 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x25 000000e2`65bff718 00007ff9`79b85c28 : 000000e2`65bff770 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!NtContinue+0x14 000000e2`65bff720 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!LdrInitializeThunk+0x18 FAULTING_SOURCE_LINE: C:\Users\pc\Desktop\vt-debuuger-main\HyperHideDrv\HookedFunctions.cpp FAULTING_SOURCE_FILE: C:\Users\pc\Desktop\vt-debuuger-main\HyperHideDrv\HookedFunctions.cpp FAULTING_SOURCE_LINE_NUMBER: 1540 FAULTING_SOURCE_CODE: 1536: } 1537: } 1538: 1539: return OriginalNtContinue(Context, TestAlert); > 1540: } 1541: 1542: NTSTATUS(NTAPI* OriginalNtQueryInformationJobObject)(HANDLE JobHandle, JOBOBJECTINFOCLASS JobInformationClass, PVOID JobInformation, ULONG JobInformationLength, PULONG ReturnLength); 1543: NTSTATUS NTAPI HookedNtQueryInformationJobObject(HANDLE JobHandle, JOBOBJECTINFOCLASS JobInformationClass, PVOID JobInformation, ULONG JobInformationLength, PULONG ReturnLength) 1544: { 1545: NTSTATUS Status = OriginalNtQueryInformationJobObject(JobHandle, JobInformationClass, JobInformation, JobInformationLength, ReturnLength); SYMBOL_NAME: HyperHideDrv!HookedNtContinue+1b1 MODULE_NAME: HyperHideDrv IMAGE_NAME: HyperHideDrv.sys STACK_COMMAND: .cxr 0xffffdf815547d070 ; kb BUCKET_ID_FUNC_OFFSET: 1b1 FAILURE_BUCKET_ID: 0x3B_C000001D_HyperHideDrv!HookedNtContinue OS_VERSION: 10.0.19041.1 BUILDLAB_STR: vb_release OSPLATFORM_TYPE: x64 OSNAME: Windows 10 FAILURE_ID_HASH: {8e106373-5690-bf65-5b28-0541e087c782} Followup: MachineOwner ---------
08-08
Debugging Details: ------------------ KEY_VALUES_STRING: 1 Key : Analysis.CPU.Sec Value: 2 Key : Analysis.DebugAnalysisProvider.CPP Value: Create: 8007007e on WIN-E6RUS8U7A5V Key : Analysis.DebugData Value: CreateObject Key : Analysis.DebugModel Value: CreateObject Key : Analysis.Elapsed.Sec Value: 18 Key : Analysis.Memory.CommitPeak.Mb Value: 77 Key : Analysis.System Value: CreateObject BUGCHECK_CODE: 139 BUGCHECK_P1: 3 BUGCHECK_P2: ffff810ac7717520 BUGCHECK_P3: ffff810ac7717478 BUGCHECK_P4: 0 TRAP_FRAME: ffff810ac7717520 -- (.trap 0xffff810ac7717520) NOTE: The trap frame does not contain all registers. Some register values may be zeroed or incorrect. rax=ffffb50eb34ff3d0 rbx=0000000000000000 rcx=0000000000000003 rdx=0000000080000000 rsi=0000000000000000 rdi=0000000000000000 rip=fffff80769772d12 rsp=ffff810ac77176b0 rbp=ffffb50eb62d8080 r8=0000000000000000 r9=fffff8076a050dc0 r10=00000000000000c1 r11=fffff8076a200010 r12=0000000000000000 r13=0000000000000000 r14=0000000000000000 r15=0000000000000000 iopl=0 nv up ei ng nz na pe cy nt!MiProcessLoaderEntry+0x1d2: fffff807`69772d12 cd29 int 29h Resetting default scope EXCEPTION_RECORD: ffff810ac7717478 -- (.exr 0xffff810ac7717478) ExceptionAddress: fffff80769772d12 (nt!MiProcessLoaderEntry+0x00000000000001d2) ExceptionCode: c0000409 (Security check failure or stack buffer overrun) ExceptionFlags: 00000001 NumberParameters: 1 Parameter[0]: 0000000000000003 Subcode: 0x3 FAST_FAIL_CORRUPT_LIST_ENTRY BLACKBOXBSD: 1 (!blackboxbsd) BLACKBOXNTFS: 1 (!blackboxntfs) BLACKBOXWINLOGON: 1 CUSTOMER_CRASH_COUNT: 1 PROCESS_NAME: YDArk.exe ERROR_CODE: (NTSTATUS) 0xc0000409 - <Unable to get error code text> EXCEPTION_CODE_STR: c0000409 EXCEPTION_PARAMETER1: 0000000000000003 EXCEPTION_STR: 0xc0000409 STACK_TEXT: ffff810a`c77171f8 fffff807`69811da9 : 00000000`00000139 00000000`00000003 ffff810a`c7717520 ffff810a`c7717478 : nt!KeBugCheckEx ffff810a`c7717200 fffff807`69812350 : ffffa300`a2347180 fffff807`696bb754 00000000`00000000 00000000`00000000 : nt!KiBugCheckDispatch+0x69 ffff810a`c7717340 fffff807`698101f2 : 00000000`ffffffff ffffb50e`b7bcf560 00000000`00772000 ffffde00`03844860 : nt!KiFastFailDispatch+0xd0 ffff810a`c7717520 fffff807`69772d12 : ffffb50e`b62d8080 ffffffff`ffffff00 ffffb50e`bd2de390 00000000`00000000 : nt!KiRaiseSecurityCheckFailure+0x332 ffff810a`c77176b0 fffff807`69afee70 : ffffb50e`bd2de390 ffff810a`c7717700 ffff810a`c77177f0 ffffb50e`b7bcf500 : nt!MiProcessLoaderEntry+0x1d2 ffff810a`c77176f0 fffff807`69b71d71 : 00000000`00000000 fffff807`ffffffff ffff025a`00000001 ffffe40e`d17a3f40 : nt!MiUnloadSystemImage+0x4b8 ffff810a`c7717890 fffff807`69b71c9e : ffffb50e`b6e72a40 ffff810a`c7717bc0 00000000`00000000 ffff810a`c7717d30 : nt!MmUnloadSystemImage+0x41 ffff810a`c77178c0 fffff807`69a3dbe0 : ffffb50e`b6e72a40 ffff810a`c7717bc0 ffffb50e`b6e72a40 fffff807`69af6faf : nt!IopDeleteDriver+0x4e ffff810a`c7717910 fffff807`696cb917 : 00000000`00000000 00000000`00000000 ffff810a`c7717bc0 ffffb50e`b6e72a70 : nt!ObpRemoveObjectRoutine+0x80 ffff810a`c7717970 fffff807`696cb83e : ffffb50e`b6e72a70 ffff810a`c7717d30 ffffb50e`b6e72a40 00000000`000a0000 : nt!ObfDereferenceObjectWithTag+0xc7 ffff810a`c77179b0 fffff807`69b68f28 : ffffb50e`b6e72a70 ffff810a`c7717bc0 ffff810a`c7717d30 00000000`c0000001 : nt!HalPutDmaAdapter+0xe ffff810a`c77179e0 fffff807`69c9b1fb : ffffb50e`b62d8080 00000000`00000000 00000000`00000001 ffffb50e`b6e72a70 : nt!IopUnloadDriver+0x250 ffff810a`c7717b10 fffff807`69811505 : 00000000`00000003 00000000`000000c0 00000000`000000c8 00000000`00000000 : nt!NtUnloadDriver+0xb ffff810a`c7717b40 fffff807`698023b0 : fffff807`69c3a9b6 ffffb50e`b62d8080 fffff807`699dd32d 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x25 ffff810a`c7717cd8 fffff807`69c3a9b6 : ffffb50e`b62d8080 fffff807`699dd32d 00000000`00000000 ffffe40e`d1e19060 : nt!KiServiceLinkage ffff810a`c7717ce0 fffff807`69c9b1fb : ffffb50e`b62d8080 00000000`00000002 00000000`00000000 00000000`00000000 : nt!IopUnloadDriver+0xd1cde ffff810a`c7717e10 fffff807`69811505 : 00000000`00000000 ffff810a`c805f500 ffff810a`c7717ec0 ffffc79e`36026c88 : nt!NtUnloadDriver+0xb ffff810a`c7717e40 00007fff`f0370e94 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x25 0000008d`775fe698 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`f0370e94 SYMBOL_NAME: nt!KiFastFailDispatch+d0 MODULE_NAME: nt IMAGE_NAME: ntkrnlmp.exe IMAGE_VERSION: 10.0.19041.6456 STACK_COMMAND: .thread ; .cxr ; kb BUCKET_ID_FUNC_OFFSET: d0 FAILURE_BUCKET_ID: 0x139_3_CORRUPT_LIST_ENTRY_nt!KiFastFailDispatch OS_VERSION: 10.0.19041.1 BUILDLAB_STR: vb_release OSPLATFORM_TYPE: x64 OSNAME: Windows 10 FAILURE_ID_HASH: {3aede96a-54dd-40d6-d4cb-2a161a843851} Followup: MachineOwner 不吃
最新发布
11-18
kd> ed nt!Kd_DEFAULT_Mask 0xFFFFFFFF kd> ed nt!Kd_IHVDRIVER_Mask 0xFFFFFFFF kd> g [+] [DriverEntry] 驱动加载开始 [+] [DriverEntry] 驱动加载成功 [+] [ProcessNotifyCallback] 目标进程 oxygen.exe 创建 (PID: 8052) [+] [ProcessNotifyCallback] 工作线程已创建 [+] Worker thread started for hook installation on PID: 8052 Break instruction exception - code 80000003 (first chance) obpcallback!InstallHook+0x50: fffff803`0e2a12f0 cc int 3 kd> g [+] [InstallHook] 找到目标函数地址: FFFFF803062EFB60 [PTE_HOOK] 开始隔离页面: PID=8052, 地址=0xFFFFF803062EFB60 [PTE_HOOK] 正在拆分大页: 输入PDE=0xa00000002a001a1, 输出PDE=0xFFFFBB878EFA3F80 [PTE_HOOK] 大页拆分完成: 新PTE表物理地址=0x239dab000 [PTE_HOOK] G-Bit Info: Align Address: 0xFFFFF803062EF000 IsLargePage: 1 PDE: 0xa00000002a000a1 (Address: 0xFFFFFE7F3E00C188) [PTE_HOOK] 清除大页G位: PDE=0xa00000002a000a1 [PTE_HOOK] 开始隔离页表: CR3=0x12e16c000, 地址=0xFFFFF803062EF000 KDTARGET: Refreshing KD connection *** Fatal System Error: 0x0000007e (0xFFFFFFFFC0000005,0xFFFFF8030E2A2265,0xFFFF80031C95B638,0xFFFF80031C95AE70) Break instruction exception - code 80000003 (first chance) A fatal system error has occurred. Debugger entered on first try; Bugcheck callbacks have not been invoked. A fatal system error has occurred. For analysis of this file, run !analyze -v nt!DbgBreakPointWithStatus: fffff803`05ffd0b0 cc int 3 kd> !analyze -v Connected to Windows 10 19041 x64 target at (Wed Jul 9 20:20:01.053 2025 (UTC + 8:00)), ptr64 TRUE Loading Kernel Symbols ................................... Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that take too long. Run !sym noisy before .reload to track down problems loading symbols. ............................ ................................................................ ..................................................... Loading User Symbols PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details Loading unloaded module list ...... ERROR: FindPlugIns 8007007b ******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (7e) This is a very common BugCheck. Usually the exception address pinpoints the driver/function that caused the problem. Always note this address as well as the link date of the driver/image that contains this address. Arguments: Arg1: ffffffffc0000005, The exception code that was not handled Arg2: fffff8030e2a2265, The address that the exception occurred at Arg3: ffff80031c95b638, Exception Record Address Arg4: ffff80031c95ae70, Context Record Address Debugging Details: ------------------ Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that take too long. Run !sym noisy before .reload to track down problems loading symbols. PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 00000000`00259018). Type ".hh dbgerr001" for details KEY_VALUES_STRING: 1 Key : AV.Type Value: Read Key : Analysis.CPU.mSec Value: 4234 Key : Analysis.Elapsed.mSec Value: 39170 Key : Analysis.IO.Other.Mb Value: 0 Key : Analysis.IO.Read.Mb Value: 2 Key : Analysis.IO.Write.Mb Value: 0 Key : Analysis.Init.CPU.mSec Value: 3250 Key : Analysis.Init.Elapsed.mSec Value: 59417 Key : Analysis.Memory.CommitPeak.Mb Value: 72 Key : Analysis.Version.DbgEng Value: 10.0.27829.1001 Key : Analysis.Version.Description Value: 10.2503.24.01 amd64fre Key : Analysis.Version.Ext Value: 1.2503.24.1 Key : Bugcheck.Code.KiBugCheckData Value: 0x7e Key : Bugcheck.Code.LegacyAPI Value: 0x7e Key : Bugcheck.Code.TargetModel Value: 0x7e Key : Failure.Bucket Value: AV_obpcallback!PteHookManager::fn_isolation_pagetable Key : Failure.Exception.Code Value: 0xc0000005 Key : Failure.Exception.IP.Address Value: 0xfffff8030e2a2265 Key : Failure.Exception.IP.Module Value: obpcallback Key : Failure.Exception.IP.Offset Value: 0x2265 Key : Failure.Exception.Record Value: 0xffff80031c95b638 Key : Failure.Hash Value: {03bbd39e-299b-91b8-212d-d002a6bff650} Key : Hypervisor.Enlightenments.Value Value: 12576 Key : Hypervisor.Enlightenments.ValueHex Value: 0x3120 Key : Hypervisor.Flags.AnyHypervisorPresent Value: 1 Key : Hypervisor.Flags.ApicEnlightened Value: 0 Key : Hypervisor.Flags.ApicVirtualizationAvailable Value: 0 Key : Hypervisor.Flags.AsyncMemoryHint Value: 0 Key : Hypervisor.Flags.CoreSchedulerRequested Value: 0 Key : Hypervisor.Flags.CpuManager Value: 0 Key : Hypervisor.Flags.DeprecateAutoEoi Value: 1 Key : Hypervisor.Flags.DynamicCpuDisabled Value: 0 Key : Hypervisor.Flags.Epf Value: 0 Key : Hypervisor.Flags.ExtendedProcessorMasks Value: 0 Key : Hypervisor.Flags.HardwareMbecAvailable Value: 0 Key : Hypervisor.Flags.MaxBankNumber Value: 0 Key : Hypervisor.Flags.MemoryZeroingControl Value: 0 Key : Hypervisor.Flags.NoExtendedRangeFlush Value: 1 Key : Hypervisor.Flags.NoNonArchCoreSharing Value: 0 Key : Hypervisor.Flags.Phase0InitDone Value: 1 Key : Hypervisor.Flags.PowerSchedulerQos Value: 0 Key : Hypervisor.Flags.RootScheduler Value: 0 Key : Hypervisor.Flags.SynicAvailable Value: 1 Key : Hypervisor.Flags.UseQpcBias Value: 0 Key : Hypervisor.Flags.Value Value: 536632 Key : Hypervisor.Flags.ValueHex Value: 0x83038 Key : Hypervisor.Flags.VpAssistPage Value: 1 Key : Hypervisor.Flags.VsmAvailable Value: 0 Key : Hypervisor.RootFlags.AccessStats Value: 0 Key : Hypervisor.RootFlags.CrashdumpEnlightened Value: 0 Key : Hypervisor.RootFlags.CreateVirtualProcessor Value: 0 Key : Hypervisor.RootFlags.DisableHyperthreading Value: 0 Key : Hypervisor.RootFlags.HostTimelineSync Value: 0 Key : Hypervisor.RootFlags.HypervisorDebuggingEnabled Value: 0 Key : Hypervisor.RootFlags.IsHyperV Value: 0 Key : Hypervisor.RootFlags.LivedumpEnlightened Value: 0 Key : Hypervisor.RootFlags.MapDeviceInterrupt Value: 0 Key : Hypervisor.RootFlags.MceEnlightened Value: 0 Key : Hypervisor.RootFlags.Nested Value: 0 Key : Hypervisor.RootFlags.StartLogicalProcessor Value: 0 Key : Hypervisor.RootFlags.Value Value: 0 Key : Hypervisor.RootFlags.ValueHex Value: 0x0 Key : SecureKernel.HalpHvciEnabled Value: 0 Key : WER.OS.Branch Value: vb_release Key : WER.OS.Version Value: 10.0.19041.1 BUGCHECK_CODE: 7e BUGCHECK_P1: ffffffffc0000005 BUGCHECK_P2: fffff8030e2a2265 BUGCHECK_P3: ffff80031c95b638 BUGCHECK_P4: ffff80031c95ae70 FAULTING_THREAD: ffffbb8793f90080 EXCEPTION_RECORD: ffff80031c95b638 -- (.exr 0xffff80031c95b638) ExceptionAddress: fffff8030e2a2265 (obpcallback!PteHookManager::fn_isolation_pagetable+0x0000000000000315) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 0000000000000000 Parameter[1]: 0000000239dab000 Attempt to read from address 0000000239dab000 CONTEXT: ffff80031c95ae70 -- (.cxr 0xffff80031c95ae70) rax=0000000239dab000 rbx=ffffbb8793f90080 rcx=0000000000001000 rdx=0000000000000000 rsi=0000000239dab000 rdi=ffff9181d99a7000 rip=fffff8030e2a2265 rsp=ffff80031c95b870 rbp=0000000000000080 r8=ffff80031c95b940 r9=8000000000000200 r10=0000000000000000 r11=ffffbb8790910000 r12=0000000000000280 r13=0000000000000000 r14=ffffbb878f4af040 r15=fffff8030c094000 iopl=0 nv up ei pl nz ac po nc cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00050216 obpcallback!PteHookManager::fn_isolation_pagetable+0x315: fffff803`0e2a2265 f3a4 rep movs byte ptr [rdi],byte ptr [rsi] Resetting default scope PROCESS_NAME: oxygen.exe READ_ADDRESS: unable to get nt!PspSessionIdBitmap 0000000239dab000 ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p 0x%p %s EXCEPTION_CODE_STR: c0000005 EXCEPTION_PARAMETER1: 0000000000000000 EXCEPTION_PARAMETER2: 0000000239dab000 EXCEPTION_STR: 0xc0000005 STACK_TEXT: ffff8003`1c95b870 fffff803`0e2a1da1 : ffffbb87`8efa7000 00000001`2e16c000 fffff803`062ef000 ffffbb87`8efa3f80 : obpcallback!PteHookManager::fn_isolation_pagetable+0x315 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 526] ffff8003`1c95b9c0 fffff803`0e2a25df : ffffbb87`8efa7000 00000000`00001f74 fffff803`062efb60 00000000`00000035 : obpcallback!PteHookManager::fn_isolation_pages+0x261 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 602] ffff8003`1c95bad0 fffff803`0e2a1344 : ffffbb87`8efa7000 00000000`00001f74 ffff8003`1c95bbb0 fffff803`0e2a1500 : obpcallback!PteHookManager::fn_pte_inline_hook_bp_pg+0x4f [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 723] ffff8003`1c95bb90 fffff803`0e2a13d4 : fffff803`0e2a44a0 00000000`00001f74 00000000`00000000 fffff803`040ef180 : obpcallback!InstallHook+0xa4 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 982] ffff8003`1c95bbe0 fffff803`05ea29a5 : 00000000`00001f74 fffff803`0e2a13a0 00000000`00001f74 fffff803`00000001 : obpcallback!InstallHookWorker+0x34 [C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp @ 1010] ffff8003`1c95bc10 fffff803`05ffc868 : fffff803`040ef180 ffffbb87`93f90080 fffff803`05ea2950 ffff8003`1c95bc80 : nt!PspSystemThreadStartup+0x55 ffff8003`1c95bc60 00000000`00000000 : ffff8003`1c95c000 ffff8003`1c956000 00000000`00000000 00000000`00000000 : nt!KiStartSystemThread+0x28 FAULTING_SOURCE_LINE: C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp FAULTING_SOURCE_FILE: C:\Users\17116\source\repos\obpcallback\obpcallback\Ô´.cpp FAULTING_SOURCE_LINE_NUMBER: 526 FAULTING_SOURCE_CODE: 522: memcpy(Va4kb, replace_align_addr, PAGE_SIZE); 523: 524: if (Table.IsLargePage && split_pde_ptr) { 525: auto split_pde = (decltype(PAGE_TABLE::PdeAddress))split_pde_ptr; > 526: memcpy(VaPt, (void*)(split_pde->flags.page_frame_number << 12), PAGE_SIZE); 527: } 528: else { 529: memcpy(VaPt, (void*)(Table.PdeAddress->flags.page_frame_number << 12), PAGE_SIZE); 530: } 531: SYMBOL_NAME: obpcallback!PteHookManager::fn_isolation_pagetable+315 MODULE_NAME: obpcallback IMAGE_NAME: obpcallback.sys STACK_COMMAND: .cxr 0xffff80031c95ae70 ; kb BUCKET_ID_FUNC_OFFSET: 315 FAILURE_BUCKET_ID: AV_obpcallback!PteHookManager::fn_isolation_pagetable OS_VERSION: 10.0.19041.1 BUILDLAB_STR: vb_release OSPLATFORM_TYPE: x64 OSNAME: Windows 10 FAILURE_ID_HASH: {03bbd39e-299b-91b8-212d-d002a6bff650} Followup: MachineOwner ---------按照你改的结果出错了。代码如下:#include <ntifs.h> #include <ntddk.h> #include <intrin.h> #include "ptehook.h" #define CR0_WP (1 << 16) HANDLE targetProcessId = NULL; typedef INT(*LDE_DISASM)(PVOID address, INT bits); typedef unsigned long DWORD; typedef unsigned __int64 ULONG64; // 使用WDK标准类型 typedef unsigned char BYTE; typedef LONG NTSTATUS; // 修正后的跳转指令结构 #pragma pack(push, 1) typedef struct _JMP_ABS { BYTE opcode[6]; // FF 25 00 00 00 00 ULONG64 address; // 8字节绝对地址 } JMP_ABS, * PJMP_ABS; #pragma pack(pop) LDE_DISASM lde_disasm; // 初始化引擎 VOID lde_init() { lde_disasm = (LDE_DISASM)ExAllocatePool(NonPagedPool, 12800); memcpy(lde_disasm, szShellCode, 12800); } // 得到完整指令长度,避免截断 ULONG GetFullPatchSize(PUCHAR Address) { ULONG LenCount = 0, Len = 0; // 至少需要14字节 while (LenCount <= 14) { Len = lde_disasm(Address, 64); Address = Address + Len; LenCount = LenCount + Len; } return LenCount; } #define PROCESS_NAME_LENGTH 16 #define DRIVER_TAG 'HKOB' EXTERN_C char* PsGetProcessImageFileName(PEPROCESS process); char target_process_name[] = "oxygen.exe"; typedef NTSTATUS(*fn_ObReferenceObjectByHandleWithTag)( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ); fn_ObReferenceObjectByHandleWithTag g_OriginalObReferenceObjectByHandleWithTag = NULL; // PTE Hook Framework #define MAX_G_BIT_RECORDS 128 #define MAX_HOOK_COUNT 64 #define PAGE_ALIGN(va) ((PVOID)((ULONG_PTR)(va) & ~0xFFF)) #define PDPTE_PS_BIT (1 << 7) #define PDE_PS_BIT (1 << 7) #define PTE_NX_BIT (1ULL << 63) #define CACHE_WB (6ULL << 3) // 页表结构定义 typedef struct _PAGE_TABLE { UINT64 LineAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 ignored_1 : 1; UINT64 page_size : 1; UINT64 ignored_2 : 4; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdpteAddress; UINT64* Pml4Address; BOOLEAN IsLargePage; BOOLEAN Is1GBPage; UINT64 OriginalPte; UINT64 OriginalPde; UINT64 OriginalPdpte; UINT64 OriginalPml4e; HANDLE ProcessId; } PAGE_TABLE, * PPAGE_TABLE; // G位信息记录结构体 typedef struct _G_BIT_INFO { void* AlignAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; BOOLEAN IsLargePage; } G_BIT_INFO, * PG_BIT_INFO; typedef struct _HOOK_INFO { void* OriginalAddress; void* HookAddress; UINT8 OriginalBytes[20]; UINT8 HookBytes[20]; UINT32 HookLength; BOOLEAN IsHooked; HANDLE ProcessId; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*HookedPte; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*HookedPde; } HOOK_INFO; class PteHookManager { public: bool fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr); bool fn_remove_hook(HANDLE process_id, void* hook_addr); static PteHookManager* GetInstance(); HOOK_INFO* GetHookInfo() { return m_HookInfo; } char* GetTrampLinePool() { return m_TrampLinePool; } UINT32 GetHookCount() { return m_HookCount; } bool fn_resume_global_bits(void* align_addr); ~PteHookManager(); // 添加析构函数声明 private: bool WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd); void fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address); bool fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde); bool fn_isolation_pages(HANDLE process_id, void* ori_addr); bool fn_split_large_pages(void* in_pde, void* out_pde); NTSTATUS get_page_table(UINT64 cr3, PAGE_TABLE& table); void* fn_pa_to_va(UINT64 pa); UINT64 fn_va_to_pa(void* va); __forceinline KIRQL DisableWriteProtection(); __forceinline void EnableWriteProtection(KIRQL oldIrql); void logger(const char* info, bool is_err, LONG err_code = 0); void PrintPageTableInfo(const PAGE_TABLE& table); void PrintHookInfo(const HOOK_INFO& hookInfo); void PrintGBitInfo(const G_BIT_INFO& gbitInfo); static constexpr SIZE_T MAX_HOOKS = 256; // 根据需求调整 G_BIT_INFO m_GbitRecords[MAX_G_BIT_RECORDS]; UINT32 m_GbitCount = 0; void* m_PteBase = 0; HOOK_INFO m_HookInfo[MAX_HOOK_COUNT] = { 0 }; DWORD m_HookCount = 0; char* m_TrampLinePool = nullptr; // 合并为一个声明 UINT32 m_PoolUsed = 0; static PteHookManager* m_Instance; }; PteHookManager* PteHookManager::m_Instance = nullptr; // 实现部分 __forceinline KIRQL PteHookManager::DisableWriteProtection() { KIRQL oldIrql = KeRaiseIrqlToDpcLevel(); UINT64 cr0 = __readcr0(); __writecr0(cr0 & ~0x10000); // 清除CR0.WP位 _mm_mfence(); return oldIrql; } __forceinline void PteHookManager::EnableWriteProtection(KIRQL oldIrql) { _mm_mfence(); UINT64 cr0 = __readcr0(); __writecr0(cr0 | 0x10000); // 设置CR0.WP位 KeLowerIrql(oldIrql); } void PteHookManager::logger(const char* info, bool is_err, LONG err_code) { if (is_err) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] ERROR: %s (0x%X)\n", info, err_code); } else { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] INFO: %s\n", info); } } void PteHookManager::PrintPageTableInfo(const PAGE_TABLE& table) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Page Table Info for VA: 0x%p\n", (void*)table.LineAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PML4E: 0x%llx (Address: 0x%p)\n", table.OriginalPml4e, table.Pml4Address); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDPTE: 0x%llx (Address: 0x%p), Is1GBPage: %d\n", table.OriginalPdpte, table.PdpteAddress, table.Is1GBPage); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDE: 0x%llx (Address: 0x%p), IsLargePage: %d\n", table.OriginalPde, table.PdeAddress, table.IsLargePage); if (!table.IsLargePage && !table.Is1GBPage) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PTE: 0x%llx (Address: 0x%p)\n", table.OriginalPte, table.PteAddress); } } void PteHookManager::PrintHookInfo(const HOOK_INFO& hookInfo) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook Info:\n"); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Original Address: 0x%p\n", hookInfo.OriginalAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Address: 0x%p\n", hookInfo.HookAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Length: %d\n", hookInfo.HookLength); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Is Hooked: %d\n", hookInfo.IsHooked); // 打印原始字节 DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Original Bytes: "); for (UINT32 i = 0; i < sizeof(hookInfo.OriginalBytes); i++) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", hookInfo.OriginalBytes[i]); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); // 打印Hook字节 DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Bytes: "); for (UINT32 i = 0; i < sizeof(hookInfo.HookBytes); i++) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", hookInfo.HookBytes[i]); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); } void PteHookManager::PrintGBitInfo(const G_BIT_INFO& gbitInfo) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] G-Bit Info:\n"); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Align Address: 0x%p\n", gbitInfo.AlignAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " IsLargePage: %d\n", gbitInfo.IsLargePage); if (gbitInfo.PdeAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDE: 0x%llx (Address: 0x%p)\n", gbitInfo.PdeAddress->value, gbitInfo.PdeAddress); } if (gbitInfo.PteAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PTE: 0x%llx (Address: 0x%p)\n", gbitInfo.PteAddress->value, gbitInfo.PteAddress); } } void* PteHookManager::fn_pa_to_va(UINT64 pa) { PHYSICAL_ADDRESS physAddr; physAddr.QuadPart = pa; return MmGetVirtualForPhysical(physAddr); } UINT64 PteHookManager::fn_va_to_pa(void* va) { PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(va); return physAddr.QuadPart; } NTSTATUS PteHookManager::get_page_table(UINT64 cr3_val, PAGE_TABLE& table) { UINT64 va = table.LineAddress; UINT64 pml4e_index = (va >> 39) & 0x1FF; UINT64 pdpte_index = (va >> 30) & 0x1FF; UINT64 pde_index = (va >> 21) & 0x1FF; UINT64 pte_index = (va >> 12) & 0x1FF; // PML4 UINT64 pml4_pa = cr3_val & ~0xFFF; UINT64* pml4_va = (UINT64*)fn_pa_to_va(pml4_pa); if (!pml4_va) return STATUS_INVALID_ADDRESS; table.Pml4Address = &pml4_va[pml4e_index]; table.OriginalPml4e = *table.Pml4Address; if (!(table.OriginalPml4e & 1)) return STATUS_ACCESS_VIOLATION; // PDPTE UINT64 pdpte_pa = table.OriginalPml4e & ~0xFFF; UINT64* pdpte_va = (UINT64*)fn_pa_to_va(pdpte_pa); if (!pdpte_va) return STATUS_INVALID_ADDRESS; table.PdpteAddress = (decltype(table.PdpteAddress))&pdpte_va[pdpte_index]; table.OriginalPdpte = table.PdpteAddress->value; table.Is1GBPage = (table.PdpteAddress->flags.page_size) ? TRUE : FALSE; if (!(table.OriginalPdpte & 1)) return STATUS_ACCESS_VIOLATION; if (table.Is1GBPage) return STATUS_SUCCESS; // PDE UINT64 pde_pa = table.OriginalPdpte & ~0xFFF; UINT64* pde_va = (UINT64*)fn_pa_to_va(pde_pa); if (!pde_va) return STATUS_INVALID_ADDRESS; table.PdeAddress = (decltype(table.PdeAddress))&pde_va[pde_index]; table.OriginalPde = table.PdeAddress->value; table.IsLargePage = (table.PdeAddress->flags.large_page) ? TRUE : FALSE; if (!(table.OriginalPde & 1)) return STATUS_ACCESS_VIOLATION; if (table.IsLargePage) return STATUS_SUCCESS; // PTE UINT64 pte_pa = table.OriginalPde & ~0xFFF; UINT64* pte_va = (UINT64*)fn_pa_to_va(pte_pa); if (!pte_va) return STATUS_INVALID_ADDRESS; table.PteAddress = (decltype(table.PteAddress))&pte_va[pte_index]; table.OriginalPte = table.PteAddress->value; if (!(table.OriginalPte & 1)) return STATUS_ACCESS_VIOLATION; // 打印页表信息 PrintPageTableInfo(table); return STATUS_SUCCESS; } bool PteHookManager::fn_split_large_pages(void* in_pde_ptr, void* out_pde_ptr) { auto in_pde = (decltype(PAGE_TABLE::PdeAddress))in_pde_ptr; auto out_pde = (decltype(PAGE_TABLE::PdeAddress))out_pde_ptr; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 正在拆分大页: 输入PDE=0x%llx, 输出PDE=0x%p\n", in_pde->value, out_pde); PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; auto pt = (decltype(PAGE_TABLE::PteAddress))MmAllocateContiguousMemorySpecifyCache( PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!pt) { logger("分配连续内存失败 (用于拆分大页)", true); return false; } UINT64 start_pfn = in_pde->flags.page_frame_number; for (int i = 0; i < 512; i++) { pt[i].value = 0; pt[i].flags.present = 1; pt[i].flags.write = in_pde->flags.write; pt[i].flags.user = in_pde->flags.user; pt[i].flags.write_through = in_pde->flags.write_through; pt[i].flags.cache_disable = in_pde->flags.cache_disable; pt[i].flags.accessed = in_pde->flags.accessed; pt[i].flags.dirty = in_pde->flags.dirty; pt[i].flags.global = 0; pt[i].flags.page_frame_number = start_pfn + i; } out_pde->value = in_pde->value; out_pde->flags.large_page = 0; out_pde->flags.page_frame_number = fn_va_to_pa(pt) >> 12; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 大页拆分完成: 新PTE表物理地址=0x%llx\n", fn_va_to_pa(pt)); return true; } bool PteHookManager::fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde_ptr) { PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始隔离页表: CR3=0x%llx, 地址=0x%p\n", cr3_val, replace_align_addr); auto Va4kb = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPdt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPdpt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!VaPt || !Va4kb || !VaPdt || !VaPdpt) { if (VaPt) MmFreeContiguousMemory(VaPt); if (Va4kb) MmFreeContiguousMemory(Va4kb); if (VaPdt) MmFreeContiguousMemory(VaPdt); if (VaPdpt) MmFreeContiguousMemory(VaPdpt); logger("分配连续内存失败 (用于隔离页表)", true); return false; } PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)replace_align_addr; NTSTATUS status = get_page_table(cr3_val, Table); if (!NT_SUCCESS(status)) { MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); logger("获取页表信息失败", true, status); return false; } UINT64 pte_index = (Table.LineAddress >> 12) & 0x1FF; UINT64 pde_index = (Table.LineAddress >> 21) & 0x1FF; UINT64 pdpte_index = (Table.LineAddress >> 30) & 0x1FF; UINT64 pml4e_index = (Table.LineAddress >> 39) & 0x1FF; memcpy(Va4kb, replace_align_addr, PAGE_SIZE); if (Table.IsLargePage && split_pde_ptr) { auto split_pde = (decltype(PAGE_TABLE::PdeAddress))split_pde_ptr; memcpy(VaPt, (void*)(split_pde->flags.page_frame_number << 12), PAGE_SIZE); } else { memcpy(VaPt, (void*)(Table.PdeAddress->flags.page_frame_number << 12), PAGE_SIZE); } memcpy(VaPdt, (void*)(Table.PdpteAddress->flags.page_frame_number << 12), PAGE_SIZE); memcpy(VaPdpt, (void*)(Table.Pml4Address[pml4e_index] & ~0xFFF), PAGE_SIZE); auto new_pte = (decltype(PAGE_TABLE::PteAddress))VaPt; new_pte[pte_index].flags.page_frame_number = fn_va_to_pa(Va4kb) >> 12; auto new_pde = (decltype(PAGE_TABLE::PdeAddress))VaPdt; new_pde[pde_index].value = Table.OriginalPde; new_pde[pde_index].flags.large_page = 0; new_pde[pde_index].flags.page_frame_number = fn_va_to_pa(VaPt) >> 12; auto new_pdpte = (decltype(PAGE_TABLE::PdpteAddress))VaPdpt; new_pdpte[pdpte_index].flags.page_frame_number = fn_va_to_pa(VaPdt) >> 12; auto new_pml4 = (UINT64*)fn_pa_to_va(cr3_val & ~0xFFF); new_pml4[pml4e_index] = (new_pml4[pml4e_index] & 0xFFF) | (fn_va_to_pa(VaPdpt) & ~0xFFF); __invlpg(replace_align_addr); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页表隔离完成: 新PFN=0x%llx\n", fn_va_to_pa(Va4kb) >> 12); return true; } bool PteHookManager::fn_isolation_pages(HANDLE process_id, void* ori_addr) { PEPROCESS Process; if (!NT_SUCCESS(PsLookupProcessByProcessId(process_id, &Process))) { logger("查找进程失败", true); return false; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始隔离页面: PID=%d, 地址=0x%p\n", (ULONG)(ULONG_PTR)process_id, ori_addr); KAPC_STATE ApcState; KeStackAttachProcess(Process, &ApcState); void* AlignAddr = PAGE_ALIGN(ori_addr); PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)AlignAddr; UINT64 target_cr3 = *(UINT64*)((UCHAR*)Process + 0x28); if (!NT_SUCCESS(get_page_table(target_cr3, Table))) { KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); logger("获取目标进程页表失败", true); return false; } bool success = false; decltype(PAGE_TABLE::PdeAddress) split_pde = nullptr; if (Table.IsLargePage) { split_pde = (decltype(PAGE_TABLE::PdeAddress))ExAllocatePoolWithTag(NonPagedPool, sizeof(*split_pde), 'pdeS'); if (!split_pde || !fn_split_large_pages(Table.PdeAddress, split_pde)) { if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); logger("拆分大页失败", true); return false; } if (Table.PdeAddress->flags.global) { Table.PdeAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, Table.PdeAddress, nullptr); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 清除大页G位: PDE=0x%llx\n", Table.PdeAddress->value); } success = fn_isolation_pagetable(target_cr3, AlignAddr, split_pde); } else if (Table.PteAddress && Table.PteAddress->flags.global) { Table.PteAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, nullptr, Table.PteAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 清除PTE G位: PTE=0x%llx\n", Table.PteAddress->value); success = fn_isolation_pagetable(target_cr3, AlignAddr, split_pde); if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页表状态: IsLargePage=%d, Is1GBPage=%d\n", Table.IsLargePage, Table.Is1GBPage); if (Table.PteAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] PTE 值: 0x%llx (G位=%d)\n", Table.PteAddress->value, Table.PteAddress->flags.global); } KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); if (success) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页面隔离成功\n"); } else { logger("页面隔离失败", true); } return success; } KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); return true; } bool PteHookManager::WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd) { if (!MmIsAddressValid(trampoline)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 内存地址无效 (VA=%p)\n", trampoline); return false; } PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(trampoline); if (physAddr.QuadPart == 0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 无法获取物理地址 (VA=%p)\n", trampoline); return false; } KIRQL oldIrql = KeRaiseIrqlToDpcLevel(); BOOLEAN wpEnabled = (__readcr0() & CR0_WP); if (wpEnabled) { __writecr0(__readcr0() & ~CR0_WP); _mm_mfence(); } PMDL pMdl = IoAllocateMdl(trampoline, sizeof(JMP_ABS), FALSE, FALSE, NULL); if (!pMdl) { if (wpEnabled) __writecr0(__readcr0() | CR0_WP); KeLowerIrql(oldIrql); return false; } NTSTATUS status = STATUS_SUCCESS; __try { MmBuildMdlForNonPagedPool(pMdl); MmProtectMdlSystemAddress(pMdl, PAGE_READWRITE); // 正确写入 FF25 00000000 和 8字节地址 memcpy(trampoline, jmpCmd.opcode, 6); // FF25 00000000 *(ULONG64*)((BYTE*)trampoline + 6) = jmpCmd.address; // 地址写入 RIP+0 的位置 _mm_sfence(); _mm_clflush(trampoline); _mm_clflush((BYTE*)trampoline + 8); __invlpg(trampoline); _mm_mfence(); } __except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 异常: 写入跳板失败 (代码: 0x%X)\n", status); } IoFreeMdl(pMdl); if (wpEnabled) { __writecr0(__readcr0() | CR0_WP); _mm_mfence(); } KeLowerIrql(oldIrql); if (!NT_SUCCESS(status)) return false; // 验证写入结果 if (*(USHORT*)trampoline != 0x25FF || *(ULONG64*)((BYTE*)trampoline + 6) != jmpCmd.address) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 验证失败: 跳板内容不匹配\n" " 预期: FF25 [%p]\n" " 实际: %02X%02X %02X%02X%02X%02X [%p]\n", jmpCmd.address, ((BYTE*)trampoline)[0], ((BYTE*)trampoline)[1], ((BYTE*)trampoline)[2], ((BYTE*)trampoline)[3], ((BYTE*)trampoline)[4], ((BYTE*)trampoline)[5], *(ULONG64*)((BYTE*)trampoline + 6)); return false; } return true; } bool PteHookManager::fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr) { // [1] 页表隔离 if (!fn_isolation_pages(process_id, *ori_addr)) { return false; } // [2] 获取目标进程上下文 PEPROCESS targetProcess; if (!NT_SUCCESS(PsLookupProcessByProcessId(process_id, &targetProcess))) { return false; } KAPC_STATE apcState; KeStackAttachProcess(targetProcess, &apcState); // [3] 构造跳转指令 JMP_ABS jmpCmd = {}; memcpy(jmpCmd.opcode, "\xFF\x25\x00\x00\x00\x00", 6); // FF25 00000000 jmpCmd.address = reinterpret_cast<ULONG64>(hk_addr); // [4] 直接写入被隔离页 void* targetFunc = *ori_addr; bool success = false; // 禁用写保护 KIRQL oldIrql = DisableWriteProtection(); __try { // 保存原始指令 (用于卸载) RtlCopyMemory(m_HookInfo[m_HookCount].OriginalBytes, targetFunc, sizeof(jmpCmd)); // 写入跳转指令到隔离页 memcpy(targetFunc, &jmpCmd, 6); *(ULONG64*)((BYTE*)targetFunc + 6) = jmpCmd.address; // 刷新缓存 _mm_sfence(); _mm_clflush(targetFunc); __invlpg(targetFunc); _mm_mfence(); success = true; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 直接写入隔离页成功: VA=%p -> Hook=%p\n", targetFunc, hk_addr); } __except (EXCEPTION_EXECUTE_HANDLER) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 写入隔离页异常: 0x%X\n", GetExceptionCode()); } // 恢复写保护 EnableWriteProtection(oldIrql); // [5] 记录Hook信息 if (success) { m_HookInfo[m_HookCount].OriginalAddress = targetFunc; m_HookInfo[m_HookCount].HookAddress = hk_addr; m_HookInfo[m_HookCount].ProcessId = process_id; m_HookInfo[m_HookCount].IsHooked = TRUE; m_HookCount++; } // [6] 清理 KeUnstackDetachProcess(&apcState); ObDereferenceObject(targetProcess); return success; } // 析构函数清理资源 PteHookManager::~PteHookManager() { if (m_TrampLinePool) { MmFreeContiguousMemory(m_TrampLinePool); m_TrampLinePool = nullptr; } } bool PteHookManager::fn_remove_hook(HANDLE process_id, void* hook_addr) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 尝试移除Hook: Hook地址=0x%p\n", hook_addr); for (UINT32 i = 0; i < m_HookCount; i++) { if (m_HookInfo[i].HookAddress == hook_addr && m_HookInfo[i].IsHooked) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 找到匹配的Hook: 原始地址=0x%p\n", m_HookInfo[i].OriginalAddress); KIRQL oldIrql = DisableWriteProtection(); memcpy(m_HookInfo[i].OriginalAddress, m_HookInfo[i].OriginalBytes, sizeof(m_HookInfo[i].OriginalBytes)); EnableWriteProtection(oldIrql); m_HookInfo[i].IsHooked = FALSE; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook已成功移除\n"); return true; } } logger("未找到匹配的Hook", true); return false; } void PteHookManager::fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address) { if (m_GbitCount >= MAX_G_BIT_RECORDS) { logger("达到最大G位记录数量限制", true); return; } PG_BIT_INFO record = &m_GbitRecords[m_GbitCount++]; record->AlignAddress = align_addr; record->PdeAddress = (decltype(G_BIT_INFO::PdeAddress))pde_address; record->PteAddress = (decltype(G_BIT_INFO::PteAddress))pte_address; record->IsLargePage = (pde_address && ((decltype(PAGE_TABLE::PdeAddress))pde_address)->flags.large_page); // 打印G位信息 PrintGBitInfo(*record); } bool PteHookManager::fn_resume_global_bits(void* align_addr) { KIRQL oldIrql = DisableWriteProtection(); bool found = false; DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始恢复G位: 对齐地址=0x%p\n", align_addr); for (UINT32 i = 0; i < m_GbitCount; i++) { PG_BIT_INFO record = &m_GbitRecords[i]; if (align_addr && record->AlignAddress != align_addr) continue; if (record->PteAddress) { record->PteAddress->flags.global = 1; __invlpg(record->AlignAddress); DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, " 恢复PTE G位: PTE=0x%llx, 地址=0x%p\n", record->PteAddress->value, record->AlignAddress); } if (record->PdeAddress) { record->PdeAddress->flags.global = 1; if (record->IsLargePage) { __invlpg(record->AlignAddress); } DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, " 恢复PDE G位: PDE=0x%llx, 地址=0x%p, 大页=%d\n", record->PdeAddress->value, record->AlignAddress, record->IsLargePage); } found = true; if (align_addr) break; } EnableWriteProtection(oldIrql); if (found) { DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] G位恢复完成\n"); } else { logger("未找到匹配的G位记录", true); } return found; } PteHookManager* PteHookManager::GetInstance() { if (!m_Instance) { m_Instance = static_cast<PteHookManager*>( ExAllocatePoolWithTag(NonPagedPool, sizeof(PteHookManager), 'tpHk')); if (m_Instance) { RtlZeroMemory(m_Instance, sizeof(PteHookManager)); DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] PTE Hook管理器实例已创建: 地址=0x%p\n", m_Instance); } else { DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 创建PTE Hook管理器实例失败\n"); } } return m_Instance; } // 全局PTE Hook管理器实例 PteHookManager* g_PteHookManager = nullptr; // 辅助函数:检查是否为目标进程 BOOLEAN IsTargetProcess(CHAR* imageName) { CHAR currentName[16]; // 复制到本地缓冲区并确保 NULL 终止 RtlCopyMemory(currentName, imageName, 16); currentName[15] = '\0'; // 确保终止 // 修剪尾部空格 for (int i = 15; i >= 0; i--) { if (currentName[i] == ' ') currentName[i] = '\0'; else if (currentName[i] != '\0') break; } return (strcmp(currentName, target_process_name) == 0); } // Hook 函数 NTSTATUS MyObReferenceObjectByHandleWithTag( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ) { PEPROCESS currentProcess = PsGetCurrentProcess(); CHAR* imageName = PsGetProcessImageFileName(currentProcess); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[!] [HookFunction] 进入 Hook 函数! 当前进程: %s\n", imageName); __debugbreak(); // 强制中断,确认是否执行到这里 if (IsTargetProcess(imageName)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[!] [HookFunction] 拒绝访问目标进程 PID=%d\n", HandleToULong(PsGetCurrentProcessId())); return STATUS_ACCESS_DENIED; } return g_OriginalObReferenceObjectByHandleWithTag( Handle, DesiredAccess, ObjectType, AccessMode, Tag, Object, HandleInformation ); } NTSTATUS InstallHook() { UNICODE_STRING funcName; RtlInitUnicodeString(&funcName, L"ObReferenceObjectByHandleWithTag"); g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)MmGetSystemRoutineAddress(&funcName); if (!g_OriginalObReferenceObjectByHandleWithTag) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [InstallHook] 找不到 ObReferenceObjectByHandleWithTag\n"); return STATUS_NOT_FOUND; } __debugbreak(); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [InstallHook] 找到目标函数地址: %p\n", g_OriginalObReferenceObjectByHandleWithTag); void* targetFunc = (void*)g_OriginalObReferenceObjectByHandleWithTag; void* hookFunc = (void*)MyObReferenceObjectByHandleWithTag; if (!g_PteHookManager->fn_pte_inline_hook_bp_pg(targetProcessId, &targetFunc, hookFunc)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [InstallHook] PTE Hook 安装失败\n"); return STATUS_UNSUCCESSFUL; } g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)targetFunc; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [InstallHook] Hook 成功安装. 跳板地址: %p\n", targetFunc); __debugbreak(); // 强制中断,验证是否执行到这里 return STATUS_SUCCESS; } // 移除 Hook VOID RemoveHook() { if (g_OriginalObReferenceObjectByHandleWithTag && g_PteHookManager) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), (void*)MyObReferenceObjectByHandleWithTag); } } // 工作线程函数 VOID InstallHookWorker(PVOID Context) { targetProcessId = (HANDLE)Context; DbgPrint("[+] Worker thread started for hook installation on PID: %d\n", HandleToULong(targetProcessId)); InstallHook(); PsTerminateSystemThread(STATUS_SUCCESS); } // 进程创建回调 VOID ProcessNotifyCallback( _In_ HANDLE ParentId, _In_ HANDLE ProcessId, _In_ BOOLEAN Create ) { UNREFERENCED_PARAMETER(ParentId); if (Create) { PEPROCESS process = NULL; if (NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &process))) { CHAR* imageName = PsGetProcessImageFileName(process); CHAR currentName[16]; RtlCopyMemory(currentName, imageName, 16); currentName[15] = '\0'; for (int i = 15; i >= 0; i--) { if (currentName[i] == ' ') currentName[i] = '\0'; else if (currentName[i] != '\0') break; } if (strcmp(currentName, target_process_name) == 0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [ProcessNotifyCallback] 目标进程 %s 创建 (PID: %d)\n", currentName, HandleToULong(ProcessId)); HANDLE threadHandle; NTSTATUS status = PsCreateSystemThread( &threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, InstallHookWorker, (PVOID)ProcessId // 关键:传递目标进程ID ); if (NT_SUCCESS(status)) { ZwClose(threadHandle); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [ProcessNotifyCallback] 工作线程已创建\n"); } else { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [ProcessNotifyCallback] 创建线程失败: 0x%X\n", status); } } ObDereferenceObject(process); } } } // 驱动卸载函数 VOID DriverUnload(PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); DbgPrint("[+] Driver unloading...\n"); // 移除进程通知回调 PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)ProcessNotifyCallback, TRUE); // 移除Hook RemoveHook(); // 清理PTE Hook资源 if (g_PteHookManager) { DbgPrint("[PTE_HOOK] Cleaning up PTE...\n"); // 恢复所有被修改的G位 g_PteHookManager->fn_resume_global_bits(nullptr); // 移除所有活动的Hook HOOK_INFO* hookInfo = g_PteHookManager->GetHookInfo(); UINT32 hookCount = g_PteHookManager->GetHookCount(); for (UINT32 i = 0; i < hookCount; i++) { if (hookInfo[i].IsHooked) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), hookInfo[i].HookAddress); } } // 释放跳板池内存 char* trampLinePool = g_PteHookManager->GetTrampLinePool(); if (trampLinePool) { ExFreePoolWithTag(trampLinePool, 'JmpP'); } // 释放管理器实例 ExFreePoolWithTag(g_PteHookManager, 'tpHk'); g_PteHookManager = nullptr; } DbgPrint("[+] Driver unloaded successfully\n"); } extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [DriverEntry] 驱动加载开始\n"); DriverObject->DriverUnload = DriverUnload; g_PteHookManager = PteHookManager::GetInstance(); if (!g_PteHookManager) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [DriverEntry] 初始化 PteHookManager 失败\n"); return STATUS_INSUFFICIENT_RESOURCES; } NTSTATUS status = PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)ProcessNotifyCallback, FALSE); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [DriverEntry] 注册进程通知失败 (0x%X)\n", status); return status; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [DriverEntry] 驱动加载成功\n"); return STATUS_SUCCESS; }
07-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值