[笔记]Windows核心编程《番外篇》常用的NT API及使用示例

简介: [笔记]Windows核心编程《番外篇》常用的NT API及使用示例

前言

NTAPI:泛指ntdll.dll模块不对外提供的API接口,大多是提供给内核层开发人员使用的。

一般通过动态载入库的方式(LoadLibrary + GetProcAddress)调用

注意:本文主要使用phlib库作为调用NTAPI的库

NtQueryInformationProcess函数

NtQueryInformationProcess

NtQueryInformationProcess用法

函数原型

作用:

通过ProcessInformationClass参数可以查找进程的不同信息,包括PEB信息、WOW64信息、子系统信息、imageFileName映像文件名信息等。

NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationProcess(
    _In_ HANDLE ProcessHandle,
    _In_ PROCESSINFOCLASS ProcessInformationClass,
    _Out_writes_bytes_(ProcessInformationLength) PVOID ProcessInformation,
    _In_ ULONG ProcessInformationLength,
    _Out_opt_ PULONG ReturnLength
    );

ProcessHandle:进程句柄

ProcessInformationClass:需要检索的进程信息类型,具体参数类型,见本节结尾“进程信息类型表”。

如果第二个参数是ProcessBasicInformation的话,则第三个参数必须为一个指针指向结构PROCESS_BASIC_INFORMATION:

ProcessInformation: 缓冲指针,保存进程信息,大小取决于进程信息类型。

ProcessInformationLength:以字节为单位的缓冲大小

ReturnLength:实际写入到缓冲的字节数

返回值

返回一个NTSTATUS成功或错误代码

附录

进程信息类型表

含义
ProcessBasicInformation 0 返回PEB结构指针,检索判断特定进程是否正在被调试
ProcessDebugPort 7 返回DWORD指针,检索获得当前进程的调试端口号
ProcessWow64Information 26 判断进程是否运行在WOW64环境(WOW64指基于Win32的程序运行在x64系统上)
ProcessImageFileName 27 返回Unicode字符串,包含进程的映像文件名
ProcessBreakOnTermination 29 返回ULONG值, 判断是否这个进程被认为是重要进程的。(一般系统级别的exe都是重要进程)
ProcessSubsystemInformation 75 返回SUBSYSTEM_INFORMATION_TYPE,指出进程的子系统类型。

当ProcessInformationClass为ProcessBasicInformation时:

缓冲区指针 应该指向 _PROCESS_BASIC_INFORMATION

typedef struct
{   
    DWORD ExitStatus; // 接收进程终止状态
      DWORD PebBaseAddress; // 接收PEB进程环境块地址
      DWORD AffinityMask; // 接收进程关联掩码
      DWORD BasePriority; // 接收进程的优先级类
      ULONG UniqueProcessId; // 接收进程ID
      ULONG InheritedFromUniqueProcessId; //接收父进程ID
} PROCESS_BASIC_INFORMATION;

示例:从PEB32获得进程路径

代码参考:

CSDN博主「MailSloter」的原创文章

