从内存中加载DLL指南

合集下载

汇编内存加载dll

汇编内存加载dll
.endif
.break .if @len_j < 0
invoke RtlMoveMemory,@start1,@start2,@len_j
add esi,sizeof IMAGE_SECTION_HEADER
从内存加载DLL
dll_jz proc uses ebx esi,_lpdllfile,_len
local @PEtou,@ImageBase
local @hmem,@hmodule
local @start1,@start2,@endbiao,@len_j
add esi,sizeof IMAGE_DATA_DIRECTORY
assume esi:ptr IMAGE_DATA_DIRECTORY
mov esi,[esi].VirtualAddress
mov eax,[esi].SizeOfRawData
.endif
.endif
mov @len_j,eax
add esi,@PEtou
assume esi:ptr IMAGE_IMPORT_DESCRIPTOR
.while 1
.break .if [esi].Name1 == 0
mov eax,-1
.break
.endif
;获取PE头
add esi,[esi].e_lfanew
mov @PEtou,esi
mov esi,@PEtou
assume esi:ptr IMAGE_NT_HEADERS
movzx ebx,[esi].FileHeader.NumberOfSections
add esi,sizeof IMAGE_NT_HEADERS

dll加载原理

dll加载原理

dll加载原理DLL加载原理概述•DLL(动态链接库)是一种可执行文件格式,用于存储和共享程序代码和数据。

•DLL加载是将DLL文件加载到内存并解析其导出函数的过程。

DLL的分类•内核模式DLL:运行在操作系统内核空间中,提供给操作系统使用。

•用户模式DLL:运行在应用程序进程的用户空间中,为应用程序提供功能支持。

DLL的加载方式1.隐式加载:在应用程序启动时由操作系统自动加载所需的DLL文件。

–应用程序代码中使用函数,操作系统自动在加载应用程序的同时加载其依赖的DLL。

–应用程序代码需要将DLL的路径告知操作系统,操作系统根据路径找到DLL并加载。

2.显式加载:在应用程序运行时手动加载所需的DLL文件。

–应用程序通过调用加载函数(如LoadLibrary函数)手动加载DLL。

–调用GetProcAdress函数获取DLL中函数的入口地址,从而调用DLL中的函数。

DLL的加载过程1.读取DLL文件:–操作系统通过文件系统读取DLL文件的内容。

2.根据DLL文件的导入表(Import Table)解析DLL的依赖:–导入表记录了DLL所依赖的其他DLL,以及导出函数的名称和地址。

3.加载DLL依赖的其他DLL:–递归地加载DLL所依赖的其他DLL文件。

4.解析DLL导出函数:–根据导入表中记录的函数名称,找到导出函数的入口地址。

5.将DLL文件映射到进程空间:–将DLL文件映射到进程的虚拟内存空间中,以便能够访问DLL中的代码和数据。

6.更新进程的导入表:–更新进程的导入表,将DLL中导出函数的地址填入相应的入口地址。

DLL的卸载•当不再需要某个DLL时,可以将其从内存中卸载。

•DLL卸载的条件通常是没有其他模块依赖该DLL,或者由操作系统决定。

总结•DLL加载是将DLL文件加载到内存并解析导出函数的过程。

•DLL可以通过隐式加载或显式加载的方式加载。

•DLL的加载过程包括读取DLL文件、解析依赖、加载其他DLL、解析导出函数等步骤。

从内存中加载DLL指南

从内存中加载DLL指南

从内存中加载DLL指南从内存中加载DLL指南 ..................................................................... ............................................. 1 前言 ..................................................................... ........................................................................ .. 2 内容提纲 ..................................................................... .................................................................. 2 简介 ..................................................................... ........................................................................ .. 2 PE文件格式 ..................................................................... ............................................................. 2 DOS header /DOS stub 格式...................................................................... ................................ 3 PEheader ................................................................. ........................................................ 3 格式Sectionheader ................................................................. .................................................. 6 格式加载LIBRARY ................................................................ . (6)Section ............................................................ ...................................................... 7 拷贝的内容.................................................................... ........................................................ 7 基地址重定位.................................................................... ........................................................ 8 处理导入信息内存访问权限设置 ..................................................................... ............................................... 9 通知library被进程加载...................................................................... ...................................... 9 调用导出函数 ..................................................................... ..................................................... 10 释放library ................................................................ . (10)MEMORYMODULE工具包...................................................................... (11).................................................................... ............................................................. 11 下载位置已知的问题...................................................................... .. (11)License ................................................................ (11)版本移植 ..................................................................... ............................................................ 11 版权声明 ..................................................................... (12)前言本篇指南是讲解如何不借助文件系统的帮助来加载内存中载入DLL的技术。

dll导入

dll导入

复制代码复制代码MFC DLL向导虽然能用DLL实现的东西都可以用COM来实现,但DLL的优点确实不少,它更容易创建。

本文将讨论如何利用MFC来创建不同类型的DLL,以及如何使用他们。

一、DLL的不同类型使用MFC可以生成两种类型的DLL:MFC扩展DLL和常规DLL。

常规DLL有可以分为动态连接和静态连接。

Visual C++还可以生成W IN32 DLL,但不是这里讨论的主要对象。

1、MFC扩展DLL每个DLL都有某种类型的接口:变量、指针、函数、客户程序访问的类。

它们的作用是让客户程序使用DLL,MFC扩展DLL可以有C+ +的接口。

也就是它可以导出C++类给客户端。

导出的函数可以使用C ++/MFC数据类型做参数或返回值,导出一个类时客户端能创建类对象或者派生这个类。

同时,在DLL中也可以使用DLL和MFC。

Visual C++使用的MFC类库也是保存在一个DLL中,MFC扩展D LL动态连接到MFC代码库的DLL,客户程序也必须要动态连接到MFC 代码库的DLL。

(这里谈到的两个DLL,一个是我们自己编写的DLL,一个装MFC类库的DLL)现在MFC代码库的DLL也存在多个版本,客户程序和扩展DLL都必须使用相同版本的MFC代码DLL。

所以为了让MFC扩展DLL能很好的工作,扩展DLL和客户程序都必须动态连接到MFC代码库DLL。

而这个DLL必须在客户程序运行的计算机上。

2、常规DLL使用MFC扩展DLL的一个问题就是DLL仅能和MFC客户程序一起工作,如果需要一个使用更广泛的DLL,最好采用常规DLL,因为它不受MFC的某些限制。

常规DLL也有缺点:它不能和客户程序发送指针或MFC派生类和对象的引用。

一句话就是常规DLL和客户程序的接口不能使用MFC,但在DLL和客户程序的内部还是可以使用MFC。

当在常规DLL的内部使用MFC代码库的DLL时,可以是动态连接/静态连接。

如果是动态连接,也就是常规DLL需要的MFC代码没有构建到DLL中,这种情况有点和扩展DLL类似,在DLL运行的计算机上必须要MFC代码库的DLL。

DLL的11种注入方法资料

DLL的11种注入方法资料

闲着没事整理了一下DLL的N种注入方法,对学习外挂的朋友,应该有用!第一种方法:利用CreateRemoteThread 远程建立线程的方式注入DLL.首先,我们要提升自己的权限,因为远程注入必不可免的要访问到目标进程的内存空间,如果没有足够的系统权限,将无法作任何事.下面是这个函数是用来提升我们想要的权限用的.function EnableDebugPriv : Boolean;varhToken : THANDLE;tp : TTokenPrivileges;rl : Cardinal;beginresult := false;//打开进程令牌环OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);//获得进程本地唯一IDif LookupPrivilegeValue(nil, 'SeDebugPrivilege',tp.Privileges[0].Luid) thenbegintp.PrivilegeCount := 1;tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;//调整权限result := AdjustTokenPrivileges(hToken, False, tp,sizeof(tp), nil, rl);end;end;关于OpenProcessToken() 和AdjustTokenPrivileges() 两个API的简单介绍:OpenProcessToken():获得进程访问令牌的句柄.function OpenProcessToken(ProcessHandle: THandle; //要修改访问权限的进程句柄DesiredAccess: DWORD; //指定你要进行的操作类型var TokenHandle: THandle): BOOL; //返回的访问令牌指针AdjustTokenPrivileges() :调整进程的权限.function AdjustTokenPrivileges(TokenHandle: THandle; // 访问令牌的句柄DisableAllPrivileges: BOOL; // 决定是进行权限修改还是除能(Disable)所有权限const NewState: TTokenPrivileges; // 指明要修改的权限,是一个指向TOKEN_PRIVILEGES结构的指针,该结构包含一个数组,数据组的每个项指明了权限的类型和要进行的操作;BufferLength: DWORD; //结构PreviousState的长度,如果PreviousState为空,该参数应为0var PreviousState: TTokenPrivileges; // 指向TOKEN_PRIVILEGES结构的指针,存放修改前的访问权限的信息var ReturnLength: DWORD //实际PreviousState结构返回的大小) : BOOL;远程注入DLL其实是通过CreateRemoteThread 建立一个远程线程调用LoadLibrary 函数来加载我们指定的DLL,可是如何能让远程线程知道我要加载DLL呢,要知道在Win32系统下,每个进程都拥有自己的4G虚拟地址空间,各个进程之间都是相互独立的。

DLL 劫持技术(内存补丁技术)

DLL 劫持技术(内存补丁技术)
// 释放原始模块 inline VOID WINAPI Free() { if (m_hModule) FreeLibrary(m_hModule); } // 获取原始函数地址 FARPROC WINAPI GetAddress(PCSTR pszProcName) {
d FARPROC fpAddress; e TCHAR szProcName[16]={0}; r TCHAR tzTemp[MAX_PATH]={0}; te if (m_hModule == NULL) is {
00401496 EB 29 jmp short 004014C1
补丁编程实现就是: 代码:
unsigned char p401496[2] = {0xEB, 0x29}; WriteProcessMemory(hProcess,(LPVOID)0x401496, p401496, 2, NULL);
Printed with FinePrint - purchase at
丁任务。伪造的 ws2_32.dll 有着真实 ws2_32.dll 一样的输出函数,完整源码见光盘。实现时,可以利用 DLL 模块中的函数转发器来实现这个目标,其会将对一个函数的调用转至另一个 DLL 中的另一个函数。可 以这样使用一个 pragma 指令: 代码:
tered 利用这种方法取得控制权后,可以对主程序进行补丁。此种方法只对除 kernel32.dll, ntdll.dll 等核心 is 系统库以外的 DLL 有效,如网络应用程序的 ws2_32.dll,游戏程序中的 d3d8.dll,还有大部分应用程序
都调用的 lpk.dll,这些 DLL 都可被劫持。
Printed with FinePrint - purchase at

总结的c#调用DLL方法

总结的c#调用DLL方法
The MaxCD of 456 and 123 is 3
小结:
动态链接具有下列优点:
节省内存和减少交换操作。很多进程可以同时使用一个DLL,在内存中共享该DLL的一个副本。相反,对于每个用静态链接库生成的应用程序,Windows必须在内存中加载库代码的一个副本。
节省磁盘空间。许多应用程序可在磁盘上共享DLL的一个副本。相反,每个用静态链接库生成的应用程序均具有作为单独的副本链接到其可执行图像中的库代码。
long maxcd = MaxCDClass.MaxCD(num1,num2);
Console.WriteLine("The MaxCD of {0} and {1} is {2}",num1, num2, maxcd);
}
}
若要生成可执行文件MyClient.exe,请使用以下命令行:
csc /out:MyClient.exe /reference:MyLibrary.DLL MyClient.cs
升级到DLL更为容易。DLL中的函数更改时,只要函数的参数和返回值没有更改,就不需重新编译或重新链接使用它们的应用程序。相反,静态链接的对象代码要求在函数更改时重新链接应用程序。
提供售后支持。例如,可修改显示器驱动程序DLL以支持当初交付应用程序时不可用的显示器。
支持多语言程序。只要程序遵循函数的调用约定,用不同编程语言编写的程序就可以调用相同的DLL函数。程序与DLL函数在下列方面必须是兼容的:函数期望其参数被推送到堆栈上的顺序,是函数还是应用程序负责清理堆栈,以及寄存器中是否传递了任何参数。
}
(3)在CS编辑器中再次添加一个CS文件,名字自取,但包函main入口函数,在这个文件中便可以引用C++写的DLL文件中的函数了

DLL两种加载的详解

DLL两种加载的详解

DLL两种加载的详解目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。

静态库是一个或者多个obj文件的打包,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。

比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。

动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。

有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。

导入库和静态库的区别很大,他们实质是不一样的东西。

静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。

这也是实际上很多开源代码发布的惯用方式:1. 预编译的开发包:包含一些.dll文件和一些.lib文件。

其中这里的.lib就是导入库,而不要错以为是静态库。

但是引入方式和静态库一样,要在链接路径上添加找到这些.lib的路径。

而.dll则最好放到最后产生的应用程序exe执行文件相同的目录。

这样运行时,就会自动调入动态链接库。

2. 用户自己编译:下载的是源代码,按照readme自己编译。

生成很可能也是.dll + .lib(导入库)的库文件3. 如果你只有dll,并且你知道dll中函数的函数原型,那么你可以直接在自己程序中使用LoadLibary调入DLL文件,GetProcAddressDLL:动态链接库 (DLL) 是作为共享函数库的可执行文件。

动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。

函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。

VC DLL加载方法

VC DLL加载方法

调用DLL,首先需要将DLL文件映像到用户进程的地址空间中,然后才能进行函数调用,这个函数和进程内部一般函数的调用方法相同。

Windows提供了两种将DLL映像到进程地址空间的方法:1. 隐式的加载时链接这种方法需要DLL工程经编译产生的LIB文件,此文件中包含了DLL允许应用程序调用的所有函数的列表,当链接器发现应用程序调用了LIB文件列出的某个函数,就会在应用程序的可执行文件的文件映像中加入一些信息,这些信息指出了包含这个函数的DLL文件的名字。

当这个应用程序运行时,也就是它的可执行文件被操作系统产生映像文件时,系统会查看这个映像文件中关于DLL的信息,然后将这个DLL文件映像到进程的地址空间。

系统通过DLL文件的名称,试图加载这个文件到进程地址空间时,它寻找DLL 文件的路径按照先后顺序如下:·程序运行时的目录,即可执行文件所在的目录;·当前程序工作目录·系统目录:对于Windows95/98来说,可以调用GetSystemDirectory函数来得到,对于WindowsNT/2000 来说,指的是32位Windows的系统目录,也可以调用GetSystemDirectory函数来得到,得到的值为SYSTEM32。

·Windows目录·列在PATH环境变量中的所有目录VC中加载DLL的LIB文件的方法有以下三种:①LIB文件直接加入到工程文件列表中在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中“Add Files to Project”菜单,在弹出的文件对话框中选中要加入DLL的LIB文件即可。

②设置工程的 Project Settings来加载DLL的LIB文件打开工程的 Project Settings菜单,选中Link,然后在Object/library modules 下的文本框中输入DLL的LIB文件。

③通过程序代码的方式加入预编译指令#pragma comment (lib,”*.lib”),这种方法优点是可以利用条件预编译指令链接不同版本的LIB文件。

DLL文件的生成和引用方法

DLL文件的生成和引用方法

一、动态链接库什么是动态链接库?DLL三个字母对于你来说一定很熟悉吧,它是Dynamic Link Library 的缩写形式,动态链接库(DLL) 是作为共享函数库的可执行文件。

动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。

函数的可执行代码位于一个DLL 中,该DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。

DLL 还有助于共享数据和资源。

多个应用程序可同时访问内存中单个DLL 副本的内容。

和大多数程序员一样,你一定很使用过DLL吧。

也曾感受到它的带给你程序设计和编码上的好错吧今天我想和大家探讨一个主题:如何在C#创建和调用DLL(动态链接库), 其实在很大意义上而讲,DLL让我更灵活的组织编写我们的应用程序,作为软件设计者,可一个根据它来达到很高的代码重用效果。

