RING3下SSDT原始地址的获取

SSDT获取原始服务地址的方法与原理(灯灯灯灯,我肥来了..) 好吧,我胡汉三肥来了..(确实肥了- -),几个月没发什么文章.其实.我也只是一个新丁~欢迎大家交流,高手勿喷,谢谢合作^_^     对于SSDT,不知道的同学请自己百度,判断出SSDT被HOOK之后,如何恢复成原始服务地址?主要方法有两个,简单来说,一个Ring0,一个Ring3的方法(可能分类不够准确),我今天除了介绍方法之外,主要还是讲讲里面的原理吧,原理神马的才是最吸引人的对吧. 阅读详情


#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;

#define RVATOVA(base,offset)             ((PVOID)((DWORD)(base)+(DWORD)(offset)))
#define ibaseDD *(PDWORD)&ibase
#define STATUS_INFO_LENGTH_MISMATCH      ((NTSTATUS)0xC0000004L)
#define NT_SUCCESS(Status)               ((NTSTATUS)(Status) >= 0)


typedef struct {
    WORD    offset:12;
    WORD    type:4;
} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;


typedef LONG NTSTATUS;

long ( __stdcall *NtQuerySystemInformation )( DWORD, PVOID, DWORD, DWORD );

typedef struct _SYSTEM_MODULE_INFORMATION {//Information Class 11
    ULONG    Reserved[2];
    PVOID    Base;
    ULONG    Size;
    ULONG    Flags;
    USHORT    Index;
    USHORT    Unknown;
    USHORT    LoadCount;
    USHORT    ModuleNameOffset;
    CHAR    ImageName[256];
}SYSTEM_MODULE_INFORMATION,*PSYSTEM_MODULE_INFORMATION;

typedef struct {
    DWORD    dwNumberOfModules;
    SYSTEM_MODULE_INFORMATION    smi;
} MODULES, *PMODULES;

#define    SystemModuleInformation    11




DWORD GetHeaders(PCHAR ibase,
                 PIMAGE_FILE_HEADER *pfh,
                 PIMAGE_OPTIONAL_HEADER *poh,
                 PIMAGE_SECTION_HEADER *psh)
                 
{
    PIMAGE_DOS_HEADER mzhead=(PIMAGE_DOS_HEADER)ibase;
   
    if    ((mzhead->e_magic!=IMAGE_DOS_SIGNATURE) ||       
        (ibaseDD[mzhead->e_lfanew]!=IMAGE_NT_SIGNATURE))
        return FALSE;
   
    *pfh=(PIMAGE_FILE_HEADER)&ibase[mzhead->e_lfanew];
    if (((PIMAGE_NT_HEADERS)*pfh)->Signature!=IMAGE_NT_SIGNATURE)
        return FALSE;
    *pfh=(PIMAGE_FILE_HEADER)((PBYTE)*pfh+sizeof(IMAGE_NT_SIGNATURE));
   
    *poh=(PIMAGE_OPTIONAL_HEADER)((PBYTE)*pfh+sizeof(IMAGE_FILE_HEADER));
    if ((*poh)->Magic!=IMAGE_NT_OPTIONAL_HDR32_MAGIC)
        return FALSE;
   
    *psh=(PIMAGE_SECTION_HEADER)((PBYTE)*poh+sizeof(IMAGE_OPTIONAL_HEADER));
    return TRUE;
}


