【系列:CCG Crypto CrackMe 逆向全解析 · 第 1 篇】
导读2001 年CCGChina Cracking Group的 Blowfish 放出了一个 CrackMe声称本题多解。这个系列将完整记录破解它的全过程——从最基础的字节解析到自定义壳的算法复原到最后跑出一个能通过真实程序验证的 Keygen。系列的第一条原则很朴素任何结论都必须能用代码复现本系列都是围绕破解过程中一步步推导过程来写的。第一篇我们先不谈算法只把手里这个 123,904 字节的文件用最笨的方法过一遍。逆向分析的第一步不是猜壳猜算法而是把文件当成一堆确定的字节。这篇文章不做任何推测只用 Python 逐字段解析一个 crackme 样本的 PE 结构每个数字都附带可运行的代码看完你也能自己验证一遍。很多逆向教程一上来就说这是 UPX 壳“这是自定义加密”。但这些判断的依据是什么大多数时候答案是经验和直觉不是当场验证的事实。这篇文章想做一件更基础的事打开crackme_crypto.exe只用struct和open把能确定的东西一条条读出来。不下结论只呈现数字。文件大小从来不是大概网上流传的说法是这个样本大约124KB。用代码量一下就知道这种四舍五入的说法从一开始就是错的。importos pathcrackme_crypto.exesizeos.path.getsize(path)print(size)# 123904123904 字节不是 124000也不是 126976124×1024。逆向工作里大约没有意义只有精确的字节数才能拿来做后续比对。PE 头的位置不用猜文件里写着DOS 头的第 0x3C 字节处存的就是 PE 头的偏移量e_lfanew。这是 PE 格式规定死的不需要经验判断。importstructwithopen(path,rb)asf:dataf.read()e_lfanewstruct.unpack(I,data[0x3C:0x40])[0]print(hex(e_lfanew))# 0xe0pe_sigdata[e_lfanew:e_lfanew4]print(pe_sig)# bPE\x00\x00e_lfanew 0xE0跳到这个偏移四个字节正好是PE\0\0。这两个值互相印证偏移对了签名也对了说明这是一个结构完整的 PE 文件而不是拼接出来的伪装文件。COFF 头里的三个数字决定了后面怎么读PE 签名之后紧跟的 20 字节是 COFF 文件头里面的Machine、NumberOfSections、SizeOfOptionalHeader三个字段直接决定了后续解析要怎么走。coff_offsete_lfanew4machine,num_sectionsstruct.unpack(HH,data[coff_offset:coff_offset4])size_opt_headerstruct.unpack(H,data[coff_offset16:coff_offset18])[0]print(hex(machine))# 0x14cprint(num_sections)# 6print(hex(size_opt_header))# 0xe0Machine 0x14C对应 32 位 x86 架构。NumberOfSections 6告诉我们后面要读几个节区表条目。SizeOfOptionalHeader 0xE0告诉我们可选头占多少字节从而算出节区表从哪里开始。这三个数字不是背景信息是接下来每一步计算的输入参数。入口点从 RVA 到实际虚拟地址,只差一次加法可选头里最关心的是入口点。这里涉及两个数字AddressOfEntryPoint相对虚拟地址和ImageBase镶像基址两者相加才是程序运行时真正跳转到的地址。opt_offsetcoff_offset20magicstruct.unpack(H,data[opt_offset:opt_offset2])[0]entry_rvastruct.unpack(I,data[opt_offset16:opt_offset20])[0]image_basestruct.unpack(I,data[opt_offset28:opt_offset32])[0]entry_vaimage_baseentry_rvaprint(hex(magic))# 0x10bprint(hex(entry_rva))# 0x44bd6print(hex(image_base))# 0x400000print(hex(entry_va))# 0x444bd6Magic 0x10B说明这是 PE3232位格式不是 PE32。ImageBase 0x400000是默认加载基址。两者相加AddressOfEntryPoint的 RVA0x44BD6换算成实际虚拟地址就是0x444BD6。这个地址意味着什么现在先不下结论。它只是一个确定的数字后续调试器里下断点会用到。六个节区六组数字,先只记录节区表紧跟在可选头之后起始偏移是opt_offset size_opt_header。每个节区头固定 40 字节按顺序读就行。sec_table_offsetopt_offsetsize_opt_headerforiinrange(num_sections):offsec_table_offseti*40namedata[off:off8].rstrip(b\x00)virtual_size,virtual_addressstruct.unpack(II,data[off8:off16])size_raw,ptr_rawstruct.unpack(II,data[off16:off24])print(name,hex(virtual_address),hex(virtual_size),hex(size_raw),hex(ptr_raw))跑出来是六组固定的数字节区名称VirtualAddressVirtualSizeSizeOfRawDataPointerToRawData0UPX!0x10000x120000xA4000x10001UPX!0x130000x10000x8000xB4002UPX!0x140000xA0000x6000xBC003UPX!0x1E0000x20000x6000xC2004.rsrc0x200000x230000xF2000xC8005UPX!0x430000x30000x2A000x1BA00注意一个细节五个节区的名字字面就是UPX!四个字符第 4 个节区叫.rsrc。同时VirtualSize和SizeOfRawData之间的差距在几个节区里相当大。这些名字和数字本身不能证明任何事——名字字段可以被任意改写大小差异也可能有多种原因。它们只是文件里当场读出来的字符串和整数。这组数字要说明什么留到下一篇。文件末尾的六个字节节区数据之外文件还有个容易被忽略的角落——最后几个字节。taildata[-6:]print(tail)# bBF2000print(tail.decode())# BF2000文件末尾的最后 6 个字节解码成 ASCII 正好是BF2000这六个字符。它出现在文件的最末尾不属于任何节区的正常数据范围。这六个字符是什么含义为什么会出现在这个位置这篇不做推测。它是下一篇要处理的第一个问题。先把地基打稳回顾一下这次拿到的确定信息文件大小 123904 字节PE 头偏移0xE0架构0x14C6 个节区入口点实际地址0x444BD6。这些都是当场用代码验证过的事实不依赖任何转述。节区表里五个UPX!名称和一个.rsrc还有文件末尾那六个字符BF2000这两组线索先记下来,不着急下结论。逆向的第一原则很简单先把能用代码确认的东西全部确认完再去谈假设和推理。你在分析文件时通常是先看结构还是先跑一遍再说小结本文是CCG Crypto CrackMe 逆向全解析系列的开篇只做了一件事把crackme_crypto.exe的 PE 结构逐字段解析出来不下任何算法结论。文件大小精确为123,904 字节而不是网上常见的约124KBPE 头、COFF 头、Optional 头的关键字段全部现场验证Machine0x14C、NumberOfSections6、入口点实际地址0x444BD66 个节区表条目全部逐字段读出5 个命名为UPX!1 个为.rsrc文件末尾 6 字节解码为BF2000这些都只是事实还不是结论。5 个UPX!节区是否真的是 UPX 压缩BF2000这 6 个字符意味着什么下一篇开始回答。下一篇预告《字符串侦察从 find() 命中到编译器身份识别》——在不碰任何反汇编工具的前提下我们将展示如何通过字符串搜索和上下文分析从这个文件里挖出编译器遗留的源文件路径直接锁定程序使用的密码学算法组件。参考文献与引用Microsoft PE/COFF 格式官方规范learn.microsoft.com/windows/win32/debug/pe-format——本文所有字段偏移量和结构定义均依据此规范pefile — Python PE 解析库[github.com/erocarrera/pefile](https://github.com/erocarrera/pefile觉得有用点个关注持续获取优质内容。

