硬盘文件->加载到内存(FileBuffer)->PE Loader加载并拉伸->ImageBuffer(起始位置ImageBase)
从0x00~0x3f共0x40字节固定大小
e_magic: pe指纹 "MZ"
e_lfanew: pe头的偏移
其他成员无关紧要
从dos头到pe头之间是dos存根
dos存根的数据基本没用,主要是在DOS环境运行时执行
我们可以用DosBox的DOS环境运行exe程序
运行结果
查看DosStub处代码
PE文件头由PE文件头标识,标准PE头,扩展PE头三部分组成
32位
64位
Signature=50 40 00 00 'PE\0\0'
FileHeader是标准PE头
OptionalHeader是可选PE头 但是非常重要
占20字节 在pe文件头标识后即可找到
重要成员
Machine //cpu型号
NumberOfSections //节区数
SizeOfOptionalHeader //可选PE头大小 有默认值,可修改
WORD Characteristics; //属性
重要成员:
紧跟在可选头后面的就是节表,PE中的节表以数组形式存在
重要成员
Name[IMAGE_SIZEOF_SHORT_NAME]; 节区名
VirtualSize; 节区大小
VirtualAddress; 节区起始地址
PointerToRawData; 节区文件偏移
Characteristics; 节区属性
打印节表
运行结果
在代码区添加硬编码(汇编代码的十六进制形式),修改oep使得程序开始执行时执行注入的代码
最后再跳转回原始的oep
注意: 需要先关闭程序的随机基址,在可选头的DllCharacteristics中,将0x40改为0x00即可
示例程序代码
运行后会弹出HelloWorld弹窗,这里仅做简单注入,四个参数全部压入0,此时会弹出错误窗口
分析:
首先在.text段中找一段空白代码区用于写入硬编码
这里选取59A0处开始写入 5A00开始是.rdata段
确定硬编码
首先是四个参数 6A 00 6A 00 6A 00 6A 00 (4个push 0)
然后是call MessageBox和jmp oep
MessageBox地址可以运行od 输入bp MessageBoxA下断点找到
OEP为411023(ImageBase=400000 ep=11023)
计算call和jmp的偏移
call和jmp的硬编码分别为E8 E9 他们后面跟的4字节数据是偏移值
且offset=desAddr-(call/jmp Addr+5)
即偏移值等于目的地址减去自身地址的下个指令地址(自身指令长度为5,所以+5是下个指令地址)
由于.text段的rva=11000 所以va=400000+11000=411000
那么59A0处的RVA=59A0-400+411000=4165A0
call offset=763C0E50-4165AD=75FAA8A3
jmp offset=411023-4165B2=FFFFAA71
写入硬编码并修改
写入后的代码
修改oep 这里改的是rva 将原本的入口点11023改为165A0即可
执行结果
可以看到程序入口点已经被修改为4165A0 并且输出错误弹窗,之后会跳转到原始的OEP处输出HelloWorld弹窗
通过.text段空白区注入代码实用性不高,通过新增节可以增大注入代码量,灵活性更高
基本过程:
判断是否有足够空间创建新的节表
每个节表占40字节 要保证有80字节空白区(多余40字节用于兼容部分系统)
在节表尾部和段首部之间便是空白区
如果尾部空白区大小不足,可以将PE头整体向上移动,覆盖掉DOS Stub(这段数据不影响程序运行)
创建新的节表
这里可以通过复制.text段的节表实现,复制之后需要调整部分成员
矫正PE文件信息
需要修改的成员有
申请新的空间用于存储新的PE文件
写入注入代码
保存文件
代码实现
执行结果
inject节表
inject节区
程序运行情况
当节表后的空白区大小不够时,可以选择扩大节
注意只能扩大最后一个节区,因为这样才不会影响到后续偏移
基本过程:
申请空间存储新的FileBuffer
修正Pe信息
需要修正的成员有
保存修改后的PE文件
代码
执行结果
可以看到原始节区VirtualSize=57E RawSize=600
扩大0x1400后
新VirtualSize=57E+1400=197E
新RawSize=600+1400=1A00
Image大小仅增加1000
这是由于400+600=A00没有超过内存对齐大小,原来的内存额外空间可以容纳这400字节,所以映像只需增加一个页
合并节也是针对ImageBuffer而言,可以直接对Imagebuffer操作
代码
执行结果
合并前节表包含9个节区,PE文件很紧凑 原文件大小39KB
合并后仅剩一个节区 并且PE文件很空旷,大部分空间是0 新文件大小128KB
合并后节区开始地址为1000 而headers到200处截止 此时又可以添加新的节区
RVA(Relative Virtual Address)VA(Virtual Address)
RVA = VA - ImageBase
VA(Virtual Address) VA是虚拟地址,它是代码或数据在内存中的真实地址,用于指定在内存中的具体位置。在运行时,操作系统会将RVA转换为真实的VA,即根据模块的加载基址(ImageBase)将RVA映射到内存中的实际地址。
VA = RVA + ImageBase
FOA(File Offset Address) 是可执行文件(如PE文件)中的文件偏移地址,它指的是代码或数据在文件中的位置偏移量。与RVA和VA不同,FOA是直接表示在文件中的偏移量,不涉及地址重定位或内存映射。
FOA和RAW均是指文件偏移
总结:
RVA=VA-ImageBase
确定RVA所在节区
可通过节区内存起始地址RVA<=RVA<=节区内存起始地址RVA+节区大小
即 VirtualAddress<=RVA<=VirtualAddress+VirtualSize判断RVA应该属于哪个节区
FOA=RVA-节区起始地址RVA+节区文件偏移=RVA - VirtualAddress + PointerToRawData
节区文件起始地址<=FOA<=节区文件起始地址+节区大小
即 PointerToRawData<=FOA<=PointerToRawData+SizeOfRawData
OEP的VA=411023
ImageBase=400000
.text 段
VirtualAddress=11000 (节区内存起始地址RVA) PointerToRawData=400 (节区文件偏移FOA)
VirtualSize(节区在内存中的大小)=5585 SizeOfRawData=5600(节区在文件中的大小)
节区在文件中的大小大于内存中的大小,因为文件对齐所以会有部分填充0的空白区域
注: 这里的VirtualSize并不一定准确,因为加载后内存对齐值为1000 所以实际内存大小应该是6000
所以OEP RVA=411023-400000=11023
显然该RVA属于.text段: 11000<=RVA<=11000+5585
OEP FOA=11023-11000+400=423
通过PETools检查可以发现入口点FOA(即RAW)=0x423 与计算结果一致
在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。
优点 方便
缺点 二进制代码需要编译到exe中,浪费空间
注: 静态库的二进制代码保存在.lib中
在VS中可以创建静态库项目,建议创建空项目
在静态库项目中创建StaticLib.cpp源文件和StaticLib.h头文件
代码实例
点击生成即可生成静态库得到.lib文件
在项目中找到StaticLib.lib和StaticLib.h文件,复制到需要使用该静态库的工程目录中
在工程目录中导入StaticLib.h文件
程序代码
运行结果
动态库是在程序需要使用时加载,不同程序可以使用同一份dll,大大节省了空间
dll查看工具推荐https://github.com/lucasg/Dependencies
同创建静态库类似,建议使用空项目,创建好后将项目属性中的生成文件修改为动态库Dll即可
然后创建头文件和源文件
生成动态库文件有关键字导出和.def导出两种方式
关键字功能解释
代码实例
点击生成即可得到.dll和.lib文件
首先在源文件目录创建.def文件
代码示例
设置一下链接器,找到输入,修改模块定义文件如下
点击生成即可得到.dll和.lib文件
注意NONAME导出的函数只有序号没有函数名,原来的sub函数在这里是Oridinal_3
基本步骤
将.dll .lib放到工程目录中
使用#pragma comment(lib,"dllname.lib")导入lib文件
静态库的.lib文件保存二进制代码,而dll中的.lib文件仅仅是指示函数位置
加入函数声明
extern "C" __declspec(dllexport) void func();
具体示例
首先将.dll和.lib放到工程目录中
程序代码
运行结果
基本使用方法
示例程序代码
运行结果
定义
表项定义
可选头的最后两个成员分别定义了数据目录表的个数和数据目录表数组,指向了一些关键表格
比较重要的有导出表,导入表,重定位表,IAT表
打印数据目录表
导出表记录了pe文件导出的函数,所以.exe和.dll程序都可以导出函数
数据目录表中记录了导出表的地址和偏移 这个地址是RVA,需要转换为FOA
通过NONAME关键字可以使部分导出函数没有名称仅有地址
关键成员
具体示例
假设:
导出函数名称表 FuncNameTable
导出函数序号表 FuncOridinalTable
导出函数地址表 FuncAddressTable
函数地址RVA FuncAddress
使用上一节的Dll函数
DLL的导出表信息
假设已知导出函数序号OridinalNum
那么FuncAddress=FuncAddressTable[OridinalNum-Base]
即导出函数序号-Base值可以直接作为下标查找导出函数地址表得到导出函数地址
已知函数sub的导出序号为3 所以3-1=2直接查找得到其地址
所以无名函数的序号可以通过遍历导出函数地址表来得到
通过函数名称查找函数地址的过程
首先查找导出函数名称表,判断数组中哪个字符串和目的函数名称相同
将该元素的下标作为索引,查找导出函数序号表
将导出函数序号表中该下标元素的内容作为下标查找导出函数地址表,该值即为函数地址
即
假设要查找plus函数
plus这个函数名在函数名称表中的下标为1
而FuncOridinalTable[1]=0
所以plus Address=FuncAddressTable[0]=1125d
由于导出函数地址表的大小=NumberOfFunctions=导出函数最大序号-最小序号
当序号不是连续时,就会用0地址填充多余表项
导出函数序号表存储的序号是真实序号-Base
所以序号最小的导出函数对应的存储序号是0
导出函数序号表中不保存无名称函数的序号
通过序号查找函数时,将序号值-Base直接作为下标查找导出函数地址表
代码
运行结果和PE工具显示的一致
运行结果
查看二进制文件
导出函数地址表 从7CC8开始共0xE个表项
导出函数序号表 从7D0C开始共2个表项 每个表项2字节
存储序号分别是0xe(f func1) 0x0(1 plus)
导出函数名称表 从7D04开始共2个表项 每个表项四字节 指向字符串指针
重定位的概念: 进程拥有独立的4GB虚拟空间,.exe最先被加载,其次加载.dll 显然exe可以占用默认基址400000起始的空间,但是dll默认基址10000000会有冲突
如果能按照预定ImageBase加载则不需要重定位表,所以很多exe程序没有重定位表但是dll有
部分编译生成的地址=ImageBase+RVA (VA绝对地址)
假设全局变量x的RVA=62153 基址400000
那么mov eax,[x] =A1 53 21 46 00
即一些指令中涉及到地址的硬编码是固定写好的(绝对地址)
如果dll模块没有加载到默认的基址处,那么这些使用绝对地址的指令就需要修正
重定位表则记录了需要修正的指令地址
重定位表定义
数据目录表中第6个表项指向了重定位表
重定位表是一块一块存储的,每块的大小不一定相等,通过重定位表起始地址+SizeOfBlock可以查找下一块数据
重定位表的每个块会存储每一页(1000h)需要修改的表项 VirtualAddress即是页面起始地址
所以真正需要修复的地址=VirtualAddress+表项地址
假设VirtualAddress=8000 表项存储 12 34 56 78
那么需要修改的地址为8012 8034 8056 8078 (不考虑下面的高四位标识)
每个重定位项占2字节 其中高四位用于表示这个地址是否需要修改,低12位用于存储偏移值
如果高四位=0011那么需要修改
注意: 由于内存对齐的需要,假设表项有5个共10字节,那么实际表项会多一个空项用于内存对齐
结束时重定位表结构全为0
查看重定位表
运行结果
数据目录表第2个表项是导入表,紧跟在导出表后
PE文件可能会有多个导入表以结构体数组形式存在,结束标识为全0
重要成员
OriginalFirstThunk 指向INT表
FirstThunk 指向IAT表
INT: 导入名称表 存储导入函数名称
IAT: 导入地址表 存储导入函数地址
这两张表的定义如下
IAT表中,该结构存储的是导入函数地址RVA
INT表中,该结构可能存储导入函数序号或者是导入函数名称结构地址RVA
IAT表有两种情况
在PE文件加载到内存前,两张表存储的内容一致,加载后修复IAT
PE加载前 INT和IAT都指向IMAGE_IMPORT_BY_NAME 即导入函数名称结构
加载到内存后 IAT表被修复 存储导入函数地址
PE文件加载前IAT表已经修复过
此时IAT已经保存了导入函数地址 地址=RVA+ImageBase,这就是绑定导入
导入表的TimeDateStamp为-1时表示已经进行绑定导入,如果为0表示没有绑定导入
优点: 启动程序快
缺点: 如果没有加载到正确基址仍然需要修复IAT表
以DllTest.dll为例,用PEStudy打开
上方区域有三张导入表,分别列出了dllname以及它们INT和IAT的位置
下方区域第一列是IAT表项(即导入函数地址) 第二列是INT表项的FOA(ThunkData) 第三列是INT表项指向的值(*ThunkData)
打印导入表的代码
运行结果
附: 示例程序和修改后的程序
typedef
struct
_IMAGE_DOS_HEADER {
WORD
e_magic;
WORD
e_cblp;
WORD
e_cp;
WORD
e_crlc;
WORD
e_cparhdr;
WORD
e_minalloc;
WORD
e_maxalloc;
WORD
e_ss;
WORD
e_sp;
WORD
e_csum;
WORD
e_ip;
WORD
e_cs;
WORD
e_lfarlc;
WORD
e_ovno;
WORD
e_res[4];
WORD
e_oemid;
WORD
e_oeminfo;
WORD
e_res2[10];
LONG
e_lfanew;
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
typedef
struct
_IMAGE_DOS_HEADER {
WORD
e_magic;
WORD
e_cblp;
WORD
e_cp;
WORD
e_crlc;
WORD
e_cparhdr;
WORD
e_minalloc;
WORD
e_maxalloc;
WORD
e_ss;
WORD
e_sp;
WORD
e_csum;
WORD
e_ip;
WORD
e_cs;
WORD
e_lfarlc;
WORD
e_ovno;
WORD
e_res[4];
WORD
e_oemid;
WORD
e_oeminfo;
WORD
e_res2[10];
LONG
e_lfanew;
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
typedef
struct
_IMAGE_NT_HEADERS {
DWORD
Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
typedef
struct
_IMAGE_NT_HEADERS {
DWORD
Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
typedef
struct
_IMAGE_NT_HEADERS64 {
DWORD
Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
typedef
struct
_IMAGE_NT_HEADERS64 {
DWORD
Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
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;
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;
typedef
struct
_IMAGE_OPTIONAL_HEADER {
WORD
Magic;
BYTE
MajorLinkerVersion;
BYTE
MinorLinkerVersion;
DWORD
SizeOfCode;
DWORD
SizeOfInitializedData;
DWORD
SizeOfUninitializedData;
DWORD
AddressOfEntryPoint;
DWORD
BaseOfCode;
DWORD
BaseOfData;
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_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
typedef
struct
_IMAGE_OPTIONAL_HEADER {
WORD
Magic;
BYTE
MajorLinkerVersion;
BYTE
MinorLinkerVersion;
DWORD
SizeOfCode;
DWORD
SizeOfInitializedData;
DWORD
SizeOfUninitializedData;
DWORD
AddressOfEntryPoint;
DWORD
BaseOfCode;
DWORD
BaseOfData;
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_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
AddressOfEntryPoint;
ImageBase;
SectionAlignment;
FileAlignment;
SizeOfImage;
SizeOfHeaders;
NumberOfRvaAndSizes
DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]
AddressOfEntryPoint;
ImageBase;
SectionAlignment;
FileAlignment;
SizeOfImage;
SizeOfHeaders;
NumberOfRvaAndSizes
DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]
typedef
struct
_IMAGE_SECTION_HEADER {
BYTE
Name[IMAGE_SIZEOF_SHORT_NAME];
unio{
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;
typedef
struct
_IMAGE_SECTION_HEADER {
BYTE
Name[IMAGE_SIZEOF_SHORT_NAME];
unio{
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;
void
showSectionHeaders() {
printf
(
"\n----------SectionHeaders----------\n"
);
for
(
DWORD
i = 0; i < numberOfSections; i++) {
printf
(
"\n----------Section%d----------\n"
, i);
printf
(
"Name: %8s\n"
, pSectionHeader[i].Name);
printf
(
"VirtualSize: %x\n"
, pSectionHeader[i].Misc.VirtualSize);
printf
(
"VirtualAddress: %x\n"
, pSectionHeader[i].VirtualAddress);
printf
(
"SizeOfRawData: %x\n"
, pSectionHeader[i].SizeOfRawData);
printf
(
"PointerToRawData: %x\n"
, pSectionHeader[i].PointerToRawData);
printf
(
"Characteristics: %x\n"
, pSectionHeader[i].Characteristics);
printf
(
"\n----------Section%d----------\n"
, i);
}
printf
(
"\n----------SectionHeaders----------\n"
);
}
void
showSectionHeaders() {
printf
(
"\n----------SectionHeaders----------\n"
);
for
(
DWORD
i = 0; i < numberOfSections; i++) {
printf
(
"\n----------Section%d----------\n"
, i);
printf
(
"Name: %8s\n"
, pSectionHeader[i].Name);
printf
(
"VirtualSize: %x\n"
, pSectionHeader[i].Misc.VirtualSize);
printf
(
"VirtualAddress: %x\n"
, pSectionHeader[i].VirtualAddress);
printf
(
"SizeOfRawData: %x\n"
, pSectionHeader[i].SizeOfRawData);
printf
(
"PointerToRawData: %x\n"
, pSectionHeader[i].PointerToRawData);
printf
(
"Characteristics: %x\n"
, pSectionHeader[i].Characteristics);
printf
(
"\n----------Section%d----------\n"
, i);
}
printf
(
"\n----------SectionHeaders----------\n"
);
}
#include <Windows.h>
#include <stdio.h>
int
main() {
MessageBox(0, L
"HelloWorld!"
, L
"Title"
, 0);
return
0;
}
#include <Windows.h>
#include <stdio.h>
int
main() {
MessageBox(0, L
"HelloWorld!"
, L
"Title"
, 0);
return
0;
}
Name
VirtualAddress
SizeOfRawData
PointerToRawData
Characteristics
NumberOfSections
SizeOfImage
Name
VirtualAddress
SizeOfRawData
PointerToRawData
Characteristics
NumberOfSections
SizeOfImage
PIMAGE_SECTION_HEADER CreateNewSection(
const
char
* NewSectionName,
DWORD
NewSectionSize) {
DWORD
BlankMemAddr = (NToffset +
sizeof
(IMAGE_NT_HEADERS)) + numberOfSections *
sizeof
(IMAGE_SECTION_HEADER);
DWORD
BlankMemSize = sizeOfHeaders - BlankMemAddr;
if
(BlankMemSize <
sizeof
(IMAGE_SECTION_HEADER) * 2)
return
NULL;
ExpandFileBuffer(NewSectionSize);
PIMAGE_SECTION_HEADER pNewSectionHeader = (PIMAGE_SECTION_HEADER)(FileBuffer + BlankMemAddr);
for
(
DWORD
i = 0; i < numberOfSections; i++) {
if
(!
strcmp
((
char
*)pSectionHeader[i].Name,
".text"
))
{
memcpy
(pNewSectionHeader, (
LPVOID
)&pSectionHeader[i],
sizeof
(IMAGE_SECTION_HEADER));
break
;
}
}
pFileHeader->NumberOfSections = ++numberOfSections;
memcpy
(pNewSectionHeader->Name, NewSectionName,
strlen
(NewSectionName));
pNewSectionHeader->Misc.VirtualSize = NewSectionSize;
pNewSectionHeader->VirtualAddress = AlignSize(pSectionHeader[numberOfSections - 2].VirtualAddress + pSectionHeader[numberOfSections - 2].SizeOfRawData, 0x1000);
pNewSectionHeader->SizeOfRawData = NewSectionSize;
pNewSectionHeader->PointerToRawData = pSectionHeader[numberOfSections - 2].PointerToRawData + pSectionHeader[numberOfSections - 2].SizeOfRawData;
pNewSectionHeader->Characteristics |= 0x20000000;
pOptionalHeader->SizeOfImage = sizeOfImage = sizeOfImage + AlignSize(NewSectionSize,0x1000);
return
pNewSectionHeader;
}
BOOL
InjectCodeByCreateNewSection() {
PIMAGE_SECTION_HEADER pNewSectionHeader = CreateNewSection(
".inject"
, 0x1000);
DWORD
OEP = addressOfEntryPoint;
pOptionalHeader->DllCharacteristics &= 0xFFFFFFBF;
pOptionalHeader->AddressOfEntryPoint = addressOfEntryPoint= pNewSectionHeader->VirtualAddress;
BYTE
InjectCode[18] = {
0x6a,0x00,
0x6a,0x00,
0x6a,0x00,
0x6a,0x00,
0xe8,0x00,0x00,0x00,0x00,
0xe9,0x00,0x00,0x00,0x00
};
DWORD
MessageBoxAddr = 0x76260E50;
*(
DWORD
*)&InjectCode[9] =OffsetOfCallAndJmp(MessageBoxAddr, imageBase + pNewSectionHeader->VirtualAddress+8) ;
*(
DWORD
*)&InjectCode[14] = OffsetOfCallAndJmp(OEP, pNewSectionHeader->VirtualAddress + 13);
memcpy
(FileBuffer + pNewSectionHeader->PointerToRawData, InjectCode,
sizeof
(InjectCode));
return
FileBufferWriteToFile(L
"InjectCodeByCreateNewSection1.exe"
);
}
PIMAGE_SECTION_HEADER CreateNewSection(
const
char
* NewSectionName,
DWORD
NewSectionSize) {
DWORD
BlankMemAddr = (NToffset +
sizeof
(IMAGE_NT_HEADERS)) + numberOfSections *
sizeof
(IMAGE_SECTION_HEADER);
DWORD
BlankMemSize = sizeOfHeaders - BlankMemAddr;
if
(BlankMemSize <
sizeof
(IMAGE_SECTION_HEADER) * 2)
return
NULL;
ExpandFileBuffer(NewSectionSize);
PIMAGE_SECTION_HEADER pNewSectionHeader = (PIMAGE_SECTION_HEADER)(FileBuffer + BlankMemAddr);
for
(
DWORD
i = 0; i < numberOfSections; i++) {
if
(!
strcmp
((
char
*)pSectionHeader[i].Name,
".text"
))
{
memcpy
(pNewSectionHeader, (
LPVOID
)&pSectionHeader[i],
sizeof
(IMAGE_SECTION_HEADER));
break
;
}
}
pFileHeader->NumberOfSections = ++numberOfSections;
memcpy
(pNewSectionHeader->Name, NewSectionName,
strlen
(NewSectionName));
pNewSectionHeader->Misc.VirtualSize = NewSectionSize;
pNewSectionHeader->VirtualAddress = AlignSize(pSectionHeader[numberOfSections - 2].VirtualAddress + pSectionHeader[numberOfSections - 2].SizeOfRawData, 0x1000);
pNewSectionHeader->SizeOfRawData = NewSectionSize;
pNewSectionHeader->PointerToRawData = pSectionHeader[numberOfSections - 2].PointerToRawData + pSectionHeader[numberOfSections - 2].SizeOfRawData;
pNewSectionHeader->Characteristics |= 0x20000000;
pOptionalHeader->SizeOfImage = sizeOfImage = sizeOfImage + AlignSize(NewSectionSize,0x1000);
return
pNewSectionHeader;
}
BOOL
InjectCodeByCreateNewSection() {
PIMAGE_SECTION_HEADER pNewSectionHeader = CreateNewSection(
".inject"
, 0x1000);
DWORD
OEP = addressOfEntryPoint;
pOptionalHeader->DllCharacteristics &= 0xFFFFFFBF;
pOptionalHeader->AddressOfEntryPoint = addressOfEntryPoint= pNewSectionHeader->VirtualAddress;
BYTE
InjectCode[18] = {
0x6a,0x00,
0x6a,0x00,
0x6a,0x00,
0x6a,0x00,
0xe8,0x00,0x00,0x00,0x00,
0xe9,0x00,0x00,0x00,0x00
};
DWORD
MessageBoxAddr = 0x76260E50;
*(
DWORD
*)&InjectCode[9] =OffsetOfCallAndJmp(MessageBoxAddr, imageBase + pNewSectionHeader->VirtualAddress+8) ;
*(
DWORD
*)&InjectCode[14] = OffsetOfCallAndJmp(OEP, pNewSectionHeader->VirtualAddress + 13);
memcpy
(FileBuffer + pNewSectionHeader->PointerToRawData, InjectCode,
sizeof
(InjectCode));
return
FileBufferWriteToFile(L
"InjectCodeByCreateNewSection1.exe"
);
}
SizeOfRawData
VirtualSize
SizeOfImage
SizeOfRawData
VirtualSize
SizeOfImage
BOOL
ExpandSection(
DWORD
ExSize) {
ExpandFileBuffer(ExSize);
PIMAGE_SECTION_HEADER pLastSectionHeader = &pSectionHeader[numberOfSections - 1];
DWORD
AlignExImage = AlignSize(pLastSectionHeader->Misc.VirtualSize + ExSize, 0x1000) -
AlignSize(max(pLastSectionHeader->Misc.VirtualSize, pLastSectionHeader->SizeOfRawData), 0x1000);
if
(AlignExImage >0)
pOptionalHeader->SizeOfImage = sizeOfImage = sizeOfImage + AlignExImage;
pLastSectionHeader->SizeOfRawData += AlignSize(ExSize, 0x200);
pLastSectionHeader->Misc.VirtualSize += ExSize;
return
FileBufferWriteToFile(L
"ExpandSectionFile.exe"
);
}
BOOL
ExpandSection(
DWORD
ExSize) {
ExpandFileBuffer(ExSize);
PIMAGE_SECTION_HEADER pLastSectionHeader = &pSectionHeader[numberOfSections - 1];
DWORD
AlignExImage = AlignSize(pLastSectionHeader->Misc.VirtualSize + ExSize, 0x1000) -
AlignSize(max(pLastSectionHeader->Misc.VirtualSize, pLastSectionHeader->SizeOfRawData), 0x1000);
if
(AlignExImage >0)
pOptionalHeader->SizeOfImage = sizeOfImage = sizeOfImage + AlignExImage;
pLastSectionHeader->SizeOfRawData += AlignSize(ExSize, 0x200);
pLastSectionHeader->Misc.VirtualSize += ExSize;
return
FileBufferWriteToFile(L
"ExpandSectionFile.exe"
);
}
BOOL
CombineSection() {
PIMAGE_DOS_HEADER pDosHeaderOfImage = (PIMAGE_DOS_HEADER)imageBuffer;
PIMAGE_NT_HEADERS pNtHeadersOfImage = (PIMAGE_NT_HEADERS)(imageBuffer + pDosHeader->e_lfanew);
PIMAGE_FILE_HEADER pFileHeaderOfImage = (PIMAGE_FILE_HEADER)(&pNtHeadersOfImage->FileHeader);
PIMAGE_OPTIONAL_HEADER pOptionalHeaderOfImage = (PIMAGE_OPTIONAL_HEADER)(&pNtHeadersOfImage->OptionalHeader);
PIMAGE_SECTION_HEADER pSectionHeaderOfImage = (PIMAGE_SECTION_HEADER)((
DWORD
)pOptionalHeaderOfImage + pFileHeaderOfImage->SizeOfOptionalHeader);
for
(
DWORD
i = 1; i < numberOfSections; i++) {
pSectionHeaderOfImage[0].Characteristics |= pSectionHeaderOfImage[i].Characteristics;
}
pSectionHeaderOfImage[0].PointerToRawData = pSectionHeaderOfImage[0].VirtualAddress;
pSectionHeaderOfImage[0].Misc.VirtualSize = pSectionHeaderOfImage[0].SizeOfRawData = sizeOfImage - pSectionHeaderOfImage[0].VirtualAddress;
pOptionalHeaderOfImage->SizeOfHeaders = AlignSize(sizeOfHeaders - (numberOfSections - 1) *
sizeof
(IMAGE_SECTION_HEADER), 0x200);
memset
(&pSectionHeaderOfImage[1], 0,
sizeof
(IMAGE_SECTION_HEADER) * (numberOfSections - 1));
pFileHeaderOfImage->NumberOfSections = 1;
return
ImageBufferWriteToFile(L
"CombineSectionFromDailyExercise.exe"
);
}
BOOL
CombineSection() {
PIMAGE_DOS_HEADER pDosHeaderOfImage = (PIMAGE_DOS_HEADER)imageBuffer;
PIMAGE_NT_HEADERS pNtHeadersOfImage = (PIMAGE_NT_HEADERS)(imageBuffer + pDosHeader->e_lfanew);
PIMAGE_FILE_HEADER pFileHeaderOfImage = (PIMAGE_FILE_HEADER)(&pNtHeadersOfImage->FileHeader);
PIMAGE_OPTIONAL_HEADER pOptionalHeaderOfImage = (PIMAGE_OPTIONAL_HEADER)(&pNtHeadersOfImage->OptionalHeader);
PIMAGE_SECTION_HEADER pSectionHeaderOfImage = (PIMAGE_SECTION_HEADER)((
DWORD
)pOptionalHeaderOfImage + pFileHeaderOfImage->SizeOfOptionalHeader);
for
(
DWORD
i = 1; i < numberOfSections; i++) {
pSectionHeaderOfImage[0].Characteristics |= pSectionHeaderOfImage[i].Characteristics;
}
pSectionHeaderOfImage[0].PointerToRawData = pSectionHeaderOfImage[0].VirtualAddress;
pSectionHeaderOfImage[0].Misc.VirtualSize = pSectionHeaderOfImage[0].SizeOfRawData = sizeOfImage - pSectionHeaderOfImage[0].VirtualAddress;
pOptionalHeaderOfImage->SizeOfHeaders = AlignSize(sizeOfHeaders - (numberOfSections - 1) *
sizeof
(IMAGE_SECTION_HEADER), 0x200);
memset
(&pSectionHeaderOfImage[1], 0,
sizeof
(IMAGE_SECTION_HEADER) * (numberOfSections - 1));
pFileHeaderOfImage->NumberOfSections = 1;
return
ImageBufferWriteToFile(L
"CombineSectionFromDailyExercise.exe"
);
}
DWORD
RVA2FOA(
DWORD
RVA) {
DWORD
FOA = 0;
for
(
DWORD
i = 0; i < numberOfSections; i++) {
if
(RVA >= pSectionHeader[i].VirtualAddress && RVA < pSectionHeader[i].VirtualAddress + AlignSize(pSectionHeader[i].Misc.VirtualSize, 0x1000))
{
FOA = RVA - pSectionHeader[i].VirtualAddress + pSectionHeader[i].PointerToRawData;
break
;
}
}
return
FOA;
}
DWORD
FOA2RVA(
DWORD
FOA) {
DWORD
RVA = 0;
for
(
DWORD
i = 0; i < numberOfSections; i++) {
if
(FOA >= pSectionHeader[i].PointerToRawData && FOA < pSectionHeader[i].PointerToRawData + pSectionHeader[i].SizeOfRawData) {
RVA = FOA - pSectionHeader[i].PointerToRawData + pSectionHeader[i].VirtualAddress;
break
;
}
}
return
RVA;
}
DWORD
AlignSize(
DWORD
OrigSize,
DWORD
AlignVal) {
return
OrigSize % AlignVal ? (OrigSize / AlignVal + 1) * AlignVal : OrigSize;
}
DWORD
RVA2FOA(
DWORD
RVA) {
DWORD
FOA = 0;
for
(
DWORD
i = 0; i < numberOfSections; i++) {
if
(RVA >= pSectionHeader[i].VirtualAddress && RVA < pSectionHeader[i].VirtualAddress + AlignSize(pSectionHeader[i].Misc.VirtualSize, 0x1000))
{
FOA = RVA - pSectionHeader[i].VirtualAddress + pSectionHeader[i].PointerToRawData;
break
;
}
}
return
FOA;
}
DWORD
FOA2RVA(
DWORD
FOA) {
DWORD
RVA = 0;
for
(
DWORD
i = 0; i < numberOfSections; i++) {
if
(FOA >= pSectionHeader[i].PointerToRawData && FOA < pSectionHeader[i].PointerToRawData + pSectionHeader[i].SizeOfRawData) {
RVA = FOA - pSectionHeader[i].PointerToRawData + pSectionHeader[i].VirtualAddress;
break
;
}
}
return
RVA;
}
DWORD
AlignSize(
DWORD
OrigSize,
DWORD
AlignVal) {
return
OrigSize % AlignVal ? (OrigSize / AlignVal + 1) * AlignVal : OrigSize;
}
#include <stdio.h>
void
func() {
printf
(
"HelloStaticLib!"
);
}
void
func();
#include <stdio.h>
void
func() {
printf
(
"HelloStaticLib!"
);
}
void
func();
#include <stdio.h>
#include "StaticLib.h" //导入头文件,头文件有函数声明
#pragma comment(lib,"StaticLib.lib")//加载静态库,这里保存函数二进制代码
int
main() {
func();
return
0;
}
#include <stdio.h>
#include "StaticLib.h" //导入头文件,头文件有函数声明
#pragma comment(lib,"StaticLib.lib")//加载静态库,这里保存函数二进制代码
int
main() {
func();
return
0;
}
extern
"C"
__declspec
(
dllexport
)
extern
"C"
__declspec
(
dllexport
)
extern
"C"
__declspec
(
dllexport
)
void
func();
#include<stdio.h>
extern
"C"
__declspec
(
dllexport
)
void
func() {
printf
(
"HelloDynamicLib!"
);
}
extern
"C"
__declspec
(
dllexport
)
void
func();
#include<stdio.h>
extern
"C"
__declspec
(
dllexport
)
void
func() {
printf
(
"HelloDynamicLib!"
);
}
#include<stdio.h>
void
func1() {
printf
(
"HelloDynamicLib!"
);
}
int
plus(
int
x,
int
y) {
return
x + y;
}
int
sub(
int
x,
int
y) {
return
x - y;
}
LIBRARY
"DllTest"
EXPORTS
func1 @15
plus @1
sub @3 NONAME
#include<stdio.h>
void
func1() {
printf
(
"HelloDynamicLib!"
);
}
int
plus(
int
x,
int
y) {
return
x + y;
}
int
sub(
int
x,
int
y) {
return
x - y;
}
LIBRARY
"DllTest"
EXPORTS
func1 @15
plus @1
sub @3 NONAME
#pragma comment(lib,"DllTest.lib") //导入.lib
extern
"C"
__declspec
(
dllimport
)
void
func();
int
main() {
func();
return
0;
}
#pragma comment(lib,"DllTest.lib") //导入.lib
extern
"C"
__declspec
(
dllimport
)
void
func();
int
main() {
func();
return
0;
}
typedef
int
(__stdcall *lpPlus)(
int
,
int
);
lpPlus plus;
HINSTANCE
hModule=LoadLibrary(
"Dllname.dll"
);
plus=(lpPlus)GetProcAddress(hModule,
"_Plus@8"
);
int
a=plus(1,2);
typedef
int
(__stdcall *lpPlus)(
int
,
int
);
lpPlus plus;
HINSTANCE
hModule=LoadLibrary(
"Dllname.dll"
);
plus=(lpPlus)GetProcAddress(hModule,
"_Plus@8"
);
int
a=plus(1,2);
#include<Windows.h>//包含了win32的函数和数据结构
#include<stdio.h>
int
main() {
typedef
int
(*lpPlus)(
int
,
int
);
lpPlus plus;
HINSTANCE
hModule = LoadLibrary(L
"DllTest.dll"
);
plus = (lpPlus)GetProcAddress(hModule,
"plus"
);
printf
(
"%d"
, plus(1, 2));
return
0;
}
#include<Windows.h>//包含了win32的函数和数据结构
#include<stdio.h>
int
main() {
typedef
int
(*lpPlus)(
int
,
int
);
lpPlus plus;
HINSTANCE
hModule = LoadLibrary(L
"DllTest.dll"
);
plus = (lpPlus)GetProcAddress(hModule,
"plus"
);
printf
(
"%d"
, plus(1, 2));
return
0;
}
typedef
struct
_IMAGE_DATA_DIRECTORY {
DWORD
VirtualAddress;
DWORD
Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
typedef
struct
_IMAGE_DATA_DIRECTORY {
DWORD
VirtualAddress;
DWORD
Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
#define IMAGE_DIRECTORY_ENTRY_EXPORT //0 导出表
#define IMAGE_DIRECTORY_ENTRY_IMPORT //1 导入表
#define IMAGE_DIRECTORY_ENTRY_RESOURCE //2 资源目录
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION //3 异常目录
#define IMAGE_DIRECTORY_ENTRY_SECURITY //4 安全目录
#define IMAGE_DIRECTORY_ENTRY_BASERELOC //5 重定位基本表
#define IMAGE_DIRECTORY_ENTRY_DEBUG //6 调试目录
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT //7 描述字串 64位为ARCHITECTURE
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR //8 机器值
#define IMAGE_DIRECTORY_ENTRY_TLS //9 TLS目录
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG //10 载入配值目录
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT //11 绑定输入表
#define IMAGE_DIRECTORY_ENTRY_IAT //12 导入地址表
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT //13 延迟载入描述
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR//14 COM信息
#define IMAGE_DIRECTORY_ENTRY_EXPORT //0 导出表
#define IMAGE_DIRECTORY_ENTRY_IMPORT //1 导入表
#define IMAGE_DIRECTORY_ENTRY_RESOURCE //2 资源目录
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION //3 异常目录
#define IMAGE_DIRECTORY_ENTRY_SECURITY //4 安全目录
#define IMAGE_DIRECTORY_ENTRY_BASERELOC //5 重定位基本表
#define IMAGE_DIRECTORY_ENTRY_DEBUG //6 调试目录
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT //7 描述字串 64位为ARCHITECTURE
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR //8 机器值
#define IMAGE_DIRECTORY_ENTRY_TLS //9 TLS目录
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG //10 载入配值目录
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT //11 绑定输入表
#define IMAGE_DIRECTORY_ENTRY_IAT //12 导入地址表
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT //13 延迟载入描述
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR//14 COM信息
DWORD
NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
DWORD
NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
void
PrintDirectory() {
PIMAGE_DATA_DIRECTORY pDirectory = pOptionalHeader->DataDirectory;
printf
(
"\n**********数据目录表**********\n"
);
for
(
DWORD
i = 0; i < pOptionalHeader->NumberOfRvaAndSizes; i++) {
switch
(i) {
case
IMAGE_DIRECTORY_ENTRY_EXPORT:
printf
(
"\n==========导出表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_IMPORT:
printf
(
"\n==========导入表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_RESOURCE:
printf
(
"\n==========资源目录==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_EXCEPTION:
printf
(
"\n==========异常目录==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_SECURITY:
printf
(
"\n==========安全目录=========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_BASERELOC:
printf
(
"\n==========重定位基本表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_DEBUG:
printf
(
"\n==========调试目录==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE:
printf
(
"\n==========描述字串==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_GLOBALPTR:
printf
(
"\n==========机器值==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_TLS:
printf
(
"\n==========TLS目录==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG:
printf
(
"\n==========载入配置目录==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT:
printf
(
"\n==========绑定输入表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_IAT:
printf
(
"\n==========导入地址表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT:
printf
(
"\n==========延迟导入表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR:
printf
(
"\n==========COM信息==========\n"
);
break
;
case
15:
printf
(
"\n==========保留表==========\n"
);
break
;
}
printf
(
"VirtualAddress=%x\nSize=%x\nFOA=%x\n"
, pDirectory[i].VirtualAddress, pDirectory[i].Size,RVA2FOA(pDirectory[i].VirtualAddress));
}
printf
(
"\n**********数据目录表打印完毕**********\n\n"
);
}
void
PrintDirectory() {
PIMAGE_DATA_DIRECTORY pDirectory = pOptionalHeader->DataDirectory;
printf
(
"\n**********数据目录表**********\n"
);
for
(
DWORD
i = 0; i < pOptionalHeader->NumberOfRvaAndSizes; i++) {
switch
(i) {
case
IMAGE_DIRECTORY_ENTRY_EXPORT:
printf
(
"\n==========导出表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_IMPORT:
printf
(
"\n==========导入表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_RESOURCE:
printf
(
"\n==========资源目录==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_EXCEPTION:
printf
(
"\n==========异常目录==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_SECURITY:
printf
(
"\n==========安全目录=========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_BASERELOC:
printf
(
"\n==========重定位基本表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_DEBUG:
printf
(
"\n==========调试目录==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE:
printf
(
"\n==========描述字串==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_GLOBALPTR:
printf
(
"\n==========机器值==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_TLS:
printf
(
"\n==========TLS目录==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG:
printf
(
"\n==========载入配置目录==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT:
printf
(
"\n==========绑定输入表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_IAT:
printf
(
"\n==========导入地址表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT:
printf
(
"\n==========延迟导入表==========\n"
);
break
;
case
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR:
printf
(
"\n==========COM信息==========\n"
);
break
;
case
15:
printf
(
"\n==========保留表==========\n"
);
break
;
}
printf
(
"VirtualAddress=%x\nSize=%x\nFOA=%x\n"
, pDirectory[i].VirtualAddress, pDirectory[i].Size,RVA2FOA(pDirectory[i].VirtualAddress));
}
printf
(
"\n**********数据目录表打印完毕**********\n\n"
);
}
typedef
struct
_IMAGE_EXPORT_DIRECTORY {
DWORD
Characteristics;
DWORD
TimeDateStamp;
WORD
MajorVersion;
WORD
MinorVersion;
DWORD
Name;
DWORD
Base;
DWORD
NumberOfFunctions;
DWORD
NumberOfNames;
DWORD
AddressOfFunctions;
DWORD
AddressOfNames;
DWORD
AddressOfNameOrdinals;
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
typedef
struct
_IMAGE_EXPORT_DIRECTORY {
DWORD
Characteristics;
DWORD
TimeDateStamp;
WORD
MajorVersion;
WORD
MinorVersion;
DWORD
Name;
DWORD
Base;
DWORD
NumberOfFunctions;
DWORD
NumberOfNames;
DWORD
AddressOfFunctions;
DWORD
AddressOfNames;
DWORD
AddressOfNameOrdinals;
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
Name
Base
NumberOfFunctions
NumberOfNames
AddressOfFunctions
AddressOfNames
AddressOfNameOrdinals
Name
Base
NumberOfFunctions
NumberOfNames
AddressOfFunctions
AddressOfNames
AddressOfNameOrdinals
LIBRARY
"DllTest"
EXPORTS
func1 @15
plus @1
sub @3 NONAME
#include<stdio.h>
#include<windows.h>
void
func1() {
printf
(
"HelloDynamicLib!"
);
}
int
plus(
int
x,
int
y) {
return
x + y;
}
int
sub(
int
x,
int
y) {
return
x - y;
}
LIBRARY
"DllTest"
EXPORTS
func1 @15
plus @1
sub @3 NONAME
#include<stdio.h>
#include<windows.h>
void
func1() {
printf
(
"HelloDynamicLib!"
);
}
int
plus(
int
x,
int
y) {
return
x + y;
}
int
sub(
int
x,
int
y) {
return
x - y;
}
if
(
strcmp
(name,FuncNameTable[i])==0)
FuncAddress=FuncAddressTable[FuncOridinalTable[i]];
if
(
strcmp
(name,FuncNameTable[i])==0)
FuncAddress=FuncAddressTable[FuncOridinalTable[i]];
DWORD
GetFuncAddrByOridinals(
WORD
OridinalNum) {
DWORD
* pExportFuncAddressTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfFunctions) + FileBuffer);
return
pExportFuncAddressTable[OridinalNum - pExportDirectory->Base];
}
DWORD
GetFuncAddrByOridinals(
WORD
OridinalNum) {
DWORD
* pExportFuncAddressTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfFunctions) + FileBuffer);
return
pExportFuncAddressTable[OridinalNum - pExportDirectory->Base];
}
DWORD
GetFuncAddrByName(
const
char
* FuncName) {
WORD
* pExportFuncOridinalsTable = (
WORD
*)(RVA2FOA(pExportDirectory->AddressOfNameOrdinals) + FileBuffer);
DWORD
* pExportFuncAddressTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfFunctions) + FileBuffer);
DWORD
* pExportFuncNamesTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfNames) + FileBuffer);
DWORD
pos = -1,OridinalNum=0;
for
(
DWORD
i = 0; i < pExportDirectory->NumberOfNames; i++) {
if
(
strcmp
(FuncName, (
char
*)(RVA2FOA(pExportFuncNamesTable[i])+FileBuffer)) == 0)
{
pos = i;
break
;
}
}
if
(pos == -1)
return
0;
OridinalNum = pExportFuncOridinalsTable[pos];
return
pExportFuncAddressTable[OridinalNum];
}
DWORD
GetFuncAddrByName(
const
char
* FuncName) {
WORD
* pExportFuncOridinalsTable = (
WORD
*)(RVA2FOA(pExportDirectory->AddressOfNameOrdinals) + FileBuffer);
DWORD
* pExportFuncAddressTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfFunctions) + FileBuffer);
DWORD
* pExportFuncNamesTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfNames) + FileBuffer);
DWORD
pos = -1,OridinalNum=0;
for
(
DWORD
i = 0; i < pExportDirectory->NumberOfNames; i++) {
if
(
strcmp
(FuncName, (
char
*)(RVA2FOA(pExportFuncNamesTable[i])+FileBuffer)) == 0)
{
pos = i;
break
;
}
}
if
(pos == -1)
return
0;
OridinalNum = pExportFuncOridinalsTable[pos];
return
pExportFuncAddressTable[OridinalNum];
}
BYTE
* GetFuncNameByOridinals(
WORD
OridinalNum) {
WORD
* pExportFuncOridinalsTable = (
WORD
*)(RVA2FOA(pExportDirectory->AddressOfNameOrdinals) + FileBuffer);
DWORD
* pExportFuncNamesTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfNames) + FileBuffer);
for
(
DWORD
i = 0; i < pExportDirectory->NumberOfNames; i++)
{
if
(pExportFuncOridinalsTable[i] == OridinalNum)
return
RVA2FOA(pExportFuncNamesTable[i])+FileBuffer;
}
return
NULL;
}
void
PrintExportDirectory() {
printf
(
"\n==========导出表==========\n"
);
printf
(
"Name: %x (%s)\n"
,pExportDirectory->Name,(
char
*)(FileBuffer+RVA2FOA(pExportDirectory->Name)));
printf
(
"Base: %x\n"
, pExportDirectory->Base);
printf
(
"NumberOfFunctions: \t%x\n"
, pExportDirectory->NumberOfFunctions);
printf
(
"NumberOfNames: \t\t%x\n"
, pExportDirectory->NumberOfNames);
printf
(
"AddressOfFunctions: \tRVA=%x\tFOA=%x\n"
, pExportDirectory->AddressOfFunctions,RVA2FOA(pExportDirectory->AddressOfFunctions));
printf
(
"AddressOfNames: \tRVA=%x\tFOA=%x\n"
, pExportDirectory->AddressOfNames, RVA2FOA(pExportDirectory->AddressOfNames));
printf
(
"AddressOfNameOrdinals: \tRVA=%x\tFOA=%x\n"
, pExportDirectory->AddressOfNameOrdinals , RVA2FOA(pExportDirectory->AddressOfNameOrdinals));
WORD
* pExportFuncOridinalsTable =(
WORD
*)(RVA2FOA(pExportDirectory->AddressOfNameOrdinals) + FileBuffer);
DWORD
* pExportFuncAddressTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfFunctions)+ FileBuffer);
DWORD
* pExportFuncNamesTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfNames )+ FileBuffer);
printf
(
"\nOridinal\t RVA\t FOA\tFunctionName\n"
);
for
(
DWORD
i = 0; i < pExportDirectory->NumberOfFunctions; i++) {
if
(pExportFuncAddressTable[i] == 0)
continue
;
BYTE
* FuncName = NULL;
printf
(
"%08x\t%08x\t%08x\t"
,i+pExportDirectory->Base, pExportFuncAddressTable[i],RVA2FOA(pExportFuncAddressTable[i]));
if
(FuncName = GetFuncNameByOridinals(i))
printf
(
"%s\n"
, FuncName);
else
printf
(
"NONAME\n"
);
}
printf
(
"\n==========导出表结束==========\n"
);
}
BYTE
* GetFuncNameByOridinals(
WORD
OridinalNum) {
WORD
* pExportFuncOridinalsTable = (
WORD
*)(RVA2FOA(pExportDirectory->AddressOfNameOrdinals) + FileBuffer);
DWORD
* pExportFuncNamesTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfNames) + FileBuffer);
for
(
DWORD
i = 0; i < pExportDirectory->NumberOfNames; i++)
{
if
(pExportFuncOridinalsTable[i] == OridinalNum)
return
RVA2FOA(pExportFuncNamesTable[i])+FileBuffer;
}
return
NULL;
}
void
PrintExportDirectory() {
printf
(
"\n==========导出表==========\n"
);
printf
(
"Name: %x (%s)\n"
,pExportDirectory->Name,(
char
*)(FileBuffer+RVA2FOA(pExportDirectory->Name)));
printf
(
"Base: %x\n"
, pExportDirectory->Base);
printf
(
"NumberOfFunctions: \t%x\n"
, pExportDirectory->NumberOfFunctions);
printf
(
"NumberOfNames: \t\t%x\n"
, pExportDirectory->NumberOfNames);
printf
(
"AddressOfFunctions: \tRVA=%x\tFOA=%x\n"
, pExportDirectory->AddressOfFunctions,RVA2FOA(pExportDirectory->AddressOfFunctions));
printf
(
"AddressOfNames: \tRVA=%x\tFOA=%x\n"
, pExportDirectory->AddressOfNames, RVA2FOA(pExportDirectory->AddressOfNames));
printf
(
"AddressOfNameOrdinals: \tRVA=%x\tFOA=%x\n"
, pExportDirectory->AddressOfNameOrdinals , RVA2FOA(pExportDirectory->AddressOfNameOrdinals));
WORD
* pExportFuncOridinalsTable =(
WORD
*)(RVA2FOA(pExportDirectory->AddressOfNameOrdinals) + FileBuffer);
DWORD
* pExportFuncAddressTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfFunctions)+ FileBuffer);
DWORD
* pExportFuncNamesTable = (
DWORD
*)(RVA2FOA(pExportDirectory->AddressOfNames )+ FileBuffer);
printf
(
"\nOridinal\t RVA\t FOA\tFunctionName\n"
);
for
(
DWORD
i = 0; i < pExportDirectory->NumberOfFunctions; i++) {
if
(pExportFuncAddressTable[i] == 0)
continue
;
BYTE
* FuncName = NULL;
printf
(
"%08x\t%08x\t%08x\t"
,i+pExportDirectory->Base, pExportFuncAddressTable[i],RVA2FOA(pExportFuncAddressTable[i]));
if
(FuncName = GetFuncNameByOridinals(i))
printf
(
"%s\n"
, FuncName);
else
printf
(
"NONAME\n"
);
}
printf
(
"\n==========导出表结束==========\n"
);
}
typedef
struct
_IMAGE_BASE_RELOCATION {
DWORD
VirtualAddress;
DWORD
SizeOfBlock;
} IMAGE_BASE_RELOCATION;
typedef
IMAGE_BASE_RELOCATION*,PIMAGE_BASE_RELOCATION;
typedef
struct
_IMAGE_BASE_RELOCATION {
DWORD
VirtualAddress;
DWORD
SizeOfBlock;
} IMAGE_BASE_RELOCATION;
typedef
IMAGE_BASE_RELOCATION*,PIMAGE_BASE_RELOCATION;
PCHAR
GetSectionNameByRva(
DWORD
RVA) {
for
(
DWORD
i = 0; i < numberOfSections; i++) {
if
(RVA >= pSectionHeader[i].VirtualAddress && RVA < pSectionHeader[i].VirtualAddress + AlignSize(pSectionHeader[i].Misc.VirtualSize, 0x1000))
return
(
PCHAR
)pSectionHeader[i].Name;
}
}
void
PrintRelocationBlock(PIMAGE_BASE_RELOCATION pRelocationBlock) {
PWORD
pBlock = (
PWORD
)((
DWORD
)pRelocationBlock + 8);
DWORD
PageOffset = pRelocationBlock->VirtualAddress;
printf
(
"序号\t属性\t RVA\t FOA\t指向RVA\n"
);
for
(
DWORD
i = 0; i < (pRelocationBlock->SizeOfBlock - 8) / 2; i++) {
printf
(
"%04x\t%4x\t%08x\t%08x\t%08x\n"
, i, pBlock[i] >> 12, (pBlock[i] & 0x0fff) + PageOffset, RVA2FOA((pBlock[i] & 0x0fff) + PageOffset), *(
DWORD
*)(FileBuffer + RVA2FOA((pBlock[i] & 0x0fff) + PageOffset)) & 0x00ffffff);
}
}
void
PrintRelocationTable() {
PIMAGE_BASE_RELOCATION pRelocationTable = pBaseRelocation;
printf
(
"\n==========重定位表==========\n"
);
printf
(
"序号\t 区段\t RVA\t FOA\t项目数\n"
);
DWORD
count = 0;
while
(pRelocationTable->VirtualAddress || pRelocationTable->SizeOfBlock) {
printf
(
"%4d\t%8s\t%08x\t%08x\t%08x\n"
, count++, GetSectionNameByRva(pRelocationTable->VirtualAddress), pRelocationTable->VirtualAddress, RVA2FOA(pRelocationTable->VirtualAddress), (pRelocationTable->SizeOfBlock - 8) / 2);
pRelocationTable = (PIMAGE_BASE_RELOCATION)((
DWORD
)pRelocationTable + pRelocationTable->SizeOfBlock);
}
pRelocationTable = pBaseRelocation;
count = 0;
while
(pRelocationTable->VirtualAddress || pRelocationTable->SizeOfBlock) {
printf
(
"\n==========Block%d==========\n"
, count++);
PrintRelocationBlock(pRelocationTable);
pRelocationTable = (PIMAGE_BASE_RELOCATION)((
DWORD
)pRelocationTable + pRelocationTable->SizeOfBlock);
}
printf
(
"\n==========重定位表结束==========\n"
);
}
PCHAR
GetSectionNameByRva(
DWORD
RVA) {
for
(
DWORD
i = 0; i < numberOfSections; i++) {
if
(RVA >= pSectionHeader[i].VirtualAddress && RVA < pSectionHeader[i].VirtualAddress + AlignSize(pSectionHeader[i].Misc.VirtualSize, 0x1000))
return
(
PCHAR
)pSectionHeader[i].Name;
}
}
void
PrintRelocationBlock(PIMAGE_BASE_RELOCATION pRelocationBlock) {
PWORD
pBlock = (
PWORD
)((
DWORD
)pRelocationBlock + 8);
DWORD
PageOffset = pRelocationBlock->VirtualAddress;
printf
(
"序号\t属性\t RVA\t FOA\t指向RVA\n"
);
for
(
DWORD
i = 0; i < (pRelocationBlock->SizeOfBlock - 8) / 2; i++) {
printf
(
"%04x\t%4x\t%08x\t%08x\t%08x\n"
, i, pBlock[i] >> 12, (pBlock[i] & 0x0fff) + PageOffset, RVA2FOA((pBlock[i] & 0x0fff) + PageOffset), *(
DWORD
*)(FileBuffer + RVA2FOA((pBlock[i] & 0x0fff) + PageOffset)) & 0x00ffffff);
}
}
void
PrintRelocationTable() {
PIMAGE_BASE_RELOCATION pRelocationTable = pBaseRelocation;
printf
(
"\n==========重定位表==========\n"
);
printf
(
"序号\t 区段\t RVA\t FOA\t项目数\n"
);
DWORD
count = 0;
while
(pRelocationTable->VirtualAddress || pRelocationTable->SizeOfBlock) {
printf
(
"%4d\t%8s\t%08x\t%08x\t%08x\n"
, count++, GetSectionNameByRva(pRelocationTable->VirtualAddress), pRelocationTable->VirtualAddress, RVA2FOA(pRelocationTable->VirtualAddress), (pRelocationTable->SizeOfBlock - 8) / 2);
pRelocationTable = (PIMAGE_BASE_RELOCATION)((
DWORD
)pRelocationTable + pRelocationTable->SizeOfBlock);
}
pRelocationTable = pBaseRelocation;
count = 0;
while
(pRelocationTable->VirtualAddress || pRelocationTable->SizeOfBlock) {
printf
(
"\n==========Block%d==========\n"
, count++);
PrintRelocationBlock(pRelocationTable);
pRelocationTable = (PIMAGE_BASE_RELOCATION)((
DWORD
)pRelocationTable + pRelocationTable->SizeOfBlock);
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2023-8-12 11:05
被东方玻璃编辑
,原因: 排版图片