首页
社区
课程
招聘
[原创]新手学ssdt_hook
发表于: 2013-8-1 20:06 53732

[原创]新手学ssdt_hook

2013-8-1 20:06
53732

看了梦无极的ssdt_hook教程,虽然大牛讲得很细,但是很多细节还是要自己去体会,才会更加深入。在这里我总结一下我的分析过程,若有不对的地方,希望大家指出来。
首先我们应该认识 ssdt是什么?从梦无极的讲解过程中,我联想到了这样一个场景:

古时候有一户人家,姓李,住在皇宫外面,他们家有一个女儿进皇宫当宫女。有一天,李家的老大爷要送东西给他女儿,我们假定他可以进皇宫,于是就开始了这样一个过程。进皇宫只有一条路,那就是走正门,于是李大爷带着东西从家走到了城外,进皇宫前必须从这门口进去,通过一条路后才能到达皇宫,守门的侍卫挺友善的,把老大爷的东西让一个侍卫拿到一个地方去放着,然后叫了一个手下带着老大爷往里走,当走到皇宫门口时,守城门的侍卫就离开了,让另一个人带着老大爷继续走,然后老大爷就进了皇宫,进了皇宫后,有一个侍卫来问李大爷的女儿是在哪边,这里皇宫只有东边和西边。于是李大爷跟他说在东边,于是侍卫把李大爷带到了东边,然后见到一个总管,李大爷给出女儿是几号房的,总管根据一个皇室总表,找到了李大爷的女儿住址,于是李大爷就找到了他女儿,总管还告诉他,你带的东西可以在哪 里去取。

这里拿OpenProcess函数比作李大爷,NtOpenProcess比作李大爷的女儿,OpenProcess通过普通的调用规则进行调用来到城外,再通过ZwOpenProcess进行接见,带着它往皇宫走,然后遇到KiFastSystemCall,带他进入了皇宫。进了ring0后,需要知道是ssdt还是shawssdt,于是分东边的西边,我们假定ssdt就是东西。于是从东边 的路走过去,遇到总管KiFastCallEntry,给出函数偏移号,总管手里的皇室总表就是ssdt这个数据结构,于是找到了NtOPenProcess,而OpenProcess的参数即李大爷带的东西在ParamTableBase这里去找。

好吧,故事讲完了,我们继续分析。
ssdt竟然是一个数组,那么我们就需要先得到这个数组的首地址,于是这个结构就出来了。

