关于SetProcessValidCallTargets函数

·

结论

经测试,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;
}

运行结果

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注