DWORD FindKiServiceTable(HMODULE hModule,DWORD dwKSDT)
{
    PIMAGE_FILE_HEADER    pfh;
    PIMAGE_OPTIONAL_HEADER    poh;
    PIMAGE_SECTION_HEADER    psh;
    PIMAGE_BASE_RELOCATION    pbr;
    PIMAGE_FIXUP_ENTRY    pfe;   
   
    DWORD    dwFixups=0,i,dwPointerRva,dwPointsToRva,dwKiServiceTable;
    BOOL    bFirstChunk;
   
    GetHeaders((char *)hModule,&pfh,&poh,&psh);
   
    // loop thru relocs to speed up the search
    if ((poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) &&
        (!((pfh->Characteristics)&IMAGE_FILE_RELOCS_STRIPPED))) {
       
        pbr=(PIMAGE_BASE_RELOCATION)RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,hModule);
       
        bFirstChunk=TRUE;
        // 1st IMAGE_BASE_RELOCATION.VirtualAddress of ntoskrnl is 0
        while (bFirstChunk || pbr->VirtualAddress) {
            bFirstChunk=FALSE;
           
            pfe=(PIMAGE_FIXUP_ENTRY)((DWORD)pbr+sizeof(IMAGE_BASE_RELOCATION));
           
            for (i=0;i<(pbr->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))>>1;i++,pfe++) {
                if (pfe->type==IMAGE_REL_BASED_HIGHLOW) {
                    dwFixups++;
                    dwPointerRva=pbr->VirtualAddress+pfe->offset;
                    // DONT_RESOLVE_DLL_REFERENCES flag means relocs aren't fixed
                    dwPointsToRva=*(PDWORD)((DWORD)hModule+dwPointerRva)-(DWORD)poh->ImageBase;
                   
                    // does this reloc point to KeServiceDescriptorTable.Base?
                    if (dwPointsToRva==dwKSDT) {
                        // check for mov [mem32],imm32. we are trying to find
                        // "mov ds:_KeServiceDescriptorTable.Base, offset _KiServiceTable"
                        // from the KiInitSystem.
                        if (*(PWORD)((DWORD)hModule+dwPointerRva-2)==0x05c7) {
                            // should check for a reloc presence on KiServiceTable here
                            // but forget it
                            dwKiServiceTable=*(PDWORD)((DWORD)hModule+dwPointerRva+4)-poh->ImageBase;
                            return dwKiServiceTable;
                        }
                    }
                   
                }
            }
            *(PDWORD)&pbr+=pbr->SizeOfBlock;
        }
    }   
   
   
   
    return 0;
}


int EnumSSDT()
{
    HMODULE  hKernel;
    DWORD    dwKSDT;                // rva of KeServiceDescriptorTable
    DWORD    dwKiServiceTable;    // rva of KiServiceTable
    PMODULES    pModules=(PMODULES)&pModules;
    DWORD    dwNeededSize,rc;
    DWORD    dwKernelBase,dwServices=0;
    PCHAR    pKernelName;
    PDWORD    pService;
    PIMAGE_FILE_HEADER    pfh;
    PIMAGE_OPTIONAL_HEADER    poh;
    PIMAGE_SECTION_HEADER    psh;
    NtQuerySystemInformation = (long(__stdcall*)(DWORD,PVOID,DWORD,DWORD))GetProcAddress( GetModuleHandle( "ntdll.dll" ),"NtQuerySystemInformation" );
    //通过NtQuerySystemInformation取得系统内核文件,判断为是ntoskrnl.exe ntkrnlmp.exe ntkrnlpa.exe
    rc=NtQuerySystemInformation(SystemModuleInformation,pModules,4,(ULONG)&dwNeededSize);
    if (rc==STATUS_INFO_LENGTH_MISMATCH) //如果内存不够
    {
        pModules=(PMODULES)GlobalAlloc(GPTR,dwNeededSize) ; //重新分配内存
        rc=NtQuerySystemInformation(SystemModuleInformation,pModules,dwNeededSize,NULL); //系统内核文件是总是在第一个,枚举1次
    }
   
    if (!NT_SUCCESS(rc))
    {
        cout << "NtQuerySystemInformation() Failed !/n"; //NtQuerySystemInformation执行失败,检查当前进程权限
        return 0;
    }
   
    dwKernelBase=(DWORD)pModules->smi.Base;   // imagebase
    pKernelName=pModules->smi.ModuleNameOffset+pModules->smi.ImageName;
    hKernel=LoadLibraryEx(pKernelName,0,DONT_RESOLVE_DLL_REFERENCES);     // 映射ntoskrnl //高
    if (!hKernel)
    {
        cout << "Failed to load /n";
        return 0;       
    }
    GlobalFree(pModules);
    if (!(dwKSDT=(DWORD)GetProcAddress(hKernel,"KeServiceDescriptorTable"))) //在内核文件中查找KeServiceDescriptorTable地址
    {
        cout << "Can't find KeServiceDescriptorTable/n";
        return 0;
    }
   
    dwKSDT-=(DWORD)hKernel;       // 获取 KeServiceDescriptorTable RVA
    if (!(dwKiServiceTable=FindKiServiceTable(hKernel,dwKSDT)))   // 获取KiServiceTable地址
    {
        cout << "Can't find KiServiceTable.../n";
        return 0;
    }
   
    GetHeaders((char *)hKernel,&pfh,&poh,&psh);
   
    int dwIndex=0;
    for (pService=(PDWORD)((DWORD)hKernel+dwKiServiceTable);
        *pService-poh->ImageBase<poh->SizeOfImage;
        pService++,dwServices++,dwIndex++)
    {
        printf("0x%03X-0x%08X/n",dwIndex,*pService-poh->ImageBase+dwKernelBase);   //SSDT索引和地址
    }
    FreeLibrary(hKernel);
    return 1;
}



