首页
社区
课程
招聘
[原创]归纳PE结构基础知识,顺便手撕个PE
发表于: 2021-11-11 07:41 37969

[原创]归纳PE结构基础知识,顺便手撕个PE

2021-11-11 07:41
37969

PE是由微软设计的一种程序文件规范格式,微软设计PE文件格式的目的主要有二:a.为了兼容16位DOS系统;b.为了兼容其它操作系统。且不论初心是否达成,只是如此的雄心壮志,就注定导致PE的学习是需要掉他个大把头发的,因为当中设计了诸多与DOS和其它操作系统相关的内容,一眼望去茫茫一片着实让人心慌。尤其在学习PE之初,面对PE内容体系繁杂的结构和内容,难免心生忐忑(比如楼主,至今看到PE这两个字依然打哆嗦),不过我可可爱爱的王老师说了:用不到的,不用管它!对此楼主表示深以为然。

在正式开始手撕PE之前,还是要先捋捋相关的理论概念。

可执行文件就是无需借助其它应用程序,由操作系统直接负责加载运行的文件,如.exe后缀文件。反之需要借助其它软件才能被加载使用的诸如.txt等后缀文件,即为非可执行文件。此处的后缀名说明仅作为辅助理解,实际上,在操作系统中,判断可执行文件的主要依据并非文件名后缀标识,而是文件结构格式。

本文将以Windows平台的"PE文件格式"作为研究对象,相关资料来源于科锐学习笔记,如有错漏不妥之处,还望各位大佬多多指教。

图3-1    PE结构详图

图3-2    IMAGE_DOS_HEADER成员图析

MAGE_FILE_HEADER:描述磁盘上PE文件的相关信息。

*定位文件头地址:DOS头中的e_lfanew+4

图3-3    IMAGE_FILE_HEADER成员图析

IMAGE_FILE_HEADER::以供操作系统加载PE文件使用,必选。

*定位选项头地址:DOS头中的e_lfanew+4+0x14(文件头大小)。

图3-4    IMAGE_OPTIONAL_HEADER成员图析

节表:描述PE文件与内存之间的映射关系,由一系列的IMAGE_SECTION_HEADER结构排列而成,每个结构用来描述一个节(每个节占用0x28B),说明PE文件的指定内容拷贝至内存的哪个位置、拷贝大小及内存属性的设置。结构的排列顺序和它们描述的节在文件中的排列顺序是一致的。全部有效结构的最后以一个空的IMAGE_SECTION_HEADER结构作为结束,所以节表中总的IMAGE_SECTION_HEADER结构数量等于节的数量加一。节表总是被存放在紧接在PE文件头的地方。

节表大小 = FileHeader.NumberOfSections(节数量)* IMAGE_SECTION_HEADER 结构体。

图3-5    节属性常用位含义

节表置于选项头之后,节表首地址 计算方法:

(1)选项头的地址 + 选项头的大小;

(2) e_lfanew+4+0x14(文件头大小)+0xE0(32位选项头大小)。

图3-6   节表定位图析

数据目录用来描述PE中各个表的位置及大小信息,重点表:导出表、导入表、重定位表、资源表。

在这个数据目录结构体中只有两个成员 VirtualAddress Size :

参数1VirtualAddress指定了数据块的相对虚拟地址(RVA),因为当exe在处理导入表的时候,已经映射进进程内存了,取值RVA更方便。

Size则指定了该数据块的大小,有时并不是该类型数据的总大小,可能只是该类型数据一个数据项的大小。这两个成员(主要是VirtualAddress)成为了定位各种表的关键,所以一定要知道每个数组元素所指向的数据块类型,以下表格就是它的对应关系:

图3-7    IMAGE_DATA_DIRECTORY数组元素项图析

定位数据目录的技巧:数据目录向上找10h,+4即为DataDirectory的地址,编译器生成的一般都是10h。

图3-8    数据目录定位图析

IMP(导入表):导入表用来描述模块调用的API列表,位于PE数据目录中的第二项即DataDirectory[1],其中记录了导入表的地址和大小,VirtualAddress指向IMAGE_IMPORT_DESCRIPTOR 结构体数组,这个结构体数组中的每个元素对应着一个dll文件,以全0作为最后一个元素结尾。程序产生调用会生成CALL指令,两大问题及解决思路如下:

