Dll 模块隐藏技术

合集下载

模块隐藏三种方法

模块隐藏三种方法

摘要(转自网络):一、从PEB的Ldr链中消失引用内容lkd> dt _PEB 7ffdc000 //当前PEB的地址nt!_PEB...+0x00c Ldr : 0x001a1e90_PEB_LDR_DATA //这里指向Ldr结构lkd> dt _PEB_LDR_DATA 0x001a1e90 //这个结构里有三个链表的表头nt!_PEB_LDR_DATA+0x000 Length : 0x28+0x004 Initialized : 0x1 ''+0x008 SsHandle : (null)+0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x1a1ec0 - 0x1a34f8 ]+0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x1a1ec8 -0x1a3500 ]+0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x1a1f28 - 0x1a3508 ]+0x024 EntryInProgress : (null)这里看到有三个链表,其实三个链表的内容是一样的,但是链表的顺序不一样,分别按加载顺序、内存顺序、初始化顺序排列。

每一个DLL由一个LDR_DATA_TABLE_ENTRY结构描述,但是第一个结构被链入了三个链表。

取一个来看看:引用内容lkd> dt _LDR_DATA_TABLE_ENTRY 0x1a34f8nt!_LDR_DATA_TABLE_ENTRY+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x1a1e9c - 0x1a3450 ]+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x1a1ea4 - 0x1a3458 ]+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x1a1eac -0x1a3460 ]+0x018 DllBase : 0x20000000+0x01c EntryPoint : (null)+0x020 SizeOfImage : 0x549000+0x024 FullDllName : _UNICODE_STRING"C:\WINDOWS\system32\xpsp2res.dll"+0x02c BaseDllName : _UNICODE_STRING"xpsp2res.dll"......//省略部分内容随便取一个链表进行遍历,根据DllBase找到自己的DLL之后,从三个链中RemoveEntryList就可以了,这样所有使用PEB->Ldr结构来枚举DLL链表的就无法找到了。

自定义DLL入口点dllmain()的第2个参数数值传递从而达到隐藏导出接口

自定义DLL入口点dllmain()的第2个参数数值传递从而达到隐藏导出接口
return 0 ;
// 定位 PE 的 NT 头并校验 pstruct_pImageNTHeaders (PIMAGE_NT_HEADERS)((PBYTE)pstruct_ImageDOSHeaders pstruct_ImageDOSHeaders->e_lfanew); if (pstruct_pImageNTHeaders->Signature != IMAGE_NT_SIGNATURE)
// 开始发送扩展定义 DllMain(handle_Dll, 100, &dword_Error ); DllMain(handle_Dห้องสมุดไป่ตู้l, 101, &dword_Error ); DllMain(handle_Dll, 101, &dword_Error );
return 0; }
[结束]
希望这个编程技巧对大家有用,感谢大家对这个技巧的支持
// 加载目标 DLL HINSTANCE handle_Dll = ::LoadLibrary("Test_Dll.dll") ; if (handle_Dll == NULL) {
return 0 ; } // 校验 PE 头是否合法 pstruct_ImageDOSHeaders = (PIMAGE_DOS_HEADER)handle_Dll; if (pstruct_ImageDOSHeaders->e_magic != IMAGE_DOS_SIGNATURE)
[技术作用]
我们知道 dll 的主要作用是提供接口别人使用,按照正规的方式需要把函数名导出出来,但这 对于有安全瘾的人来说,但有时我们需要更加安全不想把函数名导出.下面我提供一个技术.

进程中dll模块的隐藏

进程中dll模块的隐藏

进程中dll模块的隐藏为了避免自己的某个dll模块被别人检测出来,有时候希望在自己加载一个dll之后,或者将dll注入到他人进程之后避免被检查出来。

这就需要想办法抹掉这个dll的模块信息,使得Toolhelp、psapi等枚举模块的API无法枚举它。

我们可以先简单看看Windows枚举进程内模块的办法吧:首先是BOOL EnumProcessModules( HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);EnumProcessModules实际调用EnumProcessModulesInternal进行枚举。

