当前位置: 首页 > wzjs >正文

怎么做自己的刷赞网站免费招聘信息发布平台

怎么做自己的刷赞网站,免费招聘信息发布平台,学校官网网页设计模板,群晖wordpress获取SSDT基址 在32位Windows系统中,SSDT(System Service Descriptor Table)作为系统服务调用的核心数据结构,其基址信息是公开且稳定的。由于ntoskrnl.exe内核模块默认导出KeServiceDescriptorTable符号,开发者只需使…

获取SSDT基址

在32位Windows系统中,SSDT(System Service Descriptor Table)作为系统服务调用的核心数据结构,其基址信息是公开且稳定的。由于ntoskrnl.exe内核模块默认导出KeServiceDescriptorTable符号,开发者只需使用extern声明即可直接访问:

extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;

然而,64位系统架构带来了重大变化。微软出于安全考虑,不再导出SSDT相关符号,并引入了以下保护机制:

  1. SSDT表基址变为动态变化,每次系统启动都会重新随机化
  2. 移除了直接的符号导出
  3. 增加了内核PatchGuard保护
    因此,想要获取64位SSDT基址就需要一些特殊技术手段来实现,常见方法包括:
  • 借助第三方符号(PDB)或调试器
    在这里插入图片描述

  • 通过msr寄存器读取

通过读取msr 0xC0000082可得到 KiSystemCall64的函数地址,从此函数地址向下可以定位到KiSystemServiceRepeat函数,从而间接获取 SSDT。
在这里插入图片描述
从上图中可以看出,4C 8D 15[lea r10] 指令后面的操作数即为SSDT地址的相对偏移,因此在通过特征值定位到此处时,可以通过以下公式计算出实际的SSDT地址。

SSDT地址 = Rip + offset = 0x140070FF9 + 0x237847

这种方法的实现在网络上可以轻松获取,这里就不详细展开了。值得注意的一点是,win10 1903版本之后,由于引入了内核隔离机制,通过msr获取到的地址不再是 KiSystemCall64,而是KiSystemCall64Shadow,这也导致了无法按照以上方法找到SSDT表。
在这里插入图片描述

  • 通过特征码扫描内核映像

由于无法再通过msr来实现查找,因此在此基础上又延伸出了类似的方案。即通过某些确定的系统函数地址,向上或向下寻找SSDT的特征值。通过IDA分析内核模块中Zw* 系统调用接口(这里并非ntdll中的用户态调用接口,而是提供给wdm驱动使用的内核态接口),可以看出内核模块中的系统调用实际上同样是通过SSDT表实现的。以ZwCreateFile 函数为例,内部调用KiServiceInternal ,然后通过jmp指令跳转到KiSystemCall64函数中。
在这里插入图片描述
在这里插入图片描述

PLONG HookHandler::GetSSDTBase() {
#ifdef _WIN64const PVOID zw_close = ZwClose;const ULONG offset = 0x400;static PSSDTEntry ssdt_address = nullptr;__try {if (ssdt_address) return ssdt_address->ServiceTableBase;PUCHAR service_internal_address = nullptr;PUCHAR zw_route_address = (PUCHAR)zw_close;// .text:000000014006A653 50               push    rax// .text:000000014006A654 B8 0C 00 00 00   mov     eax, 0Ch// .text:000000014006A659 E9 E2 67 00 00   jmp     KiServiceInternalconst UCHAR service_internal_code[] = {0x50, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x00};for (ULONG i = 0; i < offset; i++) {if ((*(PULONGLONG)&zw_route_address[i] & *(PULONGLONG)&service_internal_code) ==*(PULONGLONG)&service_internal_code) {ULONG jmp_offset = *(PULONG)&zw_route_address[i + 7];service_internal_address = &zw_route_address[i + 6] + 5 + jmp_offset;break;}}if (!service_internal_address) return nullptr;// .text:0000000140070FF2 4C 8D 15 47 78 23 00   lea     r10, KeServiceDescriptorTable// .text:0000000140070FF9 4C 8D 1D 80 78 23 00   lea     r11, KeServiceDescriptorTableShadowconst UCHAR ssdt_table_code[] = {0x4C, 0x8D, 0x15, 0x00};for (ULONG i = 0; i < offset; i++) {if ((*(PULONG)&service_internal_address[i] & *(PULONG)&ssdt_table_code) ==*(PULONG)&ssdt_table_code) {ULONG jmp_offset = *(PULONG)&service_internal_address[i + 3];ssdt_address = (PSSDTEntry)(&service_internal_address[i] + 7 + jmp_offset);break;}}if (!ssdt_address) return nullptr;return ssdt_address->ServiceTableBase;} __except (EXCEPTION_EXECUTE_HANDLER) {return nullptr;}
#elsereturn KeServiceDescriptorTable.ServiceTableBase;
#endif
}

除了上述方法,在网上还见过一种通过在_strnicmp函数到KdDebuggerNotPresent之间搜索8b f8 c1 ef 07 83 e7 20 25 ff 0f 00 00的定位方式。

SSDT解析

前一篇中提到SSDT中的ServiceTableBase指向的一个ULONG数组,32位系统中的数组元素代表函数地址,而在64位系统中,由于ULONG类型无法存储完整的指针类型,因此实际存储的是函数地址相对于SSDT基址的"偏移"。需要注意的是这里的偏移并不仅仅是简单的偏移,而是需要固定公式计算出的偏移长度。

在这里插入图片描述

// 计算函数地址
PVOID func_addr = (PVOID)(((LONG)ssdt_base[info.func_index] >> 4) + (ULONGLONG)func_addr);
// 计算偏移
ssdt_base[info.func_index] = (LONG)((ULONGLONG)target_addr - (ULONGLONG)ssdt_base) << 4

跳转指令

由于ServiceTableBase中存储的实际上是相对于SSDT基址的"偏移",因此hook函数的地址必须在以SSDT基址为中心的4GB内存范围内。而通常情况下我们自己的驱动的加载地址必然在4GB范围外,因此我们不能简单的将Hook函数的地址写入SSDT表,而应该在范围内选择一块地址作为函数跳转的中转。

第一步,选择合适的跳转指令

这里我们选择长度最小的12字节跳转法,实现从中转地址跳转到Hook函数。

#pragma pack(push, 1)
struct HookShellCode {USHORT mov;ULONG_PTR addr;UCHAR push;UCHAR ret;
};
#pragma pack(pop)
HookShellCode shell_code;
shell_code.mov = 0xB848;
shell_code.addr = (ULONG_PTR)func_addr;
shell_code.push = 0x50;
shell_code.ret = 0xC3;

第二步,遍历所有的代码段,从中找出合适的中转地址

PULONG kernel_base = GetKernelBase();// 获取内核模块基址
if (!kernel_base) return nullptr;// Dos Header
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)kernel_base;
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) return nullptr;// NT Header
PIMAGE_NT_HEADERS nt_header = (PIMAGE_NT_HEADERS)((PUCHAR)dos_header + dos_header->e_lfanew);
if (nt_header->Signature != IMAGE_NT_SIGNATURE) return nullptr;// Section Header
IMAGE_SECTION_HEADER* section_header = IMAGE_FIRST_SECTION(nt_header);
ULONG rva = (ULONG)((PUCHAR)base_addr - (PUCHAR)kernel_base);
// 遍历代码段
for (USHORT i = 0; i < nt_header->FileHeader.NumberOfSections; i++) {// find the section which function existsif (section_header[i].VirtualAddress <= rva &&section_header[i].VirtualAddress + section_header[i].Misc.VirtualSize > rva) {PUCHAR section_addr = (PUCHAR)kernel_base + section_header[i].VirtualAddress;for (ULONG offset = 0, size = 0; offset < section_header[i].SizeOfRawData; offset++) {if (section_addr[i] == 0x90 || section_addr[i] == 0xCC)  // NOP or INT3size++;elsesize = 0;// 找到大小匹配的空闲内存if (size == HOOK_CODE_SIZE)return (PULONG)(section_addr + offset - HOOK_CODE_SIZE + 1);}}
}

PatchGuard

基于以上内容,就可以实现在64位系统上的SSDT Hook了。然而,当实际运行Hook驱动程序时,会发现正常运行一段时间后,系统就会触发BSOD(错误代码:0x109,内核检测到关键内核代码或数据损坏),而这就是PatchGuard的作用了。

到目前为止,通过PatchGuard的方法未作深入研究,仅通过网络得知可能存在以下两种方法:

  • 通过某种方式伪装骗过PG检测,例如EPT Hook等。
  • 直接与PG对抗
http://www.dtcms.com/wzjs/16407.html

相关文章:

  • 做网批的网站小学生简短小新闻十条
  • 公司有域名 如何做网站seo营销名词解释
  • 网摘网站推广法seo关键词分析
  • 做网站虚拟主机好还是交换链接的作用
  • 网站建设 天津google play store
  • 海外购物网站建设南京网站设计公司大全
  • 汕头潮南网站建设郑州关键词优化顾问
  • wordpress 安装问题武汉seo网络营销推广
  • 网站建设与推广百度网页版网址
  • wix做的网站 网址是什么附近广告公司
  • 建设工程教育网站石家庄百度seo
  • 做数据可视化图的网站制作一个网站需要多少费用
  • 网站建设哪里好陕西今日头条新闻
  • 中国建设银行学习网站设计本网站
  • 厦门做返利网站的公司免费网站统计
  • 建个视频网站多少钱宁波建站模板系统
  • 做网站自动赚钱吗专门做网站的公司
  • 做站长工具网站网站推广的渠道有
  • seo技术培训东莞百度网站如何优化排名
  • 绵阳网站建设信赖辉煌百度导航是哪个国家的
  • 能自己做的ppt网站百度top排行榜
  • 建设工程主管部门网站建站教程
  • 找人做网站需要注意什么问题推广方案有哪些
  • 北京网站建设的服务友情链接网站
  • 游戏网站模板免费下载app拉新推广
  • 丰都专业网站建设公司站长网站优化公司
  • 可以免费推广的网站知名seo公司
  • 小区媒体网站建设今日头条收录入口
  • 前端代码 分享网站网络软文推广案例
  • 深圳做网站建设比较好的公司咖啡seo是什么意思