扩大节
节有很多个,在我们扩大节时,一般会选择扩大最后一个节,因为如果扩大其他节,那么要修改这个节后面所有节的偏移和属性,如果扩大最后一个节,那么只需修改最后一个节的数据。
扩大节的步骤:
- 拉伸到内存
- 分配一块新空间,大小为原来的sizeofimage(内存中整个PE文件的映射的尺寸)+EX(需要扩大的大小+)
- 将最后一个节的节表里面的SizeOfRawData(节在文件中对齐后的尺寸)和VirtualSize(节在没有对齐前的真实尺寸)都改成N(N = SizeOfRawData和VirtualSize中大的一个+EX)。
也可以直接在这两个数据后加上EX。 - 修改sizeofimage的大小
操作:
1.扩大内存:
假设我要增加的内存是0x1000,那么文件大小就要调为0x1B000(初始大小)+0x1000=0x1C000
,调整完后就获得了0x1000的空间。
2.修改SizeOfRawData和VirtualSize成员的值。
将SizeOfRawData加0x1000 (0x800+0x1000=0x1800)
将VirtualSize加0x1000(0x1000+0x1000=0x2000)
3.修改sizeofimage:
sizeofimage的值修改为0x1F000 (0x1E000 + 0x1000)
合并节
1.先将文件对齐改为和内存对齐一样:
- 先查看文件的内存对齐和文件对齐
如图,文件对齐是0x200,内存对齐是0x1000。
-
修改每一个节的SizeOfRawData和VirtualSize。取SizeOfRawData和VirtualSize之间的最大值按内存对齐展开
例如,图中这个节SizeOfRawData和VirtualSize之间的最大值是0x15000按内存对齐后还是0x15000,所以将SizeOfRawData和VirtualSize都修改成这个值。 - 用刚才得到的值0x15000减去SizeOfRawData修改前的值0x14600得到通过这种方式这个节在文件中扩展的大小0x400。
- 在这个节的末尾添加0x400的空间
- 这里这个节的大小改变了,那么后面节的偏移也会一并改变,所以后面节的PointerToRawData都加0x400。
- 以此方法将所有节都按文件对齐展开
2. 合并:
- 用SizeOfImage减去SizeOfHeaders(按内存对齐后)得到所有节的大小。
0x1E000 - 0x1400 = 0x1CC00
然后将该值赋给第一个节的SizeOfRawData和VirtualSize - 将第一个节的属性改为包含所有节的属性。将所有节的Characteristics进行或运算的到的结果存入第一个节的Characteristics中。
- 修改NumberOfSections的值为1
静态链接库
静态链接库(Static Library)是程序在编译时就已经被链接到最终的可执行文件中的库。这种库文件通常具有.lib
(在Windows平台上)或.a
(在Unix/Linux平台上,包括macOS)的扩展名。与动态链接库(Dynamic Link Library, DLL或.so文件)不同,静态链接库在程序运行时不需要额外加载,因为它们的代码和数据已经被直接嵌入到了最终的可执行文件中,我们通常使用的函数都是动态链接库里面的。
静态链接库的构建
先在VS里面创建一个静态库项目
创建后会有一个头文件和源文件
在项目名字处按右键选择添加,然后选择添加类
添加完后,在源文件里面会出现一个所创建类的.cpp文件在,在头文件里面会出现一个所创建类的.h文件。
在.cpp文件里面编写函数
在.h文件里面声明函数
在项目文件的Debug文件里面找到lib文件,把头文件和lib文件都复制出来
使用
把头文件和lib文件复制到需要用到的项目的目录下
法一:
写入#include "libtools.h"和#pragma comment(lib, "testlib.lib")
运行即可看到成功调用了
法二:
不写“#pragma comment(lib, "testlib.lib")”这一句,需要写“#include "libtools.h"”。然后右键项目,属性->连接器–>常规–>附加库目录–>编辑
点击右边4个图标中的第一个后,填入lib文件名称
静态链接库就配置好了。
动态链接库
动态链接库的创建:
创建项目,选择动态链接库
添加一个类
删除class,清空.h文件
在.h文件做函数声明
在.cpp文件写函数功能
生成->生成解决方案,会得到.lib文件和.dll文件
复制.lib文件和.dll文件
使用
法一:隐式连接
将.lib文件和.dll文件复制到需要调用项目目录下,然后导入
运行
法二:显式调用
将.lib文件和.dll文件复制到需要调用项目目录下,然后导入
#include<Windows.h>
#include<iostream>
//#pragma comment(lib, "testdll.lib")
typedef int (*lpadd)(int, int);
typedef int (*lpsub)(int, int);
int main()
{
lpadd myadd;
lpsub mysub;
HINSTANCE hModule = LoadLibrary(TEXT("testdll.dll"));
myadd = (lpadd)GetProcAddress(hModule, "add");
mysub = (lpsub)GetProcAddress(hModule, "sub");
printf("%d", myadd(3, 2));
}
运行
注记:
extern "C" _declspec(dllimport) int add(int x, int y)这句语句中,extern是指函数是全局函数,可以在其他地方调用;"C"代表用C语言的方式编译、链接;_declspec(dllimport)告诉编译器该函数是导入函数。
静态链接库与动态链接库的区别
- 静态链接库在调用时将代码直接编译到exe里面去,动态链接库的代码不在exe里面,他在自己独立的模块里面。
因此,如果静态链接库的代码有问题,就需要修改后重新编译程序,而如果动态链接库出了问题,只需要修改动态链接库的代码就行了。 - 静态链接库:在程序编译链接阶段,静态链接库的代码和数据被直接链接到目标程序中,成为可执行文件的一部分。这意味着在程序运行时,不再需要加载静态链接库,因为它已经被编译到程序中了。
- 动态链接库:动态链接库在程序运行时由操作系统动态加载到内存中。程序通过调用库中的函数来实现所需的功能。多个程序可以同时共享同一个动态链接库,从而节省内存空间。