导出表编程-1-枚举导出表

开始前先回忆一下导出表:


1.枚举dll函数的导出函数名字:

思路:

(1)加载dll到内存里。

(2)获取PE头,逐步找到可选头部。

(3)然后找到里面的第一个结构(导出表)地址,这个地址指向一个IMAGE_EXPORT_DIRECTORY,然后找到里面的

这个地址是一个数组(DWORD),每个值都指向一个导出函数的名字字符串所在地址,然后根据

确定个数,直接枚举就行了。

代码如下:

#include "stdafx.h"
#include <windows.h>
#include <winbase.h>
#include <stdio.h>
#include <tchar.h>
#include <imagehlp.h>
#include <vector>
#include <iostream>
#include <string>
using namespace std; typedef PVOID (CALLBACK* PFNEXPORTFUNC)(PIMAGE_NT_HEADERS,PVOID,ULONG,PIMAGE_SECTION_HEADER*); BOOL printAllFuncName(WCHAR* wcFileName ,vector<string> &vcFuncName){
vcFuncName.clear();
LPWIN32_FIND_DATA lpwfd_first=new WIN32_FIND_DATA;//接受findfirstfile的结构指针
HANDLE hFile,hFileMap;//文件句柄和内存映射文件句柄
DWORD fileAttrib=0;//存储文件属性用,在createfile中用到。
void* mod_base;//内存映射文件的起始地址,也是模块的起始地址 PFNEXPORTFUNC ImageRvaToVax=NULL;
HMODULE hModule=::LoadLibrary(L"DbgHelp.dll");
if(hModule!=NULL){
ImageRvaToVax=(PFNEXPORTFUNC)::GetProcAddress(hModule,"ImageRvaToVa");
if(ImageRvaToVax==NULL){
::FreeLibrary(hModule);
//printf("取得函数失败\n");
return FALSE;
}
}else{
//printf("加载模块失败\n");
return FALSE;
} if(FindFirstFile(wcFileName,lpwfd_first)==NULL){//返回值为NULL,则文件不存在,退出
//printf("文件不存在: %s ",wcFileName);
return FALSE;
}else{
DWORD fileAttrib=lpwfd_first->dwFileAttributes;
}
hFile=CreateFile(wcFileName,GENERIC_READ,0,0,OPEN_EXISTING,fileAttrib,0);
if(hFile==INVALID_HANDLE_VALUE){
//printf("打开文件出错!");
return FALSE;
}
hFileMap=CreateFileMapping(hFile,0,PAGE_READONLY,0,0,0);
if(hFileMap==NULL){
CloseHandle(hFile);
//printf("建立内存映射文件出错!");
return FALSE;
}
mod_base=MapViewOfFile(hFileMap,FILE_MAP_READ,0,0,0);
if (mod_base==NULL)
{
//printf("建立内存映射文件出错!");
CloseHandle(hFileMap);
CloseHandle(hFile);
return FALSE;
}
IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)mod_base;
IMAGE_NT_HEADERS * pNtHeader =
(IMAGE_NT_HEADERS *)((BYTE*)mod_base+ pDosHeader->e_lfanew);//得到NT头首址 IMAGE_OPTIONAL_HEADER * pOptHeader =
(IMAGE_OPTIONAL_HEADER *)((BYTE*)mod_base + pDosHeader->e_lfanew + 24);//optional头首址 IMAGE_EXPORT_DIRECTORY* pExportDesc = (IMAGE_EXPORT_DIRECTORY*)ImageRvaToVax(pNtHeader,mod_base,pOptHeader->DataDirectory[0].VirtualAddress,0);
//导出表首址
PDWORD nameAddr=(PDWORD)ImageRvaToVax(pNtHeader,mod_base,pExportDesc->AddressOfNames,0);//函数名称表首地址每个DWORD代表一个函数名字字符串的地址
PCHAR func_name = (PCHAR)ImageRvaToVax(pNtHeader,mod_base,(DWORD)nameAddr[0],0);
DWORD i=0;
DWORD unti=pExportDesc->NumberOfNames;
for(i=0;i<unti;i++){
func_name = (PCHAR)ImageRvaToVax(pNtHeader,mod_base,(DWORD)nameAddr[i],0);
//printf("%s\n",func_name);
vcFuncName.push_back(string(func_name));
}
::FreeLibrary(hModule);
CloseHandle(hFileMap);
CloseHandle(hFile);
return TRUE;
} int main(int argc, char* argv[]){ vector<string>vcFuncName;
printAllFuncName(L"C:\\A.dll" ,vcFuncName); for(vector<string>::iterator it = vcFuncName.begin(); it != vcFuncName.end();it++){
cout<<*(it)<<endl;
}
getchar();
return 0;
}

下面两个不去实现了,和上面的差不多。

2.根据编号查找函数地址

3.根据名字查找函数地址


WindowsPE 第五章 导出表编程-1(枚举导出表)的更多相关文章

  1. WindowsPE 第五章 导出表

    导出表 PE中的导出表存在于动态链接库文件里.导出表的主要作用是将PE中存在的函数导出到外部,以便其他人可以使用这些函数,实现代码重用. 5.1导出表的作用 代码重用机制提供了重用代码的动态链接库,它 ...

  2. #《Essential C++》读书笔记# 第五章 面向对象编程风格

    基础知识 继承机制定义了父子(parent/child)关系.父类(parent)定义了所有子类(children)共通的共有接口(public interface)和私有实现(private imp ...

  3. 第五章 javascript编程可养成的好习惯

    用户点击某个链接时弹出一个新窗口javascript使用window对象的open()方法来创建新的浏览器窗口,这个方法有三个参数:window.open(url,name,features)url: ...

  4. 《java编程思想》读书笔记(一)开篇&第五章(1)

    2017 ---新篇章  今天终于找到阅读<java编程思想>这本书方法了,表示打开了一个新世界. 第一章:对象导论 内容不多但也有20页,主要是对整本书的一个概括.因为已经有过完整JAV ...

  5. UNIX 网络编程第五章读书笔记

    刚看完 UNIX 第五章内容,我想按照自己的方式将自己获得的知识梳理一遍,以便日后查看!先贴上一段简单的 TCP 服务器端代码: #include <sys/socket.h> #incl ...

  6. 安卓权威编程指南 - 第五章学习笔记(两个Activity)

    学习安卓编程权威指南第五章的时候自己写了个简单的Demo来加深理解两个Activity互相传递数据的问题,然后将自己的学习笔记贴上来,如有错误还请指正. IntentActivityDemo学习笔记 ...

  7. C#高级编程 (第六版) 学习 第五章:数组

    第五章 数组 1,简单数组 声明:int[] myArray; 初始化:myArray = new int[4]; 为数组分配内存. 还可以用如下的方法: int[] myArray = new in ...

  8. [书籍翻译] 《JavaScript并发编程》第五章 使用Web Workers

    本文是我翻译<JavaScript Concurrency>书籍的第五章 使用Web Workers,该书主要以Promises.Generator.Web workers等技术来讲解Ja ...

  9. 《Linux命令行与shell脚本编程大全》 第十五章 学习笔记

    第十五章:控制脚本 处理信号 重温Linux信号 信号 名称 描述 1 HUP 挂起 2 INT 中断 3 QUIT 结束运行 9 KILL 无条件终止 11 SEGV 段错误 15 TERM 尽可能 ...

随机推荐

  1. 如何在 C# 8 中使用 Channels

    在面对 生产者-消费者 的场景下, netcore 提供了一个新的命名空间 System.Threading.Channels 来帮助我们更高效的处理此类问题,有了这个 Channels 存在, 生产 ...

  2. FreeBSD 中文TTY控制台

    freebsd新型终端VT,支持cjk,所以丢个字体进去,就能显示中文了1,首先你没有改过控制台程序,使用的是默认的,,2,最新版本,本说明是以freebsd12.1release字体格式为.fnt命 ...

  3. linux下redis安装运行教程——redis系列

    天没降大任于我,照样苦我心智,劳我筋骨. 安装运行的过程 由于官网太慢,csdn里的资源又要钱,所以呢,只能使用我自己本地以前下载的陈年..哦不,3.xredis安装包 资源已经放到百度云,需要的可以 ...

  4. Java流程控制:三种基本结构

    顺序结构: Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行顺序结构是最简单的算法结构语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的, ...

  5. 2018ICPC南京K. Kangaroo Puzzle

    题目:在一个20×20的地图上,1表示有袋鼠,0表示有障碍物,边界外和障碍物上不能走.        要求给出一个50000步以内的操作,每一步操作为'L', 'R', 'U', 'D', 表示所有袋 ...

  6. Java例题_31 逆序输出数组的值

    1 /*31 [程序 31 数组逆序] 2 题目:将一个数组逆序输出. 3 程序分析:用第一个与最后一个交换. 4 */ 5 6 /*分析 7 * 第一种方法:找到这个数组的中间下标,然后交换两端的数 ...

  7. 封装Vue纵向表头左右结构的table表格

    我们前端开发人员在使用表格的过程中,大概率碰到的都是表格头部在表格的最上边,然后呈一行展示,紧接着就是表格的每一行的每一个单元格来展示具体内容的场景,很少会遇到表格的头部呈纵向一行展示,也就是说表格的 ...

  8. odoo视图入门学习- tree视图的使用

    上一篇内容:如何快速在odoo中创建自己的菜单 前言 上面的内容我们已经学会了如何去创建odoo的菜单,下面我们要学习的是odoo的基础视图tree视图,我们的目标是实现型号管理的列表页面 创建mod ...

  9. JavaFX+SpringBoot+验证码功能的小型薪酬管理系统

    2020.07.22更新 1 概述 1.1 简介 一个简单的小型薪酬管理系统,前端JavaFX+后端Spring Boot,功能倒没多少,主要精力放在了UI和前端的一些逻辑上面,后端其实做得很简单. ...

  10. Tomcat集群 Nginx负载均衡 shell脚本实时监控Nginx

    第一步,安装Tomcat 系统环境:Centos7 第1步:下载tomcat安装包 tomcat官网:https://tomcat.apache.org/ 第2步:安装包上传至linux中 第3步:下 ...