这段代码是我在研究PE结构的时候写的,能提取无壳程序的图标,希望对大家有帮助,为了研究PE结构我查阅了大量资料,当然有些结构不详,学习PE结构对脱壳原理是很有帮助,希望大家共同交流学习
我想关注此论坛很久了,想申请加入,我学习了两百部天草脱壳教程,面对现在的新壳还是束手无策,希望加入此论坛继续深入学习
联系邮箱:zoujun224@qq.com
QQ:358915781
#pragma pack(push,1) //单字节对齐
#define BYTE char
#define WORD unsigned short
#define DWORD long
#define LONG long
//DOS头结构,64字节
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; // 初始的SS值(相对偏移量)
WORD e_sp; // 初始的SP值
WORD e_csum; // 校验和
WORD e_ip; // 初始的IP值
WORD e_cs; // 初始的CS值(相对偏移量)
WORD e_lfarlc; // 重分配表文件地址
WORD e_ovno; // 覆盖号
WORD e_res[4]; // 保留字
WORD e_oemid; // OEM标识符(相对e_oeminfo)
WORD e_oeminfo; // OEM信息
WORD e_res2[10]; // 保留字
LONG e_lfanew; // 新exe头部的文件地址
} IMAGE_DOS_HEADER;
//DOS实模式残余,字节数不定
//PE文件头结构【PE结构成员】,20字节
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; //运行的CPU,Intel 80386以上处理器必需为 4c 01 二字节
WORD NumberOfSections; //节个数,如只有三个节 03 00
DWORD TimeDateStamp; //文件创建日期和时间
DWORD PointerToSymbolTable; //用于调试
DWORD NumberOfSymbols; //用于调试
WORD SizeOfOptionalHeader; //可选头大小,224字节所以为 E0 00
WORD Characteristics; //EXE可执行文件为02 00
} IMAGE_FILE_HEADER;
//导入表结构[16表之二]【可选头结构成员】,8字节
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress; //导入表RVA地址 10 20 00 00
DWORD Size; //如果引入二个结构数组,每个20字节+最后一个全0结尾 3c 00 00 00
} IMAGE_DATA_DIRECTORY;
//可选头结构【PE结构成员】,224字节
typedef struct _IMAGE_OPTIONAL_HEADER {
// Standard fields.
WORD Magic; //标志字,总是0B 01
BYTE MajorLinkerVersion; //连接器首版本号
BYTE MinorLinkerVersion; //连接器次版本号
DWORD SizeOfCode; //代码块大小
DWORD SizeOfInitializedData; //已初始化数据块大小
DWORD SizeOfUninitializedData; //未初始化数据块大小
DWORD AddressOfEntryPoint; //OEP代码入口的RVA地址,程序从这里开始执行00 10 00 00
DWORD BaseOfCode; //代码段起始RVA
DWORD BaseOfData; //数据段起始RVA
// NT additional fields.
DWORD ImageBase; //载入程序的RVA地址00 00 40 00
DWORD SectionAlignment; //段加载后在内存的对齐方式 00 10 00 00
DWORD FileAlignment; //段在文件中的对齐方式 00 02 00 00
WORD MajorOperatingSystemVersion; //操作系统首版本号
WORD MinorOperatingSystemVersion; //操作系统次版本号
WORD MajorImageVersion; //用户程序首版本号
WORD MinorImageVersion; //用户程序次版本号
WORD MajorSubsystemVersion; //子系统首版本号如果不是4.0对话框不能显示3D风格 04 00
WORD MinorSubsystemVersion; //子系统次版本号
DWORD Win32VersionValue; //保留
DWORD SizeOfImage; //内存映像大小 00 40 00 00
DWORD SizeOfHeaders; //文件头长度 00 04 00 00
DWORD CheckSum; //校验和
WORD Subsystem; //程序运行所需子系统 02 00 或03 00
WORD DllCharacteristics; //DLL文件使用
DWORD SizeOfStackReserve; //保留栈大小
DWORD SizeOfStackCommit; //使用栈大小
DWORD SizeOfHeapReserve; //保留堆大小
DWORD SizeOfHeapCommit; //使用堆大小
DWORD LoaderFlags; //设置自动调用断点或调试器
DWORD NumberOfRvaAndSizes;//目录表个数当然是16个 即10 00 00 00
IMAGE_DATA_DIRECTORY DataDirectory[16]; //16表
} IMAGE_OPTIONAL_HEADER32;
//PE结构,248字节
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; //这个必需为50 45 00 00 ,PE00 4字节
IMAGE_FILE_HEADER FileHeader; //PE头结构 20字节
IMAGE_OPTIONAL_HEADER32 OptionalHeader; //可选头结构 224字节
} IMAGE_NT_HEADERS32;
//段头部结构,40字节
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[8];//节名称 如.text 2e 74 65 78 74 00 00 00
union {
DWORD PhysicalAddress;
DWORD VirtualSize; //内存中段大小
} Misc;
DWORD VirtualAddress; //文件.text段在内存的RVA 00 10 00 00
DWORD SizeOfRawData; //.text段在文件中的长度 00 02 00 00
DWORD PointerToRawData;//.text在文件中的偏移 00 04 00 00
DWORD PointerToRelocations; //OBJ文件使用
DWORD PointerToLinenumbers; //OBJ文件使用
WORD NumberOfRelocations; //OBJ文件使用
WORD NumberOfLinenumbers; //OBJ文件使用
DWORD Characteristics; //节属性可执行20 00 00 60
//代码段 00 00 00 20 可执行段 20 00 00 60
//已初始化数据段 00 00 00 40 未初始化数据段 00 00 00 80
//可丢弃段 02 00 00 00 共享段 10 00 00 00
//可读段 40 00 00 00 可写段 80 00 00 00
} IMAGE_SECTION_HEADER;
//导出表结构,40字节
typedef struct _IMAGE_EXPORT_DIRECTORY
{
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base; //输出起始序号
DWORD NumberOfFunctions; //输出函数的总数
DWORD NumberOfNames; //以函数名输出函数的个数,剩余为以索引号输出
DWORD AddressOfFunctions; //函数地址表【FAT】的RVA
DWORD AddressOfNames; //输出函数名表【FNT】的RVA
DWORD AddressOfNameOrdinals; //输出函数的序号表【FOT】的RVA
}IMAGE_EXPORT_DIRECTORY;
//导入表结构,20字节
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk; //PIMAGE_THUNK_DATA【函数名地址表】RVA,00 00 00 00为结束标志
};
DWORD TimeDateStamp;
DWORD ForwarderChain; //第一个被转向的API索引,一般00 00 00 00
DWORD Name; //指向DLL名的RVA
DWORD FirstThunk; //指向IAT的RVA,加载时由系统改写函数指针
} IMAGE_IMPORT_DESCRIPTOR;
//资源目录表结构,16字节
typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics; //保留
DWORD TimeDateStamp; //时间日期记录
WORD MajorVersion; //首版本号
WORD MinorVersion; //次版本号
WORD NumberOfNamedEntries;//目录下name名称入口项个数
WORD NumberOfIdEntries;//目录下id名称入口项个数,与NumberOfNamedEntries之和即紧跟ENTRY结构个数
} IMAGE_RESOURCE_DIRECTORY;
//重定位表结构,8字节
typedef struct _IMAGE_BASE_RELOCATION
{
DWORD VirtualAddress; //指向基底重定位资料的RVA
DWORD SizeOfBlock; //基底重定位资料大小
}IMAGE_BASE_RELOCATION;
//资源入口结构,8字节
typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
union {
struct {
DWORD NameOffset:31; //NameIsString为真有效,目录名称串的偏移,偏移RES_RVA
DWORD NameIsString:1;
};
DWORD Name;//资源种类
//CURSOR 1 BITMAP 2 ICON 3 MENU 4 DIALOG 5
//STRING 6 FONTDIR 7 FONT 8 ACCELERATOR 9 RCDATA 10 MESSAGETABLE 11
WORD Id; //资源ID
};
union {
DWORD OffsetToData;//指向资源数据,偏移RES_RVA
struct {
DWORD OffsetToDirectory:31;//DataIsDirectory为真有效,指向子目录,偏移RVA
DWORD DataIsDirectory:1;
};
};
} IMAGE_RESOURCE_DIRECTORY_ENTRY;
//图标资源信息结构,16字节
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData; //资源内存地址
DWORD Size; //大小
DWORD CodePage;
DWORD Reserved; //保留
} IMAGE_RESOURCE_DATA_ENTRY;
//ICON图象信息块,16字节
typedef struct _ICONDIRENTRY
{
BYTE bWidth; //宽 16或32
BYTE bHeight; //高 16或32
BYTE bColorCount; //Number of colors in image (0 if >=8bpp)
BYTE bReserved; //保留,必须是0
WORD wPlanes; //图片的位面数
WORD wBitCount; //每个象素的位数
DWORD dwBytesInRes; //图像字节长度
DWORD dwImageOffset; //图像文件偏移
} ICONDIRENTRY;
//ICON文件头,22字节
typedef struct _ICONDIR
{
WORD idReserved; //保留,必须是00 00
WORD idType; //文件类型,1表示icon即01 00
WORD idCount; //图片个数,1个即01 00
ICONDIRENTRY idEntries; //入口结构
} ICONDIR;
//BMP文件头,14字节
typedef struct tagBITMAPFILEHEADER
{
WORD bfType; // 位图文件的类型,必须为BM 42 4D
DWORD bfSize; // 位图文件的大小
WORD bfReserved1; // 位图文件保留字,必须为0
WORD bfReserved2; // 位图文件保留字,必须为0
DWORD bfOffBits; // 位图数据的起始位置
} BITMAPFILEHEADER;
//BMP信息头部,40字节
typedef struct tagBITMAPINFOHEADER {
DWORD biSize; //位图信息头长度 28 00
LONG biWidth; //宽
LONG biHeight; //高
WORD biPlanes; //图片位面数
WORD biBitCount; //每个象素的BIT位数,24位18 00
DWORD biCompression; //压缩说明
DWORD biSizeImage; //位图数据的大小
LONG biXPelsPerMeter;//水平每米像素个数
LONG biYPelsPerMeter;//垂直每米像素个数
DWORD biClrUsed; //位图使用的颜色数
DWORD biClrImportant; //指定重要的颜色数,0表示所有颜色都重要
} BITMAPINFOHEADER;
//位图调色板,4字节
typedef struct _RGBQUAD{
BYTE bBlue; //蓝色分量
BYTE bGreen; //绿色分量
BYTE bRed; //红色分量
BYTE bReserved;//保留
} RGBQUAD;
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
#include"conio.h"
void main(int argc,char *argv[])
{
FILE *fp;
char name[255];
DWORD i,j,File_Address,Mem_Address,offset;
void find_fun();
void find_source();
IMAGE_DOS_HEADER Dos_Header;//DOS头
IMAGE_NT_HEADERS32 Nt_Header;//PE头
IMAGE_SECTION_HEADER Section_Header[100],Section_Header_This;//段表头
void Get_EXPORT(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset);
void Get_IMPORT(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset);
void Get_RESOURCE(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset,char *fileposition);
void Get_EXCEPTION(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset);
void Get_SECURITY(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset);
void Get_BASERELOC(FILE *fp,DWORD Table_offset);
void Get_DEBUG(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset);
void Get_IAT(FILE *fp,DWORD Table_offset,DWORD Size);
if(argc<2)
{
printf("请输入文件名:");
gets(name);
if((fp=fopen(name,"rb+"))==NULL)
{
printf("找不到指定文件\n");
getch();
exit(0);
}
printf("打开文件%s\n",name);
}
else
{
if((fp=fopen(argv[1],"rb+"))==NULL)
{
printf("找不到指定文件\n");
getch();
exit(0);
}
printf("打开文件:%s\n",argv[1]);
}
fread(&Dos_Header,sizeof(IMAGE_DOS_HEADER),1,fp);//读DOS头部
fseek(fp,Dos_Header.e_lfanew,0);//定位到PE头,中间是DOS残余信息,未被使用
fread(&Nt_Header,sizeof(IMAGE_NT_HEADERS32),1,fp);//读PE头部
if(Nt_Header.Signature!=0x00004550)//注意字节序相反
{
printf("不是有效的PE文件\n");
getch();
exit(0);
}
printf("段 个 数 :%d\n",Nt_Header.FileHeader.NumberOfSections);//列出关键信息
printf("程序装载RVA地址:%08X\n",Nt_Header.OptionalHeader.ImageBase);
printf("代码入口RVA地址:%08X\n",Nt_Header.OptionalHeader.AddressOfEntryPoint);
printf("内存 对 齐 方式:%08X\n",Nt_Header.OptionalHeader.SectionAlignment);
printf("内存 映 射 长度:%08X\n",Nt_Header.OptionalHeader.SizeOfImage);
printf("文件 对 齐 方式:%08X\n",Nt_Header.OptionalHeader.FileAlignment);
printf("文 件 头 长 度 :%08X\n",Nt_Header.OptionalHeader.SizeOfHeaders);
printf("子 系 统 :%04X\n\n",Nt_Header.OptionalHeader.Subsystem);
//读取节表
for(i=0;i<Nt_Header.FileHeader.NumberOfSections;i++)
{
fread(&Section_Header[i],sizeof(IMAGE_SECTION_HEADER),1,fp);//读段结构
printf("段 名 称:");
for(int j=0;j<8;j++)
printf("%c",Section_Header[i].Name[j]);
printf("\n该段 文件 偏移:%08X\n",Section_Header[i].PointerToRawData);
printf("该段文件中长度:%08X\n",Section_Header[i].SizeOfRawData);
printf("该段 内存 偏移:%08X\n\n",Section_Header[i].VirtualAddress);
}
getch();
for(i=0;i<16;i++) //读16表
{
offset=Nt_Header.OptionalHeader.DataDirectory[i].VirtualAddress;
if(Nt_Header.OptionalHeader.DataDirectory[i].VirtualAddress==0) //不存在
continue;
j=0;//找所在区段
while(j<Nt_Header.FileHeader.NumberOfSections)
{
if( (offset>=Section_Header[j].VirtualAddress) && (offset<(Section_Header[j].VirtualAddress+Section_Header[j].SizeOfRawData)) )
{
Section_Header_This=Section_Header[j];
break;
}
j++;
}
offset=Nt_Header.OptionalHeader.DataDirectory[i].VirtualAddress-Section_Header_This.VirtualAddress;//相对偏移量
offset+=Section_Header_This.PointerToRawData;//加基址=文件实际地址
File_Address=Section_Header_This.PointerToRawData;//段文件基址
Mem_Address=Section_Header_This.VirtualAddress;//段RVA基址
printf("第%d表[%08X] ",i,Nt_Header.OptionalHeader.DataDirectory[i].VirtualAddress);
switch(i)
{
case 0: Get_EXPORT(fp,File_Address,Mem_Address,offset); break; //输出符号目录
case 1: Get_IMPORT(fp,File_Address,Mem_Address,offset); break; //输入符号目录
case 2: Get_RESOURCE(fp,File_Address,Mem_Address,offset,argv[0]); break; //资源目录
case 3: Get_EXCEPTION(fp,File_Address,Mem_Address,offset); break; //异常目录
case 4: Get_SECURITY(fp,File_Address,Mem_Address,offset); break; //安全目录
case 5: Get_BASERELOC(fp,offset); break; //基址重定位表
case 6: Get_DEBUG(fp,File_Address,Mem_Address,offset); break; //调试目录
//case 7: Get_COPYRIGHT(fp,offset,Nt_Header) break; //描述字符串
//case 8: Get_GLOBALPTR(fp,offset,Nt_Header); break; //机器值
//case 9: Get_TLS(fp,offset,Nt_Header); break; //线程级局部存储目录
//case 10: Get_LOAD_CONFIG(fp,offset,Nt_Header); break; //载入配置目录
//case 11: Get_BOUND_IMPORT(fp,offset,Nt_Header); break; //绑定输入目录
case 12: Get_IAT(fp,offset,Nt_Header.OptionalHeader.DataDirectory[i].Size); break;//输入地址表
}
}
getch();
}
void Get_EXPORT(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset)
{
char module_name[255],fun_name[255],ch;
DWORD i,j,k,Address,Image_Thunk_Ddata;
unsigned short *Ordinal;
IMAGE_EXPORT_DIRECTORY Image_Export_Descriptor;
fseek(fp,Table_offset,0);
fread(&Image_Export_Descriptor,sizeof(IMAGE_EXPORT_DIRECTORY),1,fp);
fseek(fp,File_Address+Image_Export_Descriptor.Name-Mem_Address,0);
fread(&ch,1,1,fp);//这里是一个字节一个字节读取
k=0;
while(ch!=0)
{
module_name[k++]=ch;
fread(&ch,1,1,fp);
}
module_name[k]=0;
printf("输出表[%s]获取中......\n",module_name);
Ordinal=(unsigned short *)malloc(Image_Export_Descriptor.NumberOfNames*2);
k=0;
for(i=0;i<Image_Export_Descriptor.NumberOfNames;i++)
{
fseek(fp,File_Address+Image_Export_Descriptor.AddressOfNameOrdinals-Mem_Address+i*2,0);//全部索引号
fread(&Ordinal[i],2,1,fp);
}
getch();
for(i=0;i<Image_Export_Descriptor.NumberOfFunctions;i++) //i是函数序号
{
fseek(fp,File_Address+Image_Export_Descriptor.AddressOfFunctions-Mem_Address+i*4,0);
fread(&Address,4,1,fp);//输出函数地址
for(j=0;j<Image_Export_Descriptor.NumberOfNames;j++) //判断存不存在相应的索引值?存在的话就是以函数名输出,我们需要找出函数名
{
if(Ordinal[j]==i) //遍历数组找到该搜引值的下标,下标j也是函数名指针数组的下标值,他们一一对应
{
fseek(fp,File_Address+Image_Export_Descriptor.AddressOfNames-Mem_Address+j*4,0);//读取指针数组值,指向函数名实际地址
fread(&Image_Thunk_Ddata,4,1,fp);
fseek(fp,File_Address+Image_Thunk_Ddata-Mem_Address,0);//输读取ASC函数名
fread(&ch,1,1,fp);//这里是一个字节一个字节读取
k=0;
while(ch!=0)
{
fun_name[k++]=ch;
fread(&ch,1,1,fp);
}
fun_name[k]=0;
printf("序号:%05d Hint:%05d 地址入口:%08X 函数名称:%s\n",i+1,j,Address,fun_name);
break;
}
}
if(j==Image_Export_Descriptor.NumberOfNames) //不存在相应的索引值,那么就是序号输出了
printf("序号:%05d Hint: NO 地址入口:%08X 函数名称: NO\n",i+1,Address);
getch();
}
printf("\n");
getch();
}
void Get_IMPORT(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset)
{
int i,j,k,hint;
char fun_name[255],module_name[255],ch;
DWORD Image_Thunk_Ddata;
IMAGE_IMPORT_DESCRIPTOR Image_Import_Descriptor;
i=0;//DLL个数计数
printf("导入表获取中......\n");
while(1)
{
fseek(fp,Table_offset+i*sizeof(IMAGE_IMPORT_DESCRIPTOR),0);//读取第i个DLL的结构信息
fread(&Image_Import_Descriptor,sizeof(IMAGE_IMPORT_DESCRIPTOR),1,fp);
if(!Image_Import_Descriptor.Name)
break; //NAME为00 00 00 00则结束
fseek(fp,File_Address+Image_Import_Descriptor.Name-Mem_Address,0);//定位到第i个DLL的名字
fread(&ch,1,1,fp);//这里是一个字节一个字节读取
k=0;
while(ch!=0)
{
module_name[k++]=ch;
fread(&ch,1,1,fp);
}
module_name[k]=0;
printf("模块名称[%08x]: %s \n",Image_Import_Descriptor.Name,module_name);
if(!module_name[0])
break; //模块名为NULL也结束
//获取DLL导出的函数名
j=0;//函数个数计数
while(1)
{
if(Image_Import_Descriptor.OriginalFirstThunk)//导入函数,加载后不会被修改
fseek(fp,File_Address+Image_Import_Descriptor.OriginalFirstThunk-Mem_Address+4*j,0);
else if(Image_Import_Descriptor.FirstThunk)
fseek(fp,File_Address+Image_Import_Descriptor.FirstThunk-Mem_Address+4*j,0);//指向IAT,加载后由系统填写实际地址
else break;
fread(&Image_Thunk_Ddata,4,1,fp);//4字节结构,指向ASC函数名RVA
if(!Image_Thunk_Ddata)//00000000结束标志
break;
if(Image_Thunk_Ddata&0x80000000)//按照函数hint值索引函数
{
printf("序号索引方式: %05d\n",Image_Thunk_Ddata&0x7FFFFFFF);
}
else
{
hint=0;
fseek(fp,File_Address+Image_Thunk_Ddata-Mem_Address,0);//函数序号,用于对函数的二元搜寻
fread(&hint,2,1,fp);
fseek(fp,File_Address+Image_Thunk_Ddata-Mem_Address+2,0);//按照函数名索引函数
fread(&ch,1,1,fp);//紧跟的是函数ASC字符串
k=0;
while(ch!=0)
{
fun_name[k++]=ch;
fread(&ch,1,1,fp);
}
fun_name[k]=0;
printf("函数名方式[参考Hint%05d]: %s\n",hint,fun_name);
}
j++;
}
printf("\n");
getch();
i++;
}
getch();
}
void Get_RESOURCE(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset,char *fileposition)
{
char filename[255],*image;
int i,j,k,N0,N1,N2,count=1;
FILE *to;
//资源根目录及其紧跟的ENTRY结构,有三层
IMAGE_RESOURCE_DIRECTORY dir[3];
IMAGE_RESOURCE_DIRECTORY_ENTRY entry[3];
IMAGE_RESOURCE_DATA_ENTRY entryData;//资源信息
//文件格式结构
ICONDIR Icon; //ICON
BITMAPFILEHEADER BitMapFileHeader; //BMP
//BMP信息结构头
BITMAPINFOHEADER BitMapInfoHeader;
printf("资源获取中[这里只获取ICON和BMP].....\n");
for(i=strlen(fileposition);i>=0;i--)//获取当前目录
{
if(*(fileposition+i)=='\\')
{
*(fileposition+i)=0;
break;
}
}
fseek(fp,Table_offset,0);//定位到根目录
fread(&dir[0],sizeof(IMAGE_RESOURCE_DIRECTORY),1,fp);//根目录,获知紧跟的ENTRY结构个数
N0=dir[0].NumberOfIdEntries+dir[0].NumberOfNamedEntries;
//遍历紧跟的ENTRY结构
for(i=0;i<N0;i++)
{
fseek(fp,Table_offset+16+i*8,0);//定位到ENTRY结构,这是紧跟的结构
fread(&entry[0],sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY),1,fp);
if(entry[0].Name==2||entry[0].Name==3)//位图或图标
{
fseek(fp,Table_offset+entry[0].OffsetToDirectory,0);//定位到名称目录
fread(&dir[1],sizeof(IMAGE_RESOURCE_DIRECTORY),1,fp);//获取名称目录后ENTRY个数
N1=dir[1].NumberOfIdEntries+dir[1].NumberOfNamedEntries;
//遍历紧跟的ENTRY结构
for(j=0;j<N1;j++)
{
fseek(fp,Table_offset+entry[0].OffsetToDirectory+16+j*8,0);//定位到ENTRY结构
fread(&entry[1],sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY),1,fp);
//如果还有子目录
if(entry[1].DataIsDirectory)
{
fseek(fp,Table_offset+entry[1].OffsetToDirectory,0);//定位到语言目录
fread(&dir[2],sizeof(IMAGE_RESOURCE_DIRECTORY),1,fp);
N2=dir[2].NumberOfIdEntries+dir[2].NumberOfNamedEntries;
//列出该目录下所有图标资源
for(k=0;k<N2;k++)
{
fseek(fp,Table_offset+entry[1].OffsetToDirectory+16+k*8,0);//定位到ENTRY结构
fread(&entry[2],sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY),1,fp);
fseek(fp,Table_offset+entry[2].OffsetToData,0);//定位到资源结构
fread(&entryData,sizeof(IMAGE_RESOURCE_DIRECTORY),1,fp);
fseek(fp,File_Address+entryData.OffsetToData-Mem_Address,0);//定位到图标
fread(&BitMapInfoHeader,sizeof(BITMAPINFOHEADER),1,fp);//读BMP头,文件头需用
fseek(fp,File_Address+entryData.OffsetToData-Mem_Address,0);//定位到图标
if((image=(char*)malloc(entryData.Size))==NULL)
{
printf("分配内存失败\n");
getch();
continue;
}
fread(image,entryData.Size,1,fp);//读取数据
printf("图片大小:%ld\n",entryData.Size);
printf("图片地址:%08X\n",File_Address+entryData.OffsetToData-Mem_Address);
if(entry[0].Name==2)
{
BitMapFileHeader.bfType=0X4D42; //42 4D BM标志
BitMapFileHeader.bfSize=entryData.Size;
BitMapFileHeader.bfReserved1=0;
BitMapFileHeader.bfReserved2=0;
//数据在调色板之后,每个调色板4字节,2的biBitCount方个调色板
if(BitMapInfoHeader.biBitCount==1)
BitMapFileHeader.bfOffBits=14+40+2*4;
else if(BitMapInfoHeader.biBitCount==4)
BitMapFileHeader.bfOffBits=14+40+16*4;
else if(BitMapInfoHeader.biBitCount==8)
BitMapFileHeader.bfOffBits=14+40+256*4;
else BitMapFileHeader.bfOffBits=14;
sprintf(filename,"%s\\BMP%d.bmp",fileposition,count++);//文件名.bmp n文件个数统计
printf("保存到文件:%s\n\n",filename);
if((to=fopen(filename,"wb+"))==NULL)
{
printf("创建文件:%s失败\n",filename);
getch();
continue;
}
fwrite(&BitMapFileHeader,sizeof(BITMAPFILEHEADER),1,to);//BMP文件头22字节
}
else//ICON保存到图标文件
{
Icon.idReserved=0;
Icon.idType=1;//类型
Icon.idCount=1;//个数
Icon.idEntries.bWidth=(BYTE)BitMapInfoHeader.biHeight/2;
Icon.idEntries.bHeight=(BYTE)BitMapInfoHeader.biHeight/2;;
Icon.idEntries.bColorCount=0;
Icon.idEntries.bReserved=0;
Icon.idEntries.wPlanes=BitMapInfoHeader.biPlanes;
Icon.idEntries.wBitCount=BitMapInfoHeader.biBitCount;//每个象素BYTE位数
Icon.idEntries.dwBytesInRes=entryData.Size;//图标长度
Icon.idEntries.dwImageOffset=22;//偏移
sprintf(filename,"%s\\ICON%d.ico",fileposition,count++);//文件名.ico n文件个数统计
printf("保存到文件:%s\n\n",filename);
if((to=fopen(filename,"wb+"))==NULL)
{
printf("创建文件:%s失败\n",filename);
getch();
continue;
}
fwrite(&Icon,sizeof(ICONDIR),1,to);//ICON文件头22字节
}
fwrite(image,entryData.Size,1,to);
free(image);
fclose(to);
}
}
}
}
}
printf("\n");
getch();
}
void Get_EXCEPTION(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset)
{
printf("例外结构不详....\n\n");
getch();
}
void Get_SECURITY(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset)
{
printf("安全结构不详....\n\n");
getch();
}
void Get_BASERELOC(FILE *fp,DWORD Table_offset)
{
DWORD Address,i;
IMAGE_BASE_RELOCATION Image_Base_Relocation;
fseek(fp,Table_offset,0);
fread(&Image_Base_Relocation,sizeof(IMAGE_BASE_RELOCATION),1,fp);
printf("重定位表获取中......\n");
while(Image_Base_Relocation.VirtualAddress) //以00 00 00 00结束
{
printf("页面基址:%08X\n",Image_Base_Relocation.VirtualAddress);
i=(Image_Base_Relocation.SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/2;//重定位个数
while(i>0)
{
fread(&Address,2,1,fp);
if((Address&0x0FFF)) //高4bit是类型,低12bit是偏移
printf("类型:%d 页面地址:%08X\n",(Address>>12)&0x000F,Image_Base_Relocation.VirtualAddress+(Address&0x0FFF));
i--;
}
fread(&Image_Base_Relocation,sizeof(IMAGE_BASE_RELOCATION),1,fp);
getch();
}
getch();
}
void Get_DEBUG(FILE *fp,DWORD File_Address,DWORD Mem_Address,DWORD Table_offset)
{
printf("调试结构不详....\n\n");
getch();
}
void Get_IAT(FILE *fp,DWORD Table_offset,DWORD Size)
{
DWORD Address,i;
i=0;
printf("IAT表[尚未加载,指向函数名ASC字符串]获取中.....\n");
fseek(fp,Table_offset,0);//定位
while(i<Size)
{
fread(&Address,4,1,fp);//这个地址就是由系统填写的IAT,在文件中指向函数ASC字符串RVA
printf("IAT:%08X\n",Address);
i+=4;
}
getch();
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课