下面是vista下psapi的代码片断:.text:514024B8 push ebx.text:514024B9 push 18h.text:514024BB lea eax, [ebp+stProcessBasicInfo].text:514024BE push eax.text:514024BF push ebx ;ebx=0.text:514024C0 push [ebp+hProcess].text:514024C3 call ds:__imp__NtQueryInformationProcess@20 ; NtQueryInformationProcess(x,x,x,x,x).text:514024C9 cmp eax, ebx.text:514024CB jge short loc_514024E0调用NtQueryInformationProcess获得ProcessBasicInformation,在PROCESS_BASIC_INFORMATION结构中取得PEB地址。

然后读取指定进程PEB中的数据text:514024E0 loc_514024E0: ; CODE XREF:EnumProcessModulesInternal(x,x,x,x,x)+24j.text:514024E0 mov eax, [ebp+stProcessBasicInfo.PebBaseAddress].text:514024E3 cmp eax, ebx.text:514024E5 jnz short loc_514024EE.text:514024E7 push 8000000Dh.text:514024EC jmp short loc_514024CE.text:514024EE ; —————————————————————————.text:514024EE.text:514024EE loc_514024EE: ; CODE XREF:EnumProcessModulesInternal(x,x,x,x,x)+3Ej.text:514024EE push ebx ; lpNumberOfBytesRead.text:514024EF push 4 ; nSize.text:514024F1 lea ecx, [ebp+Ldr].text:514024F4 push ecx ; lpBuffer.text:514024F5 add eax, 0Ch.text:514024F8 push eax ; lpBaseAddress.text:514024F9 push [ebp+hProcess] ; hProcess.text:514024FC mov edi, ds:__imp__ReadProcessMemory@20 ; ReadProcessMemory(x,x,x,x,x).text:51402502 call edi ; ReadProcessMemory(x,x,x,x,x) ; ReadProcessMemory(x,x,x,x,x)这里读取的是PEB地址+0C处的四个字节。

利用函数MoveFileEx和DLL远程线程注入技术相结合实现程序隐藏、自启动与自删除

利用函数MoveFileEx和DLL远程线程注入技术相结合实现程序隐藏、自启动与自删除

利用函数MoveFileEx和DLL远程线程注入技术相结合实现
程序隐藏、自启动与自删除
吴林;刘晔;宋燕
【期刊名称】《电脑知识与技术》
【年(卷),期】2010(006)032
【摘要】文章介绍了一种能有效地实现程序隐藏、自启动与自删除的方法.实践证明,该方法不仅简便易行、可靠性高,而且程序隐藏运行的效果更佳.
【总页数】3页(P9132-9134)
【作者】吴林;刘晔;宋燕
【作者单位】重庆通信学院机动作战通信系,重庆,400035;重庆通信学院基础部,重庆,400035;重庆通信学院基础部,重庆,400035
【正文语种】中文
【中图分类】TP311
【相关文献】
1.远程线程注入DLL的检测与卸载方法研究 [J], 王佩红;赵尔敦;张瑜
2.基于远程线程注入的进程隐藏技术研究 [J], 何志;范明钰;罗彬杰
3.基于远程线程注入的进程隐藏技术研究 [J], 何志;范明钰;罗彬杰
平台下利用C#语言实现远程线程注入问题的研究 [J], 刘妍
5.远程线程注入技术的实现 [J], 李元良;黄强
因版权原因,仅展示原文概要,查看原文内容请购买。

在Delphi中隐藏程序进程的方法

在Delphi中隐藏程序进程的方法

在Delphi中隐藏程序进程方法[1]主要需要解决两个问题,即隐藏窗口和设定热键。

一. 隐藏窗口通过API函数GETACTIVEWINDOW获取当前窗口;函数ShowWindow(HWND,nCmdShow)的参数nCmdShow取SW_HIDE时将之隐藏,取SW_SHOW时将之显示。

例如:showwindow(getactivewindow,sw_hide)。

隐藏好窗体后,须记住窗体句柄以便恢复。

二. 键盘监控为了实现键盘监控须用到钩子。

以下是程序的源文件:一、创建一个动态链接库unit HKHide; //链接库中的Unit文件interfaceusesWindows, Messages, sysutils;varhNextHookHide: HHook;HideSaveExit: Pointer;hbefore:longint;function KeyboardHookHandler(iCode: Integer;wParam: WPARAM;lParam: LPARAM): LRESULT; stdcall; export;function EnableHideHook: BOOL; export;function DisableHideHook: BOOL; export;procedure HideHookExit; far;implementationfunction KeyboardHookHandler(iCode: Integer;wParam: WPARAM;lParam: LPARAM): LRESULT; stdcall; export;const _KeyPressMask = $80000000;varf:textfile;temp:string;beginResult := 0;If iCode < 0 ThenbeginResult := CallNextHookEx(hNextHookHide, iCode, wParam, lParam); Exit;end;//侦测 Ctrl + Alt + F12 组合键if ((lParam and _KeyPressMask) = 0) //按下时生效and (GetKeyState(vk_Control) < 0)and (getkeystate(vk_menu)<0)and (wParam = vk_F12) thenbeginResult := 1;//文件不存在则创建if not fileexists('c:\test.txt') thenbeginassignfile(f,'c:\test.txt');rewrite(f);writeln(f,0);closefile(f);endelsebeginassignfile(f,'c:\test.txt');reset(f);readln(f,temp);hbefore:=strtoint(temp);beginhbefore:=getactivewindow;temp:=inttostr(hbefore);rewrite(f);writeln(f,temp);closefile(f);ShowWindow(hbefore, SW_HIDE);end;end; //end if FileExists(....)endelse beginshowwindow(hbefore,SW_SHOW);rewrite(f);writeln(f,0);closefile(f);end;//end if Ctrl+Alt+F12按键end;function EnableHideHook: BOOL; export;beginResult := False;if hNextHookHide <> 0 then Exit;// 挂上 WH_KEYBOARD 这型的 HOOK, 同时, 传回值必须保留下 // 来, 免得 HOOK 呼叫链结断掉hNextHookHide := SetWindowsHookEx(WH_KEYBOARD,KeyboardHookHandler,HInstance,0);Result := hNextHookHide <> 0;end;function DisableHideHook: BOOL; export;beginif hNextHookHide <> 0 thenbeginResult:=True;UnhookWindowshookEx(hNextHookHide); // 解除 Keyboard Hook hNextHookHide:=0;endelseResult:=False;end;procedure HideHookExit;begin// 如果忘了解除 HOOK, 自动代理解除的动作if hNextHookHide <> 0 then DisableHideHook;ExitProc := HideSaveExit;end;end.library HKPHide; //动态链接库工程文件usesHKHide in HKHide.pas;exportsEnableHideHook,DisableHideHook;beginhNextHookHide := 0;hbefore:=0;HideSaveExit := ExitProc;ExitProc := @HideHookExit;end.//文件制作好后先Build All编译成HKPHide.dll。

编译彻底隐藏函数的方法

编译彻底隐藏函数的方法

编译彻底隐藏函数的方法编译器是将高级语言代码转换为机器代码的程序。

在编译过程中,编译器会解析代码并生成中间代码,然后通过优化和转换,最终生成目标机器的可执行代码。

隐藏函数是一种保护代码安全性和防止代码泄漏的常用方法。

本文将介绍一些彻底隐藏函数的方法。

1.代码混淆代码混淆是通过将代码进行转换和重组,使得代码逻辑变得难以理解和分析。

这种方法可以有效地隐藏函数的实现细节。

一种常见的代码混淆技术是控制流平坦化,即将函数的控制流转变为一个平面结构,使得函数中的每个基本块都成为一个独立的代码路径。

这样可以使得函数的逻辑变得混乱,增加代码分析的难度。

2.加密和解密加密和解密是将函数的代码进行加密,并在代码执行时进行解密。

这样可以有效地隐藏函数的实现和逻辑。

在编译过程中,可以使用加密算法对函数进行加密,并将加密后的代码存储在可执行文件中。

在函数被调用时,通过解密算法对代码进行解密并执行。

这样可以防止代码被逆向工程师直接分析和理解。

3.动态链接库(DLL)加载将函数代码编译成动态链接库(DLL)可以有效地隐藏函数的实现和逻辑。

DLL是一种可被多个程序共享的文件,其中包含了函数的实现代码。

在编译过程中,可以将需要隐藏的函数编译成DLL,并将其与可执行文件分离。

在程序运行时,通过动态链接库加载机制,将DLL加载到内存中,并调用其中的函数。

这样可以有效地隐藏函数的实现和逻辑,防止代码泄漏。

4.反调试和反解析技术反调试和反解析技术是一种在程序执行过程中检测和抵御调试和解析行为的方法。

这种方法可以防止逆向工程师通过调试和解析代码来获取函数的实现和逻辑。

一种常见的反调试技术是检测调试器的存在,并在检测到调试器时改变程序的行为,使得调试器无法正常工作。

另一种常见的反解析技术是对代码进行运行时动态修改,使得解析工具无法正确解析代码。

5.代码自删除代码自删除是一种在代码执行后将自身删除的技术。

这种方法可以有效地隐藏函数的实现和逻辑,防止代码被分析和理解。

基于DLL的进程隐藏技术研究

基于DLL的进程隐藏技术研究


引言

立 的 线 程 ) 享 地 址 空 间 以及 其 他 资 源 。 过 C etR moehed也 同 共 通 rae e tT ra 样 可 以在 另 一 个 进 程 内创 建 新 线 程 . 创 建 的远 程 线 程 同 样 可 以共 享 被 在 操 作 系 统 中 , 程 是 程 序 运 行 的 实 例 . 个 进 程 都 有 自身 的 进 远 程 进 程 的地 址 空 间 , 以 , 建 一 个 远 程 线 程 , 入 远 程 进 程 的 内存 进 每 所 创 进 程 环, 可记 为 E RO E S 而 每 个 进 程 都 拥 有 各 自线 程 , 程 的执 行 和 地 址 空 间 , 拥 有 了 该 远 程 进 程 的 权 限 , 以 在 监 视 模 块 被 恶 意 终 止 P C S。 进 就 可 调 度是 以 线 程 为 基 础 的 。 每个 线 程 也 有 各 自的 线 程 环 K E 可 记 为 时 及 时重 新 启 动 。 且 T B,
的 成员 :
T p d fsr c y e e tu tEPROC Sf ES
模 块 插 入 到 epoe. e中 , 以 较 好 得 隐藏 、 护 模 块 本 身 。 其 实 现 xlrr x e 可 保 步骤为 : ① 通 过 O e Poes函数 打开 试 图嵌 入 的 进 程 ,因 为 需 要 写 入 远 pn r s c 程 进 程 的 内 存 地 址 空 间 . 以必 须 申请 足 够 的 权 限 , 括 远 程 创 建 线 所 包

K R C S c; 术在 结 构 中 的偏 移 量 为 0 0 0 * P O E S P t, x0 0 /
D WOR nq ePo esI; D U iu rcs / 表 了 进 程 的 i* d *代 d/

dll封装了还能破解吗

dll封装了还能破解吗

dll封装了还能破解吗在软件开发中,动态链接库(Dynamic Link Library,简称DLL)是一个非常重要的组成部分,它可以包含可被多个程序共享的代码和数据。

封装DLL的目的是隐藏其实现细节,提高代码的重用性和安全性。

但是,人们常常会问:dll封装了还能破解吗?DLL的封装和加密DLL的封装指的是将DLL文件中的函数和数据进行封装,隐藏其内部实现细节。

通过封装,开发者可以提供一个更高层次的接口,使得其他开发者在使用该DLL时不需要关心具体的实现,只需要调用封装后的接口即可实现相应功能。

为了进一步保护DLL,有些开发者会选择对其进行加密。

加密是指通过某种加密算法对DLL进行转换,使得其在未解密之前无法被使用。

这种加密措施可以有效防止恶意用户对DLL进行破解和篡改。

DLL的破解尽管DLL的封装和加密可以增加破解的难度,但并不能完全防止DLL被破解。

正如世界上没有绝对安全的系统一样,只要存在参与者,就有被攻击的可能。

对于坚持破解的黑客来说,破解一款封装和加密的DLL并非不可能。

最常见的DLL破解方式是通过反汇编工具对其进行分析和逆向工程。

黑客可以通过解析DLL的机器码和汇编代码,理解其内部结构和实现方式。

随后,黑客可以对其中的关键函数进行篡改,甚至是完全替换。

这种破解方式需要黑客具备较强的逆向工程技术。

防范DLL破解的措施虽然不能100%防止DLL被破解,但可以采取一些措施增加破解的难度,提高软件的安全性。

1. 加固DLL的加密算法对于DLL的加密算法来说,黑客需要花费大量时间和精力才能解密。