相关新闻

STM32 HAL库驱动IIC段码屏实战:HT1621配置与软件模拟IIC详解

STM32 HAL库驱动IIC段码屏实战:HT1621配置与软件模拟IIC详解

1. 项目概述与核心价值 最近在做一个需要显示多路参数的小型设备,选来选去,最后用上了一块基于HT1621驱动芯片的LCD段码屏。这种屏成本低、功耗小,在温控器、电表、小家电上很常见。但实际驱动时发现,网上资料要么是51单片机的&am…

2026/10/15 0:06:59 阅读更多 →
本地代码大模型评测实战(四):8个坑和1个崩溃

本地代码大模型评测实战(四):8个坑和1个崩溃

本地跑模型的8个坑(和1个崩溃恢复的故事) 系列目录 篇1: 模型选型 篇2: 评测框架 篇3: 数据挖掘的13个发现 篇4: 8个坑和1个崩溃 ← 当前 篇5: 公平对比的5个陷阱 发布后将链接替换为实际 URL 系列:本地代码大模型评测实战 第4篇 如果你正打…

2026/10/15 0:06:42 阅读更多 →
无审查模型与国内通用模型对比

无审查模型与国内通用模型对比

珍爱生命,遵纪守法,请勿在互联网随意传播不良信息!无审查模型,是一类非合规模型,请勿在互联网上进行发布和使用!!与国内通用模型对比会话记录如下:1、提示词:我要通过hac…

