首页
社区
课程
招聘
[旧帖] [已有邀请码]新手写的SSDT_HOOK例子. 0.00雪花
发表于: 2010-11-28 10:33 488609

[旧帖] [已有邀请码]新手写的SSDT_HOOK例子. 0.00雪花

2010-11-28 10:33
488609
初学驱动,练习着写了一个demo,希望能申请到邀请码,

先看看效果图:


三个函数原型参考(WDK):
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenProcess (
   __out PHANDLE ProcessHandle,       //返回被打开进程的句柄
   __in ACCESS_MASK DesiredAccess,    //访问权限
   __in POBJECT_ATTRIBUTES ObjectAttributes, //对象属性结构
   __in_opt PCLIENT_ID ClientId   //进程ID
   );

NTSYSCALLAPI
NTSYSAPI
NTSTATUS
NTAPI
NtReadVirtualMemory(
                IN HANDLE ProcessHandle,
                IN PVOID BaseAddress,
                OUT PVOID Buffer,
                IN ULONG BufferSize,
                OUT PULONG NumberOfBytesRead OPTIONAL
                );

NTSYSCALLAPI
NTSYSAPI
NTSTATUS
NTAPI
NtWriteVirtualMemory(
         IN HANDLE ProcessHandle,
         OUT PVOID BaseAddress,
         IN PVOID Buffer,
         IN ULONG BufferSize,
         OUT PULONG NumberOfBytesWritten OPTIONAL
         );

以下是main.cpp里面的代码,注释的很详细了:
//如果是C++编译器,就是用C的编译方式,不对代码做改动
#ifdef __cplusplus
extern "C"
{
#endif
#include "ntddk.h"
#ifdef __cplusplus
}
#endif

//定义SSDT结构
typedef struct _SERVICE_DESCRIPTOR_TABLE
{
        PVOID ServiceTableBase;
        PULONG ServiceCounterTableBase;
        ULONG NumberOfService;
        ULONG ParamTableBase;
}*PSERVICE_DESCRIPTOR_TABLE;

//运行时链接SSDT结构表,由ntoskrnl.exe导出,,在WINDBG里面可以用dd KeServiceDescriptorTable一步一步查看
extern "C" PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;

VOID Hook(); //钩子函数声明
VOID UnHook();//钩子卸载函数
ULONG JmpAddressOpen;//SSDT_hook后,跳转到原来NtOpenProcess的地址后面,即是NtOpenProcess+10的地方  7A
ULONG JmpAddressRead;//SSDT_hook后,跳转到原来NtReadVirtualMemory的地址后面,即是NtReadVirtualMemory+10的地方  BA
ULONG JmpAddressWrite;//SSDT_hook后,跳转到原来NtWriteVirtualMemory的地址后面,即是NtRriteVirtualMemory+10的地方  115
ULONG OldServiceAddressOpen;//真正的NtOpenProcess地址
ULONG OldServiceAddressRead;//真正的NtReadVirtualMemory地址
ULONG OldServiceAddressWrite;//真正的NtWriteVirtualMemory地址

//卸载函数
VOID Unload(PDRIVER_OBJECT driver)
{
        DbgPrint("卸载函数....");
        UnHook();
}

//声明自己的NtOpenProcess函数,,替换原有函数
_declspec(naked) NTSTATUS _stdcall MyNtOpenProcess(
                                                                                                        PHANDLE ProcessHandle,
                                                                                                        ACCESS_MASK DesiredAccess,
                                                                                                        POBJECT_ATTRIBUTES ObjectAttributes,
                                                                                                        PCLIENT_ID ClientId)
{
        DbgPrint("NtOpenProcess is called!");

        //实现原NtOpenProcess函数的前十字节,并跳转到10字节后面继续执行
        __asm{
                push 0C4h
                        push 804F52D8h
                        jmp JmpAddressOpen   
                 }
}

//声明自己的NtReadVirtualMemory函数,,替换原有函数
_declspec(naked) NTSTATUS _stdcall MyNtReadVirtualMemory(
                                                                                                        IN HANDLE ProcessHandle,
                                                                                                        IN PVOID BaseAddress,
                                                                                                        OUT PVOID Buffer,
                                                                                                        IN ULONG BufferSize,
                                                                                                        OUT PULONG NumberOfBytesRead OPTIONAL)
{
        DbgPrint("NtReadVirtualMemory is called!");

        //实现原NtReadVirtualMemory函数的前十字节,并跳转到10字节后面继续执行
        __asm{
                push 1Ch
                        push 804F6FA8h //共十个字节
                        jmp JmpAddressRead
                 }
}

//声明自己的NtWriteVirtualMemory函数,,替换原有函数
_declspec(naked) NTSTATUS _stdcall MyNtWriteVirtualMemory(
                                                                                                         IN HANDLE ProcessHandle,
                                                                                                         OUT PVOID BaseAddress,
                                                                                                         IN PVOID Buffer,
                                                                                                         IN ULONG BufferSize,
                                                                                                         OUT PULONG NumberOfBytesWritten OPTIONAL)
{
        DbgPrint("NtWriteVirtualMemory is called!");

        //实现原NtWriteVirtualMemory函数的前十字节,并跳转到10字节后面继续执行
        __asm{
                push 1Ch
                        push 804F6FC0h //共十个字节
                        jmp JmpAddressWrite
                 }
}

