Dll 模块隐藏技术
- 格式:pdf
- 大小:148.85 KB
- 文档页数:9
摘要(转自网络):一、从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模块的隐藏为了避免自己的某个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远程线程注入技术相结合实现
程序隐藏、自启动与自删除
吴林;刘晔;宋燕
【期刊名称】《电脑知识与技术》
【年(卷),期】2010(006)032
【摘要】文章介绍了一种能有效地实现程序隐藏、自启动与自删除的方法.实践证明,该方法不仅简便易行、可靠性高,而且程序隐藏运行的效果更佳.
【总页数】3页(P9132-9134)
【作者】吴林;刘晔;宋燕
【作者单位】重庆通信学院机动作战通信系,重庆,400035;重庆通信学院基础部,重庆,400035;重庆通信学院基础部,重庆,400035
【正文语种】中文
【中图分类】TP311
【相关文献】
1.远程线程注入DLL的检测与卸载方法研究 [J], 王佩红;赵尔敦;张瑜
2.基于远程线程注入的进程隐藏技术研究 [J], 何志;范明钰;罗彬杰
3.基于远程线程注入的进程隐藏技术研究 [J], 何志;范明钰;罗彬杰
平台下利用C#语言实现远程线程注入问题的研究 [J], 刘妍
5.远程线程注入技术的实现 [J], 李元良;黄强
因版权原因,仅展示原文概要,查看原文内容请购买。
在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封装了还能破解吗在软件开发中,动态链接库(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引言特洛伊木马(简称木马)是指一类伪装成合法程序或隐藏在合法程序中的恶意代码,这些代码或者执行恶意行为,或者为非授权访问系统的特权功能而提供后门。
木马的首要特征是它的隐蔽性,为了提高自身的生存能力,木马会采用各种手段来伪装隐藏以使被感染的系统表现正常。
FredCohen等人[1,2]对病毒进行了深入研究,他们将木马作为病毒的一种特例,并给出了病毒和木马的数学模型,但未对木马的隐藏特征进行分析。
HaroldThimbleby等人[3]对病毒和木马模型框架进行了研究,给出了木马的形式化模型,对木马隐藏的特征进行了描述,但未对木马协同隐藏进行描述和分析。
张新宇等人[4]仅对Linux环境下的木马隐藏(包括协同隐藏)进行了研究,但未涉及Windows环境。
笔者在对木马隐藏技术归纳研究的基础上,深入分析研究了协同隐藏,并针对现有木马对抗实时检测的缺陷和通信隐藏能力的不足,提出两种基于该思想的新型木马结构,深化了协同隐藏思想,提高了木马的隐藏能力和生存能力。
2隐藏技术木马程序与普通远程管理程序的一个显著区别是它的隐藏性。
木马被植入后,通常利用各种手段来隐藏痕迹,以避免被发现和追踪,尽可能延长生存期。
隐藏技术是木马的关键技术之一,笔者从本地隐藏、通信隐藏和协同隐藏3个方面对木马隐藏技术进行分析研究。
2.1本地隐藏本地隐藏是指木马为防止被本地用户发现而采取的隐藏手段,主要包括启动隐藏、文件隐藏、进程隐藏、内核模块隐藏、原始分发隐藏等。
这些手段可以分为三类:(1)将木马隐藏(附着、捆绑或替换)在合法程序中;(2)修改或替换相应的检测程序,对有关木马的输出信息进行隐蔽处理;(3)利用检测程序本身的工作机制或缺陷巧妙地避过木马检测。
2.1.1启动隐藏启动隐藏,是指目标机自动加载运行木马程序,而不被用户发现。
在Windows系统中,比较典型的木马启动方式有:修改系统“启动”项;修改注册表的相关键值;插入常见默认启动服务;修改系统配置文件(Config.sys、Win.ini和System.ini等);修改“组策略”等。
木马隐藏技术分析郜多投(山东大学山东省济南市250100)摘要:文章首先介绍了木马的原理和特征,然后对木马所实现的功能做了简单的介绍,最后从木马的文件隐藏,进程隐藏和通信隐藏三个方面着重进行了分析。
关键词:木马;木马隐藏;通信隐藏[引言]木马,是一种通过潜入对方电脑进非法操作的计算机成程序,是目前黑客惯用的一种攻击手段,和一般的恶意软件不同,木马不主动进行自我复制和传播,破坏其他程序,然而,木马的潜伏性是超前的,为了看起来和正常程序一样,在进入系统之前,对自身的程序进行了伪装,使被感染的系统看起来一切正常,从而严重威胁计算机网络安全。
1.木马的原理和特征一个完整的木马程序包含两部分内容,服务端和控制端,服务端程序是通过远程计算机网络植入对方电脑,而黑客通过客户端进入运行了服务端的受控电脑,通常运行了服务端的计算机会生成一个类似于系统文件的进程,此时端口被暗中打开,电脑中保存的各类数据会向控制端进行发送,黑客也可以通过这些暗中打开的端口进入目标电脑,此时,电脑中更多的隐私将会遭受更大的泄露。
木马一般具有以下特征:一,隐藏性,隐藏性是木马的最显著特征,比如,改写进程名称使其和系统文件高度相似,隐藏在任务管理器中的进程,减少程序大小,减少暗中打开端口的流量。
二、自动运行性,可以随电脑启动而启动,比如潜入启动配置文件win.ini,winstart。
Bat等,有的也可嵌入正常软件,随软件的运行而启动。
三、欺骗性:木马为了防止被发现,通常伪装成为系统中本身存在的文件,比武将文件名中的“O”改为“0”,“1改为I”等容易混淆是非的字符,或者有的系统中本身的文件名也可被木马直接套用,只不过是保存在不同的系统路径下,另外,有的木马将自己改装成为ZIP压缩文件,当用户解压时,直接运行。
四、自我恢复性。
目前大多数木马程序的功能模块已不是单一的组件构成,而是自动复制到电脑其他路径做备份,在子木马或者主木马被删除时,都可以再自动生成。
dll简单加密限制方法在计算机安全领域,保护dll文件(动态链接库)的完整性和安全性至关重要。
dll文件是程序运行时所需的重要组件,一旦被非法获取或修改,可能会导致系统不稳定或数据丢失。
本文将介绍一种简单有效的加密限制方法,用于保护dll 文件的安全。
一、加密dll文件一种简单且有效的方法是对dll文件进行加密。
通过加密dll文件,可以防止未经授权的访问和修改。
常用的加密方法包括使用加密软件或编写自定义加密程序。
这里我们介绍一种简单的加密方法,使用汇编语言对dll文件进行加密。
1.打开记事本,编写以下汇编代码:start:moveax,fs:[0x18];获取进程模块列表cmpeax,0;判断eax是否为0,即是否为空列表jzerror;若是,则输出错误信息并退出movebx,eax;保存列表头部地址xoredi,edi;清空ebx指向的内存块movecx,0x200;内存块大小为0x200字节repmovsb;将内存块设置为空movdword[ebx],“加密后的dll文件内容”;将加密后的dll文件内容写入内存块addebx,0x3C;移动到内存块的结尾以便保存结束标记mov[ebx],0x0;保存结束标记mov[fs:ebx+eax*4+2*4],cs:start;将内存块添加到进程模块列表中error:exitwitherrorcode;错误处理exit2.将上述代码保存为扩展名为“.asm”的汇编语言文件。
3.使用汇编器将汇编代码编译为可执行文件。
在命令行中输入以下命令:nasm-felffilename.asm(将“filename”替换为实际的文件名)。
4.生成的可执行文件包含一个加密dll文件的程序。
运行该程序后,它会将加密后的dll文件写入当前目录下的一个临时文件中。
二、限制dll文件的使用加密dll文件只是保护dll文件的第一步,我们还需要限制其使用权限。
可以使用Windows的权限管理工具或编写脚本来实现这一目标。
简单的说,dll有以下几个优点:1) 节省内存。
同一个软件模块,若是以源代码的形式重用,则会被编译到不同的可执行程序中,同时运行这些exe时这些模块的二进制码会被重复加载到内存中。
如果使用dll,则只在内存中加载一次,所有使用该dll的进程会共享此块内存(当然,像dll中的全局变量这种东西是会被每个进程复制一份的)。
2) 不需编译的软件系统升级,若一个软件系统使用了dll,则该dll被改变(函数名不变)时,系统升级只需要更换此dll即可,不需要重新编译整个系统。
事实上,很多软件都是以这种方式升级的。
例如我们经常玩的星际、魔兽等游戏也是这样进行版本升级的。
3) Dll库可以供多种编程语言使用,例如用c编写的dll可以在vb中调用。
这一点上DLL还做得很不够,因此在dll的基础上发明了COM技术,更好的解决了一系列问题。
最简单的dll开始写dll之前,你需要一个c/c++编译器和链接器,并关闭你的IDE。
是的,把你的VC和C++ BUILDER之类的东东都关掉,并打开你以往只用来记电话的记事本程序。
不这样做的话,你可能一辈子也不明白dll的真谛。
我使用了VC自带的cl编译器和link链接器,它们一般都在vc的bin目录下。
(若你没有在安装vc的时候选择注册环境变量,那么就立刻将它们的路径加入path吧)如果你还是因为离开了IDE而害怕到哭泣的话,你可以关闭这个页面并继续去看《VC++技术内幕》之类无聊的书了。
最简单的dll并不比c的helloworld难,只要一个DllMain函数即可,包含objbase.h头文件(支持COM技术的一个头文件)。
若你觉得这个头文件名字难记,那么用windows.H也可以。
源代码如下:dll_nolib.cpp#include <objbase.h>#include <iostream.h>BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved){HANDLE g_hModule;switch(dwReason){case DLL_PROCESS_ATTACH:cout<<"Dll is attached!"<<endl;g_hModule = (HINSTANCE)hModule;break;case DLL_PROCESS_DETACH:cout<<"Dll is detached!"<<endl;g_hModule=NULL;break;}return true;}其中DllMain是每个dll的入口函数,如同c的main函数一样。
利⽤C++实现模块隐藏(R3层断链)⼀、模块隐藏的实现原理 普通API查找模块实现思路:其通过查询在R3中的PEB(Process Environment Block 进程环境块)与TEB(Thread Environment Block 进程环境块)来找到⼀个双向链表,通过遍历双向链表中某⼀成员(字符串)来查找全部模块。
模块隐藏实现思路:在R3层的模块隐藏,我们需要做的就是将其该链表断链,将某⼀模块从这个双向链表中摘除,这样再调⽤传统的API时就会搜索不到。
⼆、结构体成员详细介绍<1> TEB结构体 -- 内存地址为 fs:[0] 处。
使⽤Windbg的 "dt _TEB"命令来查看TEB结构体kd> dt _TEBntdll!_TEB+0x000 NtTib : _NT_TIB+0x01c EnvironmentPointer : Ptr32 Void+0x020 ClientId : _CLIENT_ID+0x028 ActiveRpcHandle : Ptr32 Void+0x02c ThreadLocalStoragePointer : Ptr32 Void+0x030 ProcessEnvironmentBlock : Ptr32 _PEB+0x034 LastErrorValue : Uint4B1. 属性介绍 1.1)_NT_TIB:重点两个属性,栈顶与栈⼤⼩。
/kernel_struct/vista/NT_TIB.html 1.2) _CLIENT_ID: 存储该进程ID与当前主线程ID。
https:///en-us/openspecs/windows_protocols/ms-tsts/a11e7129-685b-4535-8d37-21d4596ac057? redirectedfrom=MSDN 1.3) _PEB:进程环境块,记住其在 TEB 偏移 0x30处即可。
2007·6中小学电教EasyRecoveryProfessional6.04后点击“DataRecovery”按钮,再点击右边窗口中的“EmergencyDiskette”按钮,当出现急救盘制作向导窗口后将软盘插入软驱,然后相继点击“Continue→Yes→Start→确定→Exit”等几个按钮即可完成急救盘的制作。
2.在DOS下恢复数据进入需要恢复数据的计算机的BIOS设置,将第一启动设备设置为软驱,然后利用所制作的急救盘引导系统进入DOS版的EasyRecoveryProfessional6.04。
进入主界面后,点击“Next”按钮,扫描后出现硬盘分区显示窗口,在此选中需要恢复的数据所在的硬盘分区。
点击“Next”之后进入设置窗口,可在此选择恢复的模式,一般用默认值,直接点击“Next”。
此后,软件会弹出一个提示窗口,点击“OK”进入恢复设置、选择窗口。
选中需要恢复的文件,点击下面“Destination”栏后面的“Browse”按钮,设置一个用来存放欲恢复数据的目录。
注意,不能将被恢复数据存放在数据本身所在的那个分区。
完成设置后,点击“Next”,程序会弹出一个是否保存恢复报告的提示窗口,点击“No”,程序会将选中的文件恢复到指定的位置。
DOS版的EasyRecoveryProfessional6.04没有过多的功能按钮,不论是恢复数据还是恢复误格式化分区上的数据,其操作方法都是一样的。
另外,前面说过EasyRecoveryProfessional6.04可以恢复误格式化分区上的数据,但要获得好的恢复效果,必须保证该分区在格式化之后没有再写入数据:格式化硬盘时,计算机也只是将根目录区清零。
由于删除与格式化操作只是在文件名或根目录名上做了一些手脚,对于文件的数据部分没有丝毫变动,这才给文件恢复提供了可能。
如果在删除文件之后又对磁盘进行了写操作,那么新文件有可能会覆盖被删除文件原先所占据的硬盘空间,那么该文件就不能成功地恢复了。
【木马各种隐藏技术全方位大披露】被木马隐藏的文件以前,我曾认为只要不随便运行网友发来的文件就不会中病毒或木马,但后来出现了利用漏洞传播的冲击波、震荡波;以前,我曾认为不上小网站就不会中网页木马,但后来包括国内某知名游戏网站在内的多个大网站均在其首页被黑客挂上了木马。
从此,我知道:安全,从来没有绝对的。
虽然没有绝对的安全,但如果能知已知彼,了解木马的隐藏手段,对于木马即使不能百战百胜,也能做到及时发现,使损失最小化。
那么,木马究竟是如何躲在我们的系统中的呢?最基本的隐藏:不可见窗体+隐藏文件木马程序无论如何神秘,但归根究底,仍是Win32平台下的一种程序。
Windows下常见的程序有两种:1.Win32应用程序(Win32 Application),比如QQ、Office等都属于此行列。
2.Win32控制台程序(Win32 Console),比如硬盘引导修复程序FixMBR。
其中,Win32应用程序通常会有应用程序界面,比如系统中自带的"计算器"就有提供各种数字按钮的应用程序界面。
木马虽然属于Win32应用程序,但其一般不包含窗体或隐藏了窗体(但也有某些特殊情况,如木马使用者与被害者聊天的窗口),并且将木马文件属性设置为"隐藏",这就是最基本的隐藏手段,稍有经验的用户只需打开"任务管理器",并且将"文件夹选项"中的"显示所有文件"勾选即可轻松找出木马(见图1),于是便出现了下面要介绍的"进程隐藏"技术。
第一代进程隐藏技术:Windows 98的后门在Windows 98中,微软提供了一种能将进程注册为服务进程的方法。
尽管微软没有公开提供这种方法的技术实现细节(因为Windows的后续版本中没有提供这个机制),但仍有高手发现了这个秘密,这种技术称为RegisterServiceProcess。
只要利用此方法,任何程序的进程都能将自己注册为服务进程,而服务进程在Windows 98中的任务管理器中恰巧又是不显示的,所以便被木马程序钻了空子。
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文件。