/**
*
* 获得PEB的进程路径
*
*/
#include <phnt_windows.h>
#include <phnt.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
BOOL GetProcessFullPathByProcessID(ULONG32 ProcessID, WCHAR* BufferData, ULONG BufferLegnth) {
  HANDLE  ProcessHandle = NULL; 
  ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessID);
  if (ProcessHandle == NULL) {
    return FALSE;
  }
  PROCESS_BASIC_INFORMATION pbi = { 0 };
  SIZE_T  ReturnLength = 0;
  NTSTATUS status = NtQueryInformationProcess(ProcessHandle, ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION),
    (PULONG)&ReturnLength);
  if (!NT_SUCCESS(status)) {
    CloseHandle(ProcessHandle);
    ProcessHandle = NULL;
    return FALSE;
  }
  PEB Peb = { 0 };
  status = NtReadVirtualMemory(ProcessHandle, pbi.PebBaseAddress, &Peb, sizeof(PEB32), (SIZE_T*)&ReturnLength);
  if (!NT_SUCCESS(status)) {
    CloseHandle(ProcessHandle);
    ProcessHandle = NULL;
    return FALSE;
  }
  RTL_USER_PROCESS_PARAMETERS RtlUserProcessParameters = { 0 };
  status = NtReadVirtualMemory(ProcessHandle, Peb.ProcessParameters, &RtlUserProcessParameters,
    sizeof(RTL_USER_PROCESS_PARAMETERS), (SIZE_T*)&ReturnLength);
  if (!NT_SUCCESS(status)) {
    CloseHandle(ProcessHandle);
    ProcessHandle = NULL;
    return FALSE;
  }
  if (RtlUserProcessParameters.ImagePathName.Buffer != NULL)
  {
    ULONG v1 = 0;
    if (RtlUserProcessParameters.ImagePathName.Length < BufferLegnth)
    {
      v1 = RtlUserProcessParameters.ImagePathName.Length;
    }
    else
    {
      v1 = BufferLegnth - 10;
    }
    status = ReadProcessMemory(ProcessHandle, RtlUserProcessParameters.ImagePathName.Buffer,
      BufferData, v1, (SIZE_T*)&ReturnLength);
    if (!NT_SUCCESS(status)) 
    {
      CloseHandle(ProcessHandle);
      ProcessHandle = NULL;
      return FALSE;
    }
  }
  CloseHandle(ProcessHandle);
  return TRUE;
}
int main() {
  BOOL bOk = FALSE;
  ULONG32 ProcessID = 0;
  WCHAR   BufferData[MAX_PATH] = { 0 };
  //定义完整路径数组,
  //windows规定存放完整路径的数组最大为260个字节;
  printf("Input Process ID\r\n");
  scanf_s("%d", &ProcessID);
  bOk = GetProcessFullPathByProcessID(ProcessID, BufferData, MAX_PATH);
  //用自定义函数实现从进程ID得到进程完整路径的过程(进程ID,完整路径(存放的数组名),数组长度)
  std::cout << bOk << std::endl;
  if (bOk == TRUE)
  {
    printf("%S\r\n", BufferData);
    //BufferData双字,故用大S输出字符串;
  }
  system("pause");
  return 0;
}

NtSetInformationProcess函数

参考 SetProcessInformation function msdn

设置指定进程的信息

函数原型

BOOL SetProcessInformation(
  [in] HANDLE                    hProcess,
  [in] PROCESS_INFORMATION_CLASS ProcessInformationClass,
       LPVOID                    ProcessInformation,
  [in] DWORD                     ProcessInformationSize
);

示例:使进程跳过DEP检测 关闭DEP

代码可参考

ZwCreateThreadEx函数

函数原型

NtQueryVirtualMemory

解密NtQueryVirtualMemory

msdn NtQueryVirtualMemor

查询指定进程的某个虚拟地址控件所在的内存对象的一些信息。

函数原型

NTSTATUS NTAPI NtQueryVirtualMemory(
          IN HANDLE                 ProcessHandle,          //目标进程句柄
          IN PVOID                  BaseAddress,          //目标内存地址
          IN MEMORY_INFORMATION_CLASS   MemoryInformationClass,     //查询内存信息的类别
          OUT PVOID                 Buffer,               //用于存储获取到的内存信息的结构地址
          IN ULONG                  Length,               //Buffer的最大长度
          OUT PULONG                ResultLength OPTIONAL);     //存储该函数处理返回的信息的长度的ULONG的地址
);

第一个参数是目标进程的句柄;

第二个参数是要查询的内存地址;

第四个参数是根据第三个参数选用不同的结构去接收内存信息的地址。

第五个和第六个参数为Buffer长度,和函数处理结果返回的长度。

第三个参数MEMORY_INFORMATION_CLASS 表示需要获取内存的信息的类型

类型有以下几种:

//MEMORY_INFORMATION_CLASS定义
typedef enum _MEMORY_INFORMATION_CLASS
{
 MemoryBasicInformation,        //内存基本信息
 MemoryWorkingSetInformation,     //工作集信息
 MemoryMappedFilenameInformation    //内存映射文件名信息
} MEMORY_INFORMATION_CLASS;

MemoryBasicInformation

内存基本信息

typedef struct _MEMORY_BASIC_INFORMATION {
    PVOID     BaseAddress;
    PVOID     AllocationBase;
    DWORD     AllocationProtect;
    SIZE_T    RegionSize;
    DWORD     State;
    DWORD     Protect;
    DWORD     Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

代码使用可参考 DllFinder Process::ListModulesVQ

MemoryWorkingSetInformation

工作集信息

typedef struct _MEMORY_WORKING_SET_INFORMATION {
  ULONG   SizeOfWorkingSet;
  DWORD   WsEntries[ANYSIZE_ARRAY];
} MEMORY_WORKING_SET_INFORMATION, *PMEMORY_WORKING_SET_INFORMATION;

MemoryMappedFilenameInformation

内存映射文件名信息

#define _MAX_OBJECT_NAME 1024/sizeof(WCHAR)
typedef struct _MEMORY_MAPPED_FILE_NAME_INFORMATION {
 UNICODE_STRING Name;
 WCHAR     Buffer[_MAX_OBJECT_NAME];
} MEMORY_MAPPED_FILE_NAME_INFORMATION, *PMEMORY_MAPPED_FILE_NAME_INFORMATION; 

示例:获取进程映像文件名

示例:查询内存保护模式类型 PAGE_EXECUTE_READWRITE

int main() {
  DWORD dwProcessId = 33700;
  HANDLE hProcess;
  NTSTATUS status = PhNtOpenProcess(&hProcess,
    PROCESS_QUERY_INFORMATION |
    PROCESS_VM_READ, dwProcessId);
  if (!NT_SUCCESS(status)) {
    status = PhNtOpenProcess(&hProcess,
      PROCESS_QUERY_INFORMATION, dwProcessId);
    if (!NT_SUCCESS(status))
      return -1;
  }
  void* pBaseAddres = NULL;
  MEMORY_BASIC_INFORMATION basicInfo;
  while (NT_SUCCESS(NtQueryVirtualMemory(
    hProcess, pBaseAddres, MemoryBasicInformation, &basicInfo,
    sizeof(MEMORY_BASIC_INFORMATION), NULL))) {
    ULONG dwState = basicInfo.State;
    DWORD protectStatus = basicInfo.Protect;
    if (protectStatus == PAGE_EXECUTE_READWRITE) {
      printf("memery PAGE_EXECUTE_READWRITE exist! \n");
      break;
    }
    pBaseAddres = PTR_ADD_OFFSET(pBaseAddres, basicInfo.RegionSize);
  }
  return 0;
}

NtReadVirtualMemory

函数原型

读取进程内存内容

NTSTATUS
NtReadVirtualMemory (
     IN HANDLE ProcessHandle,//进程句柄
     IN PVOID BaseAddress,//基地址
     OUT PVOID Buffer,//输出的内容
     IN SIZE_T BufferSize,//输出大小
     OUT PSIZE_T NumberOfBytesRead OPTIONAL//读取字节数
)

示例:简单用法

int main() {
  int adrnum = 0;
  DWORD dwPid = 26392;
  HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);
  NtReadVirtualMemory(hProcess, (PVOID)0x90000, (LPVOID)&adrnum, 4, 0);
  CloseHandle(hProcess);
  printf("%d\n", adrnum);
  system("pause");
  return 0;
}

NtQuerySystemInformation

查询到特定的系统信息

函数原型

NTSYSCALLAPI
NTSTATUS
NTAPI
NtQuerySystemInformation(
    _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
    _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation,
    _In_ ULONG SystemInformationLength,
    _Out_opt_ PULONG ReturnLength
    );

第一个参数 SystemInformationClass: 所要查询的系统信息的类型

第二个参数 SystemInformation:输出的系统信息内容的指针

第三个参数 SystemInformationLength:接受长度

第四个参数 ReturnLength:实际返回长度

示例:查询系统基本信息

SYSTEM_BASIC_INFORMATION systemBasicInformation = {};
NTSTATUS status = NtQuerySystemInformation(
  SystemBasicInformation, &systemBasicInformation, sizeof(SYSTEM_BASIC_INFORMATION), NULL);

NtQueryInformationThread

检索指定的线程信息。

函数原型

NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationThread(
    _In_ HANDLE ThreadHandle,//线程句柄
    _In_ THREADINFOCLASS ThreadInformationClass, //查询线程信息的类型
    _Out_writes_bytes_(ThreadInformationLength) PVOID ThreadInformation, //接受线程信息的指针
    _In_ ULONG ThreadInformationLength,//线程信息长度
    _Out_opt_ PULONG ReturnLength//返回长度
    );

示例:获得线程起始地址

#include <phnt_windows.h>
#include <phnt.h>
#include <stdio.h>
int main()
{   
    DWORD dwThreadId = GetCurrentThreadId();
    HANDLE hThread = NULL;
    hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, dwThreadId);
    if (!hThread)
    {
      return -1;
    }
    DWORD dwStaAddr = NULL;
    DWORD dwReturnLength = 0;
    NTSTATUS status = NtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress,
      &dwStaAddr, sizeof(dwStaAddr), &dwReturnLength);
    if (!NT_SUCCESS(status))
    {
      return -1;
    }
    printf("0x%p", dwStaAddr);
    return 0;
}

示例:通过线程获得进程ID

