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:
@@ -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
@@ -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 应用分析**如何**工作,让从业者能够推理自己手上的工具。这里没有任何服务、产品,也不构成对
|
||||
任何特定用途的认可。
|
||||
|
||||
材料按"原样"提供,不附带任何形式的担保。结果是在一台机器、某一时刻测得的;这里不承诺某条路线在你
|
||||
的目标、你的宿主或你的工具链上同样可行。信任之前先验证,并且对副本动手。
|
||||
|
||||
工具、库、文件格式与加固产品的名称出现,只是为了让材料可复用;它们属于各自的拥有者,本项目与它们
|
||||
没有关联。
|
||||
这里没有任何服务、产品,也不构成对任何特定用途的认可。工具、库、文件格式与加固产品的名称出现,
|
||||
只是为了让材料可复用;它们属于各自的拥有者,本项目与它们没有关联。
|
||||
|
||||
@@ -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,不要只看讲义。
|
||||
@@ -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,偏移每次加载都不变;但软件一升级、重新编译,偏移就变了。所以跨版本不能死记偏移,要用特征码这类能在新版本里重新定位的办法。
|
||||
|
||||
|
||||
|
||||
下一篇,找偏移的方法。
|
||||
@@ -0,0 +1,94 @@
|
||||
Windows逆向分析入门(三)——方法篇
|
||||
前言
|
||||
|
||||
上一篇,聊到逆向分析是找偏移,有依据地找,效率会快。这一篇聊下找偏移方法。只说概念,具体的细节,后续会配合实战再展开细说。
|
||||
|
||||
|
||||
|
||||
找偏移的方法
|
||||
|
||||
1、内存
|
||||
|
||||
逆向的目的,是找功能或者数据在内存的地址。最直接的方法,就是在内存里面搜索。
|
||||
|
||||
|
||||
|
||||
对于数据:可以直接在内存搜索。
|
||||
|
||||
对于功能:如果知道代码的特征码,也可以直接在内存寻找。
|
||||
|
||||
(所谓代码的特征码,具体是一串字符串,在内存是唯一的,可以用来搜索定位)。
|
||||
|
||||
|
||||
|
||||
2、界面
|
||||
|
||||
带界面的软件,一般流程就是:
|
||||
|
||||
1、软件生成界面,界面上会有按钮,编辑框这些控件。
|
||||
|
||||
2、用户操作界面,点击按钮或者输入文字等等。
|
||||
|
||||
3、软件接收到用户的操作,调用对应的功能。
|
||||
|
||||
4、调用的功能对数据进行处理。
|
||||
|
||||
5、处理结果显示在界面上。
|
||||
|
||||
|
||||
|
||||
如果知道这个流程在代码里面是怎么实现的,就能找到对应的功能和数据。
|
||||
|
||||
|
||||
|
||||
3、日志
|
||||
|
||||
软件运行的过程,是没办法像视频那样可以倒放。
|
||||
|
||||
想了解软件的运行过程,需要在软件里面埋下标记。
|
||||
|
||||
当软件运行过程,经过做标记的位置,就可以输出信息。(也就是所谓的日志)
|
||||
|
||||
而逆向分析,通过日志找到标记,能知道对应的功能在哪里。
|
||||
|
||||
|
||||
|
||||
4、字符串
|
||||
|
||||
代码里面写的字符串,编译成软件的过程,会被当作全局数据,存在固定的地方。
|
||||
|
||||
而字符串可能有对应的功能,比如 send msg,可能出现在发送信息的功能附近。
|
||||
|
||||
通过搜索字符串,看看哪里用了这个字符串,就可以找到对应的功能。
|
||||
|
||||
|
||||
|
||||
5、系统函数
|
||||
|
||||
写代码的过程中,需要用到一些比较基础的功能。(比如读写文件,收发网络信息)
|
||||
|
||||
这个时候直接用系统提供的接口就可以了。
|
||||
|
||||
这些接口是公用的,所以偏移固定的。
|
||||
|
||||
通过拦截这些接口,就可以定位了。
|
||||
|
||||
但这招有个前提:目标确实经过导入表(IAT)调用这个接口。现在的软件常在运行时才解析API地址,或者直接发系统调用,导入表里根本没有这一行,这时拦截就落空了,要换别的方法定位。
|
||||
|
||||
|
||||
|
||||
6、第三方库
|
||||
|
||||
软件可以看成由多个模块组成的,像搭积木那样。
|
||||
|
||||
而这些模块大多通用的,比如:界面模块,日志模块。
|
||||
|
||||
为了加快开发速度,一般会使用别人写好的第三方模块。
|
||||
|
||||
如果第三方模块是开源的,相当知道软件的一部分代码。
|
||||
|
||||
通过第三方的代码,可以推算出软件还没解开的另一部分。
|
||||
|
||||
|
||||
|
||||
下一篇,找到偏移之后,聊聊利用偏移写代码的思路。
|
||||
@@ -0,0 +1,85 @@
|
||||
偏移之后,就是写辅助工具了。这一篇聊聊写辅助工具的原理。具体的代码细节,等到实战会展开细说。
|
||||
|
||||
|
||||
|
||||
明确一下
|
||||
|
||||
逆向两个目的
|
||||
|
||||
1、调用功能
|
||||
|
||||
2、获取数据
|
||||
|
||||
|
||||
|
||||
对应的实现方法
|
||||
|
||||
1、调用功能
|
||||
|
||||
找到偏移,直接调用。
|
||||
|
||||
2、获取数据
|
||||
|
||||
对于全局数据,找到偏移,直接得到。
|
||||
|
||||
对于局部数据,拦截代码,间接得到 。
|
||||
|
||||
|
||||
|
||||
写外部工具
|
||||
|
||||
1、调用功能
|
||||
|
||||
windows系统提供了接口(CreateRemoteThread),允许一个软件调用另一个软件的功能。
|
||||
|
||||
2、获取数据
|
||||
|
||||
对于全局数据
|
||||
|
||||
windows系统提供了接口(ReadProcessMemory),允许一个软件获取另一个软件的数据。
|
||||
|
||||
对于局部数据
|
||||
|
||||
windows系统提供了调试机制,就是在目标软件设置陷阱,当软件触发到陷阱,会暂停下并且抛出报错信息
|
||||
|
||||
辅助工具监听到报错信息,进而获取目标软件的数据。
|
||||
|
||||
|
||||
|
||||
写内部工具
|
||||
|
||||
辅助工具,可以写个间谍模块(dll),然后注入到目标软件里面去。
|
||||
|
||||
通过间谍模块,辅助工具就可以操控目标软件,进而调用功能或者获取数据。
|
||||
|
||||
|
||||
|
||||
1、调用功能
|
||||
|
||||
在内部,可以直接调用
|
||||
|
||||
2、获取数据
|
||||
|
||||
对于全局数据
|
||||
|
||||
在内部,可以直接获取
|
||||
|
||||
对于局部数据
|
||||
|
||||
内部修改代码拦截(HOOK)
|
||||
|
||||
|
||||
|
||||
正常流程:步骤1 -> 步骤2
|
||||
|
||||
拦截流程:步骤1 -> hook拦截 -> 步骤2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
理论上的东西,差不多这样,下一篇,聊逆向分析用到的工具。
|
||||
|
||||
|
||||
@@ -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用来看代码,多灵活结合。
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user