H5W3
当前位置:H5W3 > 其他技术问题 > 正文

内核获取未导出函数

第一步:IDA查看这个函数的交叉引用,看到PspAlloCateThread 调用了该函数

 

 

 

 

 

 

 

 

 二. 继续查看有谁调用了PspAllocateThread 这个函数

 

 

 

看到了一个导出函数 NtCreateUserProcess ,思路就是   NtCreateUserProcess –> PspAllocateThread –> PspUserThreadStartup  这样子就能找到 PspUserThreadStartup  函数的地址

记录一下特征码 这里我在  NtCreateUserProcess 调用  PspAllocateThread 的call 附加寻找特征码 ,我寻找的特征码是  94 24 18 01   其实这种特征码不靠谱 但这个函数很小而且从函数头到调用的位置只出现一次

这里顺便记录一下  94这个字节  距离真正调用call 相差 9 个字节

 

 

 

接下来寻找 PspAllocateThread 调用 PspUserThreadStartup   附加的特征码,8B 86 10 06   这里距离 lea r8,PspUserThreadStartup   相差16个字节

 

 

 接下来编写一个函数暴力枚举出来

PVOID GetPspUserThreadStartup2(ULONG64 函数地址, 暴力扫描* 信息, UCHAR 特征码[])
{
if (!MmIsAddressValid(&函数地址))
{
return 0;
}
INT code1 = NULL;
ULONG64 addr = NULL;
ULONG64 返回地址 = NULL;
for (size_t i = 0; i < 0x1BF8CA; i++)
{
if (memcmp((PVOID)(函数地址 + i), 特征码, 信息->特征码长度) == 0)
{
addr = 函数地址 + i + 信息->特征码距离函数地址偏移;
信息->偏移 = __insn_len_x86((PVOID)addr, __b64);   //信息->偏移  可以理解为地址的汇编长度  比如 0x123456   E8 01  这个0x123456地址长度就是 2
for (int i = 信息->偏移; i >= 4; i--)
{
if (i == 4)
{
信息->偏移 = 信息->偏移 - i;    //这里算法可以计算出函数调用位置的后四字节
break;
}
}
memcpy(&code1, (PVOID)(addr + 信息->偏移), 4);  //这里拷贝 调用的位置后四个字节  比如上面看到的 call PspAllocateThread  E8 0D 4E 0C  00    这里需要拿到后四个字节计算函数真正地址  计算公式  函数真正地址=当前地址+后四字节地址+地址长度
函数地址 = (addr + code1 + __insn_len_x86((PVOID)addr, __b64));
返回地址 = 函数地址;
break;
}
}
return (PVOID)返回地址;
}

使用方法,可以定义一个结构体

 

 

 

 

 上面GetFUnaddr  是 NtcreateUserProcess 在SSDT中的编号  获取它在SSDT中的地址获取

结果:

 

未经允许不得转载:H5W3 » 内核获取未导出函数

赞 (0)

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址