因此,选择高强度的加密算法,并定期升级加密算法可以提高破解的门槛。

2. 定期更新封装DLLDLL的封装通常是一个迭代的过程,随着软件的发展和需求的变化,需要不断改进和更新封装。

通过定期更新封装DLL,可以修复一些可能存在的漏洞,增强封装的安全性。

3. 发布DLL的散列值散列值(hash value)是对DLL文件内容的唯一标识,黑客无法伪造散列值。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Dll模块隐藏技术学习各种外挂制作技术,马上去百度搜索"魔鬼作坊"点击第一个站进入、快速成为做挂达人。

如果你细细读完这篇文章,你会学到一下内容:1.PEB,TEB,LDR_DATA_TABLE_ENTRY等数据结构2.自己覆盖掉自己执行过的一段代码3.调试这个Dll你会发现DLL_PROCESS_ATTACH中的代码在OD首次停下即加载停止时已经执行完了!多么美妙啊!哈哈,OD不会发现你执行了什么4.本例最后附件有个ASM的控制台程序,用SDK编写,你可以学到用汇编写一个基本的控制台程序的格式5.最后那个控制台源码还包含完整的CreateRemoteThread注入进程的写法本文主要讲的是怎样隐藏一个dll模块,这里说的隐藏是指,dll被加载后怎样使它用一般的工具无法检测出来。

为什么要这么做呢?1.远程线程中的应用(1)大家都知道,远程线程注入主要有两种一种是直接copy母体中预注入的代码到目标进程地址空间(WriteProcessMemory),然后启动注入的代码(CreateRemoteThread),这种远程线程一旦成功实现,那么它只出现在目标进程的内存中,并没有对应的磁盘文件,堪称进程隐藏中的高招,可是缺点就是,你必须要在注入代码中对所有直接寻址的指令进行修正,这可是个力气活,用汇编写起来很烦。

(2)另一种更为常用的方法是注入一个dll文件到目标进程,这种方法的实现可以是以一个消息Hook为由进行注入,或者仍然使用CreateRemoteThread,这种方法的优点是Dll文件自带重定位表,也就是说你不必再为修正直接寻址指令而烦恼了!,dll自己会重定位!~~~嗯,真是不错的方法---可是我们说它不如上面说的方法牛。

为什么?因为它的致命伤就是可以用进程管理工具看见被加载的dll文件名、文件路径。

这真是太不爽了,因为只要用户看看模块列表很容易发现可疑模块!,再依据名字,找到路径,定位文件---dll文件就这样暴露了.这样也就不是很完美的隐藏进程。

