首页
社区
课程
招聘
[旧帖] PE结构代码[申请邀请码] 0.00雪花
发表于: 2009-12-24 11:37 3688

[旧帖] PE结构代码[申请邀请码] 0.00雪花

2009-12-24 11:37
3688
这段代码是我在研究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直播授课

收藏
免费
支持
分享
最新回复 (40)
雪    币: 32
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
看不懂,不过还是支持一下楼主,顺便坐个沙发!
2009-12-24 12:46
0
雪    币: 77
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
这应该不能拿到推广邀请吗吧,不过支持一下
2009-12-24 14:40
0
雪    币: 54
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
要如何才能拿到呢?
2009-12-24 15:19
0
雪    币: 54
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
上面代码我花了一个月学习PE所写出来的,我还学习并亲手写了几种加密算法,比如MD5,DES,RAS比较著名的算法
2009-12-24 15:47
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
写的不错,支持
2009-12-24 19:05
0
雪    币: 92
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
不错.......
天草的教程, 哪里有下啊??  window7  下面纳米盘下载不了
2009-12-24 21:08
0
雪    币: 54
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
网上很多都可以下天草视频,一共200部教程
2009-12-24 22:15
0
雪    币: 80
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
看不懂,不过还是支持一下楼主
2009-12-25 09:10
0
雪    币: 29
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
好多结构体  学习
2009-12-27 08:15
0
雪    币: 1876
活跃值: (1730)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
LZ这是C++吧?我试试先~~~
2009-12-27 13:46
0
雪    币: 72
活跃值: (52)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
看不懂 支持下
2009-12-27 14:18
0
雪    币: 32
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
楼上的写的不错,不过如果楼上看了罗老师的win32位下的汇编的话,可能发现这个东西早就有了!
2009-12-27 14:27
0
雪    币: 458
活跃值: (426)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
14
楼主测试过了吗 我用MFC写的程序 图标都提取不出来的!- -! 提取出来的是错误的文件不能正确显示!
2010-1-5 17:26
0
雪    币: 13
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
这是什么代码呀,看得头发晕
2010-1-5 17:39
0
雪    币: 6145
活跃值: (4276)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
16
我的天,这么多?
2010-1-5 18:51
0
雪    币: 12
活跃值: (120)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
支持下,看看~
2010-1-6 13:38
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
正在学PE 不过看不懂
2010-1-6 15:57
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
看不懂 头晕中 占位慢慢看
2010-1-6 16:09
0
雪    币: 66
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
哎,我当年也学了一阵子,然后学完PE后就茫然了,就迷失了,就不知道该干嘛了,
2010-1-6 16:14
0
雪    币: 555
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
支持下 呵呵
2010-1-6 16:15
0
雪    币: 525
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
就是排版看的晕。  不过整理肯定也比较辛苦  支持了
2010-1-8 19:10
0
雪    币: 6
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
**,jiayou a
2010-1-8 19:59
0
雪    币: 6
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
怎么把我的字屏蔽了?我发的ding ni
2010-1-8 20:01
0
雪    币: 152
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
支持下 我也正想学这个!
2010-1-8 23:38
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册