PE文件之dll导出私有函数

最近在看《Windows PE 权威指南》,才看完导出表。

动动手,跟着做一下好了。

看完这章,基本可以做一个网上常见的基本的PeInfo(pe文件查看器)了,(不是只看完这章就能做,而是从前往后看完这章)

自己也写了一个,但是还不太完整,不过还是有参考价值的。

工欲善其事必先利其器,没有一个称手的工具,效率上不去啊。

为什么要自己写,因为对别人的不满意,而且自己能做。

不满意又不能做,就只能接受别人的了。

Peinfo 实验文件

刚开始确实是不太好理解,但是用多了,还确实是熟稔于心了。(夸张了,有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随便改就好了,地址什么的,也不重要,自己根据需要改到合适的地方就好了。

只需要符号结构体的规范,能正确定位就好了。

posted @ 2022-03-06 11:47  念秋  阅读(162)  评论(0编辑  收藏  举报