1.地址存放问题:出于运行环境等因素考虑,导入函数的地址不能为固定地址。所以在exe中保存导入函数的相关信息,系统和链接器对其进行约定:链接器在生成exe的时候,为所有调用API的地方填写一个间接地址,当程序运行起来后,相应地址则会被写入真正API的地址,此区域即为IAT表(导入地址表);

2.exe如何存储导入dll及其函数信息:dll与函数是一对多的关系,原则上应该设计为多方填写1方信息的数据关系,但考虑到数据较多的情况,遍历不便。反过来设计为1方存储多方信息的数据结构,虽然会造成插入删除的不方便,但是考虑到exe加载dll的实际场景,无插入删除需求,所以应该设计为后者结构更贴合遍历查询需求。

IAT(导入地址表):IMP中的FirstThunk指向IAT表。

INT(导入名称表):IMP中的OriginalFirstThunk指向INT表,也是DataDirectory[12]项。

PE加载后,IAT有变:加载后的IAT每一项存储的是所对应的导入函数地址。

图3-9    PE加载前后IMP、IAT、INT之间的关系

节数据:即是由不同属性数据组成的不同节。

实现目标:手写实现196 Byte大小的PE文件(又名:畸形PE/变形PE),要求MessageBox弹框显示"hello world"。

实现要点:充分利用空间,在保证遵循PE结构的基础上对数据结构进行重构存放。

运行环境--XP系统:XP对于畸形PE的兼容性更高。

编辑器--winhex:用于编写PE文件。

使用winhex工具,新建196字节大小的PE文件并将数据初始化为全CC,以便分辨空闲区。

图4-1    myWinPE.exe文件创建流程

文件偏移+0x00(注1),WORD e_magic→'MZ'文件头标识:0x5A4D(注2)

文件偏移+0x3C,LONG e_lfanew→指向NT头'PE'标识的地址:0x00000004

此处设置NT头地址为0x4偏移的原因:1.充分利用每字节可用空间,DOS除首尾两字段外都非必要字段,可用;2.当NT头置于0x4处,0x3C的功能不仅是指向NT头标识,还将成为选项头的成员SectionAlignment(文件对齐值),在XP中,此项最小值为4。综上两点,此处写入0x4最为合适。

图4-2    DOS_HEADER部分内容

文件偏移+0x04,DWORD Signature→'PE00'NT头标识:0x00004550

图4-3    NT头的Signature部分内容

