看到大手子们都在分享自己的学习成果,我也分享一个叭,是在内核中调用ZwQueryVirtualMemory查询目标内存地址的保护属性或者Type,你想查什么直接改即可,欢迎大家多多交流,已测试没有毛病,废话不多说直接上代码。
========================================================
附上内存属性具体信息:
PAGE_NOACCESS =1 任何访问该区域的操作将被拒绝(无权限)
PAGE_READONLY =2 试图写入或执行页面中的代码将引发访问违规(只读)
PAGE_READWRITE =4 试图执行页面中的代码将引发访问违规(可读可写)
PAGE_WRITECOPY =8 写时复制
PAGE_EXECUTE=16 试图读取或写入页面将引发访问违规
PAGE_EXECUTE_READ =32 试图写入页面将引发访问违规
PAGE_EXECUTE_READWRITE =64 对页面执行任何操作都不会引发访问违规
PAGE_EXECUTE_WRITECOPY =128试图执行页面中的代码将引发访问违规。试图写入页面将使系统为进程单独创建一份该页面的私有副本(以页交换文件为后备存储器)
========================================================
下面随意取了一个受某AC保护的程序,可以看到取出属性是32,对照表看是PAGE_EXECUTE_READ,禁止写入。
/
/
此为主要操作代码且全部在内核,应用层直接调用DevIoc函数通讯即可
/
/
ULONG MyQueryVirtualMemoryBasicInfo(IN HANDLE ProcessHandle, IN PVOID DesiredAddress)
/
/
传入目标进程PID,和内存地址
{
MEMORY_BASIC_INFORMATION mbi;
/
/
内存属性结构
ULONG Protect;
/
/
初始化保护类型
if
((ULONG_PTR)DesiredAddress >
=
0x70000000
&& (ULONG_PTR)DesiredAddress <
0x80000000
)
DesiredAddress
=
(PVOID)
0x70000000
;
HANDLE hProcess
=
NULL;
CLIENT_ID stClientId
=
{
0
};
OBJECT_ATTRIBUTES objectAttributs
=
{
0
};
stClientId.UniqueProcess
=
ProcessHandle;
stClientId.UniqueThread
=
0
;
InitializeObjectAttributes(&objectAttributs,
0
,
0
,
0
,
0
);
/
/
打开进程,获取进程句柄
NTSTATUS status
=
ZwOpenProcess(&hProcess,
1
, &objectAttributs, &stClientId);
if
(!NT_SUCCESS(status))
{
return
-
32767
;
/
/
自己看的,没打开成功
}
if
(NULL !
=
hProcess)
{
if
(!NT_SUCCESS(ZwQueryVirtualMemory(hProcess, DesiredAddress, MemoryBasicInformation, &mbi, sizeof(mbi), NULL)))
return
-
32768
;
/
/
查询操作失败自定义返回
Protect
=
mbi.Protect;
/
/
需要返回的信息可以是保护也可以是状态也可以是类型 Protect
/
State
/
type
}
ZwClose(hProcess);
/
/
关闭打开的句柄
return
Protect;
/
/
返回需要的信息
}
/
/
然后下面是驱动IO通讯中的代码
/
/
case IOCTL_IO_QueryVirtualMemory:
/
/
自定义
{
ULONG PtExw;
PtExw
=
QueryVirtualMemoryBasicInfo(((PDataStruct)InputData)
-
>Pid, ((PDataStruct)InputData)
-
>VMAddress);
/
/
传入的结构体 PID和地址
RtlCopyMemory(OutputData, &PtExw, OutputDataLength);
/
/
复制到返回信息,应用层就可以接收到了
Status
=
STATUS_SUCCESS;
break
;
}
/
/
下面是需要用到的结构体等信息
/
/
/
/
可以直接引入这三个常用的就有
/
/
/
/
/
/
typedef struct _MEMORY_BASIC_INFORMATION {
PVOID BaseAddress;
PVOID AllocationBase;
ULONG AllocationProtect;
USHORT PartitionId;
SIZE_T RegionSize;
ULONG State;
ULONG Protect;
ULONG
Type
;
} MEMORY_BASIC_INFORMATION,
*
PMEMORY_BASIC_INFORMATION;
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
/
/
Points to
type
SECURITY_DESCRIPTOR
PVOID SecurityQualityOfService;
/
/
Points to
type
SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES;
/
/
此为主要操作代码且全部在内核,应用层直接调用DevIoc函数通讯即可
/
/
ULONG MyQueryVirtualMemoryBasicInfo(IN HANDLE ProcessHandle, IN PVOID DesiredAddress)
/
/
传入目标进程PID,和内存地址
{
MEMORY_BASIC_INFORMATION mbi;
/
/
内存属性结构
ULONG Protect;
/
/
初始化保护类型
if
((ULONG_PTR)DesiredAddress >
=
0x70000000
&& (ULONG_PTR)DesiredAddress <
0x80000000
)
DesiredAddress
=
(PVOID)
0x70000000
;
HANDLE hProcess
=
NULL;
CLIENT_ID stClientId
=
{
0
};
OBJECT_ATTRIBUTES objectAttributs
=
{
0
};
stClientId.UniqueProcess
=
ProcessHandle;
stClientId.UniqueThread
=
0
;
InitializeObjectAttributes(&objectAttributs,
0
,
0
,
0
,
0
);
/
/
打开进程,获取进程句柄
NTSTATUS status
=
ZwOpenProcess(&hProcess,
1
, &objectAttributs, &stClientId);
if
(!NT_SUCCESS(status))
{
return
-
32767
;
/
/
自己看的,没打开成功
}
if
(NULL !
=
hProcess)
{
if
(!NT_SUCCESS(ZwQueryVirtualMemory(hProcess, DesiredAddress, MemoryBasicInformation, &mbi, sizeof(mbi), NULL)))
return
-
32768
;
/
/
查询操作失败自定义返回
Protect
=
mbi.Protect;
/
/
需要返回的信息可以是保护也可以是状态也可以是类型 Protect
/
State
/
type
}
ZwClose(hProcess);
/
/
关闭打开的句柄
return
Protect;
/
/
返回需要的信息
}
/
/
然后下面是驱动IO通讯中的代码
/
/
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-7-10 20:10
被月生沧海编辑
,原因: