DLL劫持(HiJack)原理以及实现细节

来源:互联网 发布:企业铃声制作软件 编辑:程序博客网 时间:2024/05/17 05:57

Dll劫持(HiJack)原理以及实现细节

    之前就说个要研究一下这个,今天自己尝试了一下,接下来就说下HiJack的原理以及如何实现,至于拿它来做什么,这个...不可描述

    原理: 这个技术的原理很简单,就是A.exe想要调用B.dll,并且使用里面的FunC函数,这样的话我们把B.Dll改名BB.Dll(有的不用,直接根据路径劫持),然后我们自己写一个B.Dll里面有一个FunC这个函数,然后我们在这个函数里加载BB.Dll,并且调用里面的FunC函数,之后我们在干一些自己的事,对于A.exe来说通常没什么异常感觉,这样我们的目的就达到了,记住此时的你,也就是B.dll的权限和内存归属都是A的,也即是你和A是一家的了,类似于代码注入之后直接修改内存一样。

    原理:上面是最表面的介绍原理,接下来就在编程方面说下原理,因为WIndows上的Dll加载有一个默认的规则,就是先在主程序目录下查找B.dll,如果没有就在系统路径下找,如果还没有,就去环境变量路径里找,就因为这个我们可以轻松的在相应的位置给做劫持,然后问题就如果是实现劫持,就要知道B.Dll里面的所有函数名字以及函数参数,这个地方比较蛋疼,但是也不是绝对不可以实现,分为几种情况,首先就是公用库问题,随便看一下qq的目录:


    看到那个zlib.dll了吗,他是个开源项目,我们可以直接找到源码,然后自己进行编译修改,刚刚我拿了另一个项目的zilb.dll,直接换进去,QQ正常运行了,so...,这个是一种方式,也是最省事的方式,还有一种方式比较麻烦,但是比较通用,就是我们先用CFF Explorer进行dll的分析,把所有导出函数都拿出来,CFF Explorer是这一款软件:


    安装后显示出来的那个大辣椒,得到dll导出函数时候我们可以直接用IDA去分析这个函数的参数,IDA就是上面大辣椒下面的那个程序,这两个需要自己安装,并且IDA安装的话估计比较蛋疼,直接找小伙伴要吧,还有就是有一点需要说明,IDA的话本身不能完全精准的翻译出来真正的函数参数类型,这个需要结合上下文理解,但是通常参数个数应该是对的,(而且貌似不需要真正的去模拟一定对的参数类型,好像说满足所谓的栈平衡就可以了,这个目前不理解,也不确定)。然后就是我刚刚随便写了一个DLL里面有一个函数是这样:

int Add(int a ,int b ,char c)  然后

CFF Explorer的结果是这样:


然后在IDA上进行分析结果是这样:


    额...显然要结合上下文分析,逆向果真是一个耐心和悟性都要很高才能行的活,之后肯定会学习汇编和逆向相关的东西的再有就是驱动编程,这些都是好东西,但首要当前还是继续学架构和一些其他的东西吧,不管你是搞什么开发,什么方向,架构不行写出来的东西简直就是...,慢慢学一样一样来,都是好东西。

    OK,接下来我就模拟实现一个Dll劫持的全过程。

需要准备的东西

A.exe(自己写的一个,直接调用dll里面Add函数)

B.Dll(这个是A调用的东西)

HiJack.Dll(劫持用的Dll)

 

根据使用的顺序进行编写吧,先来B.Dll

创建一个dll项目,然后添加一个类MyCode里面细节是:

MyCode.h#pragma once#ifdef TESTDLL_EXPORTS#define EXPORTS_DEMO _declspec(dllexport)#else#define EXPORTS_DEMO _declspec(dllimport)#endifextern "C" EXPORTS_DEMO int Add (int a , int b);MyCode.cpp#include "stdafx.h"#include "MyCode.h"int Add ( int a , int b){    return ( a + b );}

然后创建使用者A.exe,就是直接调用一下

#include "stdafx.h"#include <windows.h>#include <iostream>using namespace std;typedef int (*AddFunc)(int a, int b);int main(int argc, _TCHAR* argv[]){      HMODULE hDll = LoadLibrary(L"B.dll");      if (hDll != NULL)      {            AddFunc add = (AddFunc)GetProcAddress(hDll, "Add");            if (add != NULL)            {                  cout<<add(2, 3)<<endl;            }            FreeLibrary(hDll);      }return 0;}

    然后再来一个HiJack.Dll 这个里面我就直接默认调用BB.dll,BB.dll就是本身的B.dll,为了不重名真正用的时候会进行改名。(但是如果用的dll不在项目里的话就不用这样了,直接添加B.dll就行,因为dll的查找顺序是先找根目录,我们直接在根目录下放自己的就行了)。实现也是差不多,创建一个dll项目,然后有一个接口,不同的是接口的实现是我们直接载入BB.dll就行。

MyCode.h#pragma once#ifdef HIJACK_EXPORTS#define EXPORTS_DEMO _declspec(dllexport)#else#define EXPORTS_DEMO _declspec(dllimport)#endifextern "C" EXPORTS_DEMO int Add (int a , int b);MyCode.Cpp#include "stdafx.h"#include "MyCode.h"#include <iostream>#include <windows.h>using namespace std;typedef int (*AddFunc)(int a, int b);int Add ( int a , int b){      HMODULE hDll = LoadLibrary(L"BB.dll");      if (hDll != NULL)      {            AddFunc add = (AddFunc)GetProcAddress(hDll, "Add");            if (add != NULL)            {  cout<<"HiJack Success"<<endl;                  return add(2, 3);            }            FreeLibrary(hDll);      }}

    上面那个写完之后就可以直接把B.Dll改成BB.Dll,然后把HiJack.Dll改成B.Dll,放在一起,然后执行A.exe发现原来的B.dll被成功劫持。所有的东西都准备好了,我们来简单走一下流程加深理解。

1.首先我们分析下A.exe调用了那些DLL.

现用CFF Explorer 静态分析一次试试



额...结果只是分析出来几个系统的DLL,应该是因为我动态加载的原因或者别的吧,不过没事,

我们可以直接Procmon动态分析:


OK 动态抓到了它加载了B.dll


2.接下来就分析B.dll的导出函数:

CFF Explorer


找到导出函数Add,然后我们IDA分析一下B.dll


然后根据上下文分析,这个就看自己逆向能力和经验了,这个我经验不足,就不废话了,分析后确定结果是 int Add(int nA ,int nB)

2.根据分析结果实现HiJack

3.之后我们把A.exeB.dll(改名BB.dll),HiJack(改名B.dll)放在一起,运行A看效果

注入前执行结果


注入后执行结果:


    OK以上就是HiJack的基本实现,记住先找开源好弄的方式,比如那个zlib或者是导出少的dll等等,这都是简化流程,我上面说的是最最麻烦的那种情况才这么弄。然后我也看了下通常对手是如何防护HiJack的,他们的基本防护大体有两种,第一种是修改dll加载的顺序,就是直接就去系统目录加载,对方认为程序直接去修改系统目录下的dll成功率很低,而且如果装了杀软修改几乎就是不可能的,但是然并卵,因为他们实现这个功能的方式是修改注册表,...你改了,我在劫持前改回来不就得了,可爱的防护思路,还有一种比较绝的方式就是杀软的文件保护的那种方式,这个比较难破,目前不知道。而且告诉一个好消息,除了杀毒软件等特别的保护程序,很少有程序做到了dll保护和验证,因为保护涉及到的东西过于底层,代价比较大,验证的话对升级维护会造成很大麻烦。所以dll劫持目前依然可以横行装逼,让我想起了几乎给赶尽杀绝了的那个洪水DDOS攻击问题,MS已经封闭了伪造IP之后的那个sendto函数,之后会单独再好好说下这几天遇到的DDOS攻击思路和测试结果。

    再补上一张被劫持后的A.exe的动态分析图片(里面可以看到A.exe加载了B.dll,但是BB.dll也被调用,HiJack.dll成功劫持了B.dll




1 0
原创粉丝点击