首页
社区
课程
招聘
[原创]重载内核之二接管流程
发表于: 2014-5-17 07:53 10864

[原创]重载内核之二接管流程

2014-5-17 07:53
10864

  重载内核的相关文章实在是太多了,鉴于还是有很多初学者研究这一块,本文仅作为一个引导作用,文笔不好,见谅。
  我的博客:http://blog.csdn.net/sidyhe
  开发环境:VS2010 + WinDDK
  测试环境:VirtualDDK + VMware + Win7 sp1 x86
  第一部分链接:http://bbs.pediy.com/showthread.php?t=187863
第二部分:接管流程
  在第一部分完成之后,已经重载了一份新的NT内核,接下来就是接管执行流程。
  自Windows XP以后从RING3进RING0统一调用sysenter汇编指令,但仍保留了INT 2E中断,在sysenter调用之后会执行内核空间中的KiFastCallEntry函数,这个函数负责所有的应用层请求,即使是INT 2E也会走这个函数,而KiFastCallEntry在经过简单的处理后会通过KeServiceDescriptorTable或者KeServiceDescriptorTableShadow来获取内核函数指针并调用,重载内核的目的就是为了在执行内核函数的时候转移到新的模块上,从而不被其他HOOK所影响。那么需要做的就是在调用内核函数的时候转移指令,但并不是所有内核函数都由ntoskrnl实现,内核中GUI函数却是由win32k.sys实现,由于目前只重载了ntoskrnl,所以只能做到转移SSDT中的函数。额外说明一下,即使NT内核有不同的版本,但所有NT内核的导出模块名称都是ntoskrnl.exe(详见输出表),所以我所说的ntoskrnl泛指NT内核,而不是具体的文件名。
  在KiFastCallEntry中调用内核函数的地方大家很容易找到资料,最先是谁提出的我记不清了,反正现在是被某出名软件所使用,下面HOOK的地方与其他软件可能会冲突,所以在测试的时候需要保证没有安装任何安全软件。
  用户态程序调用内核函数的流程简述为:用户态->ntdll.ZwApi->sysenter->内核态->KiFastCallEntry->ServiceTable->ServiceRoutine。ServiceTable分为两种,上面已经提到了,接下来要做的就是在调用SSDT中函数的时候转移到新模块上,在WRK中可以找到这样的代码:

        mov     esi, edx                ; (esi)->User arguments
        mov     ebx, [edi]+SdNumber     ; get argument table address
        xor     ecx, ecx
        mov     cl, byte ptr [ebx+eax]  ; (ecx) = argument size
        mov     edi, [edi]+SdBase       ; get service table address
        mov     ebx, [edi+eax*4]        ; (ebx)-> service routine
        sub     esp, ecx                ; allocate space for arguments
        shr     ecx, 2                  ; (ecx) = number of argument DWORDs
        mov     edi, esp                ; (edi)->location to receive 1st arg
        //省略部分代码
        call    ebx                     ; call system service
PVOID __declspec(naked) _GetKiFastCallEntryAddress()
{
  __asm
  {
    MOV  ECX, 0x00000176;
    RDMSR;
    RETN;
  }
}
PVOID FindHookKiFastCallEntryAddress(PVOID lpKiFastCallEntry)
{
  /*
  sub    esp, ecx
  shr    ecx, 2
  mov    edi, esp
  */
  UCHAR HookBytes[] = {0x2B, 0xE1, 0xC1, 0xE9, 0x02, 0x8B, 0xFC};

  return RtlFindMemory(lpKiFastCallEntry, 0x300, HookBytes, sizeof(HookBytes));
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 4
支持
分享
最新回复 (9)
雪    币: 2895
活跃值: (3929)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
的确还不错
2014-5-17 08:28
0
雪    币: 129
活跃值: (2768)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
期待下一篇
2014-5-17 09:38
0
雪    币: 70
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
__asm
  {
    MOV  ECX, 0x00000176;
    RDMSR;
    RETN;
  }

你这个是严格来说是有问题的。

  xor     ecx, ecx
        mov     cl, byte ptr [ebx+eax]  ; (ecx) = argument size
        mov     edi, [edi]+SdBase       ; get service table address
        mov     ebx, [edi+eax*4]        ; (ebx)-> service routine
        sub     esp, ecx                ; allocate space for arguments
        shr     ecx, 2                  ; (ecx) = number of argument DWORDs
        mov     edi, esp                ; (edi)->location to receive 1st arg

这个hook点,在360,金山上都用到了,只是360在hook方法上已经发生了变化,金山采用的方法有点类似你的这个,不过还不是,不过hook点都差不多在这块。
这个hook点,国内起初最先使用的是360,所以很多人都误认为是360的大牛发现的,其实我不知道是不是360大牛发现的,但这个点最初是一位俄罗斯的工程师发现的,也是最早应用的,记得不太清楚了,是在2006年,当初看过忘记了,而360是在2007年,貌似才开始使用这个点。后来发生的大家估计都知道的,各种在这个点hook ,去年金山的蓝屏事件等。。。。后来被各种研究的人在这个位置爆菊了N次,搞的系统那叫个惨不忍睹打住,不说了,感觉说太多了,第一次技术性的问题说了这么多,回家该打屁股了。少说,多做,且做且珍惜!
2014-5-17 10:40
0
雪    币: 2161
活跃值: (750)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
5
[QUOTE=yxhbboy;1285162]__asm
  {
    MOV  ECX, 0x00000176;
    RDMSR;
    RETN;
  }

你这个是严格来说是有问题的。

  xor     ecx, ecx
        mov     cl, byte ptr [ebx+eax]  ; (...[/QUOTE]

拜托说清楚哪里有问题啊,我好改正。
获取方式问题?
2014-5-17 11:11
0
雪    币: 341
活跃值: (143)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
6
[QUOTE=yxhbboy;1285162]__asm
  {
    MOV  ECX, 0x00000176;
    RDMSR;
    RETN;
  }

你这个是严格来说是有问题的。

  xor     ecx, ecx
        mov     cl, byte ptr [ebx+eax]  ; (...[/QUOTE]

膜拜。。
2014-5-17 11:34
0
雪    币: 70
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
你是想通过MSR寄存器获得KiFastCallEntry的基地址,我之所以说严格来说是有问题的:
1,你没有计算段基地址,而这里通过 rdmsr 读取到的值,段基地址是0x0000,线性的。虽然在AI32下这个段基地址总是0x0000,但严格来说,这个值应该是通过计算得到的;
2,这个处理你没有考虑多CPU的情况;
3,你采用的这种方法,很容易被检测到,而且很容易把自己的代码暴露出来,可以被动态跟踪;你所有代码上的想法都被暴露了;
4,没有中断处理函数;
最近有点SB,破例说了这么多,该回家打屁股。哥们加油,看好你。我只能说这么多了,至于采纳情况这个还要看你自己。
最后我想说,做内核开发,不是你写一段代码,运行不蓝屏就算完事大吉了。这个和做应用层的是不同的。好好体会哥们,加油。
2014-5-17 11:41
0
雪    币: 2161
活跃值: (750)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
谢谢你给我说了那么多,我先记下来,如果遇到了这些问题我会尽力解决,当然啦在没遇到之前它就是通用的,嘿嘿。
至此写了两篇文章,但这仅仅是开始,还有很多扩展与BUG没有处理,所以后续还会有几篇文章的。
2014-5-17 12:18
0
雪    币: 2664
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
9
很长时间没碰内核了
2014-5-17 12:53
0
雪    币: 77
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
mark
2014-5-19 11:37
0
游客
登录 | 注册 方可回帖
返回
//