下面我来介绍一下在C#中如何创建和调用DLL。

二、准备工作我们需要对我们接下来要做的事情做个简单的介绍,在本文我们将利用C#语言创建一个名为MyDLL.DLL的动态链接库,在这个动态链接库文件中我们将提供两个功能一个是对两个参数交换他们的值,另一个功能是求两个参数的最大公约数。

然后创建一个应用程序使用这个DLL。

运行并输出结果。

1、MySwap.csnamespace MyMethods{public class SwapClass{public static bool Swap(ref long i,ref long j){i = i+j;j = i-j;i = i-j;return true;}}}2、MyMaxCD.csnamespace MyMethods{public class MaxCDClass{public static long MaxCD(long i, long j){long a,b,temp;if(i>j){a = i;b = j;}else{b = i;a = j;}temp = a % b;while(temp!=0){a = b;b = temp;temp = a % b;}return b;}}}需要注意的是:我们在制作这两个文件的时候可以用Visual 或者其他的文本编辑器,就算是记事本也可以。

dll的两种加载方式(pend)+delayload

dll的两种加载方式(pend)+delayload

dll的两种加载⽅式(pend)+delayload看过关于动态库的调⽤例⼦,于是决定动⼿做⼀做:dll的对外接⼝声明头⽂件,Mydll.h://Mydll.h#include <stdio.h>#include <stdlib.h>#include "Public.h"#define DLL_EXPORT /*extern "c"*/ __declspec(dllexport) //导出#define CUST_API _stdcall //标准调⽤DLL_EXPORT void CUST_API DisplayVersion(TCHAR *Info); //显⽰版本DLL_EXPORT int CUST_API Calc(int ia,int ib);//DLL_EXPORT int CUST_API MetiCalc(int ia,int ib); //新增加接⼝//mydll.cpp#include "MyDll.h"void CUST_API DisplayVersion(TCHAR *Info){wcscpy_s(Info,sizeof(VERSION),VERSION); //#define VERSION ver 1.0return;}int CUST_API Calc(int ia,int ib){return ia+ib;}int CUST_API MetiCalc(int ia,int ib){return ia*ib;}编译后,⽣成DllTest.lib 和 DllTest.dll第⼀种⽅法:静态调⽤理解:lib描述dll信息和函数⼊⼝地址,在编译时期加载到可执⾏程序中的。

若dll增加新API接⼝,新接⼝在使⽤时,必须要同时更新lib 才能使⽤,否则会找不到新接⼝函数的地址,由此可见,lib包含了描述dll 的接⼝描述信息。

闲着没事整理了一下DLL的N种注入方法

闲着没事整理了一下DLL的N种注入方法

闲着没事整理了一下DLL的N种注入方法,对学习外挂的朋友,应该有用!第一种方法:利用CreateRemoteThread 远程建立线程的方式注入DLL.首先,我们要提升自己的权限,因为远程注入必不可免的要访问到目标进程的内存空间,如果没有足够的系统权限,将无法作任何事.下面是这个函数是用来提升我们想要的权限用的.function EnableDebugPriv : Boolean;varhToken : THANDLE;tp : TTokenPrivileges;rl : Cardinal;beginresult := false;//打开进程令牌环OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);//获得进程本地唯一IDif LookupPrivilegeValue(nil, 'SeDebugPrivilege',tp.Privileges[0].Luid) thenbegintp.PrivilegeCount := 1;tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;//调整权限result := AdjustTokenPrivileges(hToken, False, tp,sizeof(tp), nil, rl);end;end;关于OpenProcessToken() 和AdjustTokenPrivileges() 两个API的简单介绍:OpenProcessToken():获得进程访问令牌的句柄.function OpenProcessToken(ProcessHandle: THandle; //要修改访问权限的进程句柄DesiredAccess: DWORD; //指定你要进行的操作类型var TokenHandle: THandle): BOOL; //返回的访问令牌指针AdjustTokenPrivileges() :调整进程的权限.function AdjustTokenPrivileges(TokenHandle: THandle; // 访问令牌的句柄DisableAllPrivileges: BOOL; // 决定是进行权限修改还是除能(Disable)所有权限const NewState: TTokenPrivileges; // 指明要修改的权限,是一个指向TOKEN_PRIVILEGES结构的指针,该结构包含一个数组,数据组的每个项指明了权限的类型和要进行的操作;BufferLength: DWORD; //结构PreviousState的长度,如果PreviousState为空,该参数应为0var PreviousState: TTokenPrivileges; // 指向TOKEN_PRIVILEGES结构的指针,存放修改前的访问权限的信息var ReturnLength: DWORD //实际PreviousState结构返回的大小) : BOOL;远程注入DLL其实是通过CreateRemoteThread 建立一个远程线程调用LoadLibrary 函数来加载我们指定的DLL,可是如何能让远程线程知道我要加载DLL呢,要知道在Win32系统下,每个进程都拥有自己的4G虚拟地址空间,各个进程之间都是相互独立的。

如何从资源中加载DLL动态库

如何从资源中加载DLL动态库

如何从资源中加载DLL动态库就是自己使用Brcc32命令制作一个包含DLL动态库的资源文件,然后我如何从程序中加载该动态库呢!比如有一个动态库 Test.dll,然后我在制作资源文件如下:MyDll DLL Test.dll 保存为T est.rc然后使用 Brcc32 test.rc命令生成 Brcc32.res然后在程序中{$R Test.res}将该资源文件作为应用程序的一个资源编译到EXE文件中去我就想问一下,当EXE文件在运行的过程中,我如何从它的资源文件中加载我编译进去的DLL动态库,然后调用其中的函数从磁盘加载用LoadLibrary就可以了,但是,此时动态库在程序的资源文件中,也就是说他在内存中。

此时该如何加载呢?期待高手解答。

