哎呦呦 发表于 2015-8-3 22:35

菜鸟简单对程序添加DLL弹窗原理分析

文章可能会写的很差 请各位大牛不要笑!! 求大牛带我这个菜鸟装B带我飞

实验对象:NOTEPAD.EXE

<span style="background-color: white;"><font face="微软雅黑" size="3" color="#000000">DLL代码

</font></span><span style="background-color: white;"><font face="微软雅黑" size="3" color="#000000">#include "stdafx.h"
#include "windows.h"
void in ();
void out ();
void in ()
{
   MessageBox(0,"进程调用","进程调用",MB_OK);

}

void out ()
{
         MessageBox(0,"进程卸载","进程卸载",MB_OK);

}

extern "C" __declspec(dllexport)void fun()
{
         MessageBox(0,"","",MB_OK);

}


BOOL APIENTRY DllMain( HANDLE hModule,
                     DWORDul_reason_for_call,
                     LPVOID lpReserved
                                       )
{
      switch (ul_reason_for_call)
      {
      caseDLL_PROCESS_ATTACH: //进程调用

                in();
                break;
      case      DLL_PROCESS_DETACH://进程卸载

                out();
                break;
      case         DLL_THREAD_ATTACH://线程调用
                break;
      case         DLL_THREAD_DETACH://线程卸载
                break;
               
      }
    return TRUE;
}
</font></span>

编译好dll之后,使用lordPE添加导入表,方法,打开lordpe中的pe编辑器,选择文件,然后点击目录,点击输入表后面的“...”,在弹出的对话框中按右键,add import。在dll和api中填写dll的名字和导出的函数名。按加号添加后,保存即可。




通过上面的简单操作添加一个信息框就完成了,!
----------------------------------------------------------------------------------------------------

为什么这样操作后软件就会在打开我们的信息框呢这才是我们的重点!
关键点就在导入表(输入表)(_IMAGE_IMPORT_DESCRIPTOR)
<span style="background-color: white;"><font face="微软雅黑" size="3" color="#000000">typedef struct _IMAGE_IMPORT_DESCRIPTOR {

    union {

      DWORD   Characteristics;            

      DWORD   OriginalFirstThunk;      //INT表 RVA

    } DUMMYUNIONNAME;      

    DWORD   TimeDateStamp;   //时间戳(用来判断IAT)                                                   

    DWORD   ForwarderChain;               

    DWORD   Name;    //DLL名字      

    DWORD   FirstThunk;      //IAT表    RVA

} IMAGE_IMPORT_DESCRIPTOR;
</font></span>

程序可能会有多个_IMAGE_IMPORT_DESCRIPTOR这样的结构体


lordpe打开NOTEPAD.EXE打开看看导入表在文件中的样子




上面选中的二进制就是导入表通过上面的结构我们可以知道导入表的结构体的大小是20个字节 上面选中的二进制有200个字节 那我们就知道了程序有10个_IMAGE_IMPORT_DESCRIPTOR这样的结构体 最后以全0值结构结束


结构体里面有个   DWORD   Name;RVA//DLL名字   代表的要加载的DLL名字

程序有10这样的结构体代码程序要加载10个DLL 所以通过增加这样的这样的结构体 就能达到程序运行前就能加载我们的DLL 但原来的位置肯定是不够我们要添加结构的 所以我们要新建一个区段(或者找一段空闲区域) 移动导入表到新建的区段来实现增加结构体并且把原来输入表的RVA 改成 移动后RVA(大家用lordPE添加导入表 导入表位置变了的原因就在这里)
当然只是这样简单的移动导入并增加结构体还是不可以的 因为_IMAGE_IMPORT_DESCRIPTOR结构里面还有两个很重要的东西


DWORD   OriginalFirstThunk;      RVA ——》指向IAT表


DWORD   FirstThunk;   RVA ——》指向IAT表
增加完结构体后 我们还要在 新建的区段里增加两张表 分表是 IAT表和 IAT表 他们都指向一个表(_IMAGE_IMPORT_BY_NAME结构体)//只是在程序加载前程序加载后IAT并不指向这个表




他们的结构都是相同的 _IMAGE_THUNK_DATA32
<span style="background-color: white;"><font face="微软雅黑" size="3" color="#000000">typedef struct _IMAGE_THUNK_DATA32 {
    union {
      PBYTEForwarderString;
      PDWORD Function;
      DWORD Ordinal;
      PIMAGE_IMPORT_BY_NAMEAddressOfData;指向的是一个 <span style="line-height: 1.5; background-color: rgb(255, 255, 255);">_IMAGE_IMPORT_BY_NAME 的结构体</span></font></span>

_IMAGE_IMPORT_BY_NAME
<span style="background-color: white;"><font face="微软雅黑" size="3" color="#000000">typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD    Hint;//一般编译器都吧它设置为0 没什么用
    BYTE    Name;//存放的是函数名字的第一个字符
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;</font></span>

程序加载前这两张表保存的数据都是一样 除了系统提供的程序 因为系统的程序都绑定了导入表 IAT里面放的都是绝对地址(这里就不对绑定做过多的分析了)一般的程序都是不绑定的 所以一般的程序在程序没有加载前存放的值都是一样的

_IMAGE_THUNK_DATA32 这样的结构体也是可以有多个的 都是以0结束


_IMAGE_THUNK_DATA32 的结构体看的很复杂因为结构体里面又包含了一个_IMAGE_IMPORT_BY_NAME 这样的结构体其实吧它当成一个DWORD来看就可以了! 然后获取里面的值


对值进行判断 如果值的最高位(第32位是0)剩下的31就表示是一个RVA RVA指向的就是_IMAGE_IMPORT_BY_NAME这样的一个结构体


_IMAGE_IMPORT_BY_NAME结构体里面的BYTE Name就是函数的名字的第一个字符 所以BYTE Name就是函数名字的地址


通过上面的分析我们应该知道 不只是新建IAT表和INT表 就可以 还同时要新建一个_IMAGE_IMPORT_BY_NAME的结构 并把函数的名字的首地址放进BYTE Name里
并且同时把INT表的值改成指向_IMAGE_IMPORT_BY_NAME结构体的RVA 和 IAT表的值改成指向_IMAGE_IMPORT_BY_NAME结构体的RVA 都完成后 我们还要把 INT 和IAT 的
RVA都分别放在 我们新建的_IMAGE_IMPORT_DESCRIPTOR结构体里面这样我们添加一个导入表就基本完成了


因为系统在加载我们的DLL的时候会检查我们的DLL导出表里的INT IAT表是不是有函数名 如果没有那就表示这个DLL没有被加载的意义
这样就能解释我们为什么在用lordpe中dd import为什么要填写一个导出的函数名 和为什么我们在编写DLL的时候要导出一个函数!!!!!


文章写的很乱全当复习了!! 如果有什么错误和不足之处,还请各位批评指出! BY:2015/8/3





Mxhacks 发表于 2015-8-3 22:43

某早就发了!复制也还弄个原创

哎呦呦 发表于 2015-8-3 22:47

Mxhacks 发表于 2015-8-3 22:43
某早就发了!复制也还弄个原创

人家发的是添加的方法 我说的是为什么要这样 能一样吗 有本事去你复制一个給我看看

FraMeQ 发表于 2015-8-3 22:56

我只能和楼主说,我也在看滴水的课程{:5_121:}

xdr 发表于 2015-8-4 06:52

看不懂,我太菜了

x5龙龙 发表于 2015-8-4 15:35

有的DLL防止调用有没有办法搞定?

哎呦呦 发表于 2015-8-4 23:25

x5龙龙 发表于 2015-8-4 15:35
有的DLL防止调用有没有办法搞定?

不是很明白你的意思 是不是对DLL检查啊如果是对DLL检查 可以变通嘛 看程序本身有什么DLL 把DLL加到程序原有的DLL里面去

诺安 发表于 2015-10-5 18:38

看起来很厉害的样子,因为我是新手

pooh 发表于 2019-4-28 20:59

看不懂新手入過 ...

别管我了行 发表于 2022-3-22 03:37

页: [1] 2
查看完整版本: 菜鸟简单对程序添加DLL弹窗原理分析