96SEO 2026-08-06 04:10 0
这篇文章根据系列博客 “Making our own executable packer” 完整翻译 帮助你从基础开始实现一个可执行文件压缩工具。
作者在十二岁时发现把 .exe 文件重命名后能用记事本打开,看到一堆乱码却暗藏规律。这颗好奇的种子,几十年后长成了本系列。

使用者痛点:很多开发者看到 ELF、PE 等二进制格式时只能盲目猜测结构。缺乏程序化的解析思路,导致调试和逆向时常常“卡死”。本系列正是为了解决这类“看不懂二进制、无法定位入口”的痛点。
说到目标是,理解 Linux 可执行文件内部结构及其执行机制。接下来造出一个能把可执行文件压缩起来的程序——纯粹是为了好玩,也为学习底层技术提供实战案例。
整个系列专注于 64 位 Linux,使用 Rust 作为主要实现语言。作者创建了两个 crate:
delf用于解析 ELF 文件的库。elk调用 delf实现加载和执行功能的命令行工具。怎么说呢,ELF自 SysV 发布后一直是 Linux 的标准可执行文件格式。下面是一段最小汇编程序示例:
;话说回来,hello.asm
global _start
section .text
_start这方面。mov rdi,1,stdout fd
mov rsi,msg;缓冲区地址
mov rdx,msg_len;长度
mov rax,1;write syscall
syscall
xor rdi,rdi;return code 0
mov rax,60;exit syscall
syscall
section .data
从msg来看,db "hi re",10
msg_len equ $ - msg
编译后得到约 4 KiB 的 ELF。可用 gzip -9 压缩到仅 150 B——这正是我们想要做的压缩动机。
使用者痛点:初学者往往只会用 readelf -a 查看信息,却不懂如何自行定位关键字段。下面演示使用 xxd 手工查看前几字节:
$ xxd hello | head -n1
00000000: 7f45 4c46 0201 01... .ELF....
ELF 文件头包括 magic、class、endianness、version、OS ABI 等字段;话说回来,随后是类型、机器、入口点等信息。通过这些偏移量可以逐步定位段表,进而找到 .symtab/.strtab/.text/.data 等熟悉的段名。
nom 写解析器使用者痛点:Panic!在解析二进制时频繁出现,因为缺少安全的字节切片处理。话说回来,使用 Rust 的 可以声明式地组合解析器。避免手写指针运算导致未定义行为。
// delf/src/lib.rs
impl File {
const MAGIC: &'static = b"\x7fELF";pub fn parse -> parse::Result {
use nom::{
说到bytes:。complete::{tag,take},sequence::tuple,error::context,};let = tuple((
context),context),// 64‑bit
context)。// little‑endian
context),context,tag))),context),))?
,Ok)
}
}
User Pain Point: 使用关键字冲突导致代码难以阅读。例如 Rust 中的 type. 使用原始标识符 并配合宏生成安全枚举,可大幅降低错误率。
#
#
pub enum Type {
None = 0x0,Rel = 0x1,Exec = 0x2,Dyn = 0x3,Core = 0x4,}
#
#
pub enum Machine {
X86 = 0x03。X86_64 = 0x3e,}
Addr
#
pub struct Addr;impl core::fmt::Debug for Addr {
fn fmt -> core::fmt::Result {
write!不过,}
}
$ ./target/debug/elk /bin/true
File { type: Dyn,machine: X86_64。entry_point: Addr }
User Pain Point:#ASLR 导致每次运行地址不同,使得硬编码地址失效。使用本工具观察同一程序两次运行的入口地址差异:
$ ./target/debug/elk ./samples/entry_point_main main is at 0x5571c34e9139 $ ./target/debug/elk ./samples/entry_point_main main is at 0x55f7a0f27139 # 地址随机,但高位保持不变 → ASLR 生效。
Pain point:直接读取文件内容后跳转会触发 segfault,因为默认内存不可执行。不过,正确做法是使用 分配具备 R/W/X 权限的页面并使用 MAP_FIXED 将段映射到它们要求的虚拟地址。
unsafe fn jmp { let f: fn = core::mem::transmute;f,} let mem = libc::mmap( addr as *mut libc::c_void,size。prot,libc::MAP_PRIVATE | libc::MAP_FIXED,fd,offset as i64);
Pain point:传统静态链接二进制只能装载到固定地址,一旦冲突就无法启动。现代 Linux 几乎全部采用 PIE。使得二进制能够在任意基址上运行,从而让 ASLR 发挥作用。
hello-pie.asm global _start section .text 至于_start。mov rdi,1,stdout lea rsi,;相对寻址 mov rdx,msg_len mov rax,1;write syscalls syscall xor edi,edi;其实,exit code mov eax,60;exit syscalls syscall section .data msg这方面,db "hi re"。10 msg_len equ $-msg
会让汇编器生成基于当前指令指针的偏移量,无论代码被加载到哪里该偏移始终有效。
加载时先为整个映像申请连续虚拟空间,再按基址偏移分别映射两个段;入口点 = file.entry_point + base_offset。
memsz 可大于 filesz。用于 BSS 段——未初始化全局变量在磁盘上不占空间,但在内存中需要零填充。怎么说呢,
PIE 加载后需要把占位符补成真实地址。这一步叫重定位
| 字段 | 含义 |
|---|---|
| offset | 需要修改的位置 |
| type | 决定计算方式 |
| sym | 关联符号 |
| addend | 额外加数 |
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback