Trim both READMEs and add the tutorial primer

README 242 -> 180 lines: the 14-row tool table becomes three sentences pointing at capabilities.py, Read this first merges into Scope, and the six-script maintenance block becomes a table. Every path, command and anchor is unchanged.

README.zh-CN follows the same eight sections, and picks up two drifts: it named hwprobe.py as the cheapest first command (SKILL.md and the English README say doctor.py), and it translated triage as 'three categories', which sends a reader looking for categories that do not exist.

docs/primer is the Windows reverse-engineering tutorial series with an index, corrected in three places: x64dbg instead of OllyDbg, offsets fixed only within one build, and IAT hooking assuming the target imports the API it hooks.

docs/tool-acquisition keeps the part capabilities.py does not answer: licence classes, id resolution on the host, and what proves a tool runs.
This commit is contained in:
root
2026-10-24 13:51:21 +08:00
parent 863fe6b1bf
commit 25f2286cb6
8 changed files with 586 additions and 235 deletions
+70 -132
View File
@@ -17,7 +17,7 @@
</p>
<p align="center">
<a href="#what-it-is-good-at">Capabilities</a> · <a href="#structure">Structure</a> · <a href="#install">Install</a> · <a href="#requirements">Requirements</a> · <a href="#read-this-first">Failure catalogue</a> · <a href="#scope">Scope</a> · <a href="#repository-maintenance">Maintenance</a>
<a href="#what-it-is-good-at">Capabilities</a> · <a href="#structure">Structure</a> · <a href="#install">Install</a> · <a href="#tooling">Tooling</a> · <a href="#scope">Scope</a> · <a href="#repository-maintenance">Maintenance</a>
</p>
# exe-reverse
@@ -28,82 +28,54 @@ algorithm recovery, packers and code virtualisation, managed assemblies, kernel
**hardware-observation layer** — instruction tracing, hardware breakpoints, and hypervisor-assisted
observation — that software tooling cannot substitute for.
It is a **skill**, not a tutorial: it is written to be loaded by an agent while it works, so it is
organised for progressive disclosure — a short decision-oriented `skills/exe-reverse/SKILL.md`,
detailed references loaded only when a step needs them, and parameterised scripts you can run
directly.
It is a **skill**, not a tutorial: a short decision-oriented `skills/exe-reverse/SKILL.md`, references
loaded only when a step needs them, and parameterised scripts you can run directly.
## How an agent is expected to consume this
`SKILL.md` is written as a **procedure with gates**, not as advice, because the observed failure mode
is not ignorance — it is a model reading the whole thing, agreeing with it, and then reasoning from
first principles anyway.
first principles anyway. Four things in it are meant to be *acted on*:
Four things in it are meant to be *acted on*:
- **Five operating rules (O1–O5).** Where they conflict with the plan, they win until evidence does.
- **A symptom index.** A matching row is a **stop signal**: load that file before the next command.
- **Five gates (G1–G5),** each an action with a pass criterion. "I understand the idea" clears none.
- **A two-strike rule and stop conditions.** Two failures of the same shape mean the model is wrong.
- **Five operating rules (O1–O5).** Where they conflict with the current plan, they win until
evidence overrides them.
- **A symptom index.** Each row is a failure that has already been paid for. A matching row is a
**stop signal**: load that file before running another command, not after a few more attempts.
- **Five gates (G1–G5),** each an action with a pass criterion. "I understand the idea" does not
clear a gate. They exist so that classification, host truth and a control build happen *before* the
first patch, not after the third failure.
- **A two-strike rule and stop conditions.** Two failures of the same shape mean the model is wrong,
not the parameters.
One thing is meant to be *withheld*: **"done" has a definition (six items)**, and a clean log is not
one of them. Anything short of six is a checkpoint, reported as one with what remains.
And one thing at the end that is meant to be *withheld*: **"done" has a definition (six items).** A
clean log is not one of them. Anything short of all six is a checkpoint, and should be reported as a
checkpoint with what remains.
The cheapest possible first command is `python skills/exe-reverse/scripts/doctor.py`. It answers
three questions in one pass: which capabilities this host actually supports and what to install for
the ones it does not, whether every script in the kit is runnable as-is, and which host facts would
silently poison an experiment. `python skills/exe-reverse/scripts/hwprobe.py` is the deeper
hardware-level probe beneath it, and `python skills/exe-reverse/scripts/capabilities.py --verbose`
prints the next action for anything blocked.
`python skills/exe-reverse/scripts/doctor.py` is the cheapest first command: it reports which
capabilities this host supports, whether every script in the kit runs as-is, and which host facts
would silently poison an experiment. `python skills/exe-reverse/scripts/hwprobe.py` goes deeper on
hardware, and `python skills/exe-reverse/scripts/capabilities.py --verbose` prints the next action
for anything blocked.
## What it is good at
- Deciding **fast** whether a request is achievable by changing the client at all, instead of burning
hours on a decision the server owns.
- Establishing **which host you actually have** before a plan depends on it: a debugger installed, an
elevated session, test signing, a second machine, or a hypervisor that intercepts the very
mechanism the plan relies on.
- Patching **without breaking the file**: equal-length edits first, the checksum recomputed, the
written bytes re-read from disk, and a length change reported as the structural edit it is.
- Making a signature **honest about itself**: how many sites a pattern matched, whether that count
changed between builds, and whether the pattern is a locator or a coin flip.
- Separating **"the bytes are in the file" from "the code runs"** — the most common way a patch is
reported as working while nothing changed.
- Classifying a **licence decision** before touching it: client-verified, client-rendered server data,
or server-authoritative — three problems with three different answers, only two of which a binary
change can reach.
- Working through **a target that fights analysis**: recognising which anti-analysis mechanism
actually fired, and which layer can still observe the target when every hook is detected.
- Reaching for the **hardware layer** when a debugger cannot: hardware breakpoints that do not modify
the bytes they watch, instruction tracing that records control flow without executing hooks, and
an honest statement of what each of those requires and what it still cannot see.
- Keeping a **long session honest**: a live record, graded conclusions, bounded waits calibrated from
a measurement, and a control build for every claim.
- **Publishing what it learns without publishing the target** — a scanner that reports identity
shapes with their context, and an explicit list of what must *not* be redacted because redacting it
destroys the reusable part.
elevated session, test signing, a second machine, or a hypervisor that intercepts the mechanism.
- Patching **without breaking the file**: equal-length edits, the checksum recomputed, the written
bytes re-read from disk, and a length change reported as the structural edit it is.
- Making a signature **honest about itself**: how many sites it matched, whether that count changed
between builds, and whether it is a locator or a coin flip.
- Classifying a **licence decision** before touching it (client-verified, client-rendered server
data, server-authoritative), and separating "the bytes are in the file" from "the code runs".
- Reaching for the **hardware layer** when a debugger cannot, and stating what it requires and what
it still cannot see.
## Structure
`SKILL.md`, `references/` and `scripts/` live inside the skill directory, `skills/exe-reverse/`.
Everything at the repository root is maintenance tooling shared across skills, not part of an
installed skill.
Everything at the repository root is maintenance tooling, not part of an installed skill.
```
skills/exe-reverse/SKILL.md a procedure with gates, not background reading:
five moves -> five override rules (O1-O5)
symptom index (a matching row is a stop signal)
five gates (G1-G5, actions with pass criteria)
thirteen classification questions
target routing table
the tool/context budget rules
the workflow -> what "done" means -> stop conditions -> constraints
five moves -> O1-O5 -> symptom index -> gates G1-G5
thirteen classification questions -> routing table
budget rules -> workflow -> done -> stops -> constraints
skills/exe-reverse/references/ loaded on demand, one topic each; the inventory with when to load
each one is skills/exe-reverse/references/routing.md
skills/exe-reverse/scripts/ parameterised and path-agnostic; runnable on a bare Python 3.10+
@@ -114,78 +86,52 @@ tests/ the executable regression suite
```
The reference library is indexed, not memorised: `skills/exe-reverse/references/routing.md` carries
every reference file with when to load it and every script with what it does, and it is the file to
read once a route has been chosen.
every reference with when to load it and every script with what it does. Read it once a route has
been chosen.
## Install
This repository is a **skills repository**: the skill lives at `skills/exe-reverse/`, which is the
layout the `skills` CLI resolves, and it is installed by name rather than by copying a directory:
This is a **skills repository**: the skill lives at `skills/exe-reverse/`, the layout the `skills`
CLI resolves, and it is installed by name rather than by copying a directory.
```
npx skills add <owner>/exe-reverse # install every skill in the repo
npx skills add <owner>/exe-reverse --list # list what is here, install nothing
npx skills add <owner>/exe-reverse --skill exe-reverse -y
npx skills use <owner>/exe-reverse@exe-reverse # use it once, without installing
npx skills use <owner>/exe-reverse`exe-reverse # use it once, without installing
```
The CLI symlinks the skill into your agent's skills directory by default (`--copy` makes independent
copies instead), `-g` installs for every project rather than the current one, and `-a` targets
specific agents. With one skill in the repository, `--skill exe-reverse` is redundant today; it is
written out because it is what selects a single skill once a second one exists.
copies instead), `-g` installs for every project, and `-a` targets specific agents. With one skill in
the repository, `--skill exe-reverse` is redundant today; it is written out because it selects a
single skill once a second one exists. Once installed, the agent loads `SKILL.md` when a task matches
its description and pulls in `references/*` as needed: no global state, no build step.
Once installed, the agent loads `SKILL.md` when a task matches its description and pulls in
`references/*` only as needed. No global state, no machine-specific paths, and no build step.
## Tooling
## Requirements
Nothing is mandatory, and no tool needs to be on `PATH`: the scripts accept explicit paths for what
they shell out to, and a runnable archive or a script counts as installed. Three things decide which
routes exist at all — Python 3.10+, a disassembler/decompiler, and a debugger —
`skills/exe-reverse/scripts/capabilities.py` carries the full list as a probed registry, with an
executable next step and a cost estimate per entry, and `skills/exe-reverse/scripts/hwprobe.py`
reports which of them this host actually has, including the routes a virtualised host cannot take.
Nothing is mandatory; each script checks what it needs, and `skills/exe-reverse/scripts/hwprobe.py`
reports which of these are present here and which routes are therefore available — including the
routes that are *not* available on a virtualised host.
If your toolchain lives outside `PATH` (a project-local tools directory, a versioned SDK folder),
set `EXEREV_TOOLS` to one or more directories and the probes will find them:
If the toolchain lives outside `PATH` (a project-local tools directory, a versioned SDK folder), set
`EXEREV_TOOLS`:
```
set EXEREV_TOOLS=<dir>;<dir> # Windows
export EXEREV_TOOLS=<dir>:<dir> # POSIX
```
| Tool | Used for |
|---|---|
| Python 3.10+ | every script; the PE reader, patcher, host probe, capability registry and doctor are dependency-free |
| A disassembler/decompiler (IDA, Ghidra, Binary Ninja, Cutter) | reading code; several are GUI-only, and a GUI-only tool is a request for a human, not a reason to substitute a weaker one |
| A debugger (x64dbg, WinDbg) | locating runtime behaviour and watching values |
| `dumpbin` / `link` (MSVC toolchain) | header and import inspection when you have the SDK |
| An installer extractor (`innoextract`, 7-Zip, `expand`) | getting at a payload without running the installer. Extract first and re-triage what came out: it is a new unknown |
| Frida | runtime instrumentation where a hook is acceptable |
| Procmon / ETW tooling (`wpr`, `logman`) | file, registry and system event evidence |
| A .NET toolchain | managed assemblies are a different artifact with a different toolchain |
| A solver or emulator (Z3, Triton, angr, Unicorn, Qiling) | reducing a trace or a condition instead of reading it; `skills/exe-reverse/references/symbolic-execution.md` records which default of each will change your answer |
| An isolated VM | the analysis host is part of the experiment |
| A second machine | kernel debugging on a current Windows host |
| A CPU that reports the trace feature, plus a capture path | the hardware-observation routes; the probe reports what this host has, and on this platform the capture path is the open question rather than the decoding |
None of these need to be on `PATH`: the scripts accept explicit paths for the tools they shell out
to, and a runnable archive or a script counts as installed.
`skills/exe-reverse/scripts/capabilities.py` carries the
same list as a probed registry, with an executable next step and a cost estimate for each entry.
`ls skills/exe-reverse/scripts/` is the authoritative list; `skills/exe-reverse/references/routing.md`
describes each one.
## Read this first
**Published for learning, research and authorized security testing only.** It ships no exploit
payloads, no target data and no third-party binaries — it is a method, a set of scripts and an
evidence record.
Then read `skills/exe-reverse/references/pitfalls.md`. It is the most valuable file here — every
entry is a failure that produced a working-looking artifact. Read it before building.
A GUI-only tool is a request for a human, not a reason to substitute a weaker one.
## Scope
Built for working on your own software, samples you are authorized to analyse, and competition
sandboxes. It contains no vendored third-party binaries and no target-specific data.
sandboxes; published for learning, research and authorized security testing only. It ships no exploit
payloads, no target data and no vendored third-party binaries — it is a method, a set of scripts and
an evidence record.
What it covers, and what it deliberately does not, is stated in the skill itself
(`skills/exe-reverse/references/coverage-and-limits.md`). The short version: Windows PE on x86 and
@@ -196,47 +142,39 @@ protector as a product claim, and any guarantee on a Windows build this reposito
are **not** covered, and the skill is written to say so and stop rather than apply the nearest
documented procedure to a target it was not written for.
Before building, read `skills/exe-reverse/references/pitfalls.md`. It is the most valuable file here
— every entry is a failure that produced a working-looking artifact.
## Repository maintenance
Six tools live at the root and are not part of the installed skill:
Six tools live at the root and are not part of the installed skill. Each carries its own docstring;
`CONTRIBUTING.md` states what a green run means.
```
check_repo.py every skill discovered, frontmatter valid, scripts runnable, documented paths
resolve, README paths explicit and existing, and -- on the tracked surface only
-- no target identity (delegates the rules to scan_leaks.py)
check_refs.py every cross-reference that names a section of another document reaches a real
heading in that document
check_routing.py the on-demand inventory still matches the entry point: the symptom mirror agrees
with SKILL.md, and every reference file and every script is named in routing.md
check_commands.py every command a document tells you to run is checked against the script's own
argparse table -- a documented flag that does not exist is drift the anchor
checks cannot see
check_budget.py keep the always-loaded part from creeping: SKILL.md measured in lines and
tokens, index-row length, long files with no navigable head, hedged rules
build_scripts.py audit for machine-specific leftovers (absolute paths, credentials)
```
| Tool | What it keeps honest |
|---|---|
| `check_repo.py` | every skill discovered, frontmatter valid, scripts runnable, documented and README paths resolving, no target identity on the tracked surface |
| `check_refs.py` | a cross-reference that names a section reaches a real heading |
| `check_routing.py` | the on-demand inventory still matches the entry point, row for row |
| `check_commands.py` | every documented command exists in the script's own argparse table |
| `check_budget.py` | the always-loaded part does not creep: SKILL.md lines and tokens, index rows, hedged rules |
| `build_scripts.py` | machine-specific leftovers: absolute paths, credentials |
Consistency has a natural counter-pressure — a broken path fails loudly and someone fixes it. Bloat
has none, which is why the budget gate exists.
`tests/benchmark.md` holds the regression matrix: dimension → public target → the scripts the row
exercises → measured result → strength label. `docs/tool-verification/` is the evidence record for
the measurement passes: what each script actually did, which independent method confirmed it, and
which scenarios the target could not exercise. It exists so the coverage claims can be checked
against runs instead of trusted.
`tests/benchmark.md` holds the regression matrix (dimension -> public target -> scripts exercised ->
measured result -> strength label), and `docs/tool-verification/` is the evidence record behind it:
what each script actually did, which independent method confirmed it, and what the target could not
exercise.
---
## Disclaimer
**For learning, research and authorized security testing only.** Every script, reference and
recorded result in this repository exists to explain *how* Windows application analysis works, so
that practitioners can reason about the tools they already own. Nothing here is a service, a
product, or an endorsement of any particular use.
The material is provided *as is*, without warranty of any kind. Results are recorded as they were
measured on one machine at one time; nothing here promises that a route will work on your target,
your host or your toolchain. Verify before you trust, and work on copies.
Names of tools, libraries, file formats and hardening products appear only to make the material
reusable; they belong to their respective owners, and this project is not affiliated with any of them.
Nothing here is a service, a product, or an endorsement of any particular use. Names of tools,
libraries, file formats and hardening products appear only to make the material reusable; they
belong to their respective owners, and this project is not affiliated with any of them.
+66 -103
View File
@@ -4,66 +4,52 @@
<a href="README.md">English</a> · <b>简体中文</b>
</p>
一个面向 **Windows x86/x64 本地软件逆向工程**的 Agent Skill:三分类、字节级补丁、特征码工作、调试、
注入、内存转储修复、授权机制归类、算法恢复、壳与代码虚拟化、托管程序集、内核驱动,以及**硬件观测层**
—— 指令追踪、硬件断点、虚拟机监控器辅助观测 —— 这些是纯软件工具链替代不了的路子。
一个面向 **Windows x86/x64 本地软件逆向工程**的 Agent Skill:初筛、字节级补丁、特征码、调试、注入、
转储修复、授权机制归类、算法恢复、壳与代码虚拟化、托管程序集、内核驱动,以及**硬件观测层** ——
指令追踪、硬件断点、虚拟机监控器辅助观测 —— 这些是纯软件工具链替代不了的路子。
它是一个 **skill**,不是教程:为"被 agent 边做边加载"而写,因此按渐进披露组织 —— 一份短小的、
面向决策的 `skills/exe-reverse/SKILL.md`,一批只在某一步需要时才加载的 references,以及可以直接运行
的参数化脚本。
它是一个 **skill**,不是教程:一份短小、面向决策的 `skills/exe-reverse/SKILL.md`,一批只在某一步
需要时才加载的 references,以及可以直接运行的参数化脚本。
## agent 应当如何使用它
`SKILL.md` 被写成**带门禁的流程**,而不是建议,因为观察到的失败模式不是无知 —— 是模型读完全文、
表示同意,然后仍然凭第一直觉推理。
表示同意,然后仍然凭第一直觉推理。其中四样东西是要**照做**的:
其中四样东西是要**照做**的:
- **五条操作规则(O1–O5)。** 与当前计划冲突时以它们为准,直到证据推翻它们。
- **症状索引。** 每一行都是一个已经付过代价的失败。命中一行就是**停止信号**:先加载它指向的文件,
再执行下一条命令,而不是再试几次之后。
- **五道门禁(G1–G5),** 每道都是一个带通过判据的动作。"我理解这个思路"不等于通过门禁。它们存在的
意义是让分类、宿主事实和对照构建发生在**第一次打补丁之前**,而不是第三次失败之后。
- **五条操作规则(O1–O5)。** 与计划冲突时以它们为准,直到证据推翻它们。
- **症状索引。** 命中一行就是**停止信号**:先加载它指向的文件,再执行下一条命令。
- **五道门禁(G1–G5),** 每道都是一个带通过判据的动作。"我理解这个思路"不等于通过任何一道。
- **两振出局与停止条件。** 同一形状失败两次意味着模型错了,而不是参数需要微调。
还有一样在最后的、需要**暂缓**的东西:**"完成"有定义(六条)。** 日志干净不在其中。不到六条就是
检查点,并且必须口头说明还差什么。
还有一样需要**暂缓**的东西:**"完成"有定义(六条)**,日志干净不在其中。不到六条就是检查点,
并且必须说明还差什么。
最便宜的第一条命令是 `python skills/exe-reverse/scripts/hwprobe.py`。它报告**这台机器**实际支持哪些
路子 —— 包括是否存在虚拟机监控器,这会改变调试器和硬件断点能做什么 —— 而不是理论上什么可以做。
最便宜的第一条命令是 `python skills/exe-reverse/scripts/doctor.py`:它一次回答三个问题 —— 这台机器
实际支持哪些能力、套件里每个脚本能否原样运行、以及哪些宿主事实会让实验静默失效。
`python skills/exe-reverse/scripts/hwprobe.py` 是它下面更深的硬件级探测,
`python skills/exe-reverse/scripts/capabilities.py --verbose` 会为任何受阻的项打印下一步动作。
## 它擅长什么
- **快速**判断一个需求是否可能仅靠改客户端达成,而不是把时间烧在服务端拥有的决策上。
- 在计划依赖宿主之前,先确定**你实际有什么宿主**:装了调试器、提权会话、测试签名、第二台机器,
或是一个会截获计划所依赖机制的虚拟机监控器。
- **不打坏文件地打补丁**:优先等长改写,重算校验和,从磁盘回读写入的字节,并把长度变化如实报告为
结构性修改。
- 让特征码**对自己诚实**:一个模式命中了多少处、这个计数在两次构建之间是否变化、它是定位器还是掷骰子。
- 区分**"字节在文件里"与"代码被执行"** —— 这是补丁被报告为生效而实际什么都没变的最常见方式。
- 在动手之前**归类授权决策**:客户端校验、客户端渲染的服务端数据、服务端权威 —— 三个问题三种答案,
只有其中两种是二进制改动够得着的。
- 处理**会反抗分析的目标**:识别究竟是哪个反分析机制被触发,以及当所有 hook 都被检测时哪一层仍能观测。
- 在调试器看不到时转向**硬件层**:不修改所监视字节的硬件断点、不装 hook 就记录控制流的指令追踪,
并诚实说明各自需要什么、仍然看不到什么。
- 让**长会话保持诚实**:活记录、分级结论、以实测标定上下界的等待,以及每个论断都有的对照构建。
- **发布学到的东西而不发布目标** —— 一个带上下文报告身份形状的扫描器,以及一份明确列出**不该**脱敏
内容的清单(脱敏它们会毁掉可复用的部分)。
- **不打坏文件地打补丁**:等长改写,重算校验和,从磁盘回读写入的字节,并把长度变化如实报告为结构性修改。
- 让特征码**对自己诚实**:命中了多少处、这个计数在两次构建之间是否变化、它是定位器还是掷骰子。
- 在动手之前**归类授权决策**(客户端校验、客户端渲染的服务端数据、服务端权威),并区分
"字节在文件里"与"代码被执行"。
- 调试器看不到时转向**硬件层**,并诚实说明各自需要什么、仍然看不到什么。
## 结构
`SKILL.md`、`references/` 与 `scripts/` 都在 skill 目录 `skills/exe-reverse/` 内。仓库根部的一切是跨
skill 共享的维护工具,不属于已安装的 skill。
`SKILL.md`、`references/` 与 `scripts/` 都在 skill 目录 `skills/exe-reverse/` 内。仓库根部的一切是
维护工具,不属于已安装的 skill。
```
skills/exe-reverse/SKILL.md 带门禁的流程,不是背景阅读:
五个动作 -> 五条覆盖规则(O1-O5)
症状索引(命中一行即停止信号)
五道门禁(G1-G5,带通过判据的动作)
十三个分类问题
目标路由表
工具与上下文预算规则
工作流 -> "完成"的定义 -> 停止条件 -> 不可协商约束
五个动作 -> O1-O5 -> 症状索引 -> 五道门禁 G1-G5
十三个分类问题 -> 路由表
预算规则 -> 工作流 -> "完成" -> 停止条件 -> 约束
skills/exe-reverse/references/ 按需加载,一文一题;"何时加载"的清单位于
skills/exe-reverse/references/routing.md
skills/exe-reverse/scripts/ 参数化、与路径无关;在裸 Python 3.10+ 上即可运行
@@ -74,105 +60,82 @@ tests/ 可执行的回归套件
```
reference 库是被索引的,不是靠记忆的:`skills/exe-reverse/references/routing.md` 载有每个 reference
文件及其加载时机、每个脚本及其作用,是选定路线之后该读的那份文件。
的加载时机与每个脚本的作用。选定路线之后读它一次。
## 安装
本仓库是一个 **skills 仓库**:skill 位于 `skills/exe-reverse/`,正是 `skills` CLI 解析的布局,
按名字安装而不是复制目录:
按名字安装而不是复制目录。
```
npx skills add <owner>/exe-reverse # 安装仓库里的全部 skill
npx skills add <owner>/exe-reverse --list # 只列出,不安装
npx skills add <owner>/exe-reverse --skill exe-reverse -y
npx skills use <owner>/exe-reverse@exe-reverse # 用一次,不安装
npx skills use <owner>/exe-reverse`exe-reverse # 用一次,不安装
```
CLI 默认把 skill 以符号链接的方式放进你的 agent 技能目录(`--copy` 改为独立副本),`-g` 面向所有项目
安装,`-a` 指定 agent。本仓库目前只有一个 skill,`--skill exe-reverse` 暂时是多余的;写出来是因为
一旦出现第二个 skill,它就是选出单个 skill 的方式。
CLI 默认把 skill 以符号链接放进你的 agent 技能目录(`--copy` 改为独立副本),`-g` 面向所有项目,
`-a` 指定 agent。本仓库目前只有一个 skill,`--skill exe-reverse` 暂时是多余的;写出来是因为一旦
出现第二个 skill,它就是选出单个 skill 的方式。安装后,agent 在任务与描述匹配时加载 `SKILL.md`,
只在需要时拉入 `references/*`:没有全局状态,没有构建步骤。
安装后,agent 在任务与其描述匹配时加载 `SKILL.md`,并且只在需要时拉入 `references/*`。没有全局状态,
没有与本机绑定的路径,没有构建步骤。
## 工具
## 运行要求
没有强制项,也没有哪个工具必须待在 `PATH` 上:脚本接受显式路径,可运行的归档或脚本也算已安装。
真正决定"有哪些路线"的只有三样 —— Python 3.10+、一个反汇编/反编译工具、一个调试器;
`skills/exe-reverse/scripts/capabilities.py` 把完整清单作为**可探测的注册表**承载,每一条都带可执行
的下一步和代价估计,而不是一张需要手工维护的表;`skills/exe-reverse/scripts/hwprobe.py` 报告这台
机器实际具备哪些能力,包括虚拟化宿主上**不**可用的那些。
没有强制项;每个脚本自己检查需要什么,`skills/exe-reverse/scripts/hwprobe.py` 会报告这台机器上有哪些、
因而哪些路线可用 —— 包括在虚拟化宿主上**不**可用的那些。
如果工具链不在 `PATH` 上(项目内的 tools 目录、带版本的 SDK 目录),把 `EXEREV_TOOLS` 指向一个或多个
目录,探测脚本就能找到它们:
如果工具链不在 `PATH` 上(项目内的 tools 目录、带版本的 SDK 目录),设置 `EXEREV_TOOLS`:
```
set EXEREV_TOOLS=<dir>;<dir> # Windows
export EXEREV_TOOLS=<dir>:<dir> # POSIX
```
| 工具 | 用途 |
|---|---|
| Python 3.10+ | 全部脚本;PE 读取器、补丁器与探测脚本无第三方依赖 |
| 反汇编器/反编译器(IDA、Ghidra、Binary Ninja、Cutter) | 读代码;其中若干只有 GUI,而只有 GUI 的工具是"向人要"而不是"用更弱的方法顶替"的理由 |
| 调试器(x64dbg、WinDbg) | 定位运行时行为、观察取值 |
| `dumpbin` / `link`(MSVC 工具链) | 有 SDK 时的头与导入表检查 |
| Frida | 可以接受 hook 时的运行时插桩 |
| Procmon / ETW 工具(`wpr`、`logman`) | 文件、注册表与系统事件证据 |
| .NET 工具链 | 托管程序集是另一种产物,需要另一套工具链 |
| 隔离的虚拟机 | 分析宿主本身是实验的一部分 |
| 第二台机器 | 当前 Windows 主机上的内核调试 |
| 报告该特性的 CPU,外加一条采集通路 | 硬件观测路线;探测脚本会报告这台机器有什么 |
这些都不需要在 `PATH` 上:脚本接受显式路径,可运行的归档文件或脚本也算已安装。
## 先读这个
**仅供学习、研究与授权的安全测试使用。** 它不附带漏洞利用载荷、不附带目标数据、不附带第三方二进制
—— 它是一套方法、一批脚本和一份证据记录。
然后读 `skills/exe-reverse/references/pitfalls.md`。这是这里最有价值的文件 —— 每一条都是一个"看起来
一切正常"却被产出的失败。动手之前先读它。
只有 GUI 的工具是"向人要",而不是"用更弱的方法顶替"的理由。
## 覆盖范围
面向你自己的软件、你被授权分析的样本,以及竞赛沙箱。仓库内不含第三方二进制,也不含目标专属数据。
面向你自己的软件、你被授权分析的样本,以及竞赛沙箱;仅供学习、研究与授权的安全测试使用。它不附带
漏洞利用载荷、不附带目标数据、不附带第三方二进制 —— 它是一套方法、一批脚本和一份证据记录。
它覆盖什么、刻意不覆盖什么,写在 skill 自身(`skills/exe-reverse/references/coverage-and-limits.md`)。
简版:Windows PE 的 x86 与 x64,在真正做过的层上做得深 —— 三分类、补丁、特征码、授权归类、壳、
托管代码,以及硬件观测的路线图。服务端权威的破解、通用自动化去虚拟化器、把"攻破某个具名商业保护产品"
作为产品级宣称,以及对本仓库未测量过的 Windows 版本做任何保证,都**不在**覆盖内,而 skill 被写成
如实说明并停下,而不是把最近的一份文档流程套到一个它并非为此而写的目标上。
简版:Windows PE 的 x86 与 x64,在真正做过的层上做得深 —— 初筛、补丁、特征码、授权归类、壳、托管代码,
以及硬件观测的路线图。服务端权威的破解、通用自动化去虚拟化器、把"攻破某个具名商业保护产品"作为
产品级宣称,以及对本仓库未测量过的 Windows 版本做任何保证,都**不在**覆盖内,而 skill 被写成如实说明
并停下,而不是把最近的一份文档流程套到一个它并非为此而写的目标上。
动手之前先读 `skills/exe-reverse/references/pitfalls.md`。这是这里最有价值的文件 —— 每一条都是一个
"看起来一切正常"却被产出的失败。
## 仓库维护
六个工具位于仓库根部,不属于已安装的 skill:
六个工具位于仓库根部,不属于已安装的 skill。每个都带自己的 docstring;`CONTRIBUTING.md` 说明
"全绿"意味着什么。
```
check_repo.py 发现每个 skill、校验 frontmatter、脚本可运行、文档路径可解析、
README 路径显式且存在,并且在被跟踪的表面上没有目标身份
(规则委派给 scan_leaks.py)
check_refs.py 每一处"指向另一文档某章节"的交叉引用都能在该文档中命中真实标题
check_routing.py 按需清单位与入口点一致:症状镜像与 SKILL.md 相符,
且每个 reference 文件与脚本都在 routing.md 中被点名
check_commands.py 文档让你运行的每条命令都对照脚本自身的 argparse 表校验 ——
文档里写了不存在的开关,是锚点检查看不到的漂移
check_budget.py 防止常驻加载的部分膨胀:按行与 token 测量 SKILL.md、索引行长度、
过长且无可导航头部的文件、含糊表述的规则
build_scripts.py 审计与本机绑定的残留(绝对路径、凭据)
```
| 工具 | 它守住什么 |
|---|---|
| `check_repo.py` | 发现每个 skill、frontmatter 合法、脚本可运行、文档与 README 路径可解析、被跟踪表面上无目标身份 |
| `check_refs.py` | 指向某章节的交叉引用能命中真实标题 |
| `check_routing.py` | 按需清单位与入口点逐行一致 |
| `check_commands.py` | 文档里的每条命令都存在于脚本自身的 argparse 表 |
| `check_budget.py` | 常驻加载的部分不膨胀:SKILL.md 的行与 token、索引行、含糊表述的规则 |
| `build_scripts.py` | 与本机绑定的残留:绝对路径、凭据 |
一致性有天然的反向压力 —— 坏路径会大声失败,然后有人修。膨胀没有,这就是预算门存在的原因。
`tests/benchmark.md` 保存回归矩阵:维度 → 公开目标 → 该行用到的脚本 → 实测结果 → 强度标签。
`docs/tool-verification/` 是测量通行的证据记录:每个脚本实际做了什么、哪个独立方法确认了它、以及目标
无法演练哪些场景。它存在,是为了让覆盖声明可以被"对照运行结果"检查,而不是被直接信任。
`tests/benchmark.md` 保存回归矩阵(维度 -> 公开目标 -> 该行用到的脚本 -> 实测结果 -> 强度标签),
`docs/tool-verification/` 是它背后的证据记录:每个脚本实际做了什么、哪个独立方法确认了它、以及目标
无法演练哪些场景。
---
## 免责声明
**仅供学习、研究与授权的安全测试使用。** 本仓库中的每个脚本、reference 与记录结果,都是为了说明
Windows 应用分析**如何**工作,让从业者能够推理自己手上的工具。这里没有任何服务、产品,也不构成对
任何特定用途的认可。
材料按"原样"提供,不附带任何形式的担保。结果是在一台机器、某一时刻测得的;这里不承诺某条路线在你
的目标、你的宿主或你的工具链上同样可行。信任之前先验证,并且对副本动手。
工具、库、文件格式与加固产品的名称出现,只是为了让材料可复用;它们属于各自的拥有者,本项目与它们
没有关联。
这里没有任何服务、产品,也不构成对任何特定用途的认可。工具、库、文件格式与加固产品的名称出现,
只是为了让材料可复用;它们属于各自的拥有者,本项目与它们没有关联。
+25
View File
@@ -0,0 +1,25 @@
# Windows 逆向入门(讲义)
面向**人**的入门连载,按学习顺序读。它不是 `skills/exe-reverse/` 的一部分:那个 skill 是给
agent 按症状和门禁查的,这里是把同一批概念按由浅入深的顺序铺开给读者。
## 篇目
| 文件 | 内容 |
|---|---|
| `exe1.md` | 原理:程序怎么加载、基址与偏移、代码与数据的区别 |
| `exe2.md` | 缺失(原连载未找到这一篇) |
| `exe3.md` | 方法:找偏移的六条路 |
| `exe4.md` | 利用:外部工具、DLL 注入与 hook |
| `exe5.md` | 工具:CE、IDA、x64dbg |
## 读到这三处要注意
- **`exe5.md` 的调试器是 x64dbg**,不是早期教程里的 OD。OllyDbg 只支持 32 位且早已停止更新。
- **`exe1.md` 的“偏移固定”只在同一个构建内成立**。同一份 exe 每次加载偏移不变,但重新编译就变;
跨版本要靠特征码重新定位,不能死记地址。
- **`exe3.md` 的“拦截系统函数”默认目标是走 IAT 的**。运行时解析 API 或直接发系统调用的目标,
导入表里没有那一行,这一招会落空。
概念上和 `skills/exe-reverse/SKILL.md` 的 `references/pe-structure.md`、
`references/recon.md`、`references/injection-and-hooking.md` 对应;遇到具体操作时看 skill,不要只看讲义。
+135
View File
@@ -0,0 +1,135 @@
开发,是先写代码,再编译成软件。而逆向分析,到手的只有软件。从软件入手,推测对应的代码,需要了解一下编译之后的软件是怎么跑起来的。
 
软件运行过程
  1、软件加载到内存。
  2、CPU读取内存的指令。
  3、根据指令,再读取数据,进行运算。
  4、运算的过程,数据是存在CPU里面的寄存器。
  5、运算过程,用到另一个功能,需要保存当前环境,存到堆栈。
  (这里涉及操作系统和计算组成原理,大概了解,心里有底就好)
 
代码语言的变化
  1、C/C++语言:高级语言,给人看的
  2、汇编语言   :低级语言,给机器用的
  (逆向分析,接触多是汇编语言, 需要自行学习下)
 
软件加载过程
  磁盘 >>内存>>寄存器
  1、代码编译成软件,先放在磁盘(C盘,D盘这些)
  2、开始运行的时候,就会加载进内存(平时说的内存条)
  3、真正运行的是在CPU(也就是所谓的芯片),里面存数据的地方叫寄存器。
 
软件的构成
  软件的外部
    包含:一个主要程序(exe后缀),多个独立库(dll后缀)。
    内存一开始加载exe,有必要的时候,exe再把dll加载进内存来。
 
    exe或者dll在内存的开始位置,叫做基址。(每次加载,随机放置,基址不固定)
    exe或者dll里面和基址的距离,叫做偏移。(每次加载,内部不变,偏移固定)
 
    打个比喻:exe和dll相当小尺子,要放在内存这个大尺子上。
    大尺子上只要有空位,小尺子就可以随便放。
    小尺子不管怎么放,里面的刻度固定的。
     
 
  软件的内部
    软件 = 代码 + 数据
    数据 = 静态数据 (数据不会变)+ 动态数据 (数据会改变)
    动态数据 =  全局数据 (多个函数共用)+ 局部数据(单个函数私有)
 
    代码和静态数据在软件运行过程不会改变,位置固定,可以方便使用。
    全局数据,因为是共用的,位置固定,也可以方便使用。
    所以这三种的偏移是不变的。
 
    内存地址 =  基址 + 偏移。
    基址可以用GetModuleHandle得知。
    偏移又是不变的,内存地址也就可以算出来了 。
 
    而偏移会变化的局部数据,就不能直接算出来了。
    局部数据,是软件运行过程中,临时生成又销毁的。
    所以要获取局部数据,只能在软件的运行过程进行拦截。(也就是所谓的HOOK)
 
逆向分析目的
  逆向分析的两个目的
    1、调用功能
    2、获取数据
 
  通过上面的原理可以知道
    1、调用功能
      代码是固定的,找到偏移,就可以调用。
    2、获取数据
      对于全局数据,找到偏移,就可以得到。
      对于局部数据,需要拦截,才可以得到 。
      (拦截的是代码,所以要找代码的偏移)
 
  所以,逆向的核心点,是找固定的偏移。
  这里说的“固定”只在一个构建内成立:同一份exe,偏移每次加载都不变;但软件一升级、重新编译,偏移就变了。所以跨版本不能死记偏移,要用特征码这类能在新版本里重新定位的办法。
 
下一篇,找偏移的方法。
+94
View File
@@ -0,0 +1,94 @@
Windows逆向分析入门(三)——方法篇
前言
  上一篇,聊到逆向分析是找偏移,有依据地找,效率会快。这一篇聊下找偏移方法。只说概念,具体的细节,后续会配合实战再展开细说。
 
找偏移的方法
1、内存
  逆向的目的,是找功能或者数据在内存的地址。最直接的方法,就是在内存里面搜索。
 
  对于数据:可以直接在内存搜索。
  对于功能:如果知道代码的特征码,也可以直接在内存寻找。
  (所谓代码的特征码,具体是一串字符串,在内存是唯一的,可以用来搜索定位)。
 
2、界面
  带界面的软件,一般流程就是:
    1、软件生成界面,界面上会有按钮,编辑框这些控件。
    2、用户操作界面,点击按钮或者输入文字等等。
    3、软件接收到用户的操作,调用对应的功能。
    4、调用的功能对数据进行处理。
    5、处理结果显示在界面上。
 
  如果知道这个流程在代码里面是怎么实现的,就能找到对应的功能和数据。
 
3、日志
  软件运行的过程,是没办法像视频那样可以倒放。
  想了解软件的运行过程,需要在软件里面埋下标记。
  当软件运行过程,经过做标记的位置,就可以输出信息。(也就是所谓的日志)
  而逆向分析,通过日志找到标记,能知道对应的功能在哪里。
 
4、字符串
  代码里面写的字符串,编译成软件的过程,会被当作全局数据,存在固定的地方。
  而字符串可能有对应的功能,比如 send msg,可能出现在发送信息的功能附近。
  通过搜索字符串,看看哪里用了这个字符串,就可以找到对应的功能。
 
5、系统函数
  写代码的过程中,需要用到一些比较基础的功能。(比如读写文件,收发网络信息)
  这个时候直接用系统提供的接口就可以了。
  这些接口是公用的,所以偏移固定的。
  通过拦截这些接口,就可以定位了。
  但这招有个前提:目标确实经过导入表(IAT)调用这个接口。现在的软件常在运行时才解析API地址,或者直接发系统调用,导入表里根本没有这一行,这时拦截就落空了,要换别的方法定位。
 
6、第三方库
  软件可以看成由多个模块组成的,像搭积木那样。
  而这些模块大多通用的,比如:界面模块,日志模块。
  为了加快开发速度,一般会使用别人写好的第三方模块。
  如果第三方模块是开源的,相当知道软件的一部分代码。
  通过第三方的代码,可以推算出软件还没解开的另一部分。
 
下一篇,找到偏移之后,聊聊利用偏移写代码的思路。
+85
View File
@@ -0,0 +1,85 @@
偏移之后,就是写辅助工具了。这一篇聊聊写辅助工具的原理。具体的代码细节,等到实战会展开细说。
 
明确一下
  逆向两个目的
  1、调用功能
  2、获取数据
 
对应的实现方法
  1、调用功能
    找到偏移,直接调用。
  2、获取数据
    对于全局数据,找到偏移,直接得到。
    对于局部数据,拦截代码,间接得到 。
 
写外部工具
  1、调用功能
    windows系统提供了接口(CreateRemoteThread),允许一个软件调用另一个软件的功能。
  2、获取数据
    对于全局数据
      windows系统提供了接口(ReadProcessMemory),允许一个软件获取另一个软件的数据。
    对于局部数据
      windows系统提供了调试机制,就是在目标软件设置陷阱,当软件触发到陷阱,会暂停下并且抛出报错信息
      辅助工具监听到报错信息,进而获取目标软件的数据。
 
写内部工具
  辅助工具,可以写个间谍模块(dll),然后注入到目标软件里面去。
  通过间谍模块,辅助工具就可以操控目标软件,进而调用功能或者获取数据。
   
  1、调用功能
    在内部,可以直接调用
  2、获取数据
    对于全局数据
      在内部,可以直接获取
    对于局部数据
      内部修改代码拦截(HOOK)
 
    正常流程:步骤1 -> 步骤2
    拦截流程:步骤1 -> hook拦截 -> 步骤2
     
 
 
理论上的东西,差不多这样,下一篇,聊逆向分析用到的工具。
 
+52
View File
@@ -0,0 +1,52 @@
Windows逆向分析入门(五)——工具篇
前言
  老话,工欲善其事,必先利其器。这篇聊聊逆向分析用到的工具。不聊工具细节,自行百度学习。重要的是理清:使用工具,是为了解决什么问题。
工具
  1、CE
    找偏移的方法中聊到,最直接就是在内存里面搜索。
    CE(CheatEngine又称CE修改器),就是用来搜索内存里面东西,得到内存地址。
  2、IDA
    逆向分析,我们拿到手的是已经编译好的软件,看不了代码。
    要是能把软件恢复成代码,分析起来就方便多了。
    IDA这个工具,就是用来把软件恢复成代码的。
    软件编译过程会去掉一些多余的信息。
    所以IDA没办法说完全恢复代码。
    但是用来分析还是很方便的。
    这就是所谓的静态分析。
  3、x64dbg
    用IDA分析软件的时候,软件并没有运行起来,能分析的是软件的静态结构。
    如果要知道到软件运行的具体过程是什么样的,就需要用动态调试工具,比如x64dbg。
    x64dbg里面看到的是汇编的代码,需要熟悉汇编语言和CPU的运行过程,原理篇有聊到。
    早年的教程里常见的是OD(OllyDbg),它只支持32位程序,而且早已停止更新。今天用x64dbg;内核调试或者需要命令行脚本时,用WinDbg。
经验
  工具这块建议重视,多花点时间,效率会快很多。
  CE用来定位数据,x64dbg用来动态调试,IDA用来看代码,多灵活结合。
+59
View File
@@ -0,0 +1,59 @@
# Tool acquisition, and what it costs
**What this answers:** how a tool gets onto an analysis host, what its licence permits, and how
you know it actually runs. This is the part `capabilities.py` reports as a gap but does not
close -- the probe says "missing", and this says what to do about it.
**When to load this:** when a route is blocked by an absent tool, or when its real cost is a
licence rather than an install.
## Licence class before download
| Class | Examples | What it costs you |
|---|---|---|
| Open | Ghidra, radare2/rizin, x64dbg, Frida, gdb, lldb, upx, 7-Zip | nothing; support and maintenance are the real cost |
| Free, restricted | IDA Free (non-commercial), Cheat Engine, most vendor trials | a licence *condition*, not a price; a commercial engagement may exclude it |
| Commercial | IDA Pro + Hex-Rays, Binary Ninja, Hopper | a per-seat licence; procurement lead time is part of the plan |
| Trial | vendor time-limited builds | an expiry date in the middle of a session; write it down |
**No cracked builds, no key generators, no patched installers.** Two reasons, and the second is
the engineering one: a patched binary is an untrusted binary, and you would run it on the machine
whose integrity every later measurement depends on. An unlicensed tool is a capability you do not
have -- record it that way.
## An id copied from a document is `unverified` until a search returns it
`winget search`, `brew search`, `apt-cache search`. Identifiers get renamed, forks get
republished, and a mirror is not the vendor's build. The resolution is one command, and it is the
difference between a record of what happened and a guess that worked once.
Two more things worth knowing before the install: WinDbg exists as a Store build and as the SDK's
Debugging Tools (`cdb`/`kd`), and those are different command lines; on macOS a downloaded bundle
carries a quarantine attribute, so verify the hash before removing it.
## "Installed" is not "available"
| Kind | What proves it works | What it does not prove |
|---|---|---|
| CLI | the version string **and** one real command on a fixture you control | that it parses *your* target without error |
| GUI | it opened the sample and rendered a function list, witnessed by a human | that the analysis finished, or that the decompiler is licensed |
| Kernel / driver | the second machine answered on the debug link | that the driver loads on this build |
A GUI-only tool is a request for a human, not an unavailable capability. A weaker CLI substitute
is not the same capability, and a headless host cannot render the real one.
## When the tool is paid and you cannot pay
1. **Use the free implementation and record what it cannot do.** Ghidra's decompiler differs from
Hex-Rays in readability, not in existence; "recovered with Ghidra, control flow verified by
hand" is a real result.
2. **Ask the requester to license it.** A procurement question with a lead time, not a technical
blocker -- name the blocked route and its cost.
3. **Narrow the deliverable** so the missing capability is not on the critical path.
## What to record
Per tool: class, version, absolute path, **the smoke test you ran**, and a label -- `observed`
(you ran it), `inferred` (the install succeeded, you did not run it), `unverified` (someone told
you it is there). Then re-run `doctor.py` and keep both outputs: their difference is the change
you made to the experiment.