2026/10/8 23:20:54 阅读更多 →

最新新闻

064、广播数据长度超出承载上限时的分包处理

064、广播数据长度超出承载上限时的分包处理

现场:一条永远发不出去的广播 几年前做一个分布式采集系统,主控通过广播通道向所有节点下发同步命令和参数。协议栈的单帧净荷上限是 31 字节,这是链路层硬约束,改不了。前期功能很简单,同步命令就几个字节&#xff0c…

2026/10/15 0:08:01 阅读更多 →
063、广播间隔与扫描窗口错配导致的设备不可见

063、广播间隔与扫描窗口错配导致的设备不可见

一个做资产追踪标签的团队遇到过这样一件事。标签固件烧录完毕,功耗测试过了,广播内容用嗅探工具抓包也正常,RSSI 在预期范围内。但配套的接收端在实验室里就是扫不到这批标签。换一台接收端,能扫到。再换回来,又扫不到…

2026/10/15 0:08:01 阅读更多 →
062、连接建立瞬间超时断开的原因分类

062、连接建立瞬间超时断开的原因分类

一个半夜被叫起来处理的问题 去年冬天做的一个数据采集项目,现场大概两百多个节点,通过无线链路往中心网关上报数据。上线跑了三天都正常,第四天凌晨两点,值班同事打电话说监控大屏上设备在线数从两百多掉到了三十几个&#xff0c…

2026/10/15 0:08:01 阅读更多 →
061、广播包发出后没有回应时的链路排查思路

061、广播包发出后没有回应时的链路排查思路

上个月帮一个做工业数据采集的团队看问题,他们用一套自研的无线轮询协议,主站每隔两秒向从站发一轮广播包,从站收到后回传采集数据。现场跑了三个月一直正常,突然有一天主站日志里开始出现大量“广播发出后无回应”的告警&#xf…

2026/10/15 0:08:01 阅读更多 →
别再让“虚拟时装毕设”卡在论文上:数字时尚设计人的 AI 工具搭子清单 ✨

别再让“虚拟时装毕设”卡在论文上:数字时尚设计人的 AI 工具搭子清单 ✨

如果你读的是数字时尚设计,大概率会遇到这样一种“分裂”的毕业状态: 一边在用 CLO 3D / Style3D 调版片、缝份、面料垂坠和动态走秀效果;一边还要翻虚拟时尚、数字服装、AIGC、非遗纹样、用户审美评价等一大堆中英文文献;最后还…

2026/10/15 0:08:01 阅读更多 →
二次规划QP实战:从调包到手撕,解决不可行与病态问题

二次规划QP实战:从调包到手撕,解决不可行与病态问题

1. 从“调包”到“手撕”:为什么QP值得你花时间很多做算法落地的朋友,第一次接触二次规划(Quadratic Programming,简称QP)都是在MATLAB的quadprog或者Python的cvxopt.solvers.qp里填几个矩阵就完事了。模型跑通那一刻觉…

2026/10/15 0:07:00 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →