结论
经测试,SetProcessValidCallTargets函数无法设置非16字节对齐的函数地址,并不会让设置地址开始的16字节区域全部有效,而是只能让设置的地址有效(1字节),所以网上很多文章认为调用SetProcessValidCallTargets可以让CFG形同虚设的观点是怎么回事呢。我不知道。
代码
#include <Windows.h>
#include <stdio.h>
#include <Psapi.h>
#pragma comment(lib, "WindowsApp.lib")
// Map Offset is 0x19B3C8
void MyLdrpDispatchUserCallTarget(size_t BitMapAddress, size_t TargetAddress) {
// unsigned __int64 qword_180179390;
// unsigned __int64 v0; // rax
unsigned __int64 v2; // r10
__int64 v1; // r11
// size_t *p = (size_t*)(BitMapAddress + 8 * (TargetAddress >> 9));
v1 = *(size_t *)(BitMapAddress + 8 * (TargetAddress >> 9));
v2 = TargetAddress >> 3;
if ((TargetAddress & 0xF) != 0) {
v2 &= 0xFFFFFFFFFFFFFFFEui64;
if (!_bittest64(&v1, v2 % 64)) {
printf("%llx Is Not Valid\n", TargetAddress);
return;
}
} else if (_bittest64(&v1, v2 % 64)) {
printf("%llx Is Valid\n", TargetAddress);
return;
}
if (_bittest64(&v1, (v2 | 1) % 64)) {
printf("%llx Is Valid\n", TargetAddress);
return;
}
printf("%llx Is Not Valid\n", TargetAddress);
return;
}
int main(int argc, char* argv[]) {
MODULEINFO mi;
HMODULE NtDll = GetModuleHandleA("ntdll.dll");
SIZE_T CFGMapAddr = *(SIZE_T *)((PBYTE)NtDll + 0x19B3C8);
K32GetModuleInformation(GetCurrentProcess(), NtDll, &mi, sizeof(mi));
for (int i=0;i<16;i++)
MyLdrpDispatchUserCallTarget(CFGMapAddr, (SIZE_T)NtDll+i);
CFG_CALL_TARGET_INFO TargetInfo;
TargetInfo.Flags = CFG_CALL_TARGET_VALID;
TargetInfo.Offset = 0;
BOOL SetTargetResult = SetProcessValidCallTargets(
GetCurrentProcess(), (PBYTE)mi.lpBaseOfDll, mi.SizeOfImage, 1, &TargetInfo);
printf("\nSetProcessValidCallTargets\n\n");
for (int i = 0; i < 16; i++)
MyLdrpDispatchUserCallTarget(CFGMapAddr, (SIZE_T)NtDll + i);
return 0;
}
运行结果

发表回复