[现在不用怕啦~~本文将介绍的方法就是为了上述不足而存在地~~~,让一般的工具看不到已加载的某个dll]2.自身文件的需要这个说起来比较简单,比如我的一个程序运行了,我不想让用户知道我的EXE使用了某个dll,那么同样的也需要这种隐身技术.3.技术实现(1).说完了这么多,该说说,到底应该怎么实现了.熟悉SEH的肯定对PEB这个结构并不陌生--PEB(Process Environment Block)进程环境信息块,这里储存着进程的重要信息主要原理就是这个结构,和它的成员相关结构首先我们回顾一下如何找到这个结构,常见的代码是这个:mov eax,fs:[30h];就这一句足矣,执行后eax-->PEB(eax指向PEB结构,即eax中是PEB结构在进程空间中的地址)熟悉TEB和SEH中反调试知识的童鞋一定对上面这个很熟悉了~~不多说了--(不懂得童鞋去学习一下SEH的相关知识你就会认清fs了)下面看一下PEB结构的定义:;=================================================================PEB STRUCT;sizeof=1E8hInheritedAddressSpace BYTE?;0000hReadImageFileExecOptions BYTE?;0001hBeingDebugged BYTE?;0002hSpareBool BYTE?;0003hMutant PVOID?;0004hImageBaseAddress PVOID?;0008hLdr PVOID?;000Ch PTR PEB_LDR_DATAProcessParameters PVOID?;0010h PTR RTL_USER_PROCESS_PARAMETERS SubSystemData PVOID?;0014h~~~~~~~~~~~~~~~~~~~~~~~;PEB结构以下部分省略PEB ENDS;==================================================================由于PEB结构太庞大了,因此本文指截取了开头的一部分,因为我们主要使用的是它的Ldr 成员,看见了吗?对!,就是它在结构偏移0Ch处后面已经指出了Ldr成员是一个指向PEB_LDR_DATA结构的指针,下面我们就得看看这个结构了:;================================================================== PEB_LDR_DATA STRUCT;sizeof=24h_Length DWORD?;original name LengthInitialized BYTE?;04hdb3dup(?);paddingSsHandle PVOID?;08hInLoadOrderModuleList LIST_ENTRY<>;0ChInMemoryOrderModuleList LIST_ENTRY<>;14hInInitializationOrderModuleList LIST_ENTRY<>;1ChPEB_LDR_DATA ENDS;==================================================================啊哈~~~这里我们看到了想要的东西,Module这个单词被我们发现了,ModuleList就是模块列表嘛~~~InLoadOrderModuleList就是按照模块加载顺序描述模块信息的,InMemoryOrderModuleList 是按照内存中存储顺序描述,InInitializationOrderModuleList是按照初始化dll模块的顺序描述的(你可以利用它们之一获得kernel32.dll的基址这是许多无导入表程序的必做之事)为了弄清Module信息究竟是怎么储存的,我们又必须知道LIST_ENTRY结构的定义一个LIST_ENTRY结构描述了一个双链表;======================================LIST_ENTRY STRUCTFlink pLIST_ENTRYBlink pLIST_ENTRYLIST_ENTRY ENDSpLIST_ENTRY typedef PTR LIST_ENTRY;pLIST_ENTRY表示指向LIST_ENTRY结构的指针;=====================================50692根据图片我们可以看出LIST_ENTRY的用法,它嵌入在一个结构类型内,Flink指向下一个这种结构类型内的LIST_ENTRY这样由表头,就可以找到所有的data struct结构了!啊哈~~MSDN又说InMemoryOrderModuleList指向一个LDR_DATA_TABLE_ENTRY结构,也就是说,我们的图片的data struct1,2,3就是指LDR_DATA_TABLE_ENTRY结构,再看看它的定义:(虽然结构有点绕,别晕啊~~快胜利了);===========================================================LDR_DATA_TABLE_ENTRY STRUCTInLoadOrderLinks LIST_ENTRY;0hInMemoryOrderLinks;LIST_ENTRY;8hInInitializationOrderLinks;LIST_ENTRY;10hDllBase;dword;18h;DllBase模块基址EntryPoint;dword;1Ch;模块入口点SizeOfImage;dword;20h;模块的内存映像大小FullDllName;UNICODE_STRING;24hBaseDllName;UNICODE_STRING;2ChFlags;dword;34h~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;LDR_DATA_TABLE_ENTRY结构以下部分省略LDR_DATA_TABLE_ENTRY ENDS;===========================================================怎么样?看成员名字就知道~~~~,模块信息就在此处!可以肯定一个LDR_DATA_TABLE_ENTRY描述一个模块的信息,依靠LIST_ENTRY与下一个或前一个LDR_DATA_TABLE_ENTRY想连.它的前三个成员都是LIST_ENTRY类型!,再看看上面图片,你应该明白了吧,PEB_LDR_DATA中的三个LIST_ENTRY的后继依次就是这三个这里我们主要使用InLoadOrderModuleList这个成员来遍历模块,原因是InLoadOrderModuleList对应的嵌入在LDR_DATA_TABLE_ENTRY结构中的InLoadOrderLinks位于结构首部,用它寻址会方便、清楚一些(当然你用其它两个,InMemoryOrderModuleList和InInitializationOrderModuleList也可以啊)看这个汇编代码,我们要定位于首个LDR_DATA_TABLE_ENTRY:mov eax,fs:[30h];eax-->PEBmov eax,[eax+0Ch];eax==PEB.Ldr-->PEB_LDR_DATAmov eax,[eax+0Ch];eax==PEB_LDR_DATA.InLoadOrderModuleList.Flink--> LDR_DATA_TABLE_ENTRYOK,执行后eax中就是第一个LDR_DATA_TABLE_ENTRY结构的地址啦!!!3个mov指令,但是用到了好多结构啊~~~对于我们的遍历方式,第一个LDR_DATA_TABLE_ENTRY描述的应该是dll所属的EXE 的信息,包括入口点,基址,文件名什么的~~~到这里我们还差一小步那就是UNICODE_STRING结构;============================================================= UNICODE_STRING STRUCT;sizeof==08hLength word;0hMaximumLength word;02hBuffer dword;04hUNICODE_STRING STRUCT ENDS;=============================================================Length指明由Buffer字段指向的UNICODE串的长度,不包括结尾的0000比如"C:\A"这个UNICODE串那么Length就是4*2==8Buffer指向Unicode字串的指针!太好了终于大功告成,解决复杂的结构了--现在假设我们要获得某个模块的全路径:mov eax,fs:[30h];eax-->PEBmov eax,[eax+0Ch];eax==PEB.Ldr-->PEB_LDR_DATAmov eax,[eax+0Ch];eax==PEB_LDR_DATA.InLoadOrderModuleList.Flink-->LDR_DATA_TABLE_ENTRYmov eax,[eax+24h+4h];eax==LDR_DATA_TABLE_ENTRY.FullDllName.Buffer-->模块路径unicode串执行过后,eax中存储的就是我们遍历的首个模块的模块全路径字串的地址也就是模块字串名称的指针.要访问下一个LDR_DATA_TABLE_ENTRY,在上几句代码的基础上只需这样:mov eax,[eax];因为eax本身就是指向LIST_ENTRY结构地~~~,这样mov指令使得;当前LIST_ENTRY的Flink传送到eax,eax自然就指向下一个LDR_DATA_TABLE_ENTRY 结构了~~~(2).好了说说我们的dll隐身技术,我们就是要将这里的LDR_DATA_TABLE_ENTRY.FullDllName指向的字符串清除!因为快照函数或其它的函数,一般都会在底层访问这个结构,在这里查询模块的信息,我们把它给清除了,看它还能查到了吗?下面我们假设我们已经使用CreateRemoteThread创建一个远程线程,远程线程入口就是LoadLibraryA函数,传入参数就是我们的欲注入的dll文件名,现在我们看看这个dll文件的核心代码,看它如何清除自己的FullDllName串实现隐藏:;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::DllEntry proc_hInstance,_dwReason,_dwReservedpushadmov eax,_dwReason.if eax==DLL_PROCESS_ATTACH;Dll初始化时执行!push_hInstancepop hInstDll;hInstDll保存本dll加载基址;------------------------------------------;定位eax指向首个LDR_DATA_TABLE_ENTRY结构;------------------------------------------assume fs:nothingmov eax,fs:[30h];eax-->PEBmov eax,[eax+0Ch];eax==Ldr-->PEB_LDR_DATAmov eax,[eax+0Ch];LoadOrderList.Flink-->LDR_DATA_TABLE_ENTRY;-----------------------------------------------------------;通过循环遍历LDR_DATA_TABLE_ENTRY结构,比较DllBase与hInstDll;找到描述本dll模块的LDR_DATA_TABLE_ENTRY结构;-----------------------------------------------------------@@:mov ebx,[eax+18h];[eax+18h]为当前处理的模块的基址cmp ebx,hInstDll;找到本模块的LDR_DATA_TABLE_ENTRYjne_Nomov ebx,[eax+24h+4]movzx ecx,word ptr[eax+24h];Unicode String length获得子串长度mov edi,ebx;Unicode String Addresscldrep stosb;用Al的值填充mov dword ptr[ebx],0;(确保String首4个byte为0)jmp@F_No:mov eax,[eax];链表遍历jmp@B@@:.elseif---------;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::在Dll初始化时,响应DLL_PROCESS_ATTACH,在这其中清除我们的“自己的名字”,来个神不知鬼不觉!,哈哈~~这同时也说明,初始化时,Windows已经把各结构都填写好了.做到这里我们已经能实现这样的功能,即一般的进程查看工具看不到我们注入的dll了!因为我们把它要查的信息清除了!说到这可能有大牛说,我暴力搜索内存,匹配MZ--PE,看你往哪跑?的却我是跑不了~~如果你这样做的话,首先你得知道我注入的是哪个进程,其次,你得有耐心暴力搜索,然后---真的被您搜到了---此时我的dll的代码便可以被人家随便分析啦~~一看哈哈,原来就是清除了某某结构的内容啊---哼!我在你的导出表里找到你的dll名字!,然后找到你的磁盘文件,那你就任我鱼肉吧!哈哈哈哈~~~~~好可怕啊~~~,是啊,用OD看看,然后静态反汇编一下,我们的代码就露馅了--唉--等等!!要不然我们来个Self Modify将dll中的这段代码也给它清除掉,对!还有EXPORT的那个dll名,一起除掉,给它来个毁尸灭迹O(∩_∩)O哈哈~说干就干,看下面代码: ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::DllEntry proc_hInstance,_dwReason,_dwReservedpushadmov eax,_dwReason.if eax==DLL_PROCESS_ATTACHpush_hInstancepop hInstDll_BEGIN:call@F@@:pop eax;eax返回@@标号处的线性地址sub eax,5;执行后eax等于_BEGIN处的线性地址push eaxmov ebx,offset_END-offset_BEGINinvoke VirtualProtect,eax,ebx,PAGE_EXECUTE_READWRITE,addr flOldProtect;flOldProtect 万万不可少;------------------------------------------;清除PEB结构中,(UNICODE STRING)FullDllName;------------------------------------------assume fs:nothingmov eax,fs:[30h];eax-->PEBmov eax,[eax+0Ch];eax==Ldr-->PEB_LDR_DATAmov eax,[eax+0Ch];LoadOrderList.Flink-->LDR_DATA_TABLE_ENTRY@@:mov ebx,[eax+18h]cmp ebx,hInstDll;找到本模块的LDR_DATA_TABLE_ENTRYjne_Nomov ebx,[eax+24h+4]movzx ecx,word ptr[eax+24h];Unicode String lengthmov edi,ebx;Unicode String Addresscldrep stosbmov dword ptr[ebx],0;(确保String首4个byte为0)jmp@F_No:mov eax,[eax]jmp@B@@:;---------------------------------;清除Dll映像中导出表中的Dll文件名;---------------------------------mov esi,hInstDlladd esi,[esi+03Ch]assume esi:ptr IMAGE_NT_HEADERSmov edi,[esi].OptionalHeader.DataDirectory[0].VirtualAddress add edi,hInstDllassume edi:ptr IMAGE_EXPORT_DIRECTORYmov edi,[edi].nNameadd edi,hInstDll;edi-->DllName(Export)mov[esp-4*4],edixor eax,eaxmov ecx,-1cldrepnz scasb;[edi]!=0-->>continuesub edi,[esp-4*4];edi==length+1mov[esp-4*3],edimov dword ptr[esp-4*2],PAGE_EXECUTE_READWRITE lea eax,flOldProtectmov[esp-4*1],eaxsub esp,4*4call VirtualProtect;调用VirtualProtect更改页属性xor eax,eaxxchg ecx,edi;edi==length+1xchg edi,[esp-4*4];[esp-4*4]-->DllNamecldrep stosb;-------------------------------------;将_BEGIN与_END之间内容填充为int3;-------------------------------------pop edimov eax,0CChmov ecx,offset_END-offset_BEGINcldrep stosb_END:;--------------------------------------------;创建自定义线程,you can do anything you want;--------------------------------------------invoke CreateThread,0,0,addr_ThreadProc,0,0,0.elseif eax==DLL_PROCESS_DETACHNOP.endifpopadmov eax,TRUEretDllEntry Endp ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::这最后一部分就是Dll的完全的核心代码啦~~~调用VirtualProtectl两次,第一次用于更改_BEGIN与_END标号处的属性,以便毁尸灭迹填充int3.第二次用于更改导出表dll文件名的地方的属性,以便将其清零.最后程序可以创建个自定义线程,在这个线程里you can do anything you like;/////////////////////////////////////////////////////////////////////////////////////////////至此,我们的工程完成啦~~~,即使搜索内存字符串也是搜不到的--因为所有的相关串都被我们毁了##我测试环境是Win7,ProcessExplorer和360自带的进程管理器都查不出来已加载的Dll模块.####冰刃的话说是不支持win7因此未测试,不知结果不敢妄言##好了说说我们的附件:你可以看到本文使用的是MASM32的语法附件中有完整的dll文件的源代码,还有编译好的dll文件。

相关文档
最新文档