Java 1 Java基础
注释Java中的注释有三种:
单行注释
多行注释
文档注释
1234567891011121314151617public class Demo { public static void main(String[] args) { //单行注释:只能注释一行文字 // //输出一个Hello,World! System.out.println("Hello,World!"); //多行注释:可以注释一段文字 /* 注释 */ /* 123 123 */ //JavaDoc:文档注释 /** */ /** * @Descrition HelloWorld * @Author */ }}
标识符和关键字Java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符
所有的标识符都应该以字母(A-Z或者a-z ...
PE 6 文件数据目录与节表结构
数据目录(Data Directory)数据目录位于 IMAGE_OPTIONAL_HEADER 的末尾,是一个由 IMAGE_DATA_DIRECTORY 结构体数组构成的表。每个数据目录项描述了 PE 文件中某一特定数据结构的偏移和大小。常见的数据目录包括:
IMAGE_DIRECTORY_ENTRY_EXPORT(导出表)
作用:记录模块导出的函数和数据。对于 DLL 来说,这部分内容非常关键,系统及其他模块通过它来调用 DLL 中的接口。
IMAGE_DIRECTORY_ENTRY_IMPORT(导入表)
作用:记录模块依赖的外部函数和数据。通过导入表,操作系统能够在加载时将所需的外部函数地址填入模块的导入地址表。
IMAGE_DIRECTORY_ENTRY_IAT(导入地址表)
作用:保存导入函数的实际地址,加载器在加载时会根据导入表将相应地址写入 IAT,供程序调用时直接使用。
IMAGE_DIRECTORY_ENTRY_RESOURCE(资源表)
作用:存放程序所用的各种资源,如图标、对话框、字符串等。
IMAGE_DIRECTORY_ENTRY_BAS ...
PE 5 NT Optional Header 3
NT Optional Header 字段解析在 PE 文件(Portable Executable)的 IMAGE_OPTIONAL_HEADER 结构中,除了之前介绍的基地址、对齐、版本等字段外,还有一组与程序完整性、加载环境和内存资源管理相关的重要字段。下面依次对这些字段进行说明:
校验和(CheckSum)1DWORD CheckSum; //参考 校验和(驱动)
含义:
该字段存储 PE 文件的校验和,用于验证文件在存储或传输过程中的完整性。
作用:
对于大部分普通的 EXE 或 DLL 文件,校验和字段一般不影响加载过程,很多时候会被置为 0。
驱动程序(.sys 文件)要求校验和必须正确,系统在加载内核驱动时会验证该字段,确保文件未被破坏或篡改。
计算:
校验和通常由编译器或链接器计算,也可以通过专门工具(例如 CheckSumMappedFile API)重新计算校验值。
运行子系统(Subsystem)1WORD Subsystem; //重要 01(驱动) 02(窗口 ...
PE 4 NT Optional Header 2
NT Optional Header 重要字段解析在 NT 头中的 IMAGE_OPTIONAL_HEADER 结构中,包含了一些额外的重要字段(NT additional fields)。这些字段涉及 PE 文件的内存布局、对齐方式、版本信息以及镜像大小等内容,在 PE 文件的加载和运行过程中起着至关重要的作用。本文将详细解析这些字段的含义和用途。
代码与数据基地址12DWORD BaseOfCode; // 代码基地址(RVA)DWORD BaseOfData; // 数据基地址(仅适用于32位 PE)
BaseOfCode:
含义:该字段表示代码段(.text 节)在内存中的相对虚拟地址(RVA)。
作用:帮助加载器确定代码段的起始位置,以便正确映射和执行代码。
BaseOfData:
含义:表示数据段(.data 节)在内存中的相对虚拟地址(RVA)。
作用:用于确定全局变量和静态数据存放的位置,仅适用于 32 位 PE,在 64 位 PE 中该字段已被移除。
主模块基址(ImageBase) ...
PE 3 NT Optional Header 1
NT Optional Header 字段详解在 PE(Portable Executable)格式中,IMAGE_OPTIONAL_HEADER 扮演着非常重要的角色,它提供了操作系统加载程序时所需的关键信息。
Magic 字段123WORD Magic; IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
含义: Magic 字段用于标识可执行文件是32位还是64位。
对于32位 PE 文件,其值为 0x10b(IMAGE_NT_OPTIONAL_HDR32_MAGIC)。
对于64位 PE 文件,其值为 0x20b(IMAGE_NT_OPTIONAL_HDR64_MAGIC)。
作用: 加载器通过检测该字段来判断如何解析后续的可选头结构,从而选择正确的数据结构和加载方式。
链接器版本123//链接器的版本 参考使用的VS的版本BYTE MajorLinkerVersion;BYTE MinorLinkerVersion;
含义: 这两个 ...
PE 2 NT头
在Windows操作系统中,可执行文件通常采用PE(Portable Executable)格式。PE格式不仅支持32位和64位系统,而且在文件结构上具有层次分明、信息丰富的特点。其中,NT头(IMAGE_NT_HEADERS) 是整个PE文件的核心部分,它起到了连接DOS兼容部分和实际执行数据之间的桥梁作用。
NT头的整体结构NT头一般包括以下几个部分:
Signature(签名)
描述:一个DWORD类型的值,通常为"PE\0\0",用于标识文件为合法的PE格式。
作用:通过检测这个魔数,操作系统和工具可以确认文件格式并继续解析后续内容。
IMAGE_FILE_HEADER(文件头) 这一部分包含了描述文件基本属性的重要信息,例如:
Machine(机器类型):一个WORD值,用于说明目标CPU平台(如x86、x64等)。
NumberOfSections(节区数量):一个WORD值,指出文件中节(section)的个数,每个节代表一个独立的数据区,如代码、数据、资源等。
TimeDateStamp(时间戳):一个DWORD值,记录文件生成的时间,可以用来 ...
PE 1 DOS头、NT头和节表
PE 文件格式简介
PE(Portable Executable)格式:这是 Windows 系统下常用的可执行文件格式。相比于 Linux 系统下的 ELF 格式,PE 格式在 Windows 平台上具有广泛应用。
结构概览
IMAGE_DOS_HEADER:文件最开始的 DOS 头(兼容16位),其中包含了一个跳转指令以及一个指向 NT 头的偏移量(e_lfanew)。
DOS Stub:一个 DOS 程序,当在 DOS 环境下执行时显示提示信息(通常提示“此程序只能在 Windows NT/2000/XP 等系统上运行”)。
IMAGE_NT_HEADERS
:紧接 DOS Stub 后面的 NT 头,其中包含:
Signature:魔数(通常是 “PE\0\0”)。
IMAGE_FILE_HEADER:描述文件信息,如目标机器类型、节数量等。
IMAGE_OPTIONAL_HEADER:描述程序加载信息(例如入口点、程序内存布局等),以及数据目录数组,用于指向如导入表、导出表、资源表等重要数据结构。
IMAGE_SECTION_HEADER:紧 ...
PE3-31 导入表注入
导入表注入在动态链接库一章中提到 DllMain,这里再回顾一次:
当 DLL 被加载进 4GB 空间时,会调用一次 DllMain(入口方法)。
当程序执行完毕,将 DLL 从 4GB 空间卸载时,也会调用一次 DllMain。
注入的本质是想方设法将自己的 DLL 投放到其他进程的 4GB 空间中。而在前面讲解的导入表一章中提到:
只有隐式调用(静态使用)时,DLL 的名字和相关函数才会出现在调用者 PE 文件的导入表中。
显式调用(动态使用)时,被调用的 DLL 名和相关函数不会出现在调用者的导入表中。
换句话说:
写入导入表中的 DLL 必定是被隐式调用的(静态使用)。
如果将毫不相关的 DLL 写入某个 PE 文件的完整导入表中,那么打开这个 PE 文件时,该 DLL 会被直接加载(操作系统的规则)。
导入表注入的原理与过程原理当 .exe 文件被加载时,系统会根据其导入表信息加载需要的 DLL。导入表注入的原理就是修改 .exe 的导入表,将自己的 DLL 添加进去。这样,运行 .exe 时,系统会加载该 DLL 并执行其 DllMain 中的代码,从而实现注入 ...
PE3-30 绑定导入表
绑定导入表绑定导入的基本概念在程序加载前,IAT(Import Address Table)和INT(Import Name Table)中的内容通常相同,表示程序引用的 DLL 中函数的名称或序号。加载完成后,IAT 中的内容会被替换为函数的实际地址。
绑定导入的意义
如果 DLL 文件更新,绑定导入表的时间戳和 DLL 文件的时间戳将不同,此时需要修正函数序号、函数名称和函数地址表。
加载前直接写绝对地址:在 IAT 表中保存绝对地址,可以加快程序启动速度,因为省去了修复 IAT 表的步骤。
优点
加快程序启动速度:在启动程序时需要申请4gb内存空间、贴exe、贴dll、将IAT表修复为地址等等,如果直接用绝对地址,则省去了修复IAT表的操作;
缺点
DLL 重定位时,如果 DLL 没有占据其自身的 ImageBase 地址,需要修复绝对地址。
DLL 修改时,IAT 表中的函数地址可能不正确,需要重新修复。
Windows 提供的一些程序(如记事本)使用了这种绑定导入方式。
判断绑定导入的方法在导入表的结构中有一个属性:TimeDateStamp,其值可以反映是否 ...
PE3-27 IAT表&&导入表
IAT:Import Address Table 导入地址表间接寻址调用
调用 DLL 函数时,汇编代码通过 间接寻址 实现,不直接 call 函数地址,而是通过一个中间地址跳转。
示例:调用 MessageBox系统函数(属于 DLL)时,汇编代码为:
1call dword ptr [004322d4]
004322d4 中存储地址 X,程序通过跳转到 X 执行函数。
004322d4 属于 .exe 的内存区域,而 X 可以指向 DLL 的内存区域(如 77d5050b)。
为什么需要间接寻址?
DLL 在加载时可能因重定位占用不同的内存地址。
因此,调用 DLL 函数不能写死地址,而需要动态更新。
程序先将 .exe 中某个位置(如 004322d4)写入代码,然后由操作系统在运行时填充实际的函数地址。
文件状态与加载状态的区别
未运行(文件状态):
004322d4 指向的地址仅存储一个字符串,例如 MessageBox.USER32.dll。
需要根据 RVA(相对虚拟地址)转换为 FOA(文件偏移地址),再减去 ImageBase 才能找到位置。
运行中 ...