THREAD_BASIC_INFORMATION threadBasicInfo;
NtQueryInformationThread(hThread, ThreadBasicInformation, &threadBasicInfo, sizeof(threadBasicInfo), &dwReturnLength);
printf("processId:%d", threadBasicInfo.ClientId.UniqueProcess);

总结


相关文章
|
13天前
|
JSON 前端开发 搜索推荐
关于商品详情 API 接口 JSON 格式返回数据解析的示例
本文介绍商品详情API接口返回的JSON数据解析。最外层为`product`对象,包含商品基本信息(如id、name、price)、分类信息(category)、图片(images)、属性(attributes)、用户评价(reviews)、库存(stock)和卖家信息(seller)。每个字段详细描述了商品的不同方面,帮助开发者准确提取和展示数据。具体结构和字段含义需结合实际业务需求和API文档理解。
|
6天前
|
JSON 缓存 API
解析电商商品详情API接口系列,json数据示例参考
电商商品详情API接口是电商平台的重要组成部分,提供了商品的详细信息,支持用户进行商品浏览和购买决策。通过合理的API设计和优化,可以提升系统性能和用户体验。希望本文的解析和示例能够为开发者提供参考,帮助构建高效、可靠的电商系统。
24 12
|
11天前
|
XML JSON API
淘宝商品详情(item get)API接口系列,示例说明参考
淘宝商品详情(item_get)API接口是淘宝开放平台(Taobao Open Platform)提供的一个重要接口,允许开发者通过HTTP请求获取淘宝商品的详细信息。以下是对该接口系列的示例说明参考
|
22天前
|
人工智能 数据处理 C#
AI Dev Gallery:微软开源 Windows AI 模型本地运行工具包和示例库,助理开发者快速集成 AI 功能
微软推出的AI Dev Gallery,为Windows开发者提供开源AI工具包和示例库,支持本地运行AI模型,提升开发效率。
75 13
|
15天前
|
存储 JSON API
小红书获取笔记详情API接口的开发、应用与收益。
小红书笔记详情API采用Python与Django框架开发,使用MySQL数据库存储数据。接口通过HTTP GET请求获取笔记详情,返回JSON格式数据,包含笔记内容、作者信息、图片链接等。该API应用于小红书APP内笔记展示和互动功能,并支持第三方平台的内容整合与数据分析,提升用户体验与活跃度,促进品牌合作推广,优化平台运营效率,为平台带来显著收益。
86 1
|
1月前
|
JSON API 数据安全/隐私保护
淘宝评论API接口操作步骤详解,代码示例参考
淘宝评论API接口是淘宝开放平台提供的一项服务,通过该接口,开发者可以访问商品的用户评价和评论。这些评论通常包括评分、文字描述、图片或视频等内容。商家可以利用这些信息更好地了解消费者的需求和偏好,优化产品和服务。同时,消费者也可以从这些评论中获得准确的购买参考,做出更明智的购买决策。
|
1月前
|
API Python
【Azure Developer】分享一段Python代码调用Graph API创建用户的示例
分享一段Python代码调用Graph API创建用户的示例
64 11
|
1月前
|
存储 搜索推荐 API
小红书笔记详情API接口的开发、应用与收益
小红书笔记详情API接口为开发者、企业和内容创作者提供了获取平台丰富资源的通道。通过该接口,用户可以提取笔记的详细信息(如标题、正文、标签等),并应用于市场调研、竞品分析、内容创作、电商推荐等多个领域。这不仅有助于提升品牌影响力和优化用户体验,还能挖掘商业机会,促进内容创新,增强用户互动与社群凝聚力。总之,小红书笔记详情API接口为企业和个人在社交媒体领域探索新增长点提供了重要工具。
126 0
|
2月前
|
API 开发工具 开发者
探究亚马逊国际获得AMAZON商品详情 API 接口功能、作用与实际应用示例
亚马逊提供的Amazon Product Advertising API或Selling Partner API,使开发者能编程访问亚马逊商品数据,包括商品标题、描述、价格等。支持跨境电商和数据分析,提供商品搜索和详情获取等功能。示例代码展示了如何使用Python和boto3库获取特定商品信息。使用时需遵守亚马逊政策并注意可能产生的费用。
|
2月前
|
JSON API 数据安全/隐私保护
拍立淘按图搜索API接口返回数据的JSON格式示例
拍立淘按图搜索API接口允许用户通过上传图片来搜索相似的商品,该接口返回的通常是一个JSON格式的响应,其中包含了与上传图片相似的商品信息。以下是一个基于淘宝平台的拍立淘按图搜索API接口返回数据的JSON格式示例,同时提供对其关键字段的解释

热门文章

最新文章