int main()
{
    EnumSSDT();

    system("pause");
    return 0;
}

SSDT Hook实现内核级的进程保护 SSDT Hook效果图 加载驱动并成功Hook  NtTerminateProcess函数: 当对 指定的进程进行保护后,尝试使用“任务管理器”结束进程的时候,会弹出“拒绝访问”的窗口,说明,我们的目的已经达到: SSDT简介 SSDT 的全称是 System Services Descriptor Table,系统服务描述符表。 这个表 阅读详情

相关推荐

驱动开发笔记3—SSDT表详解

SSDT表 SSDT的全称是"System Services Descriptor Table",即系统服务描述表,在内核中的实际名称是KeServiceDescriptorTable,这个表由ntoskrnl.exe导出(在x64里不导出)。 SSDT用于处理应用层通过Kernel32.dll下发的各个API操作请求。ntdll.dll中的API是一个简单的包装函数,当Kernel32.dll中的API通过Ntdll.dll时,会先完成对参数的检查,再调用一个中断(int 2Eh 或者 SysEnter指

qq_42814021的博客 4459

SSDT_Helper for Delphi v1(Ring3下查看SSDT HOOK的Delphi版)

SSDT(System Services Descriptor Table) 这几年被讲烂了,各大论坛、Blog相关文章都是成堆成堆的。检测SSDT HOOK的代码也相当多,只不过放眼望去都是C的。实在不忍自己苦苦捍卫的Delphi就此末落(D2009倒是让人振奋了一把),于是把自己感兴趣的几个代码都给翻成了Delphi的,现在拿来共享。 不会驱动,这方面涉水也比较浅,只能写个查看S

zbc_vc的专栏 1040

【梅哥的Ring0湿润插入教程】第二课:Ring0实现读写SSDT

【梅哥的Ring0湿润插入教程】Email:mlkui@163.com 转载请注明出处,谢绝喷子记者等,如引起各类不适请自觉滚J8蛋!第二课:Ring0实现读写SSDT 随着驱动保护技术的逐步成熟,诸如网络游戏公司等越来越多的商业软件公司开始使用Ring0级保护技术保护自己的产品,以起到反用户级调试、反RootKit、反各类钩子、反各类远程注入等作用。目前,使用驱动保护技术的...

aejtu5698的博客 3019

SSDT原始地址, 现在地址

#include #include #include #include #include #define ibaseDD *(PDWORD)&ibaseHINSTANCE g_hInst;HWND hWinMain,hList;#define ID_LISTVIEW 104#pragma comment(lib,"comctl32")typedef ULONG NTSTATUS;#defi

KernelEx的专栏 1605

Win64 驱动内核编程-18.SSDT

SSDT  学习资料:http://blog.youkuaiyun.com/zfdyq0/article/details/26515019  学习资料:WIN64内核编程基础 胡文亮      SSDT(系统服务描述表),刚开始接触什么进程保护XXX啥的,都是看到在说SSDT(虽然说目前很多杀软都已经采用稳定简单的回调姿势了)。这次就弄清楚两个问题:     如何在内核里动态获得 SSDT 的基址;

天使也掉毛 2348

掌握Ring3下获取真实SSDT的方法与实践

在现代操作系统中,尤其是在使用了Windows NT架构的操作系统中,系统状态被分为不同的权限级别,以实现对操作系统的安全保护。Ring3层指的是用户模式,而Ring0层指的是内核模式。用户模式的运行环境是受限的,它不允许直接访问硬件资源,同时也不允许执行一些对系统稳定性可能构成威胁的操作。相比之下,内核模式拥有最高的权限,可以访问所有的硬件和系统资源。内核模式的代码运行在核心态,它负责处理硬件中断、调度进程、管理内存等关键任务。

weixin_35516624的博客 975

SSDT Restore in ring0的部分代码

NTSTATUS GetModuleBaseInformation(IN PCHAR pModuleName,OUT PSYSTEM_MODULE_INFORMATION psmi) {PSYSTEM_MODULE_INFORMATION psmi2=0;ULONG     i;ULONG     uCount;PCHAR     pName;ULONG     dData;PCHAR     B

1028

e语言-易语言实现64位全系统获取SSDT地址

获取ssdt地址 当然是用驱动编写的啦  驱动支持全系统获取(x64)位 易源码是有bug的  win7 获取真实的地址可以没啥问题  win10的就有问题实在没时间去修了  驱动没啥问题 反复测试没蓝屏 (驱动已签名)其他的问题后期在看着弄吧   提示驱动获取的ssdt地址是没问题的原始地址是要从ntoskrnl.exe获取 (驱动源码不开源)

寻找SSDT表地址

#include"ntifs.h" #include"intsafe.h" #include"ntimage.h" #define out #define in ULONG_PTR dizhi_zwclose = 0; ULONG_PTR dizhi_KiServiceInternal = 0; ULONG_PTR dizhi_KiSystemServiceStart = 0; ULONG_P

351

易语言获取R0级SSDT列表源码

易语言获取R0级SSDT列表源码,SSDT系统服务描述表

ring3 下得到真实ssdt

某期黑防的东西 ring3下得到ssdt的真实地址 老东西了 可惜偶不会.

SSDT获取原始服务地址的方法与原理

转自:http://blog.youkuaiyun.com/gaa_ra/article/details/6989406     好吧,我胡汉三肥来了..(确实肥了- -),几个月没发什么文章.其实.我也只是一个新丁~欢迎大家交流,高手勿喷,谢谢合作^_^     对于SSDT,不知道的同学请自己百度,判断出SSDT被HOOK之后,如何恢复成原始服务地址?主要方法有两个,简单来说,一个Ring0,一个Ri

cdsntxz158的专栏 4669

Shadow SSDT服务函数原始地址

可以獲取到Shadow SSDT服务函数原始地址,这更是大多数朋友所期待的。

SSDT Hook

看看大概的调用情况 左边是2000有的,右边是xp后走的 Ntdll.dll 中的 API 是一个简单的包装函数。 当 Kernel32.dll 中的 API 通过 Ntdll.dll 时,会完成参数的检查再调用一个中断(int 2Eh 或者 SysEnter 指令),从而实现从 Ring3 进入 Ring0 层 并且将所要调用的服务号(也就是在 S

zhuhuibeishadiao 3445

R0层获取ShadowSSDT函数原始地址实例

本实例由VS2008开发,在提供了一套驱动开发框架的同时,又演示了如何获取Shadow SSDT表函数原始地址的办法。 主要函数:ULONG GetShadowSSDT_Function_OriAddr(ULONG index); 原理说明: 根据特征码搜索导出函数KeAddSystemServiceTable来获取Shadow SSDT基址,以及通过ZwQuerySystemInformation()函数获取win32k.sys基址,然后解析PE定位到Shadow SSDT在win32k.sys的偏移地址,并通过进一步计算来得到Shadow SSDT表函数的原始地址。 这里只测试了三个函数:(460)NtUserMessageCall、(475)NtUserPostMessage和(502)NtUserSendInput,具体使用时可以举一反三,网上完整的源代码实例并不太多,希望可以帮到真正有需要的朋友。 系统环境: 在WinXP SP3系统 + 瑞星杀毒软件 打印输出: [ LemonInfo : Loading Shadow SSDT Original Address Driver... ] [ LemonInfo : 创建“设备”值为:0 ] [ LemonInfo : 创建“设备”成功... ] [ LemonInfo : 创建“符号链接”状态值为:0 ] [ LemonInfo : 创建“符号链接”成功... ] [ LemonInfo : 驱动加载成功... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 开始... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP Enter IRP_MJ_DEVICE_CONTROL... ] [ LemonInfo : 获取ShadowSSDT表 (460)NtUserMessageCall 函数的“当前地址”为:0xB83ECFC4,“起源地址”为:0xBF80EE6B ] [ LemonInfo : 获取ShadowSSDT表 (475)NtUserPostMessage 函数的“当前地址”为:0xB83ECFA3,“起源地址”为:0xBF8089B4 ] [ LemonInfo : 获取ShadowSSDT表 (502)NtUserSendInput 函数的“当前地址”为:0xBF8C31E7,“起源地址”为:0xBF8C31E7 ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP_MJ_DEVICE_CONTROL 成功执行... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 结束... ] [ LemonInfo : UnLoading Shadow SSDT Original Address Driver... ] [ LemonInfo : 删除“符号链接”成功... ] [ LemonInfo : 删除“设备”成功... ] [ LemonInfo : 驱动卸载成功... ]

记录Nvidia AGX Orin的配置日常(二)设置上电自动开机和远程桌面

因为要拿AGX作为机器人的主控板,所以需要给他设置一下通电后无需按电源键就自动开机,然后再配置一下远程桌面。

AutomaticForever的博客 1365

SSDT HOOK技术(1)——获得SSDT函数索引号

1.SSDT是什么? SSDT全程是System Services Discriptor Table 翻译过来就是系统服务描述符表,那么系统服务描述符是什么呢?根据官方的解释ssdt表就是把ring3的Win32 API和ring0的内核API联系起来。SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。 那么我们可以理解为SSDT就是一个很庞大的数组,它被用来保存windows系统服务地址。 比如我们在R3层调用了CreateFile这个A

苞米地里捉小鸡的博客 1163

基于Ultralytic实现多路摄像头目标检测

基于Ultralytic实现多路摄像头目标检测前面的文章分享了单路摄像头画面的YOLO目标检测,这篇文章主要分享一下多路摄像头画面的实时YOLO目标检测。测试环境在Windows系统下进行。

qq_57674776的博客 942

HOOK钩子技术4 SSDT HOOK

API 调用过程以一个demo测试为例,本测试查看OpenProcess 在R3-R0 下的调用。// test.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include <windows.h> #include <stdio.h> int main(int argc, char

Catch me if you can 2749

从0到1搭建StarRocks3.4.1存算一体架构(VM 虚拟机版)

本文详细介绍了如何在VM虚拟机上从零搭建StarRocks 3.4.1存算一体架构。首先阐述了StarRocks作为高性能分布式SQL数据仓库的优势,重点讲解了其存算一体架构的设计原理。随后提供完整的安装指南,包括环境准备(3台CentOS 8虚拟机配置)、网络互通验证、Java环境配置、软件包解压安装等关键步骤。文章特别详细说明了FE和BE节点的配置文件修改(fe.conf和be.conf)以及必要的防火墙端口开放配置。通过图文并茂的方式,帮助开发者和运维人员快速掌握StarRocks集群部署方法,为后续

小 tom的博客 1334

杰理JL701N内置flash录音配置教程

本文详细介绍了内置Flash录音功能的配置方法。主要内容包括:1) 基础模式配置(开启音乐/录音模式、Flash录音宏定义);2) 录音参数设置(格式基准值、存储区域定义、容量配置);3) MP3编码特殊处理;4) 下载时的Flash格式化操作;5) 录音开关和播放接口的使用说明。配置过程涉及多个关键文件的修改,并强调存储容量的精确分配。

qq_42014563的博客 599
上一篇: ring3 恢复SSDT
下一篇: SSDT原始地址, 现在地址
普通网友
博客等级 码龄17年 1粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值