{不支持用ASPACK压缩过的DLL}{DLL Loader by Aphex************************************************function xLoadLibrary(Src: Pointer; Imports: array ofTImportItem): TLibInfo;procedure xFreeLibrary(hModule: TLibInfo);}unit DLLUnit;interfaceusesWindows;typeTImportItem = recordName: string;PProcVar: PPointer;end;TwordArr = array[0..0] of word;PwordArr = ^TwordArr;TdwordArr = array[0..0] of dword;PdwordArr = ^TdwordArr;PImageImportDescriptor = ^TImageImportDescriptor;TImageImportDescriptor = packed recordOriginalFirstThunk: dword;TimeDateStamp: dword;ForwarderChain: dword;Name: dword;FirstThunk: dword;end;PImageBaseRelocation = ^TImageBaseRelocation;TImageBaseRelocation = packed recordVirtualAddress: cardinal;SizeOfBlock: cardinal;end;TDllEntryProc = function(hinstDLL: HMODULE; dwReason: dword; lpvReserved: Pointer): Boolean; stdcall;TStringArray = array of string;TLibInfo = recordImageBase: Pointer;DllProc: TDllEntryProc;LibsUsed: TStringArray;end;PLibInfo = ^TLibInfo;PPointer = ^Pointer;TSections = array[0..100000] of TImageSectionHeader;constIMPORTED_NAME_OFFSET = $00000002;IMAGE_ORDINAL_FLAG32 = $80000000;IMAGE_ORDINAL_MASK32 = $0000FFFF;function xLoadLibrary(Src: Pointer; Imports: array of TImportItem): TLibInfo;function xFreeLibrary(LoadedLib: TLibInfo): boolean;implementationfunction xFreeLibrary(LoadedLib: TLibInfo): boolean;varObjectLoop: integer;beginResult := False;with LoadedLib dobeginif @DllProc <> nil thenbeginDllProc(HModule(LoadedLib.ImageBase),DLL_PROCESS_DETACH, nil);end;for ObjectLoop := 0 to Length(LibsUsed) - 1 dobeginif ObjectLoop >= Length(LibsUsed) thenExit;FreeLibrary(GetModuleHandle(pchar(LibsUsed[ObjectLoop]) ));end;SetLength(LibsUsed, 0);end;VirtualFree(LoadedLib.ImageBase, 0, MEM_RELEASE);Result := True;end;function xLoadLibrary(Src: Pointer; Imports: array ofTImportItem): TLibInfo;var ImageBase: pointer;ImageBaseDelta: integer;ImageNtHeaders: PImageNtHeaders;PSections: ^TSections;SectionLoop: integer;SectionBase: pointer;VirtualSectionSize, RawSectionSize: cardinal;OldProtect: cardinal;NewLibInfo: TLibInfo;function StrT oInt(S: string): integer;beginVal(S, Result, Result);end;procedure Add(Strings: TStringArray; Text: string);beginSetLength(Strings, Length(Strings) + 1); Strings[Length(Strings) - 1] := Text;end;function Find(Strings: array of string; Text: string; var Index: integer): boolean;var StringLoop: integer;beginResult := False;for StringLoop := 0 to Length(Strings) - 1 do beginif lstrcmpi(pchar(Strings[StringLoop]), pchar(T ext)) = 0 then begin Index := StringLoop; Result := True;end;end;end;function GetSectionProtection(ImageScn: cardinal): cardinal;beginResult := 0;if (ImageScn and IMAGE_SCN_MEM_NOT_CACHED) <> 0 then beginResult := Result or PAGE_NOCACHE;end;if (ImageScn and IMAGE_SCN_MEM_EXECUTE) <> 0 then beginif (ImageScn and IMAGE_SCN_MEM_READ) <> 0 then begin if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then begin Result := Result or PAGE_EXECUTE_READWRITEend else beginResult := Result or PAGE_EXECUTE_READend;end else if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then beginResult := Result or PAGE_EXECUTE_WRITECOPYend else beginResult := Result or PAGE_EXECUTEend;end else if (ImageScn and IMAGE_SCN_MEM_READ) <> 0 then beginif (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then begin Result := Result or PAGE_READWRITEend else begin Result := Result or PAGE_READONLY endend else if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then beginResult := Result or PAGE_WRITECOPYend else beginResult := Result or PAGE_NOACCESS;end;end;procedure ProcessExports(PExports: PImageExportDirectory; BlockSize: cardinal);varExportLoop: byte;ImportedFn: cardinal;PFnName: pchar;FnIndex: dword;function IsForwarderString(Data: pchar): boolean;beginResult := Data > PExports;if Result thenResult := cardinal(Data - PExports) < BlockSize;end;function GetForwardedSymbol(ForwarderString: pchar): pointer;varsForwarderString, DllName: string;ForwarderLoop: integer;LibHandle: HModule;beginsForwarderString := ForwarderString;while ForwarderString^ <> '.' do beginInc(ForwarderString);end;DllName := Copy(sForwarderString, 1, pos('.', sForwarderString) - 1);if not Find(NewLibInfo.LibsUsed, DllName, ForwarderLoop) then beginLibHandle := LoadLibrary(pchar(DllName));Add(NewLibInfo.LibsUsed, DllName);end else begin LibHandle := cardinal(NewLibInfo.LibsUsed[ForwarderLoop]);end;if ForwarderString^ = '#' thenForwarderString := pointer(StrToInt((ForwarderString + 1)));Result := GetProcAddress(LibHandle, ForwarderString);end;beginfor ExportLoop := 0 to PExports.NumberOfNames - 1 do beginPFnName := pchar(PdwordArr(cardinal(PExports.AddressOfNames) + cardinal(ImageBase))^[ExportLoop] + cardinal(ImageBase));for ImportedFn := low(Imports) to high(Imports) do begin if Imports[ImportedFn].Name = PFnName then beginFnIndex := PwordArr(cardinal(PExports.AddressOfNameOrdinals) + cardinal(ImageBase))^[ExportLoop];Imports[ImportedFn].PProcVar^ := pointer(PdwordArr(cardinal(PExports.AddressOfFunctions) + cardinal(ImageBase))^[FnIndex] + cardinal(ImageBase));if IsForwarderString(Imports[ImportedFn].PProcVar^) thenbegin Imports[ImportedFn].PProcVar^ := GetForwardedSymbol(Imports[ImportedFn].PProcVar^);end;end;end;end;end;procedure ProcessRelocs(PRelocs: PImageBaseRelocation);varPReloc: PImageBaseRelocation;RelocsSize: cardinal;Reloc: PWord;ModCount: cardinal;RelocLoop: cardinal;beginPReloc := PRelocs;RelocsSize := ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECT ORY_ENTRY_BASERELOC].Size;while cardinal(PReloc) - cardinal(PRelocs) < RelocsSize do beginModCount := (PReloc.SizeOfBlock - Sizeof(PReloc^)) div 2;Reloc := pointer(cardinal(PReloc) + sizeof(PReloc^));for RelocLoop := 0 to ModCount - 1 dobegin if Reloc^ and $F000 <> 0 thenInc(pdword(cardinal(ImageBase) + PReloc.VirtualAddress + (Reloc^ and $0FFF))^, ImageBaseDelta);Inc(Reloc);end;PReloc := pointer(Reloc);end;end;procedure ProcessImports(PImports: PImageImportDescriptor);varPImport: PImageImportDescriptor;Import: LPDword;PImportedName: pchar;LibHandle: HModule;ProcAddress: pointer;PLibName: pchar; ImportLoop: integer;function IsImportByOrdinal(ImportDescriptor: dword; HLib: THandle): boolean;beginResult := (ImportDescriptor and IMAGE_ORDINAL_FLAG32) <> 0;end;beginPImport := PImports;while <> 0 do beginPLibName := pchar(cardinal() + cardinal(ImageBase));if not Find(NewLibInfo.LibsUsed, PLibName, ImportLoop) thenbegin LibHandle := LoadLibrary(PLibName);Add(NewLibInfo.LibsUsed, PLibName);end else begin LibHandle :=cardinal(NewLibInfo.LibsUsed[ImportLoop]);end; if PImport.TimeDateStamp = 0 then beginImport := LPDword(pImport.FirstThunk + cardinal(ImageBase))end else beginImport := LPDword(pImport.OriginalFirstThunk + cardinal(ImageBase));end;while Import^ <> 0 do beginif IsImportByOrdinal(Import^, LibHandle) then beginProcAddress := GetProcAddress(LibHandle, pchar(Import^ and $FFFF))end else beginPImportedName := pchar(Import^ + cardinal(ImageBase) + IMPORTED_NAME_OFFSET);ProcAddress := GetProcAddress(LibHandle, PImportedName);end;PPointer(Import)^ := ProcAddress;Inc(Import);end;Inc(PImport);end;end;beginImageNtHeaders := pointer(int64(cardinal(Src)) + PImageDosHeader(Src)._lfanew);ImageBase := VirtualAlloc(nil, ImageNtHeaders.OptionalHeader.SizeOfImage, MEM_RESERVE,PAGE_NOACCESS);ImageBaseDelta := cardinal(ImageBase) - ImageNtHeaders.OptionalHeader.ImageBase;SectionBase := VirtualAlloc(ImageBase, ImageNtHeaders.OptionalHeader.SizeOfHeaders,MEM_COMMIT, PAGE_READWRITE);Move(Src^, SectionBase^, ImageNtHeaders.OptionalHeader.SizeOfHeaders);VirtualProtect(SectionBase,ImageNtHeaders.OptionalHeader.SizeOfHeaders,PAGE_READONLY, OldProtect);PSections := pointer(pchar(@(ImageNtHeaders.OptionalHeader)) + ImageNtHeaders.FileHeader.SizeOfOptionalHeader);for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do beginVirtualSectionSize := PSections[SectionLoop].Misc.VirtualSize;RawSectionSize := PSections[SectionLoop].SizeOfRawData;if VirtualSectionSize < RawSectionSize thenbeginVirtualSectionSize := VirtualSectionSize xor RawSectionSize;RawSectionSize := VirtualSectionSize xor RawSectionSize;VirtualSectionSize := VirtualSectionSize xor RawSectionSize;end;SectionBase := VirtualAlloc(PSections[SectionLoop].VirtualAddress + pchar(ImageBase), VirtualSectionSize, MEM_COMMIT, PAGE_READWRITE);FillChar(SectionBase^, VirtualSectionSize, 0);Move((pchar(src) + PSections[SectionLoop].PointerToRawData)^, SectionBase^, RawSectionSize);end;NewLibInfo.DllProc := TDllEntryProc(ImageNtHeaders.OptionalHeader.AddressOfEntry Point + cardinal(ImageBase));NewLibInfo.ImageBase := ImageBase;SetLength(NewLibInfo.LibsUsed, 0);ifImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECT ORY_ENTRY_BASERELOC].VirtualAddress <> 0 thenProcessRelocs(pointer(ImageNtHeaders.OptionalHeader.Dat aDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddr ess + cardinal(ImageBase)));ifImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECT ORY_ENTRY_IMPORT].VirtualAddress <> 0 thenProcessImports(pointer(ImageNtHeaders.OptionalHeader.D ataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddres s + cardinal(ImageBase)));for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do beginVirtualProtect(PSections[SectionLoop].VirtualAddress + pchar(ImageBase), PSections[SectionLoop].Misc.VirtualSize, GetSectionProtection(PSections[SectionLoop].Characteristics), OldProtect);end;*********************<>nilthenbeginif not NewLibInfo.DllProc(cardinal(ImageBase), DLL_PROCESS_ATTACH, nil) thenbeginNewLibInfo.DllProc := nil;xFreeLibrary(Result);end;end;ifImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECT ORY_ENTRY_EXPORT].VirtualAddress <> 0 thenProcessExports(pointer(ImageNtHeaders.OptionalHeader.D ataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddres s + cardinal(ImageBase)), ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECT ORY_ENTRY_EXPORT].Size);Result := NewLibInfo;end;{//调用示例program test;UsesWindows, DLLUnit;varResourceLocation: HRSRC;ResourceSize: LongWord;ResourceHandle: THandle;ResourcePointer: Pointer;TestFunction: procedure;MyImports: array [0..0] of TImportItem =((Name: 'TestFunction'; PProcVar: @@TestFunction));MyLibrary: TLibInfo;beginResourceLocation := FindResource(HInstance, pchar('a01'), RT_RCDATA);if ResourceLocation <> 0 thenbeginResourceSize := SizeofResource(HInstance, ResourceLocation);if ResourceSize <> 0 thenbeginResourceHandle := LoadResource(HInstance, ResourceLocation);if ResourceHandle <> 0 thenbeginResourcePointer := LockResource(ResourceHandle);if ResourcePointer <> nil thenbeginMyLibrary := xLoadLibrary(ResourcePointer, MyImports);TestFunction;end;end;end;end;xFreeLibrary(MyLibrary);end.//===================================== ========================================= varFLibrary: TLibInfo;test: function(const i : Integer):integer; stdcall;constDllImports: array [0..0] of TImportItem =((Name: 'test'; PProcVar: @@test));procedure LoadLib;varBuf : Pointer;Size : DWORD;ProcessId: Cardinal;ResHandle:Cardinal;beginResHandle := FindResource(hInstance, 'testdll', 'DLL');if ResHandle > 0 thenbeginSize := SizeofResource(hInstance, ResHandle);Buf := LockResource(LoadResource(hInstance, ResHandle));FLibrary := xLoadLibrary(Buf, DllImports);end;end;procedure FreeLib;beginif FLibrary.ImageBase <> nil then beginif xFreeLibrary(FLibrary) then FLibrary.ImageBase := nil; end;end;//}end.。

dll文件怎么打开

dll文件怎么打开

.dll文件怎么打开要打开.dll文件,你需要了解.dll文件的类型和用途,因为.dll文件是一种动态链接库文件,通常包含了程序所需的函数和数据。

打开.dll文件通常需要特定的应用程序或操作系统支持。

下面我将介绍如何打开.dll文件,以及一些常见的情况和注意事项。

1. 使用相关程序:如果你知道.dll文件与特定程序或应用程序相关,通常无需直接打开.dll 文件。

只需运行相关程序,它将自动加载和使用.dll文件。

这是因为.dll文件包含了程序所需的函数和资源,而程序会在需要时自动引用.dll文件。

2. 查看.dll文件信息:你可以使用文件资源管理器来查看.dll文件的属性和信息。

右键单击.dll 文件,选择“属性”,然后切换到“详细信息”选项卡。

这里可以查看.dll文件的版本、作者和其他相关信息。

3. 使用文本编辑器:.dll文件通常是二进制文件,无法直接用文本编辑器打开。

然而,有时你可以使用文本编辑器(如Notepad++)打开.dll文件,以查看其中的文本信息。

请注意,这种方法只对包含文本信息的.dll文件有效。

4. DLL查看器工具:有一些专门的工具,如Dependency Walker或PE Explorer,可以用于查看.dll文件的内容和结构。

这些工具可以帮助你分析.dll文件并查看其中包含的函数和资源。

5. 反汇编:如果你是开发人员,你可以使用反汇编工具来查看.dll文件的汇编代码。

这对于分析和调试程序非常有用,但需要具备一定的编程和逆向工程技能。

6. 注意事项:需要特别注意的是,.dll文件通常不应该被直接打开、编辑或删除,因为它们可能是操作系统或其他程序的一部分,删除或修改它们可能导致程序不稳定或无法正常工作。

如果你不确定如何处理.dll文件,最好不要直接操作它们。

总的来说,打开.dll文件通常不是常见的操作,而是需要具备一定的专业知识和目的。

通常,我们只需要运行相关程序,它们会自动处理.dll文件。

C语言动态链接库DLL的加载

C语言动态链接库DLL的加载

C语言动态链接库DLL的加载静态链接库在链接时,编译器会将 .obj 文件和 .LIB 文件组织成一个 .exe 文件,程序运行时,将全部数据加载到内存。

如果程序体积较大,功能较为复杂,那么加载到内存中的时间就会比较长,最直接的一个例子就是双击打开一个软件,要很久才能看到界面。

这是静态链接库的一个弊端。

动态链接库有两种加载方式:隐式加载和显示加载。

•隐式加载又叫载入时加载,指在主程序载入内存时搜索DLL,并将DLL载入内存。

隐式加载也会有静态链接库的问题,如果程序稍大,加载时间就会过长,用户不能接受。

•显式加载又叫运行时加载,指主程序在运行过程中需要DLL中的函数时再加载。

显式加载是将较大的程序分开加载的,程序运行时只需要将主程序载入内存,软件打开速度快,用户体验好。

隐式加载首先创建一个工程,命名为cDemo,添加源文件main.c,内容如下:1.#include2.3.extern int add(int, int); // 也可以是_declspec(dllimport) intadd(int, int);4.extern int sub(int, int); // 也可以是_declspec(dllimport) intsub(int, int);5.6.int main(){7.int a=10, b=5;8.printf('a+b=%d\n', add(a, b));9.printf('a-b=%d\n', sub(a, b));10.return 0;11.}#includeextern int add(int, int); // 也可以是_declspec(dllimport) intadd(int, int);extern int sub(int, int); // 也可以是 _declspec(dllimport) intsub(int, int);int main(){ int a=10, b=5; printf('a+b=%d\n', add(a, b)); printf('a-b=%d\n', sub(a, b)); return 0;}找到上节创建的 dllDemo 工程,将 debug 目录下的dllDemo.lib 和dllDemo.dll 复制到当前工程目录下。

从内存中加载DLL

从内存中加载DLL

从内存中加载DLL[转]从内存中加载DLL减小字体增大字体[转]从内存中加载DLL转一篇文章,原文出处没有找到,已经转了好多了,感觉技术不错,好东东收藏也不错.——————————————————程序使用动态库DLL一般分为隐式加载和显式加载两种,分别对应两种链接情况。

本文主要讨论显式加载的技术问题。

我们知道,要显式加载一个DLL,并取得其中导出的函数地址一般是通过如下步骤:(1) 用LoadLibrary加载dll文件,获得该dll的模块句柄;(2) 定义一个函数指针类型,并声明一个变量;(3) 用GetProcAddress取得该dll中目标函数的地址,赋值给函数指针变量;(4) 调用函数指针变量。

这个方法要求dll文件位于硬盘上面。

现在假设我们的dll已经位于内存中,比如通过脱壳、解密或者解压缩得到,能不能不把它写入硬盘文件,而直接从内存加载呢?答案是肯定的。

经过多天的研究,非法操作了N次,修改了M个BUG,死亡了若干脑细胞后,终于有了初步的结果,下面做个总结与大家共享。

一、加载的步骤由于没有相关的资料说明,只能凭借感觉来写。

首先LoadLibrary是把dll的代码映射到exe进程的虚拟地址空间中,我们要实现的也是这个。

所以先要弄清楚dll的文件结构。

好在这个比较简单,它和exe一样也是PE文件结构,关于PE文件的资料很多,阅读一番后,基本上知道了必须做的几个工作:(1)判断内存数据是否是一个有效的DLL。

这个功能通过函数CheckDataValide完成。

原型是:BOOL CMemLoadDll::CheckDataValide(void* lpFileData, int DataLength);(2)计算加载该DLL所需的虚拟内存大小。

这个功能通过函数CalcTotalImageSize完成。

原型是:int CMemLoadDll::CalcTotalImageSize();(3)将DLL数据复制到所分配的虚拟内存块中。

S60 ARM平台下Dll的加载方式

S60 ARM平台下Dll的加载方式

结合日志库的实现,讨论S60 ARM平台下可写全局变量的使用一:S60 ARM平台下可写全局变量的使用在开发华为MCU客户端(S60平台)的过程中, 编译arm平台程序的时候,出现如下错误提示:ERROR: Dll ‘HuaWeiMobile[UID].APP' has initialised data.或者:ERROR: Dll HuaWeiMobile [UID].APP' has uninitialised data.(扩展名APP的应用程序其实也是一个DLL)而在为模拟器编译的时候,没有出现这个问题。

从这条错误信息的字面意思也看不出来问题出现在什么位置。

在Windows平台下,每个进程都有自己独立的DLL空间。

不同进程加载同一个DLL,互相之间是独立的。

只有在一个进程内,才是共享的。

但是S60平台的设计是所有进程都共享同一个DLL空间,每个进程只有一个机器字节的专有内存空间可以用来读写,这样的设计显然是出于节约内存的目的。

但是这样就带来一个问题,那就是DLL里不可以有可写的全局变量,否则就要造成混乱。

A进程对变量的改写会直接影响到B进程,这是程序设计者所不愿意看到的。

所以,S60平台的编译器就禁止了在DLL内申明可写全局变量。

但是全局变量还是可以用的,只要加上const声明即可。

出现上面的编译错误的原因是就工程中有可修改的全局的变量,所以在开发S60平台上面的应用时,不鼓励使用可写的全局变量,但是全局变量在某些情况下又是一个重要的实现手段,那么在S60平台下如何实现可写的全局变量呢?下面列举了几种实现方式:1. 把这个变量定义成AppUi类的私有成员,在创建view时将这个变量传引用(或传指针)到view中,或者为其写一个公共访问函数。

扼要代码如下:// CHuaWeiMobileAppUi.hpublic:TInt Share();在View里通过下面的方式访问这个变量:// 如果View继承自CAknViewCHuaWeiMobileAppUi * appUi = static_cast<CHuaWeiMobileAppUi *>(AppUi());appUi->Share();// 如果View是其它类型CHuaWeiMobileAppUi * appUi = static_cast< CHuaWeiMobileAppUi*>(CCoeEnv::Static()->AppUi());appUi->Share();2.使用线程局部存储(TLS)来保存全局变量:S60 2nd下面提供了线程局部存储(TLS)的机制来保存全局变量,TLS的关键是两个函数:void Dll::SetTls(void*)、void* Dll::Tls()SetTls()用于将任意类型的指针保存到线程局部存储中,而Tls()则取出该指针。

dll注入基础教程

dll注入基础教程

首先要明白什么是线程说到线程就不得不提到进程SDK文档里是这样描述的进程是一个正在运行的程序,它拥有自己的地址空间,拥有自己的代码、数据和其他系统资源。

一个进程包含了一个或者多个运行在此进程内的线程。

说白了,其实进程就是一个磁盘上的程序载入内存执行后的东西打开任务管理器看看,里面有好多进程...从定义上看出进程一定要有线程,线程是进程内存中的独立实体。

讲了这么多废话其实就是想说程序运行后就变成了进程,你的代码由线程来执行。

回到正题上,线程插入是什么呢?就是把一个线程弄到别的进程执行你也许觉得奇怪,自己不是有个进程好好的吗?其实这个作用大了,先说说开头提到的木马一来,有些比较由经验的用户有时会打开任务管理器,发现陌生进程?!想想你的木马还能活吗?那么插入Explorer等关键进程,你还想用电脑的话最好不要杀那个进程(不信试试)二来,大家现在都装防火墙了,网络连接经常会被虑掉,木马岂不是没用了?好,插入IE,防火墙想虑?除非你不想看网页当然,还有很多用处,比如插入系统级别的进程,哈哈,我们有Ring0权限了,(不要告诉我你不知道Ring0...就是连物理内存都可以写的超级权限)HookAPI也需要把代码注入别的进程知道了他的作用想知道怎么实现吧?别着急,慢慢来首先,这个应该属于系统编程,系统编程就不能不知道APIAPI是什么?简单点讲就是Windows为我们提供的一些函数,利用他们我们可以做很多事情Delphi花了很大力气用VCL还有一些乱七八糟的类把让我们可以尽量不要API所以会编程序但不了解API还是可能的API被封装在kernel32.dll、user32.dll等动态链接库里,程序使用时候把DLL映射到自己的内存了编写的时候我们通常需要从DLL导出这些函数function Beep; external 'kernel32.dll' name 'Beep';这样导出一个beep函数当然,实际上不要这么麻烦Delphi已经把这些导出声明写在一些单元里面了(比如windows单元)uses windows后就可以直接用了(而且建立窗口时候默认就会引用很多单元)所以实际上我们可以直接用的这个理解一下就好了开始讲线程插入了一般来说线程插入有2种方法1.DLL注入2.直接的远程线程插入DLL注入编写的时候比较简单,方法也多,但有个缺点进程会多出个模块来,可能被发现远程线程是直接修改对方内存的方法,虽然隐蔽性好,但是不小心可能会出点问题,比如你让不能有界面的进程弹出个窗口,不能上网的进程开个端口,那就等着系统崩溃吧今天重点讲DLL注入首先要知道什么是DLL,dll就是动态链接库,大家应该知道吧?怎么编写DLL呢?和写普通程序差不多是一样的新建一个工程,选DLL Wizard发现了吧?除了program改成library剩下几乎是一样的,只是需要程序加载他的入口点我们先编写个简单的DLLlibrary TestDll;usesWindows;{$R *.res}procedure func_a;beginMessageBox(0,'I love delphi','Function form Tset DLL',0);end;procedure func_b(MSG:pchar);beginMessageBox(0,MSG,'Function form Tset DLL',0);end;beginfunc_a;func_b('I like it too!');end.就是那个testdll.dpr看得懂吧,弹出2个信息框好了保存下,F9运行..出错,哈哈,DLL是不能直接运行的那怎么办?编译下(按过F9就不用了,也会编译好)看见那个DLL了吧?我们弄个程序加载它的入口点新建一个普通程序加一个按钮按钮事件只要写一句loadlibrary('testdll.dll');MainShow.dpr运行,单击按钮,怎么养?弹出东西了吧当然DLL还可以做函数库,资源库等今天暂不讨论现在DLL懂得写了吧?就是program改成library而已你可以写自己的程序了DLL会写了,现在的问题就是怎么注入了我们目的只是让对方的程序运行一句loadlibrary('testdll.dll');而已一切就OK了通常有这么几种注入方法1.利用全局消息钩子Win32下程序一般都要用收发消息用钩子函数下全局钩子,程序收到任何消息都加载我们的DLL的入口点当然,用这种方法DLL进入后要判断自己是不是被插进目标进程是的话,执行代码不是退出这个方法很麻烦但通用性很好,只要WINDOWS都可以用(但是有的系统进程消息是勾不住的,所以注入不了)早期的DLL注入大部分是用这个原理实现的2.写注册表写HKEY_LOCAL_MAHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs但是只能是NT下,而且必须是调用过user32.dll(Windows的一个内核,只要有界面的程序都调用它)的程序,在开机后所有程序会自动加载DLL,但是这个dll不能被卸载,而且不能调用某些函数,不然系统会挂掉(有危险性哦)不推荐使用3.利用远程线程注入来实现DLL注入只要能打开句柄,就能成功(强吧?)而且实现起来比较简单缺点就是9X内核的有点难度(也不是很困难)我们今天就讲利用远程线程注入来实现DLL注入吧!你可能要问,既然刚才说了远程线程可以直接注入一个线程,为什么还要多此一举反过来再调用DLL呢?这是因为,远程线程技术一般是直接对目标程序的内存进行操作我们知道不同程序的虚拟内存是不一样的所以很多函数的地址不一定一样而程序运行的时候实际上是Call函数地址进行函数调用的所以我们要注意计算很多偏移之类的这是非常烦琐的事情而且像上面说的让不能有界面的进程弹出个窗口,那就不好玩了而DLL呢?DLL调用时其实是被映射到进程内存里面DLL拥有自己的导入表、资源、函数等东西,实际上就是一个完整的程序映入内存后和执行一个程序效果是一样的这样我们就不用考虑那些乱七八糟的东西,只要安心的写功能即可好了,要明白远程线程首先当然要把程序本地线程搞清楚了不知道大家编多线程程序的时候是不是都用tthread类?反正我是不喜欢那个我们看看Windows给我们的原始API吧(tthread类也是用它写的)function CreateThread(lpThreadAttributes: Pointer;//安全指针一般nil就可以了dwStackSize: DWORD;//线程初始化尺寸,一般用0,获得与主线程一样尺寸(不够自己会增加,别担心)lpStartAddress: TFNThreadStartRoutine;//一个指向要执行线程函数的指针,这个函数必须遵守stdcall约定,并且可带一个参数,参数必须是指针类型lpParameter: Pointer;//函数的参数dwCreationFlags: DWORD;//控制创建标志,用0表示线程立刻执行var lpThreadId: DWORD)//返回标识变量我觉得没什么用,反正句柄都有了: THandle;//返回线程的句柄stdcall;//标准调用 Windows下API一般都是标准调用大家先看下看起来似乎比较复杂,等下举个例子我们把DLL源码里面的func_b拷到刚才那个EXE上稍微修改下procedure func_b(MSG:pchar); stdcall;beginMessageBox(0,MSG,'Function form Tset DLL',0);sleep(10000);//线程暂停N久(不超过10s)end;加上2个按钮第一个procedure TForm1.Button2Click(Sender: TObject);beginfunc_b('123');end;第二个procedure TForm1.Button3Click(Sender: TObject);var tid:longword;//放返回值,不放她不让执行,郁闷str:pchar;//便于获得pointerbeginstr:='123';createthread(nil,0,@func_b, //函数名前面加@是得到函数指针pointer(str),//虽然str也是指针,但是delphi就是要pointer型的,那就转一下类型0 , tid);//tid纯属放着占格式的,一般我们用不到end;//上面CreateThread看得懂吧,几乎都是默认设置,以后套下去用就是了实际上都是调用func_b,只是第二个过程用了信新线程但是效果是不一样的第一个按钮按下弹出窗口后,程序卡死了(暂停10000)第二个却不会为什么呢?我们可以这样理解窗口看做一个主线程,执行func_b,弹出窗口,然后主线程挂起,于是卡死了而第二个过程创建一个新线程,新线程执行func_b,弹出窗口,挂起10000,但是由于主线程没有挂起,所以看起来关掉窗口后没什么事情发生(实际上那个线程还在偷偷执行,直到线程代码运行完,只是它卡死不会影响你)这个如果明白了那么下面就容易理解了看看这个函数function CreateRemoteThread(hProcess: THandle;lpThreadAttributes: Pointer;dwStackSize: DWORD;lpStartAddress: TFNThreadStartRoutine;lpParameter: Pointer;dwCreationFlags: DWORD;var lpThreadId: DWORD): THandle; stdcall;除了函数名不一样,下面的参数多了个hProcess: THandle;,剩下的完全一样呵呵,这个东西就是本节课的关键了先看函数名就知道是干什么用的了‘创建远程线程’用法和刚才基本一致就是hProcess: THandle是什么呢?这里要填的是被注入线进程的句柄什么是句柄?打个比方,对象是一个门,句柄就是那个把手,通过句柄我们可以对门进行操作也就是说我们利用句柄来操作某些东西(包括进程、线程等等)你有没有注意到,CreateThread和CreateRemoteThread都返回一个THandle,也就是线程的句柄还有loadlibrary也会返回DLL的句柄,我们可以利用他们对相关对象进行操作那么怎么获得进程句柄呢?一般采用先得到进程PID再用下面的函数取得句柄function OpenProcess(dwDesiredAccess: DWORD;//访问标志一般填写 PROCESS_ALL_ACCESS,这样这个句柄可以获得最大操作权限bInheritHandle: BOOL;//可否继承,这个跟子程序有关,无所谓了,填false和true都可以,反正我们自己能操作久可以dwProcessId: DWORD): //要获得句柄的进程IDTHandle; stdcall;//返回句柄有时候会返回0,说明打开句柄失败了一般是你的权限不够(比如你想对Winlogon这些系统级程序操作)这时候我们需要提升权限一般Debug权限就可以了(其实操作权限里面最高了)提升的过程我写好了直接调用就可以了(修改进程令牌到Debug级别,为什么这样写这里不详细讲了,自己去网上搜索下)procedure GetDebugPrivs;varhToken: THandle;tkp: TTokenPrivileges;retval: dword;beginIf (OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken)) thenbeginLookupPrivilegeValue(nil, 'SeDebugPrivilege' , tkp.Privileges[0].Luid);tkp.PrivilegeCount := 1;tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken, False, tkp, 0, nil, retval);end;end;不会晕吧?应该记得我刚才提到了要PID,那怎么得到呢?一般用FindWindow和GetWindowThreadProcessId配合的到这样写先var Pid:longword;//储存那个PIDGetWindowThreadProcessId(FindWindow('Notepad', nil), @PID);这样就找到笔记本的PID,再如'Shell_TrayWnd'可以找到Explorer的窗口类名据说可以用SPY++查询,不过这东西我没见过,呵呵当然还可以枚举进程判断进程名等等这个先告一段落。

从内存资源中加载DLL 模拟PE加载器

从内存资源中加载DLL 模拟PE加载器

一种保护应用程序的方法模拟Windows PE加载器,从内存资源中加载DLL1、前言目前很多敏感和重要的DLL(Dynamic-link library) 都没有提供静态版本供编译器进行静态连接(.lib文件),即使提供了静态版本也因为兼容性问题导致无法使用,而只提供DLL版本,并且很多专业软件的授权部分的API,都是单独提供一个DLL来完成,而主模块通过调用DLL中的接口来完成授权功能。

虽然这些软件一般都采用了加壳和反调试等保护,但是一旦这些功能失去作用,比如脱壳,反反调试,HOOK API或者干脆写一个仿真的授权DLL (模拟授权DLL的所有导出函数接口),然后仿真的DLL再调用授权DLL,这样所有的输入首先被仿真DLL截获再传递给授权DLL,而授权DLL的输出也首先传递给仿真DLL再传递给主程序,这样就可以轻易的监视二者之间的输入输出之间的关系,从而轻易的截获DLL中的授权信息进行修改再返回给主程序。

2、目前隐式调用敏感DLL中可能存在的安全隐患以下通过两个软件的授权DLL来说明这种问题的严重性。

如下是两个软件中授权DLL的部分信息,如下图所示:(图1)通过工具OllyICE可以轻易的看出IoMonitor.exe调用授权DLL(XKeyAPI.DLL),这样就很容易在调用这些API的地方设置断点,然后判断输入输出的关系,从而达到破解的目的。

(图2)通过工具OllyICE可以轻易的看出sfeng.DLL中导出了很多函数,其中含义也很明显。

GetHDID获取硬盘的ID,GetCpuId获取cpu的ID,WinAntiDebug反调试接口。

而这些都是主程序需要调用的,比如:主程序通过GetHDID 来获取硬盘编码,以这个硬盘ID的伪码来生成授权码,破解者很容易修改这些接口的输出值或者干脆写一个sfeng.DLL来导出跟目标sfeng.DLL一模一样的导出函数,而主程序却完全不知晓。

只要用户有一套授权码就可以让GetHDID不管什么机器都返回一样的值,从而达到任何机器都可以使用同一套授权码。

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

从内存中加载DLL指南从内存中加载DLL指南 (1)前言 (2)内容提纲 (2)简介 (2)PE文件格式 (2)DOS header /DOS stub 格式 (3)PE header 格式 (3)Section header格式 (6)加载L IBRARY (6)拷贝Section的内容 (7)基地址重定位 (7)处理导入信息 (8)内存访问权限设置 (9)通知library被进程加载 (9)调用导出函数 (10)释放library (10)M EMORY M ODULE工具包 (11)下载位置 (11)已知的问题 (11)License (11)版本移植 (11)版权声明 (12)前言本篇指南是讲解如何不借助文件系统的帮助来加载内存中载入DLL的技术。

作者:Joachim Bauch联系方式: mail◎joachim-bauch.de版权:Creative Commons License(by-sa)内容提纲●简介●PE 文件格式⏹DOS header /DOS stub 格式⏹PE header 格式⏹Section header 格式●加载library⏹分配内存空间⏹拷贝Section内容到目标位置⏹基址重定位⏹内存访问权限设置⏹通知library被进程加载●调用导出函数●释放library●MemoryModule工具包⏹下载地址⏹已知的问题⏹License⏹移植版本●版权声明简介Windows平台提供的加载library的API(LoadLibarary, LoadLibraryEx)只能加载文件系统中的Library. 没有体哦那个从内存中加载Dll的功能。

但是,有些情况下又需要这样的功能。

譬如,你不想在发布包中包含很多文件,又或者你想给那些逆向工作者一些苦头吃。

这时一个常见的做法是先把dll文件写到一个临时文件中,然后从临时文件中导入它。

当程序终止时把临时文件删除。

PE文件格式绝大多数包含执行代码的二进制文件(.exe、.dll、.sys)都有相同的文件格式。

这种文件格式包括下面几个部分:下面将简单描述各个组成部分。

(注:在头文件winnt.h中可以找到下面要介绍的所有数据结构)DOS header /DOS stub 格式DOS格式部分有两部分组成。

分别是DOS header和DOS stubDOS头部存在的作用仅仅是为了向后兼容的目的。

跟在DOS header后面的是DOS Stub 数据,DOS stub用来显示一条错误信息来告诉用户该文件不能在DOS模式下运行。

微软对DOS Header的声明如下:typedef struct _IMAGE_DOS_HEADER { // DOS .EXE headerWORD e_magic; // Magic numberWORD e_cblp; // Bytes on last page of fileWORD e_cp; // Pages in fileWORD e_crlc; // RelocationsWORD e_cparhdr; // Size of header in paragraphsWORD e_minalloc; // Minimum extra paragraphs neededWORD e_maxalloc; // Maximum extra paragraphs neededWORD e_ss; // Initial (relative) SS valueWORD e_sp; // Initial SP valueWORD e_csum; // ChecksumWORD e_ip; // Initial IP valueWORD e_cs; // Initial (relative) CS valueWORD e_lfarlc; // File address of relocation tableWORD e_ovno; // Overlay numberWORD e_res[4]; // Reserved wordsWORD e_oemid; // OEM identifier (for e_oeminfo)WORD e_oeminfo; // OEM information; e_oemid specificWORD e_res2[10]; // Reserved wordsLONG e_lfanew; // File address of new exe header} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;PE header 格式PE Header用来描述和section相关的信息。

可执行文件用section来保存执行代码和数据,以及从其他模块导入的函数的信息和本模块导出的函数信息等。

PE Header的定义如下:typedef struct _IMAGE_NT_HEADERS {DWORD Signature;IMAGE_FILE_HEADER FileHeader;IMAGE_OPTIONAL_HEADER32 OptionalHeader;} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;FileHeader字段描述了文件的物理格式,如目录信息、Symbols的信息等。

typedef struct _IMAGE_FILE_HEADER {WORD Machine;WORD NumberOfSections;DWORD TimeDateStamp;DWORD PointerToSymbolTable;DWORD NumberOfSymbols;WORD SizeOfOptionalHeader;WORD Characteristics;} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;字段OptionalHeader保存模块的逻辑信息,这些信息包括需要的操作系统版本,需要的内存大小和入口点信息。

typedef struct _IMAGE_OPTIONAL_HEADER {//// Standard fields.//WORD Magic;BYTE MajorLinkerVersion;BYTE MinorLinkerVersion;DWORD SizeOfCode;DWORD SizeOfInitializedData;DWORD SizeOfUninitializedData;DWORD AddressOfEntryPoint;DWORD BaseOfCode;DWORD BaseOfData;//// NT additional fields.//DWORD ImageBase;DWORD SectionAlignment;DWORD FileAlignment;WORD MajorOperatingSystemVersion;WORD MinorOperatingSystemVersion;WORD MajorImageVersion;WORD MinorImageVersion;WORD MajorSubsystemVersion;WORD MinorSubsystemVersion;DWORD Win32VersionValue;DWORD SizeOfImage;DWORD SizeOfHeaders;DWORD CheckSum;WORD Subsystem;WORD DllCharacteristics;DWORD SizeOfStackReserve;DWORD SizeOfStackCommit;DWORD SizeOfHeapReserve;DWORD SizeOfHeapCommit;DWORD LoaderFlags;DWORD NumberOfRvaAndSizes;IMAGE_DATA_DIRECTORYDataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;字段DataDirectory保存着模块中定义的(IMAGE_NUMBEROF_DIRECTORY_ENTRIES)个逻辑项(Conpontents)的入口:对于只是加载DLL的任务来说,我们仅仅用到导入块和基地址重定位表块。

不过为了调用导出的函数,我们还需要用到导出函数块。

Section header格式这一部分数据保存在PE header部分的OPtionalHeader字段后面。

为了方便定位section header的位置,微软提供了一个宏定义IMAGE_FIRST_SECTION,它的值等于SectionHeader 的开始地址相对于PE Header基地址的位移。

Section header实际上是一个存储着文件中每一个Section的信息的列表:typedef struct _IMAGE_SECTION_HEADER {BYTE Name[IMAGE_SIZEOF_SHORT_NAME];union {DWORD PhysicalAddress;DWORD VirtualSize;} Misc;DWORD VirtualAddress;DWORD SizeOfRawData;DWORD PointerToRawData;DWORD PointerToRelocations;DWORD PointerToLinenumbers;WORD NumberOfRelocations;WORD NumberOfLinenumbers;DWORD Characteristics;} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;而一个Section中可以包含代码,数据,重定位信息,资源,导出导入函数等信息。

加载Library为了模拟PE loader的过程,我们首先必须弄清楚从把文件读入内存中开始到准备好可以被程序使用为止,都需要执行那些步骤。

当我们调用LoadLibrary时,Windows主要做了了以下工作:1.打开指定的文件并检查DOS和PE头部。

2.在PEHeader.OptionalHeader.ImageBase处分配PEHeader.Optionalheader.SizeOfImage个字节的内存。

3.分析section header,从IMAGE_SECTION_HEADER结构中的VirtualAddress属性中获取每个section的开始地址相对与ImageBase的位移。

相关文档
最新文档