内核注入,技术古老但很实用。现在部分RK趋向无进程,玩的是SYS+DLL,有的无文件,全部存在于内存中。可能有部分人会说:“都进内核了.什么不能干?”。是啊,要是内核中可以做包括R3上所有能做的事,软件开发商们也没必要做应用程序了。有时,我们确实需要R3程序去干驱动做起来很困难或者没必要驱动中去做的事,进程 /  DLL是不错的选择,但进程目标太大,所以更多的同学趋向于注DLL。
    若要开发安全软件、小型工具,可借鉴其思路,Anti Rootkits时,在某些极端情况下,可使用同样的技术发现、清除RK,保证用户电脑的正常使用。在此,我将探讨几种内核注入DLL的思路及实现原理。
(1) APC技术
    给一个Alertbale的用户态线程插APC,让其执行其中的ShellCode,来执行我们的代码。这个方法简单易行,但是不够稳定,兼容性不好。测试中发现经常出现Explorer.exe等插崩溃的情况,而且有杀软在的情况下,插入有时会被拦截,起不到应有的效果。(可参考我以前逆过的一个驱动:逆向fuck.sys--编译通过--源码)
(2) 内核Patch  [url=file://KnownDLLs/Kernel32.dll]\\KnownDLLs\\Kernel32.dll[/url] CreateThread
    [url=file://KnownDLLs/]\\KnownDLLs[/url]是系统加载时对象管理器加载最新磁盘DLL到内存的,当其他进程想调用某个DLL时,就不用重复从磁盘加载了,而会从这里映射一份到自己的进程空间中去。这样给我们做全局Patch提供了一个很好的机会:
        ZwOpenSection打开 [url=file://KnownDlls/kernel32.dll]\\KnownDlls\\kernel32.dll[/url],调用ZwMapViewOfSection映射一份到自己进程空间,然后寻找kernel32.dll在内存中代码节的空隙,选择这里作为我们fake函数的存储Buffer。修改CreateThread函数的开头5字节跳转到这个间隙,当系统任何一个线程创建时,会走到CreateThread函数,然后执行空隙中的ShellCode,其负责调用LoadLibrary加载我们的DLL。DLL一经加载,会发IOCTL通知本驱动,让驱动卸载HOOK。这样就完成了内核注DLL的过程。测试时发现Svchost.exe进程调用CreateThread函数很频繁,所以触发也会很快,基本1秒不到就能将DLL加载进去,而我们的HOOK也卸掉了。所以稳定性提高不少。示意图如下:

(3) 内核 HOOK ZwMapViewOfSection
    有部分模块加载时会调用ZwMapViewOfSection,比如进程创建时映射N份DLL到自己的虚拟空间中去.我们替换SSDT中的这个函数,过滤出是加载Kernel32.dll的情况,从参数中取得其基址,Inline Hook其EAT中的CreateThread函数,跳转到在这个进程虚拟地址空间中申请的Buffer,在其中完成DLL的加载过程.
关键API:
ZwAllocateVirtualMemory ---- 在此进程空间中分配内存,存放Shellcode
ZwProtectVirtualMemory ---- 使当前内存块具有可读可写属性
IoAllocateMdl ---- 创建MDL
关键Code如下:


    同方法2相比,原理类似。但修改时机不同,效果差不多,只是注入DLL的时间会慢一些。至于Shellcode的编写,就大同小异了.萝卜白菜各有所爱,主要看个人发挥。要是闲写shellcode麻烦,请到看雪学院去查资料,模板很多,在这里就不YY了。
【看雪读书月】学习ShellCode编写
[note]一个简单的Shellcode
shellcode之小小琢磨
Add_Section
(4) 内核 HOOK
NtCreateThread
    跟踪进程创建的流程,会很明晰的发现有多点可以patch来实现DLL的注入。
    进程创建完时是一个空水壶,里面没有沸腾的热水(threads),于是系统调用NtCreateThread创建其主线程(给空水壶注水 – 凉水),在这个暂停的线程里面折腾了一阵后完事了也厌倦了,于是系统跳了出来,回到进程空间中,调用Kernel32.dll去通知CSRSS.EXE,对它说:“这里有一个新进程出生了,你在你的表里标记一下”。然后就开始加载DLL啦,把系统KnownDLLs中的自己需要的DLL都Map一份到这个大水壶中。接着KiThreadStartup加热水壶中的凉水,于是水就开始沸腾了,此时主线程开始工作。。。
    拦截NtCreateThread,取得当前线程上下文,保存它要返回的地址(会回到空水壶中去),劫持为我们自己分配的地址,在其中填充ShellCode来加载目的DLL。至于选择Buffer,思路很多。这里可简单的Attach到当前进程,在充足的虚拟2GB进程地址空间中分配属于你自己的一块小内存,够放ShellCode足矣。示意图如下:

(5) 内核感染常用模块,让感染模块帮我们Load DLL
    这个方法就有点绕远了,开始了最本质最原始的感染,可增加新节,可插空隙,总之,让别人的模块Load进内存时顺路的帮我们加载下DLL,DLL一旦加载就可以恢复感染,清除痕迹。至于感染代码,网上一堆。只要不是驱动感染驱动(多了个校验和),其他性质都一样,看自己发挥啦。
(6) 拦截NtCreateUserProcessNtCreateSymbolicLinkObject
    前者在Vista下才有. 拦截后通过PsLookupProcessThreadByCid得到ETHREAD / EPROCESS,判断是否是CSRSS.EXE引起的,若是则在此进程空间内分配一块内存,调用NtGetContextThread得到当前的线程上下文,调用ZwWriteVirtualMemory填充Shellcode区域,取得LdrUnloadDllLdrGetDllHandle等函数地址,通过他们加载DLL。然后调用NtSetContextThread恢复原始的Context。关于这种方法,可参考DriverDevelop上某人发的BIN。
[”内核实现DLL注入.可以完美绕过KAV瑞星等杀毒软件”]
(7) 内核拦截NtResumeThread
(8)NtUserSetWindowsHookEx 注入
顺便提下R3上DLL的注入:
1.CreateRemoteThread (or NtCreateThreadEx (Used in Vista))
  2.SetThreadContext (change the EIP)
  3.NtQueueAPCThread
  4.RtlCreateUserThread
  5. SetWindowHookEx
小结:
    纵观进程启动的全过程,可patch的地方很多,只要保证进程、线程上下文不被破坏,注入的手法可多种多样。只要保证我们的DLL注入时间足够短,稳定性足够高即可。当我们迫不得已要从内核注入DLL到用户进程去时,系统已经中毒很深,此时运用类似上面提到的技术来加载DLL,让DLL做我们驱动无法完成的任务,是可以接受的。
    上面提到的思路是我暂时想到并且已经实现了的,详细过程可参见代码。欢迎积极探讨更好更稳定而且不邪恶的方法。
jpg改rar

N种内核注入DLL的思路及实现的更多相关文章

  1. [转]N种内核注入DLL的思路及实现

    内核注入,技术古老但很实用.现在部分RK趋向无进程,玩的是SYS+DLL,有的无文件,全部存在于内存中.可能有部分人会说:“都进内核了.什么不能干?”.是啊,要是内核中可以做包括R3上所有能做的事,软 ...

  2. Windows x86/ x64 Ring3层注入Dll总结

    欢迎转载,转载请注明出处:http://www.cnblogs.com/uAreKongqi/p/6012353.html 0x00.前言 提到Dll的注入,立马能够想到的方法就有很多,比如利用远程线 ...

  3. 远程线程注入dll,突破session 0

    前言 之前已经提到过,远线程注入和内存写入隐藏模块,今天介绍突破session 0的dll注入 其实今天写这个的主要原因就是看到倾旋大佬有篇文章提到:有些反病毒引擎限制从lsass中dump出缓存,可 ...

  4. Wow64(32位进程)注入DLL到64位进程

    转载自: https://blog.poxiao.me/p/wow64-process-inject-dll-into-x64-process/ 向其他进程注入DLL通常的做法是通过调用CreateR ...

  5. 【windows核心编程】注入DLL时BUG排除与调试

    DLL注入排除bug的思路步骤. 1.在VS中监视输入err,hr检查DLL是否注入成功 2.OD断点loadlibraryW,loadlibraryA是否已经注入成功,eax是否有值. 3.检查路径 ...

  6. 《windows核心编程系列》十九谈谈使用远程线程来注入DLL。

    windows内的各个进程有各自的地址空间.它们相互独立互不干扰保证了系统的安全性.但是windows也为调试器或是其他工具设计了一些函数,这些函数可以让一个进程对另一个进程进行操作.虽然他们是为调试 ...

  7. 通过注入DLL后使用热补丁钩取API

    通过注入DLL后使用热补丁钩取API 0x00 对比修改API的前五个字节钩取API 对前一种方法钩取API的流程梳理如下: 注入相应的DLL 修改原始AI的函数的前五个字节跳往新函数(钩取API) ...

  8. 通过注入DLL修改API代码实现钩取(一)

    通过注入DLL修改API代码实现钩取(一) Ox00 大致思路 通过CreateRemoteThread函数开辟新线程,并将DLL注入进去 通过GetProcessAddress函数找到需钩取的API ...

  9. 通过修改EIP寄存器实现强行跳转并且注入DLL到目标进程里

    /* 描述 功能:通过修改EIP寄存器实现32位程序的DLL注入(如果是64位,记得自己对应修改汇编代码部分) 原理: 挂起目标进程,停止目标进程EIP的变换,在目标进程开启空间,然后把相关的指令机器 ...

随机推荐

  1. hdu 1195

    题意:就是给你n组的四位数,在一次变化中又一位数字可以变化,而变化的方式为加一减一或者是与隔壁的互换,注意,是每一个数字都可以, 求最少的变化次数到达目标的数字 一看这个就应该知道这是一个bfs的题目 ...

  2. 使用mysqladmin ext了解MySQL运行状态【转】

    摘要: mysqladmin是 MySQL一个重要的客户端,最常见的是使用它来关闭数据库,除此,该命令还可以了解MySQL运行状态.进程信息.进程杀死等.本文介绍一下如何使用 mysqladmin e ...

  3. winrt组件库(包括翻书组件)

    http://www.mindscapehq.com/products/metroelements/controls/book-control-for-winrt 点击“down free trial ...

  4. 留只脚印(DP)

    题目链接:http://codeforces.com/problemset/problem/698/A 很久很久没做咯~~~~ dp 是个很神奇的东西.... #include <iostrea ...

  5. HDU 1159 Common Subsequence --- DP入门之最长公共子序列

    题目链接 基础的最长公共子序列 #include <bits/stdc++.h> using namespace std; ; char c[maxn],d[maxn]; int dp[m ...

  6. openURL的使用方法:

    openURL的使用方法: view plaincopy toclipboardprint?        [[UIApplication sharedApplication] openURL:[NS ...

  7. hdu 2159 FATE

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2159 思路:二维完全背包,状态转移方程为: f[j][l]=max(f[j][l],f[j-b[i]] ...

  8. Android界面性能调优手册

    界面是 Android 应用中直接影响用户体验最关键的部分.如果代码实现得不好,界面容易发生卡顿且导致应用占用大量内存. 我司这类做 ROM 的公司更不一样,预装的应用一定要非常流畅,这样给客户或用户 ...

  9. 前端模板artTemplate,handlerbars的使用心得

    写前端页面肯定离不开模板渲染,就近期项目中用的两个前端模板做一些使用总结,顺便复习一下,也方便后面温故. 1,artTemplate 优点: 1,一般web端用得较多,执行速度通常是 Mustache ...

  10. 理解Java中的引用传递和值传递

    关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习 ...