typedef struct ServiceDescriptorEntry {
	unsigned int *ServiceTableBase;
	unsigned int *ServiceCounterTableBase; 
	unsigned int NumberOfServices;
	unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
void PageProtectOff()
{
	__asm{
		cli
			mov  eax,cr0
			and  eax,not 10000h
			mov  cr0,eax
		}
}
void PageProtectOn()
{
	__asm{
		mov  eax,cr0
		or   eax,10000h
		mov  cr0,eax
		sti
	}
}
NTSTATUS ssdt_hook()
{
	O_NtOpenProcess=KeServiceDescriptorTable.ServiceTableBase[122];
	PageProtectOff();
	KeServiceDescriptorTable.ServiceTableBase[122]=(unsigned int)MyNtOpenProcess;
	PageProtectOn();
	return STATUS_SUCCESS;
}
NTSTATUS MyNtOpenProcess (
	__out PHANDLE ProcessHandle,
	__in ACCESS_MASK DesiredAccess,
	__in POBJECT_ATTRIBUTES ObjectAttributes,
	__in_opt PCLIENT_ID ClientId
	)
typedef struct _CLIENT_ID {
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
} CLIENT_ID;

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 6
支持
分享
最新回复 (87)
雪    币: 1042
活跃值: (495)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
沙发占位,通俗易懂。3MB的工程?
2013-8-1 22:08
0
雪    币: 97697
活跃值: (200734)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
3
+1
2013-8-1 22:18
0
雪    币: 9675
活跃值: (2481)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
写的不错!
2013-8-1 22:45
0
雪    币: 224
活跃值: (51)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
写的通俗易懂,不错!
2013-8-1 22:58
0
雪    币: 40
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
卸载不蓝屏就ok
2013-8-1 23:19
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
7
很不错。
不过我没有学过硬件,cr0的处理不懂。百度了下,上面写得

CR0的位16是写保护(Write Proctect)标志。当设置该标志时,处理器会禁止超级用户程序(例如特权级0的程序)向用户级只读页面执行写操作;当该位复位时则反之。该标志有利于UNIX类操作系统在创建进程时实现写时复制(Copy on Write)技术。
10000,是16位吧,感觉描述不一样啊。
2013-8-1 23:31
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
8
假设现在内核保护是开启的,那么其它位不管,只看标志位,则有

0000   0000  0000  0001  0000  0000  0000  0000  

0         0        0         1       0        0         0         0

10000h取反后
1111   1111 1111  1110  1111  1111  1111  1111

与上面进行与运算,上面的1就变0了,其它位不变.
不知道 这样解释 可以不。
排版有点问题,编辑框 中和保存后有差异,将就着看吧。
2013-8-1 23:50
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
9
林版主的表情真是百看不厌,哈哈。
2013-8-1 23:52
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
10
蓝屏多了就不蓝屏了,不过当你想让它蓝屏的时候,它又蓝屏了,这样多好玩啊。
2013-8-1 23:53
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
11
呵呵,能懂就好。
2013-8-1 23:54
0
雪    币: 19
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
MARK ,还没学到这里.
2013-8-1 23:59
0
雪    币: 382
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
NTSTATUS ssdt_hook()
{
  O_NtOpenProcess=KeServiceDescriptorTable.ServiceTableBase[122];
  PageProtectOff();
  KeServiceDescriptorTable.ServiceTableBase[122]=(unsigned int)MyNtOpenProcess;
  PageProtectOff();
  return STATUS_SUCCESS;
}

比如我们要保护计算器这个进程不被OpenProcess打开
>>if(ProtectProcess(ClientId->UniqueProcess,"notepad.exe"))

0w0
2013-8-2 00:35
0
雪    币: 478
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
还没学过呢。。。有个问题,你说的那个ssdt数组的首地址,怎么获取到啊
2013-8-2 07:37
0
雪    币: 793
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
Thanks for sharing,Good!

NTSTATUS ssdt_hook()
{
  O_NtOpenProcess=KeServiceDescriptorTable.ServiceTableBase[122];
  PageProtectOff();
  KeServiceDescriptorTable.ServiceTableBase[122]=(unsigned int)MyNtOpenProcess;
  PageProtectOff();
  return STATUS_SUCCESS;
}
下面一个PageProtectOff()函数 是PageProtectOn()吧

一个寄存器cr0,32位寄存器、
它的第17位(WP位)如果为1、表示开启页面保护 0则是去掉页面保护、
__asm    //去掉页保护
              {
                     Cli  //表示将处理器标志寄存器的中断标志位清0,不允许中断
                     mov eax,cr0
                     and eax,not 10000h //and eax,0FFFEFFFFh
                     mov cr0,eax

              }

__asm    //恢复页保护
               {
                     mov eax,cr0
                     or  eax,10000h //or eax,not 0FFFEFFFFh
                     mov cr0,eax
                     sti
               }
2013-8-2 08:45
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
16
[QUOTE=yangfff;1205376]NTSTATUS ssdt_hook()
{
  O_NtOpenProcess=KeServiceDescriptorTable.ServiceTableBase[122];
  PageProtectOff();
  KeServiceDescriptorTable.ServiceTableBa...[/QUOTE]

哈哈。。笔误。。
2013-8-2 09:26
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
17
[QUOTE=happymhx;1205410]Thanks for sharing,Good!

NTSTATUS ssdt_hook()
{
  O_NtOpenProcess=KeServiceDescriptorTable.ServiceTableBase[122];
  PageProtectOff();
  KeServiceDesc...[/QUOTE]

嗯,写得太匆忙了,笔误,马上纠正,呵呵。
2013-8-2 09:35
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
18
typedef struct ServiceDescriptorEntry {
  unsigned int *ServiceTableBase;
  unsigned int *ServiceCounterTableBase;
  unsigned int NumberOfServices;
  unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
用这个结构体导出KeServiceDescriptorTable这个结构,就可以通过KeServiceDescriptorTable->ServiceTableBase知道ssdt结构的首地址了。
2013-8-2 09:58
0
雪    币: 5047
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
牛鼻……膜拜mark!
2013-8-2 10:50
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
20
不太理解的是这个位的作用。百度上的意思的是这个位置1,r0能向r3的只读内存执行写操作。为什么能起到保护作用。
2013-8-2 11:01
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
21
修改CR0寄存器的WP位,使只读属性失效,去掉了只读属性,就可以改写数据了。
2013-8-2 11:22
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
22
四个太阳是怎样练成的。。
2013-8-2 11:23
0
雪    币: 1839
活跃值: (295)
能力值: ( LV9,RANK:370 )
在线值:
发帖
回帖
粉丝
23
当A给B讲抽象的概念的时候,B听的云里雾里,不知所云。
这不是B的错,是因为A的水平还没达到---可以把复杂抽象的东西用简单的事物比拟,换言之,A还没深刻理解。

显然,楼主已经对ssdt深刻理解了。赞一个。
2013-8-2 11:36
0
雪    币: 2781
活跃值: (2573)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
24
LZ讲的精彩。
2013-8-2 12:39
0
雪    币: 166
活跃值: (42)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
25
已标记,晚上开始学习,谢谢分享
2013-8-2 13:07
0
游客
登录 | 注册 方可回帖
返回
//