文件偏移+0x08,WORD Machine→指定程序的运行平台0x104C(运行于Intel 386

文件偏移+0x0A,WORD NumberOfSections→PE中的节数量:0x0001(最小限值)

图4-4    NT头的FILE_HEADER部分内容

文件偏移+0x1C,WORD Magic→PE标志字即程序位数0x010B(32位系统)

文件偏移+0x2C,DWORD AddressOfEntryPoint→程序执行入口RVA:0x00000000

图4-5    NT头的OPTIONAL_HEADER部分内容

文件偏移+0xA4,DWORD VirtualSize内存时机占用大小:0x000000C4

文件偏移+0xA8,DWORD VirtualAddress内存地址RVA:0x00000000

图4-6   节表部分内容

图4-7   基础PE内容总览

根据导入内容思考设计:实现弹框需要写入两项内容:1.库名(user32);2.函数名(MessageBoxA)。根据两个字符串的长度(+00结束符)找到最合适的位置并写入:

文件偏移+0x30, dll名"user32 ",7Byte

图4-8   写入库名和函数名

导入表IMAGE_IMPORT_DESCRIPTOR 0xB0处,因为PE加载后,0xB0-0xC3处内存会被初始化为全0。

文件偏移+0xBCDWORD   Name→RVA指向dll名0x00000030

图4-9   填充导入表项

文件偏移+0x9C,PIMAGE_IMPORT_BY_NAME  AddressOfData指向IMAGE_IMPORT_BY_NAME:0x0000000A

图4-10  编写IAT表

文件偏移+0x80DataDirectory[1]导入表位置:0x000000B0

图4-11  写入导入表位置

OD检测:内存窗口中跟随地址0x40009C,以"长型→地址"方式查看,可见导入成功。

图4-12  OD检测导入表

文件偏移+0x60,在选项头的堆栈空间值区编写弹框文本:"hello world"

图4-13  写入MessageBox参数

*选线头主版本号不可用,故以副链接器版本号成员处(0x1F)开始非重要区域编写指令

文件偏移+0x1F参数4 UINT uType→对话框按钮类型:6A 00 = push 0(注3)

文件偏移+0x4A,调用后返回:C3=ret

图4-14  写入指令

文件偏移+0x44,OEP:FF15 9C004000= CALL  0040009C

图4-15  修改OEP


图4-16  完整PE总览

完结撒花花

图4-17  效果展示

[注1]:编写数据时标注的偏移值为相对于文件而言,而非对应结构体。

[注2]:内存中采用小尾存储方式,高位字节存放于低地址单元,低位字节存放在高地址单元中。所以在进行文字描述时是根据其数据类型进行转换书写,例如文件前两个字节即'MZ'标识处内存分别显示0x4D、0x5A,但在描述时根据其类型WORD(2字节)就书写为0x5A4D。

typedef struct _IMAE_DOS_HEADER//  偏移, 意义
{ 
    WORD e_magic;              //  0x00, 'MZ'(0x5A4D)标识 	
		......中间成员为兼容16位操作系统,可修改可忽略......
    LONG e_lfanew;             //  0x3C, PE头的起始地址,默认0xB0处
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;  

1.WORD e_magic(0x00处)
● 对应PE文件的开头,是PE文件DOS头的标识符"MZ"→0x5A4D
  ○ 对应Winnt.h头文件中宏定义: #define IMAGE_DOS_SIGNATURE 0x4D5A // MZ
2.LONG e_lfanew(0x3C处)
● 对应PE文件0x3C处指向NT头在文件中的偏移(默认0xB0),即32位及以上系统文件头在文件中真正的偏移
对应Winnt.h头文件中宏定义:,#define IMAGE_NT_SIGNATURE 0x50450000 // PE00
// 文件头结构体: _IMAGE_FILE_HEADER
typedef struct _IMAGE_FILE_HEADER{
	 WORD Machine; 								// +0x00, 指定程序的运行平台,勿改
	 WORD NumberOfSections; 			// +0x02, PE中的节/块(section)数量,勿改
	 DWORD TimeDateStamp; 				// +0x04, 时间戳:链接器填写的文件生成时间
	 DWORD PointerToSymbolTable;  // +0x08, 指向符号表的地址(主要用于调试)
	 DWORD NumberOfSymbols; 			// +0x0C, 符号表中符号个数(同上)
	 WORD SizeOfOptionalHeader; 	// +0x10, IMAGE_OPTIONAL_HEADER32选项头结构大小,勿改
	 WORD Characteristics; 				// +0x12, 文件属性,勿改
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

//* 字段1:Machine 表CPU的类型, 定义在windows.h中,常用类型
			32位:#define IMAGE_FILE_MACHINE_I386, 0x014c // Intel 386, x86
			64位:#define IMAGE_FILE_MACHINE_AMD64, 0x8664 // AMD64(KB), x64
//* 字段2:NumberOfSections 表PE中的节(section)数量:
			节表紧跟在IMAGE_NT_HEADERS后面,此字段决定了节表中元素的个数,即节的个数
      遍历节表经验:根据此处的个数拿对应的节表数据
//* 字段6:SizeOfOptionalHeader 表IMAGE_OPTIONAL_HEADER32 结构大小
			定位节表位置=选项头地址+选项头大小
//* 字段7: Characteristics 表文件属性,EXE默认0100,DLL默认210Eh,或运算组合设置。
#define IMAGE_FILE_RELOCS_STRIPPED     0x0001 // 文件中不存在重定位信息
#define IMAGE_FILE_EXECUTABLE_IMAGE    0x0002 // 文件可执行
#define IMAGE_FILE_LINE_NUMS_STRIPPED   0x0004 // 文件中不存在行信息
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED   0x0008 // 文件中不存在符号信息
#define IMAGE_FILE_AGGRESIVE_WS_TRIM    0x0010 // 调整工作集
#define IMAGE_FILE_LARGE_ADDRESS_AWARE   0x0020 // 程序能处理大于2G的地址
#define IMAGE_FILE_BYTES_REVERSED_LO    0x0080 // 小尾方式
#define IMAGE_FILE_32BIT_MACHINE      0x0100 // 只在32位平台上运行
#define IMAGE_FILE_DEBUG_STRIPPED     0x0200 // 不包含调试信息
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // 不能从可移动盘运行
#define IMAGE_FILE_NET_RUN_FROM_SWAP    0x0800 // 不能从网络运行 
#define IMAGE_FILE_SYSTEM          0x1000 // 系统文件(如驱动程序),不能直接运行
#define IMAGE_FILE_DLL            0x2000 // 是一个dll文件
#define IMAGE_FILE_UP_SYSTEM_ONLY      0x4000 // 文件不能在多处理器计算机上运行
#define IMAGE_FILE_BYTES_REVERSED_HI     0x8000 // 大尾方式
// 32位选项头结构体:_IMAGE_OPTIONAL_HEADER
typedef struct _IMAGE_OPTIONAL_HEADER
{
	WORD   Magic;							//* PE标志字:32位(0x10B),64位(0x20B)
	BYTE   MajorLinkerVersion;				//	主链接器版本号
	BYTE   MinorLinkerVersion;				//	副链接器版本号
	DWORD  SizeOfCode;						//	代码所占空间大小(代码节大小)
	DWORD  SizeOfInitializedData;			//	已初始化数据所占空间大小
	DWORD  SizeOfUninitializedData;			//	未初始化数据所占空间大小
	DWORD  AddressOfEntryPoint;				//*	程序执行入口RVA,(w)(Win)mainCRTStartup:即0D首次断下来的自进程地址
	DWORD  BaseOfCode;						//	代码段基址
	DWORD  BaseOfData;						//	数据段基址
	DWORD  ImageBase;						//*	内存加载基址,exe默认0x400000,dll默认0x10000000
	DWORD  SectionAlignment;				//*	节区数据在内存中的对齐值,一定是4的倍数,一般是0x1000(4096=4K)
	DWORD  FileAlignment;					//*	节区数据在文件中的对齐值,一般是0x200(磁盘扇区大小512)
	WORD   MajorOperatingSystemVersion;		//	要求操作系统最低版本号的主版本号
	WORD   MinorOperatingSystemVersion;		//	要求操作系统最低版本号的副版本号
	WORD   MajorImageVersion;				//	可运行于操作系统的主版本号
	WORD   MinorImageVersion;				//	可运行于操作系统的次版本号
	WORD   MajorSubsystemVersion;			//	主子系统版本号:不可修改
	WORD   MinorSubsystemVersion;			//	副子系统版本号
	DWORD  Win32VersionValue;				//	版本号:不被病毒利用的话一般为0,XP中不可修改
	DWORD  SizeOfImage;						//*	PE文件在进程内存中的总大小,与SectionAlignment对齐
	DWORD  SizeOfHeaders;					//*	PE文件头部在文件中的按照文件对齐后的总大小(所有头 + 节表)
	DWORD  CheckSum;						//	对文件做校验,判断文件是否被修改:3环无用,MapFileAndCheckSum获取
	WORD   Subsystem;						//	子系统,与连接选项/system相关:1=驱动程序,2=图形界面,3=控制台/Dll
	WORD   DllCharacteristics;				//	文件特性
	DWORD  SizeOfStackReserve;				//	初始化时保留的栈大小
	DWORD  SizeOfStackCommit;				//	初始化时实际提交的栈大小
	DWORD  SizeOfHeapReserve;				//	初始化时保留的堆大小
	DWORD  SizeOfHeapCommit;				//	初始化时实际提交的堆大小
	DWORD  LoaderFlags;						//	已废弃,与调试有关,默认为 0
	DWORD  NumberOfRvaAndSizes;				//	下边数据目录的项数,此字段自Windows NT发布以来,一直是16
	IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];// 数据目录表
} IMAGE_OPTIONAL_HEADER32, * PIMAGE_OPTIONAL_HEADER32;

//* 字段6:AddressOfEntryPoint 表 程序入口RVA,即OEP:
      EOP:程序入口点,壳相关概念
      OEP:原本的程序入口点(实际为偏移,+模块基址=实际入口点)
      EP: 被加工后的入口点
//* 字段9:ImageBase 表 模块加载基地址,exe默认0x400000,dll默认0x10000000
      建议装载地址:exe映射加载到内存中的首地址= PE 0处,即实例句柄hInstance
      一般而言,exe文件可遵从装载地址建议,但dll文件无法满足
//* 尾字段:DataDirectory 表 数据目录表,用来定义多种不通用处的数据块。
      存储了PE中各个表的位置,详情参考IMAGE_DIRECTORY_ENTRY...系列宏
// IMAGE_SECTION_HEADER 节表结构体,大小40B
typedef struct _IMAGE_SECTION_HEADER {
  BYTE  Name[IMAGE_SIZEOF_SHORT_NAME];	// 节表名称:描述性字段
  // 下方4个字段:从文件S1处开始,拷贝S2大小的数据,到内存S3处,有效数据占用内存S4大小
  union {
    DWORD PhysicalAddress;
    DWORD VirtualSize;			// S4:内存大小
  } Misc;
  DWORD VirtualAddress;			// S3:内存地址:基于模块基址
  DWORD SizeOfRawData;			// S2:文件大小
  DWORD PointerToRawData;		// S1:文件偏移
  DWORD PointerToRelocations;	// 无用
  DWORD PointerToLinenumbers;	// 无用
  WORD  NumberOfRelocations;	// 无用
  WORD  NumberOfLinenumbers;	// 无用
  DWORD Characteristics;		// 节属性,取值IMAGE_SCN_...系列宏
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
// 数据目录 _IMAGE_DATA_DIRECTORY结构体
typedef struct _IMAGE_DATA_DIRECTORY {
  DWORD VirtualAddress;     /**指向某个数据的相对虚拟地址   RAV  偏移0x00**/
  DWORD Size;               /**某个数据块的大小                 偏移0x04**/
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
// IMAGE_IMPORT_DESCRIPTOR 导入表结构,以全0(20个0)结尾
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;     //  作用1:导入表结束标志
        DWORD   OriginalFirstThunk;  //* 作用2:*RVA指向一个结构体数组(INT表)
    }; 
    DWORD   TimeDateStamp;           //  时间戳
    DWORD   ForwarderChain;          //  -1 if no forwarders
    DWORD   Name;                    //* RVA指向以0结尾的dll名字
    DWORD   FirstThunk;              //* RVA指向一个结构体数组(IAT表,DataDirectory[12]项)
} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;
/ IMAGE_THUNK_DATA结构体汇总只有一个联合体,
// 一般用四字节的AddressOfData来获取IMAGE_IMPORT_BY_NAME的地址。
// 四字节解析,看最高位[31]:
//      1表序号导入,低word为导入函数的序号值;
//      0表RVA,指向_IMAGE_IMPORT_BY_NAME;
typedef struct _IMAGE_THUNK_DATA32 {
    union {
        PBYTE  ForwarderString;  	// PBYTE 指向一个转向者字符串的RVA;
        PDWORD Function;      	 	// PDWORD 被输入的函数的内存地址;
        DWORD Ordinal;       		// *被输入的API的序数值
        PIMAGE_IMPORT_BY_NAME  AddressOfData; //*RVA 指向IMAGE_IMPORT_BY_NAME
    } u1;
} IMAGE_THUNK_DATA32;


// IMAGE_IMPORT_BY_NAME有两个成员:1.序号;2.函数名。
typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD    Hint;   // 可能为0,编译器决定,如果不为0,是函数在导出表中的索引
    BYTE    Name[1];// 函数名称以0结尾,由于不知道到底多长,所以干脆只给出第一个字符,找到0结束
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
  • PE是由微软设计的一种程序文件规范格式,微软设计PE文件格式的目的主要有二:a.为了兼容16位DOS系统;b.为了兼容其它操作系统。且不论初心是否达成,只是如此的雄心壮志,就注定导致PE的学习是需要掉他个大把头发的,因为当中设计了诸多与DOS和其它操作系统相关的内容,一眼望去茫茫一片着实让人心慌。尤其在学习PE之初,面对PE内容体系繁杂的结构和内容,难免心生忐忑(比如楼主,至今看到PE这两个字依然打哆嗦),不过我可可爱爱的王老师说了:用不到的,不用管它!对此楼主表示深以为然。

  • 在正式开始手撕PE之前,还是要先捋捋相关的理论概念。

  • 可执行文件就是无需借助其它应用程序,由操作系统直接负责加载运行的文件,如.exe后缀文件。反之需要借助其它软件才能被加载使用的诸如.txt等后缀文件,即为非可执行文件。此处的后缀名说明仅作为辅助理解,实际上,在操作系统中,判断可执行文件的主要依据并非文件名后缀标识,而是文件结构格式。

    • Windows平台可执行文件的文件结构称为"PE文件结构(Portable Executable)";
    • Linux平台可执行文件的文件结构称为"ELF文件结构(Executable and Linkable Format)"。
  • 本文将以Windows平台的"PE文件格式"作为研究对象,相关资料来源于科锐学习笔记,如有错漏不妥之处,还望各位大佬多多指教。

  • Windows平台可执行文件的文件结构称为"PE文件结构(Portable Executable)";
  • Linux平台可执行文件的文件结构称为"ELF文件结构(Executable and Linkable Format)"。
  • MAGE_FILE_HEADER:描述磁盘上PE文件的相关信息。

  • *定位文件头地址:DOS头中的e_lfanew+4

  • IMAGE_FILE_HEADER::以供操作系统加载PE文件使用,必选。

  • *定位选项头地址:DOS头中的e_lfanew+4+0x14(文件头大小)。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-11-23 16:45 被633编辑 ,原因: 改进文章排版
收藏
免费 15
支持
分享
最新回复 (19)
雪    币: 24
活跃值: (302)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
shanjie YYDS
2021-11-11 19:14
0
雪    币: 1103
活跃值: (1662)
能力值: ( LV5,RANK:65 )
在线值:
发帖
回帖
粉丝
3
写的挺好的,刨析了较小PE的结构,加油!!!
2021-11-11 19:28
0
雪    币: 191
活跃值: (201)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
写的很棒,吃水不忘挖井人。
2021-11-11 19:32
1
雪    币: 3297
活跃值: (5395)
能力值: ( LV6,RANK:92 )
在线值:
发帖
回帖
粉丝
5
很不错,我猜你可能是我的学弟学妹
2021-11-12 08:50
0
雪    币: 493
活跃值: (1078)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
633
6
wx_〒_〒 shanjie YYDS
夸夸师强哥持续在线
2021-11-12 10:29
0
雪    币: 493
活跃值: (1078)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
633
7
瑞皇 写的挺好的,刨析了较小PE的结构,加油!!!
2021-11-12 10:30
0
雪    币: 493
活跃值: (1078)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
633
8
2021-11-12 10:32
0
雪    币: 493
活跃值: (1078)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
633
9
0xC5 很不错,我猜你可能是我的学弟学妹[em_48]
40期学妹表示久闻学长大名,感谢肯定,会继续加油哒
2021-11-12 10:33
0
雪    币: 23
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
手撸shellcode +手撸pe=最小最精简可执行文件--》变种=自己组织可执行带重定位和导入导出结构的类pe文件
2021-11-25 21:48
0
雪    币: 493
活跃值: (1078)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
633
12
大魔法狮子 手撸shellcode +手撸pe=最小最精简可执行文件--》变种=自己组织可执行带重定位和导入导出结构的类pe文件
今天刚接触到shellcode,等琢磨明白了就跟着大佬的思路来一个,谢谢指点
2021-11-30 22:18
0
雪    币: 417
活跃值: (367)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
原来是shanshan sister,认出来了,刚好可以复习一下
2022-3-4 19:20
0
雪    币: 1187
活跃值: (410)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
什么学校
2022-4-8 14:45
0
雪    币: 299
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
文件偏移+0x08,WORD Machine→指定程序的运行平台:0x104C(运行于Intel 386)
这里应该是014c
这篇文章应该设置为精华,对PE,特别是输入表的理解应该是相当透彻了
感谢MM
2022-5-26 19:27
0
雪    币: 4383
活跃值: (3393)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
学习
2022-9-20 10:27
0
雪    币: 10023
活跃值: (4416)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
受教
2022-9-20 11:41
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
看雪里面光大佬啊,我刚学PE不管咋样我都要先手撕一下PE先充实一下自己
2023-11-26 19:28
0
雪    币: 7018
活跃值: (9199)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
19
妹妹太强了,我要拜你为师
2023-11-26 20:22
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
运行不了。那里出错了。。。
2天前
0
游客
登录 | 注册 方可回帖
返回
//