PE文件之dll导出私有函数
最近在看《Windows PE 权威指南》,才看完导出表。
动动手,跟着做一下好了。
看完这章,基本可以做一个网上常见的基本的PeInfo(pe文件查看器)了,(不是只看完这章就能做,而是从前往后看完这章)
自己也写了一个,但是还不太完整,不过还是有参考价值的。
工欲善其事必先利其器,没有一个称手的工具,效率上不去啊。
为什么要自己写,因为对别人的不满意,而且自己能做。
不满意又不能做,就只能接受别人的了。
刚开始确实是不太好理解,但是用多了,还确实是熟稔于心了。(夸张了,有winnt头文件,多看看加深印象就好了)
实验目的:导出dll中的私有函数。
这里仅记录实验过程,不涉及原理讲解。
IDE:Dev-C++,简洁方便,用来学习是很不错的选择。
一:编写dll文件
dll.h
#ifndef _DLL_H_
#define _DLL_H_
#if BUILDING_DLL
#define DLLIMPORT __declspec(dllexport)
#else
#define DLLIMPORT __declspec(dllimport)
#endif
DLLIMPORT void HelloWorld();
#endif
dllmain.c
/* Replace "dll.h" with the name of your header */
#include "dll.h"
#include <windows.h>
//导出
DLLIMPORT void HelloWorld()
{
MessageBox(0,"Hello World from DLL!\n","Hi",MB_ICONINFORMATION);
}
//不导出
int add(int a,int b)
{
return a + b;
}
直接编译运行,就会生成dll文件了。
2.定位导出表的位置
不做过多解释,直接看dll文件2000H的地方。注意前面46H个字节。
没错,就是这个了,只有一个HelloWorld的导出函数。
圈了一部分,但是太淡了。这里不多解释框出来的是什么,事实上,对导出表结构了解以后,光看这个字节,就能知道大体干什么的了。
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;
这个winnt.h里面的导出表的结构,刚开始写的时候,还自己定义结构体,呵呵。
2.修改dll文件。
这个导出表结构,除了时间戳,主编译版本,次编译版本以及Base不用修改,其他的都要改一下。
这个只能对结构熟悉以后,根据实际情况改,最后别注意修改导出表的大小即可,虽然这次好像不改也能正常运行。
这里面需要注意的是,从dll里面找到add()函数的起始位置,这里提供一些小的思路。
(1)写个cpp调用原来生成的dll,利用OD调试运行,看看helloWorld函数的字节码,再找到文件对应的位置,HelloWorld结束以后,就是add函数了,因为代码是连续的。
(2)写个cpp,写个int add(int,int)函数,利用OD调试查看函数的字节码,再从UE里面搜索对应的数据,定位,即可。
修改结果如下:
没有什么章法,哪里有位置,就改到哪里,最后符合加载规范就好了。
3.修改完毕,进行测试,
#include<iostream>
#include<windows.h>
using namespace std;
int main()
{
HMODULE module = LoadLibrary("my.dll");
if(!module)
{
cout<<"加载链接库失败"<<endl;
return 0;
}
typedef void(*hello)();
hello h = (hello)GetProcAddress(module,"HelloWorldtest");
cout<<h<<endl;
h();
typedef int(*add)(int,int);
add a = (add)GetProcAddress(module,"aabbccd");
cout<<a<<endl;
cout<<a(3,5)<<endl;
}
名字什么的,不重要,dll随便改就好了,地址什么的,也不重要,自己根据需要改到合适的地方就好了。
只需要符号结构体的规范,能正确定位就好了。