从今天开始,我们要学习一门新的课,大体的课程安排是这样的。
PE概念:Portable Excutable File Formate 可移植的可执行的文件格式。
它是能够被解析的文件,里面有一个内部的格式的,比如图片、音频、视频、压缩包文件等。在 windows 上可以用来被执行的文件 比如 exe、dll,它们也有自己的格式。
PE有好多表,基本上我们只会用到跟我们安全行业相关的,比如导入表、导出表,重定位表、TLS和资源表。
PE的一段小历史,原先操作系统是 DOS 系统, DOS系统是 16 位的系统,后来才出NT windows 系统是 32 位。 DOS 系统的文件它其实是有自己的格式的,但是它只支持 16 位的。当操作系统由DOS 系统转向windows操作系统, 或者说由 16 位转向 32 位的操作系统时候。就要面临可执行文件格式的转变,就需要设计新的文件格式。比尔盖茨就希望以后所有的操作系统上的可执行文件格式都按照他的标准来,当然这个梦想微软没有实现。那么这个新的文件格式就是要兼容 16 位的文件格式,要兼容其它所有的平台方向。
生成一个比较小的PE,作为一个标准的 PE 。
程序里面就弹一个 messageBox,然后一个退出进程, 就完事了。
新建工程——》下一步——》选择win32 ——》下一步——》完成。
其余的代码都不要,就弹一个 MessageBox,如以下代码所示。
.586
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
.data
g_szText db "Standard pe",0
g_szTitle db "Tip",0
.code
start:
invoke MessageBox,NULL,offset g_szText,offset g_szTitle,MB_OK
xor eax,eax
invoke ExitProcess,eax
end start
选择构建
构建完成,无报错。
直接查看生成PE文件有3KB
或者使用WinHex工具查看,结果是3072 bytes的大小
拿出来改下名字,标准 PE
以后我们看文件格式就看它了。
使用编译器把PE文件生成到编译器的极限。编译器能生成到多小,就让它生成到多小。
ml /c /coff PE.Asm
link /subsystem:windows user32.lib kernel32.lib PE.obj
查看程序的大小 16K? 这越变越大 ???
程序中间空有非常多的0,这些0都是为了对齐文件而准备的。
所以我们要把这些0干掉。
能看出来这里 6A00680C是代码,代码下面一堆的0。
导入函数的名称
这个是用到的字符串
用到的字符串,编译器给我准备一个内存分页。1000
所以把数据段里的代码移进到代码里面,不用再帮我为数据准备单独的。
.586
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
.code
g_szText db "Standard pe",0
g_szTitle db "Tip",0
start:
invoke MessageBox,NULL,offset g_szText,offset g_szTitle,MB_OK
xor eax,eax
invoke ExitProcess,eax
end start
编译——>链接
再来看一眼,发现程序大小少了一点点,12KB
这是我用到的字符串,这个是代码,这字符串和代码放一块去了。
那么接下来把导入函数跟代码也放一块
这个时候你在源码里面就改不了,只能通过链接器。
把这两个东西合成一块。链接器有一个选项,** /MERGE:from=to**,把两块区域合到一块。
E:\CR41\第三阶段\04 PE\01 PE头\PE>link
Microsoft ® Incremental Linker Version 6.00.8447
Copyright © Microsoft Corp 1992-1998. All rights reserved.
usage: LINK [options] [files] [@commandfile]
options:
/ALIGN:#
/BASE:{address|@filename,key}
/COMMENT:comment
/DEBUG
/DEBUGTYPE:{CV|COFF}
/DEF:filename
/DEFAULTLIB:library
/DELAY:{NOBIND|UNLOAD}
/DELAYLOAD:dll
/DLL
/DRIVER[:{UPONLY|WDM}]
/ENTRY:symbol
/EXETYPE:DYNAMIC
/EXPORT:symbol
/FIXED[:NO]
/FORCE[:{MULTIPLE|UNRESOLVED}]
/GPSIZE:#
/HEAP:reserve[,commit]
/IMPLIB:filename
/INCLUDE:symbol
/INCREMENTAL:{YES|NO}
/LARGEADDRESSAWARE[:NO]
/LIBPATH:dir
/LINK50COMPAT
/MACHINE:{ALPHA|ARM|IX86|MIPS|MIPS16|MIPSR41XX|PPC|SH3|SH4}
/MAP[:filename]
/MAPINFO:{EXPORTS|FIXUPS|LINES}
** /MERGE:from=to**
/NODEFAULTLIB[:library]
/NOENTRY
/NOLOGO
/OPT:{ICF[,iterations]|NOICF|NOREF|NOWIN98|REF|WIN98}
/ORDER:@filename
/OUT:filename
/PDB:{filename|NONE}
/PDBTYPE:{CON[SOLIDATE]|SEPT[YPES]}
/PROFILE
/RELEASE
/SECTION:name,[E][R][W][S][D][K][L][P][X]
/STACK:reserve[,commit]
/STUB:filename
/SUBSYSTEM:{NATIVE|WINDOWS|CONSOLE|WINDOWSCE|POSIX}[,#[.##]]
/SWAPRUN:{CD|NET}
/TSAWARE[:NO]
/VERBOSE[:LIB]
/VERSION:#[.#]
/VXD
/WARN[:warninglevel]
/WINDOWSCE:{CONVERT|EMULATION}
/WS:AGGRESSIVE
link /MERGE:.rdata=.text /subsystem:windows user32.lib kernel32.lib PE.obj
把.rdata 放到.text 里面
合并完大小为8KB
多出来的 0 是为了对齐,说明它有个对齐值,把对齐值改小了,用来对齐的数据自然就少了。通过链接器 **/ALIGN:# **去修改对齐值。此选项指定程序的线性地址空间中的每个部分的对齐方式。number参数以字节为单位,必须是2的幂。默认值是4K。如果对齐产生无效图像,链接器发出警告。
link /ALIGN:16 /MERGE:.rdata=.text /subsystem:windows user32.lib kernel32.lib PE.obj
fatal error LNK1164: section 0x1 alignment (16) greater than /ALIGN value
致命错误LNK1164: section 0x1对齐(16)大于/ALIGN值
2B0的大小,688 KB
创建VS工程——> 控制台
包含include
:::tips
IMAGE_DOS_HEADER
IMAGE_NT_HEADERS
IMAGE_FILE_HEADER
IMAGE_OPTIONAL_HEADER
IMAGE_DATA_DIRECTORY[1]
IMAGE_SECTION_HEADER[1]
:::
IMAGE_FILE_HEADER、IMAGE_OPTIONAL_HEADER { IMAGE_DATA_DIRECTORY[1] }
都是IMAGE_NT_HEADERS 的成员。
IMAGE_DOS_HEADER 叫做DOS头
IMAGE_NT_HEADERS NT头
大概是C0从这里到1B7这里,这是 NT部分。
IMAGE_FILE_HEADER FILE头
IMAGE_OPTIONAL_HEADER
IMAGE_DATA_DIRECTORY[1]
它是一个柔性数组
常见的是 16 个,但实际上它不是固定的,它可以更加少。
IMAGE_SECTION_HEADER[1]
它也是一个柔性数组
DOS头成员有很多,这里面的成员基本上给对我们来说有用的只有两个。
:::success
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
:::
一个是 WORD e_magic; 另一个是LONG e_lfanew; 中间的这些都是都是 16 位时代的字段,跟 16 位的可执行文件是有关系的,但是到了 32 位操作系统,这个东西都是随便改的。
第一个WORD e_magic 这个是文件标识。PNG 图片的开头、还有 ZIP 文件的开头、这些文件都有着独自己独特的标识。
PDF文件
ZIP文件
文件的标识,独特的标识。这个东西能不能改。
这不是程序崩溃了,这是 windows 在加载可执行文件的时候,检查文件格式的的阶段就出了问题。它认为你不是一个可执行文件,所以直接给你报错。说明它你的格式。 检查不过关,所以这里不能改。
那么中间的字段偏移是29个WORD,(58)3A的大小。
WORD e_magic 和 LONG e_lfanew 中间的字段都是可以改的。e_lfanew是一个LONG 也就是DWORD值。
中间这些位置都是可以改的。
e_lfanew 这个是32 位T真正的NT头在文件中的偏移的位置
在这个位置到中间,你会发现是不是有一大块的残留代码。残留代码英文名指的是stub code
这一段代码其实是提示 DOS 系统的使用者的。当你把一个 32 位的程序放到 DOS 系统里面跑的时候,它就会输出字符串This program cannot be run in DOS mode
这个程序是 32 位的,不能够在DOS环境下跑。这些代码清掉。
IMAGE_NT_HEADERS32和IMAGE_NT_HEADERS64
:::success
#ifdef _WIN64
typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS;
typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS;
#else
typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS;
typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS;
#endif
:::
这两者有区别的是指针的长度。
IMAGE_NT_HEADERS32
IMAGE_NT_HEADERS64
字段意义都是一样的,只不过是长度不一样了。
32 位的 NT 头
:::success
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
:::
有 3 个成员,第一个成员是一个DWORD,叫做 Signature 签名,
这个其实是真正的 PE 文件的文件标识,这玩意儿不能随便改,这 4 个字节是不能随便动的。
IMAGE_FILE_HEADER 文件头 描述文件信息的
:::success
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
:::
大小是是一行半行,一般记 PE 行数,一行出 4 个DWORD 。 一行半一行出 12 个WORD。
第一个WORD Machine 这个是可执行文件所运行的 CPU 的平台或者机器平台。 Machine 取值有这些:
:::success
#define IMAGE_FILE_MACHINE_UNKNOWN 0
#define IMAGE_FILE_MACHINE_TARGET_HOST 0x0001 // Useful for indicating we want to interact with the host and not a WoW guest.
#define **IMAGE_FILE_MACHINE_I386 ** 0x014c // Intel 386.
#define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian
#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP
#define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3
#define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian
#define IMAGE_FILE_MACHINE_SH5 0x01a8 // SH5
#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_AM33 0x01d3
#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian
#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1
#define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64
#define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS
#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
#define IMAGE_FILE_MACHINE_TRICORE 0x0520 // Infineon
#define IMAGE_FILE_MACHINE_CEF 0x0CEF
#define IMAGE_FILE_MACHINE_EBC 0x0EBC // EFI Byte Code
#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8)
#define IMAGE_FILE_MACHINE_M32R 0x9041 // M32R little-endian
#define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian
#define IMAGE_FILE_MACHINE_CEE 0xC0EE
:::
常见的有IMAGE_FILE_MACHINE_I386 和 IMAGE_FILE_MACHINE_AMD64
在 windows 上基本上常见的就这两个。
14C,所以通过这里可以去判断一个 PE 文件,它是一个 32 位的 PE 文件,还是一个 64 位的 PE 文件。
NumberOfSections 解表项的个数
就是保存着 IMAGE_SECTION_HEADER[1] 数组中元素的个数。
这是个数组中元素的个数,将来我们遍历解表的时候来用的
所以遍历解表是个数是由文件头的第二个字段来决定的,也不能随便改。
解表决定了如何从 PE 文件拷数据到内存,你少一个解表就少一块数据。
:::success
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
:::
这三个都是没啥用的. TimeDateStamp 时间戳, PE文件生成的时间由link 打上去的。接着 PointerToSymbolTable和NumberOfSymbols, 跟符号相关的。但是 windows 的符号现在都放到.pdb文件里面了,所以这两个也啥用,直接给它干掉。
接着这个 WORD SizeOfOptionalHeader 这个是选项头的大小
IMAGE_OPTIONAL_HEADER32 它叫做选项头,这个头的大小放到这个SizeOfOptionalHeader 字段,选项图的大小来用来帮助我们定位解表的位置。
怎么定位?比如 E0大小,选项头的地址加上选项头的大小就是解表的位置。
大小不能随便改。
WORD Characteristics 属性
属性的取值有这些,这是它的属性的取值。
:::success
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved external references).
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.
#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 // Aggressively trim working set
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // App can handle >2gb addresses
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed.
#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file.
#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file.
#define IMAGE_FILE_SYSTEM 0x1000 // System File.
#define IMAGE_FILE_DLL 0x2000 // File is a DLL.
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.
:::
01F :
:::success
#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.
define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved external references).
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.
:::
8421 按位运算。
IMAGE_OPTIONAL_HEADER32 OptionalHeader 选项头
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
//
// NT additional fields.
//
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
主链接器版本号,副链接器版本号。这个是链接器版本号,这也是链接器打上去的东西,一般也没啥用。
直接干掉
接着
分别对应的汇编
.code :代码大小
.data :初始化数据大小
.data? :未初始化数据大小
这三个东西系统都没有依赖。
DWORD AddressOfEntryPoint;这个是程序的入口点。
这个值其实是一个与模块首地址的偏移,使用OD 打开。
这个是入口点。这玩意能随便改吗?
假如我要在代码段0000 0500的位置写入跳转代码 那对应的机器码是多少?代码段的起始位距离
要修改的位置偏移是100
所以在OD中偏移也是100
OD中代码起始位置是00401000,加上偏移地址100就是00401100。所以我们在00401100的位置添加修改代码。
将机器码改到0000 0500的位置中
PE 往后数两行半,修改程序入口点的偏移地址
DWORD BaseOfCode;代码的地址
DWORD BaseOfData;数据的地址
这两个东西 windows 也是操作系统是不依赖的。这种东西也是可以改。
DWORD ImageBase;模块基址 它其实就是 PE 映射进内存里面的首地址
00400000就是OD一加载,就停到这个入口点了
如果要改模块机制,你就要改很多东西,把这些原先,资源的位置,字符串、全局变量涉及到的地址都要去改掉。把模块基址改为0050 0000
这个地址,操作系统一定会满足可执行文件吗
不一定。主模块是可以满足的,是第一个被加载的模块,但是 dll 基本上是不会被满足的。比如大家都填0100000 ,dll都是这个地址。 但你肯定有一个占了,剩下占不到了,所以dll 一般情况下是满足不了的。
所以这个东西我们也叫做建议模块机制,就是可执行文件或者链接器。建议操作系统把可执行文件加载到模块地址,但是不一定就能够加载到这个地址,系统不一定能够满足这些文件。 尤其是程序,如果开了随机地址,基本上它都不会加载到00401000这个地址。 这个东西还跟实例句柄有关系,实例句柄就是可执行文件在内存中的首地址。
DWORD SectionAlignment; 内存中的对齐值
DWORD FileAlignment; 文件中的对齐值
这两个值改的时候要非常的小心。因为很多其他的值都跟这两个值息息相关,比如 模块基址它要跟谁跟这个内存对齐值对齐。
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
Win 7 以上是可以改的。但是这个值在 XP 里面是不能随便改的。
DWORD SizeOfImage; 是可执行文件在内存中所占内存的总大小。
5000的大小
使用OD查看
它占内存 5000
它是一个计算得来的值,它是由各节的内存大小计算得来的值。
DWORD SizeOfHeaders; 这个是 PE头的总大小 400
这个值的要求它是跟文件对齐值.
DWORD CheckSum; 校验值,对于我们三环程序。 你可以随便改的.
但是对于驱动来说,这个值是不能改的,驱动会严格检查这个值,因为驱动这个玩意一旦出了问题,要比什么带来的灾难,要比我们三环程序出问题带来的灾难要大得多。
WORD Subsystem;
子系统这玩意不能随便改。哪些取值?
// Subsystem Values
#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem.
#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem.
#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image runs in the Posix character subsystem.
#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 // image is a native Win9x driver.
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 // Image runs in the Windows CE subsystem.
#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 //
#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 //
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 //
#define IMAGE_SUBSYSTEM_EFI_ROM 13
#define IMAGE_SUBSYSTEM_XBOX 14
#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16
#define IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG 17
改成 03CUI 控制台
这玩意不能随便改
WORD DllCharacteristics;
// DllCharacteristics Entries
// IMAGE_LIBRARY_PROCESS_INIT 0x0001 // Reserved.
// IMAGE_LIBRARY_PROCESS_TERM 0x0002 // Reserved.
// IMAGE_LIBRARY_THREAD_INIT 0x0004 // Reserved.
// IMAGE_LIBRARY_THREAD_TERM 0x0008 // Reserved.
#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 // Image can handle a high entropy 64-bit virtual address space.
#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 // DLL can move.
#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY 0x0080 // Code Integrity Image
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 // Image is NX compatible
#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 // Image understands isolation and doesn't want it
#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 // Image does not use SEH. No SE handler may reside in this image
#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 // Do not bind this image.
#define IMAGE_DLLCHARACTERISTICS_APPCONTAINER 0x1000 // Image should execute in an AppContainer
#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 // Driver uses WDM model
#define IMAGE_DLLCHARACTERISTICS_GUARD_CF 0x4000 // Image supports Control Flow Guard.
#de
#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 // DLL can move
可以检测是否开启随机基址
OD查看
ULONGLONG SizeOfStackReserve;
ULONGLONG SizeOfStackCommit;
ULONGLONG SizeOfHeapReserve;
ULONGLONG SizeOfHeapCommit;
这几个值可以改,但不能改的太离谱。
DWORD LoaderFlags;
系统没用
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
这是个柔性数组这里面的元素的个数要看NumberOfRvaAndSizes ,DataDirectory 我们叫做数据目录。它其实是 PE 里面各种各样的表的位置 比如导入表\重导出表,重定位表, T2S 表,资源表.