//入口函数
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{

//#ifdef DEBUG
//        __asm
//                int 3   //如果是调试模式,就断下
//#endif

                DriverObject->DriverUnload=Unload;  //注册卸载函数
                DbgPrint("Unhooker load.....");
                Hook();
                return STATUS_SUCCESS;
}

VOID Hook()
{
        //三个地址分别保存真实函数的地址
        ULONG AddressOpen,AddressRead,AddressWrite;

        //HOOK前,获取被HOOK的函数的真实地址
        AddressOpen=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0x7A*4;
        AddressRead=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0xBA*4;
        AddressWrite=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0x115*4;

        //把真实地址保存,以便以后恢复
        OldServiceAddressOpen=*(ULONG *)AddressOpen;
        OldServiceAddressRead=*(ULONG *)AddressRead;
        OldServiceAddressWrite=*(ULONG *)AddressWrite;

        //打印真实函数地址
        DbgPrint("OldServiceAddressOpen:0x%08X",OldServiceAddressOpen);
        DbgPrint("OldServiceAddressRead:0x%08X",OldServiceAddressRead);
        DbgPrint("OldServiceAddressWrite:0x%08X",OldServiceAddressWrite);

        //打印自己的函数的地址
        DbgPrint("MyNtOpenProcess:0x%08X",MyNtOpenProcess);
        DbgPrint("MyNtReadVirtualMemory:0x%08X",MyNtReadVirtualMemory);
        DbgPrint("MyNtWriteVirtualMemory:0x%08X",MyNtWriteVirtualMemory);

        //计算出HOOK后腰跳转的地址
        JmpAddressOpen =OldServiceAddressOpen + 10;
        JmpAddressRead= OldServiceAddressRead + 10;
        JmpAddressWrite =OldServiceAddressWrite + 10;

        //打印跳转后的地址
        DbgPrint("JmpAddressOpen:0x%08X",JmpAddressOpen);
        DbgPrint("JmpAddressRead:0x%08X",JmpAddressRead);
        DbgPrint("JmpAddressWrite:0x%08X",JmpAddressWrite);

        //去掉内存保护
        __asm{
                cli
                        mov eax,cr0
                        and eax,not 10000h
                        mov cr0,eax
                 }
       
        //跳转!!
        *((ULONG*)AddressOpen) = (ULONG)MyNtOpenProcess;//HOOK SSDT
        *((ULONG*)AddressRead) = (ULONG)MyNtReadVirtualMemory;
        *((ULONG*)AddressWrite) = (ULONG)MyNtWriteVirtualMemory;

        //恢复内存保护
        __asm{
                mov eax,cr0
                        or eax,10000h
                        mov cr0,eax
                        sti
                 }
}

//恢复被HOOK的函数
VOID UnHook()
{
        //三个地址分别保存真实函数的地址
        ULONG AddressOpen,AddressRead,AddressWrite;

        //HOOK前,获取HOOK的函数的地址
        AddressOpen=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0x7A*4;
        AddressRead=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0xBA*4;
        AddressWrite=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0x115*4;
       
        //去掉内存保护
        __asm{
                cli
                        mov eax,cr0
                        and eax,not 10000h
                        mov cr0,eax
                 }

        //跳!!!
        *((ULONG*)AddressOpen) = (ULONG)OldServiceAddressOpen;//还原SSDT
        *((ULONG*)AddressRead) = (ULONG)OldServiceAddressRead;
        *((ULONG*)AddressWrite) = (ULONG)OldServiceAddressWrite;

        //恢复内存保护
        __asm{
                mov eax,cr0
                        or eax,10000h
                        mov cr0,eax
                        sti
                 }
        DbgPrint("Unhook....");
}

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
  • 1.jpg (54.52kb,274次下载)
  • 2.jpg (35.71kb,272次下载)
收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 221
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
恩,加油,以后尽量少用硬编码,呵呵加油
2010-11-28 11:00
0
雪    币: 601
活跃值: (256)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
3
恩,知道了,请教一个问题:
__asm{
    push 0C4h
      push 804F52D8h
      jmp JmpAddressOpen   
     }

push 804F52D8h 这里是ObWatchHandles+0x25的,我想知道怎么定位ObWatchHandles
2010-11-28 11:04
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
原创支持下!!!
2010-11-28 11:37
0
雪    币: 6092
活跃值: (654)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
5
要是有不是硬件编码的就好了正需要
2010-11-30 18:41
0
雪    币: 122
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
是啊,哪位大侠贴歌不是硬编码的代码出来啊!
2010-11-30 19:56
0
雪    币: 15
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
虽然不会,但是收藏了,以后有机会的话,学学!
2010-11-30 21:37
0
雪    币: 601
活跃值: (256)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
8
我很好奇,一夜之间,浏览量怎么可以突破8万,而且我在导航里面每个一秒刷新一次,浏览量就是涨200左右,版主解释下










上传的附件:
2010-12-1 09:27
0
雪    币: 7
活跃值: (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
哈哈,看雪作弊了
2010-12-29 02:46
0
雪    币: 42
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
写的不错~~~~~~~
2010-12-29 10:51
0
游客
登录 | 注册 方可回帖
返回
//