feat: add Windows RE plugin and multi-agent support for 9 coding agents - Add Windows reverse engineering plugin (Ghidra + ILSpy) - PowerShell scripts: check-deps, install-dep, decompile, find-api-calls - Ghidra headless Jython export script (ExportDecompiled.py) - Reference docs: setup guide, Ghidra/ILSpy CLI, API patterns, call flows - Add agent instruction files for Codex, Cursor, Copilot, Cline, Windsurf, Roo Code, Aider, OpenCode - Add universal installer (install.ps1 / install.sh) with interactive agent selection - Add AGENTS.md as universal agent instruction standard - Update README with multi-agent support and installer usage

This commit is contained in:
Samuel Mensah 2026-04-21 12:46:00 +00:00
parent ddeb9bc332
commit c1dd4f7e8c
31 changed files with 4452 additions and 14 deletions

5
.aider.conf.yml Normal file
View File

@ -0,0 +1,5 @@
# Aider configuration for reverse engineering skills
# AGENTS.md is auto-loaded as context for every session
read:
- AGENTS.md

View File

@ -22,6 +22,19 @@
"license": "Apache-2.0",
"keywords": ["android", "reverse-engineering", "apk", "jadx", "decompile", "api-extraction"],
"category": "security"
},
{
"name": "windows-reverse-engineering",
"source": "./plugins/windows-reverse-engineering",
"description": "Decompile Windows EXE/DLL/.NET assemblies with Ghidra and ILSpy, trace call flows, and document extracted Win32/network APIs.",
"version": "1.0.0",
"author": {
"name": "Simone Avogadro"
},
"repository": "https://github.com/SimoneAvogadro/android-reverse-engineering-skill",
"license": "Apache-2.0",
"keywords": ["windows", "reverse-engineering", "exe", "dll", "ghidra", "ilspy", "decompile", "pe-analysis", "api-extraction"],
"category": "security"
}
]
}

View File

@ -0,0 +1,54 @@
# Android Reverse Engineering
Decompile Android APK, XAPK, JAR, and AAR files using jadx and Fernflower/Vineflower. Extract Retrofit endpoints, OkHttp calls, hardcoded URLs, and authentication patterns.
## Dependencies
Run the dependency checker before decompiling:
```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/check-deps.sh
```
Required: Java JDK 17+, jadx.
Optional: Fernflower/Vineflower, dex2jar, apktool.
Install missing:
```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/install-dep.sh <dep>
```
## Workflow
1. **Check deps**: `check-deps.sh` → outputs `INSTALL_REQUIRED:<dep>` for missing tools
2. **Decompile**: `decompile.sh <file>` with `--engine jadx|fernflower|both`, `--deobf`
3. **Analyze**: Review AndroidManifest.xml, package structure, architecture patterns
4. **Trace flows**: Follow Activity → ViewModel → Repository → Retrofit/OkHttp → HTTP
5. **Extract APIs**: `find-api-calls.sh <dir>` with `--retrofit`, `--okhttp`, `--urls`, `--auth`
## Script Locations
All scripts are at: `plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/`
- `check-deps.sh` — verify dependencies
- `install-dep.sh` — install a dependency
- `decompile.sh` — main decompile wrapper
- `find-api-calls.sh` — API call search
## Reference Documentation
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/setup-guide.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/jadx-usage.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/fernflower-usage.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/api-extraction-patterns.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/call-flow-analysis.md`
## Output Format
Document each API endpoint as:
```markdown
### `METHOD /api/endpoint`
- **Source**: ClassName.java:42
- **Retrofit**: @POST("/api/endpoint")
- **Headers**: Authorization: Bearer {token}
- **Body**: { "key": "value" }
- **Called from**: Activity → ViewModel → Repository → ApiService
```

View File

@ -0,0 +1,58 @@
# Windows Reverse Engineering
Decompile Windows EXE, DLL, SYS, and .NET assemblies using Ghidra (native PE → C pseudocode) and ILSpy (.NET → C# source). Auto-detects binary type and selects the appropriate engine.
## Dependencies
Run the dependency checker before decompiling:
```powershell
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/check-deps.ps1
```
Required (at least one): Java JDK 17+ with Ghidra, OR ilspycmd (.NET SDK).
Optional: strings/strings2, dumpbin (Visual Studio C++ Build Tools), de4dot.
Install missing:
```powershell
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/install-dep.ps1 <dep>
```
If PowerShell execution policy blocks scripts, use: `powershell -ExecutionPolicy Bypass -File <script>`.
## Workflow
1. **Check deps**: `check-deps.ps1` → outputs `INSTALL_REQUIRED:<dep>` for missing tools
2. **Decompile**: `decompile.ps1 <file>` — auto-detects .NET (→ ILSpy) vs native (→ Ghidra)
- Options: `-Engine auto|ghidra|ilspy`, `-Output <dir>`, `-NoStrings`
3. **Analyze**: Review PE imports/exports, namespace structure, entry points
4. **Trace flows**: Follow WinMain/Main → handlers → business logic → API calls
5. **Extract APIs**: `find-api-calls.ps1 <dir>` with `-Network`, `-Registry`, `-Crypto`, `-Urls`, `-Auth`, `-Process`, `-Persistence`
## Script Locations
All scripts are at: `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/`
- `check-deps.ps1` — verify dependencies
- `install-dep.ps1` — install a dependency
- `decompile.ps1` — main decompile wrapper
- `find-api-calls.ps1` — API call search
- `ghidra-scripts/ExportDecompiled.py` — Ghidra Jython export
## Reference Documentation
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/setup-guide.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/ghidra-headless-usage.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/ilspy-usage.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/api-extraction-patterns.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/call-flow-analysis.md`
## Output Format
Document each API call as:
```markdown
### `FunctionName` (DLL: source.dll)
- **Source**: filename.c:42
- **Category**: Network / Registry / File I/O / Process / Crypto
- **Parameters**: param1: value, param2: value
- **Called from**: Main → InitNetwork → WinHttpSendRequest
- **Purpose**: Description
```

View File

@ -0,0 +1,61 @@
---
description: "Decompile Android APK/XAPK/JAR/AAR files. Use jadx or Fernflower/Vineflower. Extract Retrofit/OkHttp API endpoints, trace call flows from Activities through ViewModels to network layer."
globs: ["**/*.apk", "**/*.xapk", "**/*.jar", "**/*.aar"]
alwaysApply: false
---
# Android Reverse Engineering
Decompile Android packages using jadx (broad coverage) or Fernflower/Vineflower (higher quality Java). Extract HTTP APIs — Retrofit endpoints, OkHttp calls, hardcoded URLs.
## Quick Start
```bash
# 1. Check dependencies
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/check-deps.sh
# 2. Install missing deps
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/install-dep.sh <dep>
# 3. Decompile
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/decompile.sh app.apk
# 4. Find API calls
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/find-api-calls.sh output/sources/
```
## Workflow
1. **Verify deps** → run `check-deps.sh`, install any missing with `install-dep.sh`
2. **Decompile** → run `decompile.sh` with `--engine jadx|fernflower|both`
3. **Analyze structure** → AndroidManifest.xml, package layout, architecture patterns
4. **Trace call flows** → Activity → ViewModel → Repository → Retrofit/OkHttp → HTTP
5. **Extract APIs** → run `find-api-calls.sh` with `--retrofit`, `--okhttp`, `--urls`, `--auth`
## Engine Selection
| Situation | Engine |
|---|---|
| General APK analysis | jadx (default) |
| Complex Java decompilation | Fernflower/Vineflower |
| Side-by-side comparison | `--engine both` |
| Obfuscated APK | jadx with `--deobf` |
## API Documentation Format
```markdown
### `METHOD /api/endpoint`
- **Source**: ClassName.java:42
- **Retrofit**: @POST("/api/endpoint")
- **Headers**: Authorization: Bearer {token}
- **Body**: { "key": "value" }
- **Called from**: Activity → ViewModel → Repository → ApiService
```
## References
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/setup-guide.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/jadx-usage.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/fernflower-usage.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/api-extraction-patterns.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/call-flow-analysis.md`

View File

@ -0,0 +1,59 @@
---
description: "Decompile Windows EXE/DLL/.NET assemblies. Use Ghidra for native PE binaries and ILSpy for .NET. Extract Win32 API calls, network endpoints, registry operations. Trace call flows from entry points to API calls."
globs: ["**/*.exe", "**/*.dll", "**/*.sys"]
alwaysApply: false
---
# Windows Reverse Engineering
Decompile Windows binaries using Ghidra (native PE → C pseudocode) or ILSpy (.NET → C# source). Auto-detects binary type.
## Quick Start
```powershell
# 1. Check dependencies
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/check-deps.ps1
# 2. Install missing deps
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/install-dep.ps1 <dep>
# 3. Decompile (auto-detects engine)
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/decompile.ps1 target.exe
# 4. Find API calls
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/find-api-calls.ps1 output/sources/
```
## Workflow
1. **Verify deps** → run `check-deps.ps1`, install any missing with `install-dep.ps1`
2. **Decompile** → run `decompile.ps1` with `-Engine auto|ghidra|ilspy`
3. **Analyze structure** → review imports, exports, PE headers, namespace layout
4. **Trace call flows** → follow entry points (WinMain/Main) → handlers → API calls
5. **Extract APIs** → run `find-api-calls.ps1` with `-Network`, `-Registry`, `-Crypto`, `-Urls`, `-Process`, `-Auth`, `-Persistence`
## Auto-Detection
| Binary Type | Engine |
|---|---|
| .NET assembly (CLI header present) | ILSpy → C# source |
| Native C/C++ PE | Ghidra → C pseudocode |
| Kernel driver (.sys) | Ghidra |
## API Documentation Format
```markdown
### `FunctionName` (DLL: source.dll)
- **Source**: filename.c:42
- **Category**: Network / Registry / File I/O / Process / Crypto
- **Called from**: Main → InitNetwork → WinHttpSendRequest
- **Purpose**: Description
```
## References
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/setup-guide.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/ghidra-headless-usage.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/ilspy-usage.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/api-extraction-patterns.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/call-flow-analysis.md`

20
.github/copilot-instructions.md vendored Normal file
View File

@ -0,0 +1,20 @@
# Reverse Engineering Skills
This repository provides AI-assisted reverse engineering for Windows and Android binaries.
## Windows RE
- Decompiles EXE/DLL/.NET using Ghidra (native) and ILSpy (.NET)
- Scripts: `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/`
- Check deps: `powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/check-deps.ps1`
- Decompile: `powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/decompile.ps1 <file>`
- Find APIs: `powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/find-api-calls.ps1 <dir>`
## Android RE
- Decompiles APK/XAPK/JAR/AAR using jadx and Fernflower
- Scripts: `plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/`
- Check deps: `bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/check-deps.sh`
- Decompile: `bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/decompile.sh <file>`
- Find APIs: `bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/find-api-calls.sh <dir>`
## Detailed References
- See `plugins/*/skills/*/references/` for setup guides, tool CLI references, API patterns, and call flow analysis techniques.

View File

@ -0,0 +1,39 @@
---
description: 'Android reverse engineering with jadx and Fernflower — decompile APK/JAR/AAR, extract Retrofit/OkHttp APIs, trace call flows'
applyTo: '**/*.{apk,xapk,jar,aar}'
---
# Android Reverse Engineering
Decompile Android packages using jadx (broad coverage) or Fernflower/Vineflower (higher quality Java).
## Commands
```bash
# Check dependencies
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/check-deps.sh
# Install missing dependency
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/install-dep.sh <dep>
# Decompile
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/decompile.sh app.apk
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/decompile.sh --engine both --deobf app.apk
# Find API calls
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/find-api-calls.sh output/sources/
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/find-api-calls.sh output/sources/ --retrofit
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/find-api-calls.sh output/sources/ --urls
```
## Workflow
1. Verify dependencies → `check-deps.sh`
2. Decompile → `decompile.sh` (jadx, fernflower, or both)
3. Analyze AndroidManifest.xml and package structure
4. Trace call flows from Activities → ViewModels → Repositories → API calls
5. Extract and document APIs → `find-api-calls.sh`
## References
See `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/` for detailed guides.

View File

@ -0,0 +1,40 @@
---
description: 'Windows reverse engineering with Ghidra and ILSpy — decompile EXE/DLL/.NET, extract Win32 APIs, trace call flows'
applyTo: '**/*.{exe,dll,sys}'
---
# Windows Reverse Engineering
Decompile Windows binaries using Ghidra (native PE → C pseudocode) or ILSpy (.NET → C# source).
## Commands
```powershell
# Check dependencies
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/check-deps.ps1
# Install missing dependency
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/install-dep.ps1 <dep>
# Available: java, ghidra, ilspycmd, dotnet-sdk, strings, dumpbin, de4dot
# Decompile (auto-detects .NET vs native)
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/decompile.ps1 target.exe
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/decompile.ps1 -Engine ilspy MyDotNet.dll
# Find API calls in decompiled output
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/find-api-calls.ps1 output/sources/
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/find-api-calls.ps1 output/sources/ -Network
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/find-api-calls.ps1 output/sources/ -Urls
```
## Workflow
1. Verify dependencies → `check-deps.ps1`
2. Decompile → `decompile.ps1` (auto-detects engine)
3. Analyze PE structure (imports, exports, headers)
4. Trace call flows from entry points to API calls
5. Extract and document APIs → `find-api-calls.ps1`
## References
See `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/` for detailed guides.

View File

@ -0,0 +1,54 @@
# Android Reverse Engineering
Decompile Android APK, XAPK, JAR, and AAR files using jadx and Fernflower/Vineflower. Extract Retrofit endpoints, OkHttp calls, hardcoded URLs, and authentication patterns.
## Dependencies
Run the dependency checker before decompiling:
```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/check-deps.sh
```
Required: Java JDK 17+, jadx.
Optional: Fernflower/Vineflower, dex2jar, apktool.
Install missing:
```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/install-dep.sh <dep>
```
## Workflow
1. **Check deps**: `check-deps.sh` → outputs `INSTALL_REQUIRED:<dep>` for missing tools
2. **Decompile**: `decompile.sh <file>` with `--engine jadx|fernflower|both`, `--deobf`
3. **Analyze**: Review AndroidManifest.xml, package structure, architecture patterns
4. **Trace flows**: Follow Activity → ViewModel → Repository → Retrofit/OkHttp → HTTP
5. **Extract APIs**: `find-api-calls.sh <dir>` with `--retrofit`, `--okhttp`, `--urls`, `--auth`
## Script Locations
All scripts are at: `plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/`
- `check-deps.sh` — verify dependencies
- `install-dep.sh` — install a dependency
- `decompile.sh` — main decompile wrapper
- `find-api-calls.sh` — API call search
## Reference Documentation
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/setup-guide.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/jadx-usage.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/fernflower-usage.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/api-extraction-patterns.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/call-flow-analysis.md`
## Output Format
Document each API endpoint as:
```markdown
### `METHOD /api/endpoint`
- **Source**: ClassName.java:42
- **Retrofit**: @POST("/api/endpoint")
- **Headers**: Authorization: Bearer {token}
- **Body**: { "key": "value" }
- **Called from**: Activity → ViewModel → Repository → ApiService
```

View File

@ -0,0 +1,58 @@
# Windows Reverse Engineering
Decompile Windows EXE, DLL, SYS, and .NET assemblies using Ghidra (native PE → C pseudocode) and ILSpy (.NET → C# source). Auto-detects binary type and selects the appropriate engine.
## Dependencies
Run the dependency checker before decompiling:
```powershell
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/check-deps.ps1
```
Required (at least one): Java JDK 17+ with Ghidra, OR ilspycmd (.NET SDK).
Optional: strings/strings2, dumpbin (Visual Studio C++ Build Tools), de4dot.
Install missing:
```powershell
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/install-dep.ps1 <dep>
```
If PowerShell execution policy blocks scripts, use: `powershell -ExecutionPolicy Bypass -File <script>`.
## Workflow
1. **Check deps**: `check-deps.ps1` → outputs `INSTALL_REQUIRED:<dep>` for missing tools
2. **Decompile**: `decompile.ps1 <file>` — auto-detects .NET (→ ILSpy) vs native (→ Ghidra)
- Options: `-Engine auto|ghidra|ilspy`, `-Output <dir>`, `-NoStrings`
3. **Analyze**: Review PE imports/exports, namespace structure, entry points
4. **Trace flows**: Follow WinMain/Main → handlers → business logic → API calls
5. **Extract APIs**: `find-api-calls.ps1 <dir>` with `-Network`, `-Registry`, `-Crypto`, `-Urls`, `-Auth`, `-Process`, `-Persistence`
## Script Locations
All scripts are at: `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/`
- `check-deps.ps1` — verify dependencies
- `install-dep.ps1` — install a dependency
- `decompile.ps1` — main decompile wrapper
- `find-api-calls.ps1` — API call search
- `ghidra-scripts/ExportDecompiled.py` — Ghidra Jython export
## Reference Documentation
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/setup-guide.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/ghidra-headless-usage.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/ilspy-usage.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/api-extraction-patterns.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/call-flow-analysis.md`
## Output Format
Document each API call as:
```markdown
### `FunctionName` (DLL: source.dll)
- **Source**: filename.c:42
- **Category**: Network / Registry / File I/O / Process / Crypto
- **Parameters**: param1: value, param2: value
- **Called from**: Main → InitNetwork → WinHttpSendRequest
- **Purpose**: Description
```

View File

@ -0,0 +1,54 @@
# Android Reverse Engineering
Decompile Android APK, XAPK, JAR, and AAR files using jadx and Fernflower/Vineflower. Extract Retrofit endpoints, OkHttp calls, hardcoded URLs, and authentication patterns.
## Dependencies
Run the dependency checker before decompiling:
```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/check-deps.sh
```
Required: Java JDK 17+, jadx.
Optional: Fernflower/Vineflower, dex2jar, apktool.
Install missing:
```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/install-dep.sh <dep>
```
## Workflow
1. **Check deps**: `check-deps.sh` → outputs `INSTALL_REQUIRED:<dep>` for missing tools
2. **Decompile**: `decompile.sh <file>` with `--engine jadx|fernflower|both`, `--deobf`
3. **Analyze**: Review AndroidManifest.xml, package structure, architecture patterns
4. **Trace flows**: Follow Activity → ViewModel → Repository → Retrofit/OkHttp → HTTP
5. **Extract APIs**: `find-api-calls.sh <dir>` with `--retrofit`, `--okhttp`, `--urls`, `--auth`
## Script Locations
All scripts are at: `plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/`
- `check-deps.sh` — verify dependencies
- `install-dep.sh` — install a dependency
- `decompile.sh` — main decompile wrapper
- `find-api-calls.sh` — API call search
## Reference Documentation
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/setup-guide.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/jadx-usage.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/fernflower-usage.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/api-extraction-patterns.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/call-flow-analysis.md`
## Output Format
Document each API endpoint as:
```markdown
### `METHOD /api/endpoint`
- **Source**: ClassName.java:42
- **Retrofit**: @POST("/api/endpoint")
- **Headers**: Authorization: Bearer {token}
- **Body**: { "key": "value" }
- **Called from**: Activity → ViewModel → Repository → ApiService
```

View File

@ -0,0 +1,58 @@
# Windows Reverse Engineering
Decompile Windows EXE, DLL, SYS, and .NET assemblies using Ghidra (native PE → C pseudocode) and ILSpy (.NET → C# source). Auto-detects binary type and selects the appropriate engine.
## Dependencies
Run the dependency checker before decompiling:
```powershell
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/check-deps.ps1
```
Required (at least one): Java JDK 17+ with Ghidra, OR ilspycmd (.NET SDK).
Optional: strings/strings2, dumpbin (Visual Studio C++ Build Tools), de4dot.
Install missing:
```powershell
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/install-dep.ps1 <dep>
```
If PowerShell execution policy blocks scripts, use: `powershell -ExecutionPolicy Bypass -File <script>`.
## Workflow
1. **Check deps**: `check-deps.ps1` → outputs `INSTALL_REQUIRED:<dep>` for missing tools
2. **Decompile**: `decompile.ps1 <file>` — auto-detects .NET (→ ILSpy) vs native (→ Ghidra)
- Options: `-Engine auto|ghidra|ilspy`, `-Output <dir>`, `-NoStrings`
3. **Analyze**: Review PE imports/exports, namespace structure, entry points
4. **Trace flows**: Follow WinMain/Main → handlers → business logic → API calls
5. **Extract APIs**: `find-api-calls.ps1 <dir>` with `-Network`, `-Registry`, `-Crypto`, `-Urls`, `-Auth`, `-Process`, `-Persistence`
## Script Locations
All scripts are at: `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/`
- `check-deps.ps1` — verify dependencies
- `install-dep.ps1` — install a dependency
- `decompile.ps1` — main decompile wrapper
- `find-api-calls.ps1` — API call search
- `ghidra-scripts/ExportDecompiled.py` — Ghidra Jython export
## Reference Documentation
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/setup-guide.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/ghidra-headless-usage.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/ilspy-usage.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/api-extraction-patterns.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/call-flow-analysis.md`
## Output Format
Document each API call as:
```markdown
### `FunctionName` (DLL: source.dll)
- **Source**: filename.c:42
- **Category**: Network / Registry / File I/O / Process / Crypto
- **Parameters**: param1: value, param2: value
- **Called from**: Main → InitNetwork → WinHttpSendRequest
- **Purpose**: Description
```

166
AGENTS.md Normal file
View File

@ -0,0 +1,166 @@
# Reverse Engineering Skills
This repository provides AI-assisted reverse engineering tools for **Windows** (EXE/DLL/.NET) and **Android** (APK/XAPK/JAR/AAR) binaries. It includes decompilation scripts, API extraction, call flow tracing, and structured output documentation.
All scripts and references live under `plugins/`. The instructions below tell you how to use them.
---
## Windows Reverse Engineering
Decompile Windows EXE, DLL, SYS, and .NET assemblies using Ghidra (native PE → C pseudocode) and ILSpy (managed .NET → C# source). Auto-detects binary type.
### Dependencies
Run the dependency checker first:
```powershell
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/check-deps.ps1
```
**Required (at least one decompiler):**
- Java JDK 17+ and Ghidra (set `GHIDRA_INSTALL_DIR` env var) — for native PE
- ilspycmd (`dotnet tool install -g ilspycmd`) — for .NET assemblies
**Optional:** strings/strings2, dumpbin (requires Visual Studio C++ Build Tools), de4dot (.NET deobfuscator)
Install missing dependencies:
```powershell
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/install-dep.ps1 <dep>
# Available: java, ghidra, ilspycmd, dotnet-sdk, strings, dumpbin, de4dot
```
### PowerShell Execution Policy
If scripts are blocked, auto-fix with:
```powershell
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force
```
If group policy prevents this, prefix all script calls with `powershell -ExecutionPolicy Bypass -File`.
### Workflow
#### Phase 1: Verify Dependencies
```powershell
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/check-deps.ps1
```
Output includes `INSTALL_REQUIRED:<dep>` and `INSTALL_OPTIONAL:<dep>` lines. Install any required deps before proceeding.
#### Phase 2: Decompile
```powershell
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/decompile.ps1 [OPTIONS] <file>
```
Options:
- `-Output <dir>` — custom output directory (default: `<filename>-decompiled`)
- `-Engine auto|ghidra|ilspy` — decompiler engine (default: `auto`)
- `-NoStrings` — skip strings extraction
Auto-detection: .NET assemblies (CLI header present) → ILSpy. Native PE → Ghidra. The script reads the PE header to determine binary type.
**Output structure (Ghidra):**
```
<output>/decompiled/ — C pseudocode per function
<output>/imports.txt — import table
<output>/exports.txt — export table
<output>/strings.txt — extracted strings
<output>/summary.txt — analysis summary
```
**Output structure (ILSpy):**
```
<output>/sources/ — C# source files with .csproj
```
#### Phase 3: Analyze Structure
- Review PE headers (architecture, subsystem, entry point, security features)
- Survey import table — reveals which DLLs/APIs the binary uses
- For .NET: examine namespace structure, referenced assemblies, DI container setup
- For native: group functions by purpose, identify entry points, look for C++ vtables
#### Phase 4: Trace Call Flows
- Start from entry points: `WinMain`, `main`, `DllMain`, `ServiceMain`, `DriverEntry` (native) or `static void Main()`, `Program.cs`, `Startup.cs` (.NET)
- Follow initialization chain → user action handlers → business logic → API calls
- Map dependency injection in .NET (`AddScoped`, `AddSingleton`, `AddTransient`)
- Handle obfuscated code: use framework type names and string refs as anchors
#### Phase 5: Extract APIs
```powershell
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/find-api-calls.ps1 <output>/sources/ [OPTIONS]
```
Options: `-Network`, `-Registry`, `-FileSystem`, `-Process`, `-Crypto`, `-Com`, `-Services`, `-Urls`, `-Auth`, `-Persistence`
Document each API call:
```markdown
### `FunctionName` (DLL: source.dll)
- **Source**: filename.c:42
- **Category**: Network / Registry / File I/O / Process / Crypto
- **Parameters**: param1: value, param2: value
- **Called from**: Main → InitNetwork → SendData → WinHttpSendRequest
- **Purpose**: Description
```
### Reference Documentation
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/setup-guide.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/ghidra-headless-usage.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/ilspy-usage.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/api-extraction-patterns.md`
- `plugins/windows-reverse-engineering/skills/windows-reverse-engineering/references/call-flow-analysis.md`
---
## Android Reverse Engineering
Decompile Android APK, XAPK, JAR, and AAR files using jadx and Fernflower/Vineflower. Extract Retrofit endpoints, OkHttp calls, hardcoded URLs, and authentication patterns.
### Dependencies
```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/check-deps.sh
```
**Required:** Java JDK 17+, jadx
**Optional:** Fernflower/Vineflower, dex2jar, apktool
Install missing:
```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/install-dep.sh <dep>
```
### Workflow
#### Phase 1: Verify Dependencies
```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/check-deps.sh
```
#### Phase 2: Decompile
```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/decompile.sh [OPTIONS] <file>
```
Options:
- `--output <dir>` — custom output directory
- `--engine jadx|fernflower|both` — decompiler engine (default: `jadx`)
- `--deobf` — enable deobfuscation
#### Phase 3: Analyze Structure
- Review AndroidManifest.xml for activities, services, receivers, permissions
- Survey package structure and identify architecture patterns (MVP, MVVM, Clean Architecture)
- Find application entry points (Application class, main Activity, ContentProviders)
#### Phase 4: Trace Call Flows
- Start from Activity/Fragment → ViewModel → Repository → API client
- Follow Dagger/Hilt dependency injection
- Map Retrofit interface → OkHttp interceptors → actual HTTP calls
#### Phase 5: Extract APIs
```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ [OPTIONS]
```
Options: `--retrofit`, `--okhttp`, `--urls`, `--auth`, `--volley`
### Reference Documentation
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/setup-guide.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/jadx-usage.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/fernflower-usage.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/api-extraction-patterns.md`
- `plugins/android-reverse-engineering/skills/android-reverse-engineering/references/call-flow-analysis.md`

161
README.md
View File

@ -1,8 +1,79 @@
# Android Reverse Engineering & API Extraction — Claude Code skill
# Reverse Engineering & API Extraction — AI Coding Agent Skills
A Claude Code skill that decompiles Android APK/XAPK/JAR/AAR files and **extracts the HTTP APIs** used by the app — Retrofit endpoints, OkHttp calls, hardcoded URLs, authentication patterns — so you can document and reproduce them without the original source code.
A collection of AI coding agent skills for reverse engineering mobile and desktop applications. Includes **Android** (APK/XAPK/JAR/AAR) and **Windows** (EXE/DLL/.NET) plugins that decompile binaries, extract APIs, trace call flows, and document findings.
Works with **Claude Code**, **OpenAI Codex**, **Cursor**, **GitHub Copilot**, **Cline**, **Windsurf**, **Roo Code**, **Aider**, and **OpenCode**.
---
## 🪟 Windows Reverse Engineering (NEW)
Decompiles Windows EXE/DLL/.NET assemblies and **extracts Win32 API calls**, network endpoints, registry operations, cryptographic usage, and more.
### What it does
- **Auto-detects** binary type (.NET vs native PE) and selects the best decompiler
- **Decompiles** native PE binaries using **Ghidra** headless (C pseudocode output)
- **Decompiles** .NET assemblies using **ILSpy** (ilspycmd) to C# source
- **Extracts and documents APIs**: Win32 calls, WinHTTP/WinINet, Winsock, .NET HttpClient, registry, crypto, COM/WMI
- **Traces call flows** from entry points (WinMain, DllMain, ServiceMain, Main) through to API calls
- **Analyzes** PE structure: imports, exports, sections, strings, security features
- **Detects** persistence mechanisms, process injection patterns, and hardcoded secrets
### Requirements
**Required (at least one decompiler):**
- Java JDK 17+ and [Ghidra](https://github.com/NationalSecurityAgency/ghidra) — for native PE binaries
- [ilspycmd](https://github.com/icsharpcode/ILSpy) (`dotnet tool install -g ilspycmd`) — for .NET assemblies
**Optional (recommended):**
- [strings2](https://github.com/glmcdona/strings2) or SysInternals Strings — extract embedded strings
- dumpbin (Visual Studio C++ Build Tools) — PE header analysis
- [de4dot](https://github.com/de4dot/de4dot) — .NET deobfuscation
### Installation
Inside Claude Code, run:
```
/plugin install windows-reverse-engineering@android-reverse-engineering-skill
```
### Usage
```
/decompile path/to/app.exe
```
The skill auto-detects the binary type and runs the appropriate decompiler. You can also use natural language: "Reverse engineer this DLL", "Extract API calls from this .NET app", "Trace the login flow".
### Manual scripts (PowerShell)
```powershell
# Check dependencies
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/check-deps.ps1
# Install a missing dependency
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/install-dep.ps1 ghidra
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/install-dep.ps1 ilspycmd
# Decompile (auto-detect engine)
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/decompile.ps1 app.exe
# Decompile with specific engine
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/decompile.ps1 -Engine ilspy MyDotNetApp.dll
# Find API calls
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/find-api-calls.ps1 output/sources/
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/find-api-calls.ps1 output/sources/ -Network
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/find-api-calls.ps1 output/sources/ -Urls
powershell -ExecutionPolicy Bypass -File plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/find-api-calls.ps1 output/sources/ -Process
```
---
## 🤖 Android Reverse Engineering
## What it does
- **Decompiles** APK, XAPK, JAR, and AAR files using jadx and Fernflower/Vineflower (single engine or side-by-side comparison)
- **Extracts and documents APIs**: Retrofit endpoints, OkHttp calls, hardcoded URLs, auth headers and tokens
@ -103,39 +174,101 @@ bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scri
```
android-reverse-engineering-skill/
├── .claude-plugin/
│ └── marketplace.json # Marketplace catalog
│ └── marketplace.json # Marketplace catalog (both plugins)
├── plugins/
│ └── android-reverse-engineering/
│ ├── android-reverse-engineering/ # Android plugin
│ │ ├── .claude-plugin/
│ │ │ └── plugin.json
│ │ ├── skills/
│ │ │ └── android-reverse-engineering/
│ │ │ ├── SKILL.md
│ │ │ ├── references/
│ │ │ │ ├── setup-guide.md
│ │ │ │ ├── jadx-usage.md
│ │ │ │ ├── fernflower-usage.md
│ │ │ │ ├── api-extraction-patterns.md
│ │ │ │ └── call-flow-analysis.md
│ │ │ └── scripts/
│ │ │ ├── check-deps.sh
│ │ │ ├── install-dep.sh
│ │ │ ├── decompile.sh
│ │ │ └── find-api-calls.sh
│ │ └── commands/
│ │ └── decompile.md
│ └── windows-reverse-engineering/ # Windows plugin (NEW)
│ ├── .claude-plugin/
│ │ └── plugin.json # Plugin manifest
│ │ └── plugin.json
│ ├── skills/
│ │ └── android-reverse-engineering/
│ │ └── windows-reverse-engineering/
│ │ ├── SKILL.md # Core workflow (5 phases)
│ │ ├── references/
│ │ │ ├── setup-guide.md
│ │ │ ├── jadx-usage.md
│ │ │ ├── fernflower-usage.md
│ │ │ ├── ghidra-headless-usage.md
│ │ │ ├── ilspy-usage.md
│ │ │ ├── api-extraction-patterns.md
│ │ │ └── call-flow-analysis.md
│ │ └── scripts/
│ │ ├── check-deps.sh
│ │ ├── install-dep.sh
│ │ ├── decompile.sh
│ │ └── find-api-calls.sh
│ │ ├── check-deps.ps1
│ │ ├── install-dep.ps1
│ │ ├── decompile.ps1
│ │ ├── find-api-calls.ps1
│ │ └── ghidra-scripts/
│ │ └── ExportDecompiled.py
│ └── commands/
│ └── decompile.md # /decompile slash command
│ └── decompile.md
├── LICENSE
└── README.md
```
## References
### Android
- [jadx — Dex to Java decompiler](https://github.com/skylot/jadx)
- [Fernflower — JetBrains analytical decompiler](https://github.com/JetBrains/fernflower)
- [Vineflower — Fernflower community fork](https://github.com/Vineflower/vineflower)
- [dex2jar — DEX to JAR converter](https://github.com/pxb1988/dex2jar)
- [apktool — Android resource decoder](https://apktool.org/)
### Windows
- [Ghidra — NSA reverse engineering framework](https://github.com/NationalSecurityAgency/ghidra)
- [ILSpy — .NET decompiler](https://github.com/icsharpcode/ILSpy)
- [de4dot — .NET deobfuscator](https://github.com/de4dot/de4dot)
- [strings2 — Advanced string extraction](https://github.com/glmcdona/strings2)
- [x64dbg — Open source Windows debugger](https://x64dbg.com/)
## Supported Agents
This skill works with all major AI coding agents. Use the universal installer to set up for your agent:
```powershell
# Windows (PowerShell)
.\install.ps1 # Interactive — choose your agent
.\install.ps1 -Agent cursor # Install for Cursor
.\install.ps1 -Agent all # Install for all agents
.\install.ps1 -List # List supported agents
.\install.ps1 -CheckDeps # Run dependency check
```
```bash
# Linux / macOS / WSL
./install.sh # Interactive
./install.sh --agent codex # Install for Codex
./install.sh --agent all # Install for all agents
./install.sh --list # List supported agents
```
| Agent | Config Files | Auto-Detection |
|---|---|---|
| **Claude Code** | `.claude-plugin/` | Plugin manifest + SKILL.md |
| **OpenAI Codex** | `AGENTS.md` | Reads from repo root |
| **OpenCode** | `AGENTS.md` | Reads from repo root |
| **Cursor** | `.cursor/rules/*.mdc` | Glob-matched + description-based |
| **GitHub Copilot** | `.github/instructions/*.instructions.md` | File-pattern matched |
| **Cline** | `.clinerules/*.md` | Auto-loaded into context |
| **Windsurf** | `.windsurf/rules/*.md` | Auto-loaded by Cascade |
| **Roo Code** | `.roo/rules/*.md` | Auto-loaded, alphabetical order |
| **Aider** | `.aider.conf.yml``AGENTS.md` | Loaded via `read:` config |
## Disclaimer
This plugin is provided strictly for **lawful purposes**, including but not limited to:

290
install.ps1 Normal file
View File

@ -0,0 +1,290 @@
# install.ps1 - Universal installer for reverse engineering skills
# Installs agent-specific instruction files for any supported AI coding agent.
#
# Usage:
# .\install.ps1 # Interactive mode
# .\install.ps1 -Agent cursor # Install for Cursor
# .\install.ps1 -Agent all # Install for all agents
# .\install.ps1 -Agent copilot -Target C:\MyProject # Install into another project
# .\install.ps1 -List # List available agents
# .\install.ps1 -CheckDeps # Run dependency check only
param(
[ValidateSet('claude', 'codex', 'opencode', 'cursor', 'copilot', 'cline', 'windsurf', 'roo', 'aider', 'all')]
[string]$Agent = '',
[string]$Target = '',
[switch]$List,
[switch]$CheckDeps,
[Alias('h')]
[switch]$Help
)
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
# --- Help ---
if ($Help) {
Write-Host 'Reverse Engineering Skills - Universal Installer'
Write-Host ''
Write-Host 'Usage:'
Write-Host ' .\install.ps1 Interactive mode (choose agent)'
Write-Host ' .\install.ps1 -Agent <agent> Install for a specific agent'
Write-Host ' .\install.ps1 -Agent all Install for all agents'
Write-Host ' .\install.ps1 -Agent <agent> -Target <dir> Install into another project'
Write-Host ' .\install.ps1 -List List supported agents'
Write-Host ' .\install.ps1 -CheckDeps Run dependency check only'
Write-Host ''
Write-Host 'Agents:'
Write-Host ' claude - Claude Code (.claude-plugin/)'
Write-Host ' codex - OpenAI Codex (AGENTS.md)'
Write-Host ' opencode - OpenCode (AGENTS.md)'
Write-Host ' cursor - Cursor IDE (.cursor/rules/*.mdc)'
Write-Host ' copilot - GitHub Copilot (.github/instructions/)'
Write-Host ' cline - Cline (.clinerules/)'
Write-Host ' windsurf - Windsurf (.windsurf/rules/)'
Write-Host ' roo - Roo Code (.roo/rules/)'
Write-Host ' aider - Aider (.aider.conf.yml)'
Write-Host ' all - Install for all agents at once'
Write-Host ''
Write-Host 'Options:'
Write-Host ' -Target <dir> Target directory (default: current directory)'
Write-Host ' -List List all supported agents'
Write-Host ' -CheckDeps Run the dependency checker and exit'
Write-Host ' -Help Show this help message'
exit 0
}
# --- Agent definitions ---
$Agents = [ordered]@{
claude = @{ Name = 'Claude Code'; Files = @('.claude-plugin/') }
codex = @{ Name = 'OpenAI Codex'; Files = @('AGENTS.md') }
opencode = @{ Name = 'OpenCode'; Files = @('AGENTS.md') }
cursor = @{ Name = 'Cursor IDE'; Files = @('.cursor/rules/') }
copilot = @{ Name = 'GitHub Copilot'; Files = @('.github/copilot-instructions.md', '.github/instructions/') }
cline = @{ Name = 'Cline'; Files = @('.clinerules/') }
windsurf = @{ Name = 'Windsurf'; Files = @('.windsurf/rules/') }
roo = @{ Name = 'Roo Code'; Files = @('.roo/rules/') }
aider = @{ Name = 'Aider'; Files = @('.aider.conf.yml', 'AGENTS.md') }
}
# --- List ---
if ($List) {
Write-Host 'Supported AI Coding Agents:' -ForegroundColor Cyan
Write-Host ''
foreach ($key in $Agents.Keys) {
$agentDef = $Agents[$key]
$fileList = ($agentDef.Files -join ', ')
Write-Host (' {0,-12} {1,-20} -> {2}' -f $key, $agentDef.Name, $fileList)
}
Write-Host ''
Write-Host ' all All agents -> installs everything'
Write-Host ''
Write-Host 'Usage: .\install.ps1 -Agent <agent>' -ForegroundColor Green
exit 0
}
# --- Check deps ---
if ($CheckDeps) {
Write-Host '=== Running Dependency Checks ===' -ForegroundColor Cyan
Write-Host ''
Write-Host '--- Windows Dependencies ---' -ForegroundColor Yellow
$winScript = Join-Path $ScriptDir 'plugins\windows-reverse-engineering\skills\windows-reverse-engineering\scripts\check-deps.ps1'
if (Test-Path $winScript) {
& powershell -ExecutionPolicy Bypass -File $winScript
} else {
Write-Host ('Windows check-deps.ps1 not found at: ' + $winScript) -ForegroundColor Red
}
Write-Host ''
Write-Host '--- Android Dependencies ---' -ForegroundColor Yellow
$androidScript = Join-Path $ScriptDir 'plugins\android-reverse-engineering\skills\android-reverse-engineering\scripts\check-deps.sh'
if (Test-Path $androidScript) {
$bashCmd = Get-Command bash -ErrorAction SilentlyContinue
if ($bashCmd) {
& bash $androidScript
} else {
Write-Host 'bash not found. Android dependency check requires WSL or Git Bash.' -ForegroundColor Yellow
}
} else {
Write-Host ('Android check-deps.sh not found at: ' + $androidScript) -ForegroundColor Red
}
exit 0
}
# --- Interactive mode ---
if (-not $Agent) {
Write-Host '+------------------------------------------------------+' -ForegroundColor Cyan
Write-Host '| Reverse Engineering Skills - Universal Installer |' -ForegroundColor Cyan
Write-Host '+------------------------------------------------------+' -ForegroundColor Cyan
Write-Host ''
Write-Host 'Which AI coding agent do you use?' -ForegroundColor Yellow
Write-Host ''
$i = 1
$agentKeys = @($Agents.Keys)
foreach ($key in $agentKeys) {
Write-Host (' [{0}] {1,-12} ({2})' -f $i, $key, $Agents[$key].Name)
$i++
}
Write-Host (' [{0}] all (Install for all agents)' -f $i)
Write-Host ''
$choice = Read-Host 'Enter number or agent name'
if ($choice -match '^\d+$') {
$idx = [int]$choice - 1
if ($idx -ge 0 -and $idx -lt $agentKeys.Count) {
$Agent = $agentKeys[$idx]
} elseif ($idx -eq $agentKeys.Count) {
$Agent = 'all'
} else {
Write-Host 'Invalid choice.' -ForegroundColor Red
exit 1
}
} else {
$Agent = $choice.ToLower().Trim()
}
}
# --- Target directory ---
if (-not $Target) {
$Target = Get-Location
}
if (-not (Test-Path $Target)) {
New-Item -ItemType Directory -Path $Target -Force | Out-Null
}
$Target = (Resolve-Path $Target).Path
# --- Determine which agents to install ---
if ($Agent -eq 'all') {
$installAgents = @($Agents.Keys)
} else {
if (-not $Agents.ContainsKey($Agent)) {
Write-Host ('Unknown agent: ' + $Agent) -ForegroundColor Red
Write-Host 'Run: .\install.ps1 -List' -ForegroundColor Yellow
exit 1
}
$installAgents = @($Agent)
}
Write-Host ''
Write-Host '=== Installing Reverse Engineering Skills ===' -ForegroundColor Cyan
Write-Host ('Target: ' + $Target) -ForegroundColor DarkGray
Write-Host ('Agents: ' + ($installAgents -join ', ')) -ForegroundColor DarkGray
Write-Host ''
# --- Copy helper ---
function Copy-SkillFile {
param([string]$RelPath, [string]$SourceBase, [string]$DestBase)
$src = Join-Path $SourceBase $RelPath
$dst = Join-Path $DestBase $RelPath
if (-not (Test-Path $src)) {
Write-Host (' [SKIP] ' + $RelPath + ' (source not found)') -ForegroundColor Yellow
return $false
}
$dstDir = Split-Path $dst -Parent
if (-not (Test-Path $dstDir)) {
New-Item -ItemType Directory -Path $dstDir -Force | Out-Null
}
if (Test-Path $src -PathType Container) {
Copy-Item -Path $src -Destination $dst -Recurse -Force
Write-Host (' [DIR] ' + $RelPath) -ForegroundColor Green
} else {
Copy-Item -Path $src -Destination $dst -Force
Write-Host (' [FILE] ' + $RelPath) -ForegroundColor Green
}
return $true
}
# --- Always copy the plugins directory (core scripts + references) ---
$isLocal = ($Target -eq (Resolve-Path $ScriptDir).Path)
if (-not $isLocal) {
Write-Host 'Copying core plugins...' -ForegroundColor Yellow
Copy-SkillFile 'plugins' $ScriptDir $Target | Out-Null
}
# --- Install per-agent files ---
$copiedAgents = @()
$copiedFiles = @()
foreach ($agentKey in $installAgents) {
$agentInfo = $Agents[$agentKey]
Write-Host ''
Write-Host ('Installing for ' + $agentInfo.Name + '...') -ForegroundColor Yellow
foreach ($filePath in $agentInfo.Files) {
if ($filePath.EndsWith('/')) {
$dirPath = $filePath.TrimEnd('/')
$src = Join-Path $ScriptDir $dirPath
if (Test-Path $src) {
Copy-SkillFile $dirPath $ScriptDir $Target | Out-Null
$copiedFiles += $dirPath
} else {
Write-Host (' [SKIP] ' + $dirPath + ' (not found in source)') -ForegroundColor Yellow
}
} else {
$src = Join-Path $ScriptDir $filePath
if (Test-Path $src) {
if ($filePath -notin $copiedFiles) {
Copy-SkillFile $filePath $ScriptDir $Target | Out-Null
$copiedFiles += $filePath
} else {
Write-Host (' [SKIP] ' + $filePath + ' (already copied)') -ForegroundColor DarkGray
}
} else {
Write-Host (' [SKIP] ' + $filePath + ' (not found in source)') -ForegroundColor Yellow
}
}
}
$copiedAgents += $agentInfo.Name
}
# --- Summary ---
Write-Host ''
Write-Host '=== Installation Complete ===' -ForegroundColor Green
Write-Host ''
Write-Host ('Installed for: ' + ($copiedAgents -join ', ')) -ForegroundColor Cyan
Write-Host ('Location: ' + $Target) -ForegroundColor Cyan
Write-Host ''
# --- Next steps ---
Write-Host 'Next steps:' -ForegroundColor Yellow
Write-Host ''
if ('codex' -in $installAgents -or 'opencode' -in $installAgents -or 'all' -eq $Agent) {
Write-Host ' Codex/OpenCode: AGENTS.md is automatically detected. Just start your agent.' -ForegroundColor DarkGray
}
if ('cursor' -in $installAgents -or 'all' -eq $Agent) {
Write-Host ' Cursor: Rules in .cursor/rules/ are auto-loaded. Open the project in Cursor.' -ForegroundColor DarkGray
}
if ('copilot' -in $installAgents -or 'all' -eq $Agent) {
Write-Host ' Copilot: Instructions in .github/ are auto-loaded in VS Code/GitHub.' -ForegroundColor DarkGray
}
if ('cline' -in $installAgents -or 'all' -eq $Agent) {
Write-Host ' Cline: Rules in .clinerules/ are auto-loaded. Open project in VS Code with Cline.' -ForegroundColor DarkGray
}
if ('windsurf' -in $installAgents -or 'all' -eq $Agent) {
Write-Host ' Windsurf: Rules in .windsurf/rules/ are auto-loaded. Open project in Windsurf.' -ForegroundColor DarkGray
}
if ('roo' -in $installAgents -or 'all' -eq $Agent) {
Write-Host ' Roo Code: Rules in .roo/rules/ are auto-loaded. Open project in VS Code with Roo.' -ForegroundColor DarkGray
}
if ('aider' -in $installAgents -or 'all' -eq $Agent) {
Write-Host ' Aider: .aider.conf.yml auto-loads AGENTS.md. Just run aider in the project.' -ForegroundColor DarkGray
}
if ('claude' -in $installAgents -or 'all' -eq $Agent) {
Write-Host ' Claude Code: Plugin is auto-detected from .claude-plugin/. Just open the project.' -ForegroundColor DarkGray
}
Write-Host ''
Write-Host 'Run dependency check:' -ForegroundColor Yellow
Write-Host ' .\install.ps1 -CheckDeps' -ForegroundColor White
Write-Host ''

282
install.sh Normal file
View File

@ -0,0 +1,282 @@
#!/usr/bin/env bash
# install.sh — Universal installer for reverse engineering skills
# Installs agent-specific instruction files for any supported AI coding agent.
#
# Usage:
# ./install.sh # Interactive mode
# ./install.sh --agent cursor # Install for Cursor
# ./install.sh --agent all # Install for all agents
# ./install.sh --agent copilot --target ~/my-project
# ./install.sh --list # List available agents
# ./install.sh --check-deps # Run dependency check only
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
AGENT=""
TARGET=""
LIST=false
CHECK_DEPS=false
# --- Parse arguments ---
while [[ $# -gt 0 ]]; do
case "$1" in
--agent|-a) AGENT="${2,,}"; shift 2 ;;
--target|-t) TARGET="$2"; shift 2 ;;
--list|-l) LIST=true; shift ;;
--check-deps) CHECK_DEPS=true; shift ;;
--help|-h)
cat <<'EOF'
Reverse Engineering Skills — Universal Installer
Usage:
./install.sh Interactive mode (choose agent)
./install.sh --agent <agent> Install for a specific agent
./install.sh --agent all Install for all agents
./install.sh --agent <agent> --target <dir> Install into another project
./install.sh --list List supported agents
./install.sh --check-deps Run dependency check only
Agents:
claude — Claude Code (.claude-plugin/)
codex — OpenAI Codex (AGENTS.md)
opencode — OpenCode (AGENTS.md)
cursor — Cursor IDE (.cursor/rules/*.mdc)
copilot — GitHub Copilot (.github/instructions/)
cline — Cline (.clinerules/)
windsurf — Windsurf (.windsurf/rules/)
roo — Roo Code (.roo/rules/)
aider — Aider (.aider.conf.yml)
all — Install for all agents at once
EOF
exit 0
;;
*)
echo "Unknown option: $1"
echo "Run: ./install.sh --help"
exit 1
;;
esac
done
VALID_AGENTS=(claude codex opencode cursor copilot cline windsurf roo aider)
# --- List ---
if $LIST; then
echo "Supported AI Coding Agents:"
echo ""
echo " claude Claude Code -> .claude-plugin/"
echo " codex OpenAI Codex -> AGENTS.md"
echo " opencode OpenCode -> AGENTS.md"
echo " cursor Cursor IDE -> .cursor/rules/*.mdc"
echo " copilot GitHub Copilot -> .github/instructions/"
echo " cline Cline -> .clinerules/"
echo " windsurf Windsurf -> .windsurf/rules/"
echo " roo Roo Code -> .roo/rules/"
echo " aider Aider -> .aider.conf.yml + AGENTS.md"
echo ""
echo " all All agents -> installs everything"
echo ""
echo "Usage: ./install.sh --agent <agent>"
exit 0
fi
# --- Check deps ---
if $CHECK_DEPS; then
echo "=== Running Dependency Checks ==="
echo ""
echo "--- Windows Dependencies ---"
WIN_SCRIPT="$SCRIPT_DIR/plugins/windows-reverse-engineering/skills/windows-reverse-engineering/scripts/check-deps.ps1"
if command -v powershell &>/dev/null && [ -f "$WIN_SCRIPT" ]; then
powershell -ExecutionPolicy Bypass -File "$WIN_SCRIPT" || true
elif command -v pwsh &>/dev/null && [ -f "$WIN_SCRIPT" ]; then
pwsh -ExecutionPolicy Bypass -File "$WIN_SCRIPT" || true
else
echo "PowerShell not available. Skipping Windows dependency check."
fi
echo ""
echo "--- Android Dependencies ---"
ANDROID_SCRIPT="$SCRIPT_DIR/plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/check-deps.sh"
if [ -f "$ANDROID_SCRIPT" ]; then
bash "$ANDROID_SCRIPT" || true
else
echo "Android check-deps.sh not found."
fi
exit 0
fi
# --- Interactive mode ---
if [ -z "$AGENT" ]; then
echo "╔══════════════════════════════════════════════════════╗"
echo "║ Reverse Engineering Skills — Universal Installer ║"
echo "╚══════════════════════════════════════════════════════╝"
echo ""
echo "Which AI coding agent do you use?"
echo ""
for i in "${!VALID_AGENTS[@]}"; do
printf " [%d] %s\n" $((i+1)) "${VALID_AGENTS[$i]}"
done
printf " [%d] all (install for all agents)\n" $(( ${#VALID_AGENTS[@]} + 1 ))
echo ""
read -rp "Enter number or agent name: " CHOICE
if [[ "$CHOICE" =~ ^[0-9]+$ ]]; then
IDX=$((CHOICE - 1))
if [ "$IDX" -ge 0 ] && [ "$IDX" -lt "${#VALID_AGENTS[@]}" ]; then
AGENT="${VALID_AGENTS[$IDX]}"
elif [ "$IDX" -eq "${#VALID_AGENTS[@]}" ]; then
AGENT="all"
else
echo "Invalid choice."
exit 1
fi
else
AGENT="${CHOICE,,}"
fi
fi
# --- Validate agent ---
if [ "$AGENT" != "all" ]; then
FOUND=false
for a in "${VALID_AGENTS[@]}"; do
if [ "$a" = "$AGENT" ]; then
FOUND=true
break
fi
done
if ! $FOUND; then
echo "Unknown agent: $AGENT"
echo "Run: ./install.sh --list"
exit 1
fi
fi
# --- Target directory ---
if [ -z "$TARGET" ]; then
TARGET="$(pwd)"
fi
mkdir -p "$TARGET"
TARGET="$(cd "$TARGET" && pwd)"
# --- Determine agents to install ---
if [ "$AGENT" = "all" ]; then
INSTALL_AGENTS=("${VALID_AGENTS[@]}")
else
INSTALL_AGENTS=("$AGENT")
fi
echo ""
echo "=== Installing Reverse Engineering Skills ==="
echo "Target: $TARGET"
echo "Agents: ${INSTALL_AGENTS[*]}"
echo ""
# --- Copy helper ---
copy_skill() {
local rel_path="$1"
local src="$SCRIPT_DIR/$rel_path"
local dst="$TARGET/$rel_path"
if [ ! -e "$src" ]; then
echo " [SKIP] $rel_path (source not found)"
return 1
fi
mkdir -p "$(dirname "$dst")"
if [ -d "$src" ]; then
cp -r "$src" "$(dirname "$dst")/"
echo " [DIR] $rel_path"
else
cp "$src" "$dst"
echo " [FILE] $rel_path"
fi
return 0
}
# --- Copy core plugins if installing to a different directory ---
IS_LOCAL=false
if [ "$TARGET" = "$SCRIPT_DIR" ]; then
IS_LOCAL=true
fi
if ! $IS_LOCAL; then
echo "Copying core plugins..."
copy_skill "plugins" || true
fi
# --- Agent file map ---
COPIED_FILES=()
install_agent() {
local agent_key="$1"
case "$agent_key" in
claude)
echo ""
echo "Installing for Claude Code..."
copy_skill ".claude-plugin" || true
;;
codex|opencode)
echo ""
echo "Installing for $([ "$agent_key" = "codex" ] && echo "OpenAI Codex" || echo "OpenCode")..."
if [[ ! " ${COPIED_FILES[*]:-} " =~ " AGENTS.md " ]]; then
copy_skill "AGENTS.md" || true
COPIED_FILES+=("AGENTS.md")
else
echo " [SKIP] AGENTS.md (already copied)"
fi
;;
cursor)
echo ""
echo "Installing for Cursor IDE..."
copy_skill ".cursor/rules" || true
;;
copilot)
echo ""
echo "Installing for GitHub Copilot..."
copy_skill ".github/copilot-instructions.md" || true
copy_skill ".github/instructions" || true
;;
cline)
echo ""
echo "Installing for Cline..."
copy_skill ".clinerules" || true
;;
windsurf)
echo ""
echo "Installing for Windsurf..."
copy_skill ".windsurf/rules" || true
;;
roo)
echo ""
echo "Installing for Roo Code..."
copy_skill ".roo/rules" || true
;;
aider)
echo ""
echo "Installing for Aider..."
copy_skill ".aider.conf.yml" || true
if [[ ! " ${COPIED_FILES[*]:-} " =~ " AGENTS.md " ]]; then
copy_skill "AGENTS.md" || true
COPIED_FILES+=("AGENTS.md")
fi
;;
esac
}
for agent_key in "${INSTALL_AGENTS[@]}"; do
install_agent "$agent_key"
done
# --- Summary ---
echo ""
echo "=== Installation Complete ==="
echo ""
echo "Installed for: ${INSTALL_AGENTS[*]}"
echo "Location: $TARGET"
echo ""
echo "Next steps:"
echo " Run dependency check: ./install.sh --check-deps"
echo ""

View File

@ -0,0 +1,13 @@
{
"name": "windows-reverse-engineering",
"version": "1.0.0",
"description": "Decompile Windows EXE/DLL/.NET assemblies with Ghidra and ILSpy, trace call flows, and document extracted Win32/network APIs.",
"author": {
"name": "Simone Avogadro"
},
"repository": "https://github.com/SimoneAvogadro/android-reverse-engineering-skill",
"license": "Apache-2.0",
"keywords": ["windows", "reverse-engineering", "exe", "dll", "ghidra", "ilspy", "decompile", "pe-analysis", "api-extraction"],
"skills": "./skills/",
"commands": "./commands/"
}

View File

@ -0,0 +1,100 @@
---
allowed-tools: Bash, Read, Glob, Grep, Write, Edit
description: Decompile a Windows EXE/DLL/.NET assembly and analyze its structure
user-invocable: true
argument-hint: <path to EXE, DLL, or .NET assembly>
argument: path to EXE, DLL, or .NET assembly file (optional)
---
# /decompile
Decompile a Windows application and perform initial structure analysis.
## Instructions
You are starting the Windows reverse engineering workflow. Follow these steps:
### Step 1: Get the target file
If the user provided a file path as an argument, use that. Otherwise, ask the user for the path to the EXE, DLL, or .NET assembly they want to decompile.
### Step 2: Check PowerShell execution policy
Before running any scripts, ensure PowerShell can execute `.ps1` files. Run:
```powershell
$policy = Get-ExecutionPolicy -Scope CurrentUser
if ($policy -eq 'Restricted' -or $policy -eq 'AllSigned') {
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force
Write-Host "Execution policy updated to RemoteSigned for current user."
}
```
If setting the execution policy fails (e.g., group policy override), fall back to running scripts with:
```powershell
powershell -ExecutionPolicy Bypass -File <script.ps1>
```
### Step 3: Check and install dependencies
Run the dependency check:
```powershell
powershell -ExecutionPolicy Bypass -File "${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/scripts/check-deps.ps1"
```
Parse the output looking for `INSTALL_REQUIRED:` and `INSTALL_OPTIONAL:` lines.
**If required dependencies are missing**, install them one by one:
```powershell
powershell -ExecutionPolicy Bypass -File "${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/scripts/install-dep.ps1" java
powershell -ExecutionPolicy Bypass -File "${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/scripts/install-dep.ps1" ghidra
powershell -ExecutionPolicy Bypass -File "${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/scripts/install-dep.ps1" ilspycmd
```
The install script uses winget, Chocolatey, dotnet tool, or direct GitHub download. If an installer requires admin privileges the user doesn't have, it prints manual instructions (exit code 2). Show those to the user and stop.
**For optional dependencies** (`INSTALL_OPTIONAL:dumpbin`, `INSTALL_OPTIONAL:strings`, etc.), ask the user if they want to install them. Recommend strings for embedded URL/key extraction.
> **Note**: `dumpbin` requires Visual Studio C++ Build Tools. Make the user aware of this requirement if they want to use it.
After any installations, re-run `check-deps.ps1` to verify. Do not proceed until all required dependencies pass.
### Step 4: Decompile
Run the decompile script on the target file:
```powershell
powershell -ExecutionPolicy Bypass -File "${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/scripts/decompile.ps1" <file>
```
The script auto-detects the binary type:
- **.NET assembly** (imports `mscoree.dll`, has CLI header) → decompiles with `ilspycmd` to C# source
- **Native PE** (C/C++ compiled EXE/DLL/SYS) → decompiles with Ghidra headless to C pseudocode
The user can override detection with `-Engine ghidra` or `-Engine ilspy`.
For packed/obfuscated binaries (if the user mentions it or you detect high-entropy sections), note this and suggest manual unpacking before decompilation.
### Step 5: Analyze structure
After decompilation completes:
1. Review the PE header summary from the decompile output (architecture, subsystem, entry point)
2. Review the import table — which DLLs and functions does the binary use?
3. Review the export table (for DLLs) — what does the binary expose?
4. List the top-level source structure (packages/namespaces for .NET, function groups for native)
5. Identify the app's entry point and architecture pattern
6. Report a summary to the user
### Step 6: Offer next steps
Tell the user what they can do next:
- **Trace call flows**: "I can follow the execution flow from the entry point to network/API calls"
- **Extract APIs**: "I can search for all Win32 API calls, network endpoints, registry operations, and hardcoded secrets"
- **Analyze specific functions**: "Point me to a specific function or class to analyze in detail"
- **Re-decompile with a different engine**: If auto-detection chose the wrong engine, offer to re-run
Refer to the full skill documentation in `${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/SKILL.md` for the complete workflow.

View File

@ -0,0 +1,300 @@
---
description: Decompile Windows EXE, DLL, and .NET assemblies using Ghidra or ILSpy. Reverse engineer Windows apps, extract Win32 API calls, network endpoints, registry operations, and trace call flows from entry points to network layer. Use when the user wants to decompile, analyze, or reverse engineer Windows binaries, find API endpoints, or follow call flows.
trigger: decompile EXE|decompile DLL|reverse engineer Windows|extract API|analyze Windows|ghidra|ilspy|follow call flow|decompile .NET|Windows reverse engineering|find API endpoints|PE analysis|Win32 API
---
# Windows Reverse Engineering
Decompile Windows EXE, DLL, SYS, and .NET assemblies using Ghidra (headless) and ILSpy (ilspycmd), trace call flows through application code, and produce structured documentation of extracted APIs — Win32 calls, network endpoints, registry operations, cryptographic usage, and more.
Two decompiler engines are supported:
- **Ghidra** — for native C/C++ PE binaries (produces C pseudocode)
- **ILSpy (ilspycmd)** — for .NET assemblies (produces C# source)
The skill auto-detects the binary type and selects the appropriate engine.
## Prerequisites
This skill requires the following to be installed:
**Required (at least one decompiler):**
- **Java JDK 17+** — needed by Ghidra
- **Ghidra** — for native PE decompilation (set `GHIDRA_INSTALL_DIR` environment variable)
- **ilspycmd** — for .NET assembly decompilation (install via `dotnet tool install -g ilspycmd`)
**Optional (recommended):**
- **strings / strings2** — extract embedded strings from binaries
- **dumpbin** — PE header and import/export analysis (requires Visual Studio C++ Build Tools)
- **de4dot** — .NET deobfuscator for obfuscated assemblies
- **x64dbg** — dynamic debugging (manual use)
Run the dependency checker to verify:
```powershell
powershell -ExecutionPolicy Bypass -File "${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/scripts/check-deps.ps1"
```
If anything is missing, follow the installation instructions in `${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/references/setup-guide.md`.
## PowerShell Execution Policy
All scripts in this skill are PowerShell `.ps1` files. If the system execution policy blocks script execution, automatically adjust it:
```powershell
# Check current policy
$policy = Get-ExecutionPolicy -Scope CurrentUser
# Auto-fix if restricted
if ($policy -eq 'Restricted' -or $policy -eq 'AllSigned') {
try {
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force
} catch {
# Group policy may prevent changes — use Bypass flag per invocation
# Run all scripts as: powershell -ExecutionPolicy Bypass -File <script.ps1>
}
}
```
If `Set-ExecutionPolicy` fails due to group policy, run all scripts with:
```powershell
powershell -ExecutionPolicy Bypass -File <script.ps1> [args]
```
## Workflow
### Phase 1: Verify and Install Dependencies
Before decompiling, confirm that the required tools are available — and install any that are missing.
**Action**: Run the dependency check script.
```powershell
powershell -ExecutionPolicy Bypass -File "${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/scripts/check-deps.ps1"
```
The output contains machine-readable lines:
- `INSTALL_REQUIRED:<dep>` — must be installed before proceeding
- `INSTALL_OPTIONAL:<dep>` — recommended but not blocking
**If required dependencies are missing** (exit code 1), install them automatically:
```powershell
powershell -ExecutionPolicy Bypass -File "${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/scripts/install-dep.ps1" <dep>
```
The install script detects available package managers (winget, Chocolatey, dotnet), then:
- Installs without admin when possible (user-local installs, dotnet global tools)
- Uses winget or Chocolatey when available
- If admin is needed but unavailable, it prints the exact manual command and exits with code 2 — show these instructions to the user
**For optional dependencies**, ask the user if they want to install them.
> **Important**: `dumpbin` requires **Visual Studio C++ Build Tools** to be installed. If the user wants PE import/export analysis via dumpbin, they must install the Build Tools from https://visualstudio.microsoft.com/visual-cpp-build-tools/. Alternatively, Ghidra can extract the same information.
After installation, re-run `check-deps.ps1` to confirm everything is in place. Do not proceed to Phase 2 until at least one decompiler (Ghidra or ilspycmd) is available.
### Phase 2: Detect and Decompile
Use the decompile wrapper script to process the target file. The script auto-detects the binary type and selects the appropriate engine.
**Action**: Run the decompile script.
```powershell
powershell -ExecutionPolicy Bypass -File "${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/scripts/decompile.ps1" [OPTIONS] <file>
```
Options:
- `-Output <dir>` — Custom output directory (default: `<filename>-decompiled`)
- `-Engine auto|ghidra|ilspy` — Decompiler engine (default: `auto`)
- `-NoStrings` — Skip strings extraction (faster)
**Auto-detection logic**:
| Binary Type | Detection | Engine |
|---|---|---|
| .NET assembly (C#/VB.NET/F#) | Imports `mscoree.dll`, has CLI header | `ilspy` |
| Native C/C++ EXE/DLL | Standard PE without .NET metadata | `ghidra` |
| Kernel driver (.sys) | PE with `native` subsystem | `ghidra` |
| Packed/obfuscated | High-entropy `.text` section | Warn user, attempt `ghidra` |
**Engine selection strategy**:
| Situation | Engine |
|---|---|
| .NET assembly (any) | `ilspy` — produces clean C# source |
| Native EXE/DLL | `ghidra` — produces C pseudocode |
| .NET but obfuscated (Dotfuscator, ConfuserEx) | Run `de4dot` first, then `ilspy` |
| Quick overview of imports only | Skip decompilation, use `dumpbin /imports` |
| Mixed-mode .NET (native + managed) | `ghidra` for native, `ilspy` for managed |
**ILSpy output**:
- `<output>/sources/` — Decompiled C# source files with project structure
- `<output>/sources/*.csproj` — Reconstructed project file
**Ghidra output**:
- `<output>/decompiled/` — C pseudocode files per function
- `<output>/imports.txt` — Import table listing
- `<output>/exports.txt` — Export table listing (DLLs)
- `<output>/strings.txt` — Extracted string references
See `${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/references/ghidra-headless-usage.md` and `${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/references/ilspy-usage.md` for the full CLI references.
### Phase 3: Analyze Structure
Navigate the decompiled output to understand the application's architecture.
**Actions**:
1. **Review PE headers** from the decompile output or run separately:
- Architecture: x86, x64, ARM64
- Subsystem: console, GUI, driver, native
- Entry point address
- Compile timestamp
- Check for ASLR, DEP, code signing
2. **Survey the import table** — this is the single most revealing artifact:
- `kernel32.dll` — file I/O, process management, memory
- `user32.dll` — GUI, window messages, clipboard
- `advapi32.dll` — registry, services, security
- `ws2_32.dll` / `winhttp.dll` / `wininet.dll` — networking
- `crypt32.dll` / `bcrypt.dll` — cryptography
- `ole32.dll` / `oleaut32.dll` — COM/OLE
- `mscoree.dll` — .NET runtime
- Unusual DLLs may indicate specific libraries or custom functionality
3. **Survey the export table** (for DLLs):
- What functions does this DLL expose?
- Are exports named or ordinal-only (indicates possible evasion)?
4. **For .NET assemblies**, examine:
- Namespace structure under `<output>/sources/`
- Referenced assemblies (NuGet packages used)
- Look for namespaces containing `Api`, `Http`, `Client`, `Service`, `Data`, `Repository`
- Identify the DI container setup (Startup.cs, Program.cs)
5. **For native binaries**, examine:
- Top-level function list from Ghidra output
- Group functions by calling convention and purpose
- Identify the main entry point and initialization routines
- Look for C++ class structures (vtables, RTTI)
6. **Identify the architecture pattern**:
- **WinForms/WPF**: look for `Form`, `Window`, `UserControl` classes
- **ASP.NET**: look for `Controller`, `Startup`, `Program` classes
- **Windows Service**: look for `ServiceBase`, `OnStart`, `OnStop`
- **Native GUI**: look for `CreateWindowEx`, `RegisterClassEx`, `WndProc`
- **Console**: look for `Main` with argument parsing
### Phase 4: Trace Call Flows
Follow execution paths from entry points down to API calls.
**Actions**:
1. **Start from entry points**:
- **Native**: `WinMain`, `wWinMain`, `main`, `DllMain`, `ServiceMain`, `DriverEntry`
- **.NET**: `static void Main()`, `Program.cs`, `Startup.cs`
2. **Follow the initialization chain**:
- Native: global constructors → `WinMain` → window creation → message loop
- .NET: `Main()``HostBuilder` → dependency injection → `Startup.ConfigureServices()`
3. **Trace user actions**:
- **Native GUI**: `WndProc``WM_COMMAND` handler → business logic → API calls
- **WinForms**: button click event → method → service call → HTTP request
- **.NET Web**: HTTP request → Controller → Service → Repository → external API
4. **Map dependency injection** (.NET):
- Find `AddScoped`, `AddSingleton`, `AddTransient` registrations
- Trace interface → implementation bindings
- Follow `IHttpClientFactory` registrations for named HTTP clients
5. **Handle obfuscated code**:
- **Native**: stripped symbols — use import calls and string refs as anchors
- **.NET obfuscated**: run `de4dot` first, then string literals and framework types remain readable
- **Packed**: detect UPX or custom packers — suggest dynamic analysis or manual unpacking
See `${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/references/call-flow-analysis.md` for detailed techniques.
### Phase 5: Extract and Document APIs
Find all API calls and produce structured documentation.
**Action**: Run the API search script for a broad sweep.
```powershell
powershell -ExecutionPolicy Bypass -File "${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/scripts/find-api-calls.ps1" <output>/sources/
```
Targeted searches:
```powershell
# Only network calls
powershell -ExecutionPolicy Bypass -File "..." <output>/sources/ --network
# Only registry operations
powershell -ExecutionPolicy Bypass -File "..." <output>/sources/ --registry
# Only hardcoded URLs and secrets
powershell -ExecutionPolicy Bypass -File "..." <output>/sources/ --urls
# Only authentication patterns
powershell -ExecutionPolicy Bypass -File "..." <output>/sources/ --auth
# Only process manipulation (injection indicators)
powershell -ExecutionPolicy Bypass -File "..." <output>/sources/ --process
```
Then, for each discovered API call, read the surrounding source code to extract:
- API function name and DLL
- Parameters and their values/sources
- Return value handling
- Where it's called from (the call chain from Phase 4)
- Purpose in the application's workflow
**Document each API interaction** using this format:
```markdown
### `FunctionName` (source DLL)
- **Source**: `filename.c:42` or `Namespace.ClassName` (ClassName.cs:42)
- **Category**: Network / Registry / File I/O / Process / Crypto / COM
- **Parameters**:
- `param1`: value or source
- `param2`: value or source
- **Return handling**: checked / ignored / stored in `variable`
- **Called from**: `Main → InitNetwork → HttpClient → WinHttpSendRequest`
- **Purpose**: Sends user credentials to remote server
```
For network endpoints specifically:
```markdown
### `POST https://api.example.com/v1/auth/login`
- **Source**: `NetworkManager.cs:87`
- **Method**: POST (via HttpClient)
- **Headers**: `Authorization: Bearer <token>`, `Content-Type: application/json`
- **Request body**: `{ "username": "string", "password": "string" }`
- **Response type**: `LoginResponse { token: string, userId: int }`
- **Called from**: `LoginForm.btnLogin_Click → AuthService.Login → HttpClient.PostAsync`
```
See `${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/references/api-extraction-patterns.md` for Windows-specific search patterns and the full documentation template.
## Output
At the end of the workflow, deliver:
1. **Decompiled source** in the output directory (C pseudocode or C# source)
2. **PE analysis summary** — architecture, imports, exports, sections, security features
3. **Architecture summary** — app structure, main namespaces/modules, pattern used
4. **API documentation** — all discovered Win32/network/registry/crypto calls in the format above
5. **Call flow map** — key paths from entry point to interesting API calls (especially networking and persistence)
## References
- `${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/references/setup-guide.md` — Installing Java, Ghidra, ILSpy, strings, and optional tools on Windows
- `${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/references/ghidra-headless-usage.md` — Ghidra headless CLI and scripting reference
- `${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/references/ilspy-usage.md` — ilspycmd CLI options and .NET decompilation workflows
- `${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/references/api-extraction-patterns.md` — Windows-specific search patterns and documentation template
- `${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/references/call-flow-analysis.md` — Techniques for tracing call flows in Windows binaries

View File

@ -0,0 +1,228 @@
# API Extraction Patterns
Patterns and Select-String commands for finding API calls, network endpoints, and secrets in decompiled Windows source code. Works on both Ghidra C pseudocode output and ILSpy C# output.
## Network — Win32 API (Native)
### WinHTTP
```powershell
# WinHTTP functions
Select-String -Path "sources\*" -Pattern 'WinHttpOpen|WinHttpConnect|WinHttpOpenRequest|WinHttpSendRequest|WinHttpReceiveResponse|WinHttpReadData|WinHttpSetOption' -Recurse
# WinHTTP URL construction
Select-String -Path "sources\*" -Pattern 'WinHttpCrackUrl|WinHttpCreateUrl' -Recurse
```
### WinINet
```powershell
# WinINet functions
Select-String -Path "sources\*" -Pattern 'InternetOpen|InternetConnect|HttpOpenRequest|HttpSendRequest|InternetReadFile|InternetCloseHandle|InternetSetOption' -Recurse
# FTP via WinINet
Select-String -Path "sources\*" -Pattern 'FtpOpenFile|FtpGetFile|FtpPutFile|FtpFindFirstFile' -Recurse
```
### Winsock
```powershell
# Socket operations
Select-String -Path "sources\*" -Pattern 'WSAStartup|socket\(|connect\(|send\(|recv\(|bind\(|listen\(|accept\(|closesocket|getaddrinfo|gethostbyname' -Recurse
# Higher-level winsock
Select-String -Path "sources\*" -Pattern 'WSASocket|WSASend|WSARecv|WSAConnect|WSAAsyncSelect' -Recurse
```
## Network — .NET
### HttpClient (modern)
```powershell
# HttpClient usage
Select-String -Path "sources\*" -Pattern 'HttpClient|GetAsync|PostAsync|PutAsync|DeleteAsync|SendAsync|GetStringAsync|GetStreamAsync' -Recurse
# HttpClientFactory
Select-String -Path "sources\*" -Pattern 'IHttpClientFactory|AddHttpClient|CreateClient' -Recurse
# Request construction
Select-String -Path "sources\*" -Pattern 'HttpRequestMessage|StringContent|JsonContent|FormUrlEncodedContent|MultipartFormDataContent' -Recurse
```
### WebRequest (legacy)
```powershell
Select-String -Path "sources\*" -Pattern 'WebRequest|HttpWebRequest|WebClient|DownloadString|DownloadFile|UploadString|UploadFile' -Recurse
```
### RestSharp / Refit
```powershell
Select-String -Path "sources\*" -Pattern 'RestClient|RestRequest|RestResponse|IRestClient' -Recurse
Select-String -Path "sources\*" -Pattern '\[Get\(|Post\(|Put\(|Delete\(|Patch\(' -Recurse
```
## Registry Operations
### Native
```powershell
Select-String -Path "sources\*" -Pattern 'RegOpenKey|RegCreateKey|RegSetValue|RegQueryValue|RegDeleteKey|RegDeleteValue|RegEnumKey|RegEnumValue|RegCloseKey|RegNotifyChangeKeyValue' -Recurse
```
### .NET
```powershell
Select-String -Path "sources\*" -Pattern 'Microsoft\.Win32\.Registry|RegistryKey|OpenSubKey|SetValue|GetValue|CreateSubKey|DeleteSubKey' -Recurse
```
## File System Operations
### Native
```powershell
Select-String -Path "sources\*" -Pattern 'CreateFile[AW]?|ReadFile|WriteFile|DeleteFile[AW]?|CopyFile[AW]?|MoveFile[AW]?|FindFirstFile[AW]?|FindNextFile[AW]?|GetFileAttributes|SetFileAttributes|CreateDirectory[AW]?' -Recurse
```
### .NET
```powershell
Select-String -Path "sources\*" -Pattern 'File\.(Read|Write|Append|Copy|Move|Delete|Exists|Open|Create)|Directory\.(Create|Delete|Exists|GetFiles|GetDirectories)|FileStream|StreamReader|StreamWriter|BinaryReader|BinaryWriter' -Recurse
```
## Process and Thread Manipulation
```powershell
# Process creation
Select-String -Path "sources\*" -Pattern 'CreateProcess[AW]?|ShellExecute[AW]?|WinExec|system\(' -Recurse
# Process injection indicators
Select-String -Path "sources\*" -Pattern 'VirtualAlloc|VirtualAllocEx|VirtualProtect|WriteProcessMemory|ReadProcessMemory|CreateRemoteThread|NtCreateThreadEx|QueueUserAPC|SetThreadContext' -Recurse
# DLL injection
Select-String -Path "sources\*" -Pattern 'LoadLibrary[AW]?|GetProcAddress|FreeLibrary|GetModuleHandle[AW]?' -Recurse
# .NET process
Select-String -Path "sources\*" -Pattern 'Process\.Start|ProcessStartInfo|Process\.GetProcesses' -Recurse
```
## Cryptography
### Native (CryptoAPI / BCrypt)
```powershell
Select-String -Path "sources\*" -Pattern 'CryptAcquireContext|CryptEncrypt|CryptDecrypt|CryptHashData|CryptDeriveKey|CryptGenKey|CryptImportKey|CryptExportKey|CryptGenRandom' -Recurse
Select-String -Path "sources\*" -Pattern 'BCryptOpenAlgorithmProvider|BCryptEncrypt|BCryptDecrypt|BCryptGenerateSymmetricKey|BCryptHash|BCryptCreateHash|BCryptFinishHash' -Recurse
```
### .NET
```powershell
Select-String -Path "sources\*" -Pattern 'System\.Security\.Cryptography|Aes\.|RSA\.|SHA256|SHA512|MD5|HMAC|RijndaelManaged|AesManaged|RSACryptoServiceProvider|X509Certificate' -Recurse
```
## COM and WMI
```powershell
# COM
Select-String -Path "sources\*" -Pattern 'CoCreateInstance|CoInitialize|CoUninitialize|IDispatch|IUnknown|CLSIDFromProgID|ProgIDFromCLSID' -Recurse
# WMI (native)
Select-String -Path "sources\*" -Pattern 'IWbemLocator|IWbemServices|ConnectServer|ExecQuery' -Recurse
# WMI (.NET)
Select-String -Path "sources\*" -Pattern 'ManagementObjectSearcher|ManagementObject|ManagementScope|ObjectQuery|WqlObjectQuery|SelectQuery' -Recurse
```
## Windows Services
```powershell
# Native
Select-String -Path "sources\*" -Pattern 'OpenSCManager|CreateService[AW]?|OpenService[AW]?|StartService|ControlService|DeleteService|ChangeServiceConfig|QueryServiceStatus|RegisterServiceCtrlHandler' -Recurse
# .NET
Select-String -Path "sources\*" -Pattern 'ServiceBase|ServiceController|ServiceInstaller|ServiceProcessInstaller|OnStart|OnStop|ServiceName' -Recurse
```
## Persistence Mechanisms
```powershell
# Run keys
Select-String -Path "sources\*" -Pattern 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run|SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce' -Recurse
# Scheduled tasks
Select-String -Path "sources\*" -Pattern 'schtasks|ITaskService|ITaskDefinition|TaskScheduler|ScheduledTask' -Recurse
# Startup folder
Select-String -Path "sources\*" -Pattern 'Startup|shell:startup|Programs\\Startup' -Recurse
# Windows service registration
Select-String -Path "sources\*" -Pattern 'CreateService|sc\.exe|New-Service|Install-Service' -Recurse
```
## Hardcoded URLs, IPs, and Secrets
```powershell
# HTTP/HTTPS URLs
Select-String -Path "sources\*" -Pattern '"https?://[^"]+' -Recurse
# IP addresses
Select-String -Path "sources\*" -Pattern '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b' -Recurse
# API keys and tokens
Select-String -Path "sources\*" -Pattern 'api[_\-]?key|api[_\-]?secret|auth[_\-]?token|bearer|access[_\-]?token|client[_\-]?secret|app[_\-]?secret' -CaseSensitive:$false -Recurse
# Base URL constants
Select-String -Path "sources\*" -Pattern 'BASE_URL|API_URL|SERVER_URL|ENDPOINT|API_BASE|HOST_NAME|ServiceUrl|BaseAddress' -CaseSensitive:$false -Recurse
# Connection strings
Select-String -Path "sources\*" -Pattern 'Data Source=|Server=|Initial Catalog=|connectionString|ConnectionStrings' -Recurse
# Passwords
Select-String -Path "sources\*" -Pattern 'password|passwd|pwd|credential' -CaseSensitive:$false -Recurse
```
## Documentation Template
For each discovered API call, document it using this template:
### Win32 API Template
```markdown
### `FunctionName` (DLL: source.dll)
- **Source**: `filename.c:42` or `Namespace.ClassName` (file:line)
- **Category**: Network / Registry / File I/O / Process / Crypto / COM / Service
- **Parameters**:
- `param1`: value or source description
- `param2`: value or source description
- **Return handling**: checked / ignored / stored in `variable`
- **Called from**: `Main → InitNetwork → SendData → WinHttpSendRequest`
- **Purpose**: Brief description of what this call accomplishes
```
### Network Endpoint Template
```markdown
### `METHOD https://api.example.com/v1/endpoint`
- **Source**: `NetworkManager.cs:87` or `sub_401234.c:15`
- **Method**: GET / POST / PUT / DELETE
- **Transport**: HttpClient / WinHTTP / WinINet / Winsock
- **Headers**:
- `Authorization: Bearer <token>`
- `Content-Type: application/json`
- **Request body**: `{ "username": "string", "password": "string" }`
- **Response handling**: parsed as JSON / written to file / displayed in UI
- **Called from**: `LoginForm.btnLogin_Click → AuthService.Login → HttpClient.PostAsync`
```
## Search Strategy
1. Start with **import table analysis** — see what DLLs the binary imports (ws2_32.dll = networking, advapi32.dll = registry/services, etc.)
2. Search for **hardcoded URLs and IPs** — find where the app communicates externally
3. Search for **HTTP client construction** — HttpClient, WinHTTP, WinINet setup reveals base URLs and auth config
4. Check for **authentication patterns** — tokens, credentials, API keys
5. Look for **persistence mechanisms** — registry Run keys, scheduled tasks, services
6. Search for **crypto operations** — may reveal how data is encrypted/decrypted before transmission
7. Check for **process manipulation** — indicates potential injection or privilege escalation

View File

@ -0,0 +1,296 @@
# Call Flow Analysis
Techniques for tracing execution flows in decompiled Windows applications, from entry points down to API calls.
## 1. Start from the PE Import Table
The import table is the single most revealing artifact in static analysis. It lists every DLL and function the binary uses at load time.
### What imports reveal
| Imported DLL | Indicates |
|---|---|
| `ws2_32.dll` | Network communication (sockets) |
| `winhttp.dll` | HTTP/HTTPS requests |
| `wininet.dll` | Internet/HTTP (legacy) |
| `advapi32.dll` | Registry, services, security |
| `crypt32.dll` / `bcrypt.dll` | Cryptography |
| `user32.dll` | GUI, windows, message handling |
| `ole32.dll` / `oleaut32.dll` | COM/OLE automation |
| `mscoree.dll` | .NET runtime (managed binary) |
| `ntdll.dll` (direct) | Low-level / possible evasion |
| `kernel32.dll` | File I/O, process management, memory |
### Extracting imports
```powershell
# Via dumpbin (if Visual Studio C++ Build Tools installed)
dumpbin /imports target.exe
# Via Ghidra (see ExportDecompiled.py output)
# Check <output>/imports.txt
# Via PowerShell (basic PE parsing)
# The decompile.ps1 script includes PE header reading
```
## 2. Entry Points
### Native executables
| Entry Point | Context |
|---|---|
| `WinMain` / `wWinMain` | GUI application |
| `main` / `wmain` | Console application |
| `DllMain` | DLL initialization/cleanup |
| `ServiceMain` | Windows service |
| `DriverEntry` | Kernel driver |
| CRT `mainCRTStartup` | C runtime initialization → calls `main` |
Search in decompiled output:
```powershell
# Find main entry points (Ghidra output)
Select-String -Path "decompiled\*" -Pattern 'WinMain|wWinMain|main\(|DllMain|ServiceMain|DriverEntry' -Recurse
# Find the PE entry point function
Select-String -Path "decompiled\*" -Pattern 'entry|_start|mainCRTStartup' -Recurse
```
### .NET applications
| Entry Point | Context |
|---|---|
| `static void Main()` | Console / WinForms / WPF |
| `Program.cs` | ASP.NET Core / Generic Host |
| `Startup.cs` | ASP.NET Core (older pattern) |
| `App.xaml.cs` | WPF application startup |
| `Global.asax.cs` | ASP.NET Framework |
```powershell
# Find .NET entry points
Select-String -Path "sources\*" -Pattern 'static\s+(void|async\s+Task)\s+Main|class\s+Program|class\s+Startup|class\s+App\s*:' -Recurse
```
## 3. Follow the Initialization Chain
### Native C/C++ application
```
CRT mainCRTStartup()
→ main() / WinMain()
→ Initialize global singletons (COM, Winsock, etc.)
→ Parse command line
→ Create main window (RegisterClassEx → CreateWindowEx)
→ Enter message loop (GetMessage → DispatchMessage)
→ WndProc handles messages
→ WM_COMMAND → menu/button handlers
→ Business logic functions
→ API calls (network, registry, file I/O)
```
Key initialization to search:
```powershell
# COM initialization
Select-String -Path "decompiled\*" -Pattern 'CoInitialize|OleInitialize' -Recurse
# Winsock initialization
Select-String -Path "decompiled\*" -Pattern 'WSAStartup' -Recurse
# Window creation
Select-String -Path "decompiled\*" -Pattern 'CreateWindowEx|RegisterClassEx|RegisterClass\(' -Recurse
# Message loop
Select-String -Path "decompiled\*" -Pattern 'GetMessage|PeekMessage|DispatchMessage|TranslateMessage' -Recurse
```
### .NET application
```
Program.Main()
→ Host.CreateDefaultBuilder()
→ ConfigureServices()
→ Register DI services
→ Configure HttpClient / API clients
→ Configure authentication
→ Configure()
→ Set up middleware pipeline
→ Map routes / endpoints
```
```powershell
# DI registration
Select-String -Path "sources\*" -Pattern 'AddScoped|AddSingleton|AddTransient|AddHttpClient|AddDbContext' -Recurse
# Configuration
Select-String -Path "sources\*" -Pattern 'Configuration\[|GetSection|GetValue|IOptions|appsettings' -Recurse
# Middleware
Select-String -Path "sources\*" -Pattern 'UseAuthentication|UseAuthorization|UseRouting|MapControllers|MapGet|MapPost' -Recurse
```
## 4. Identify User Action Handlers
### Native GUI (Win32)
```
User clicks button
→ WM_COMMAND message sent
→ WndProc receives with LOWORD(wParam) = button ID
→ Switch/if on button IDs
→ Calls handler function
→ Handler calls business logic → API calls
```
```powershell
# Window procedure
Select-String -Path "decompiled\*" -Pattern 'WndProc|WNDPROC|WM_COMMAND|WM_NOTIFY|WM_CREATE' -Recurse
# Dialog procedures
Select-String -Path "decompiled\*" -Pattern 'DialogBox|CreateDialog|DlgProc|DLGPROC|EndDialog' -Recurse
# Common control notifications
Select-String -Path "decompiled\*" -Pattern 'BN_CLICKED|LVN_ITEMCHANGED|TVN_SELCHANGED' -Recurse
```
### WinForms (.NET)
```powershell
# Event handlers
Select-String -Path "sources\*" -Pattern 'Click\s*\+=|_Click\(|button.*Click|EventHandler' -Recurse
# Form lifecycle
Select-String -Path "sources\*" -Pattern 'InitializeComponent|Form_Load|Form_Shown|Form_Closing' -Recurse
```
### WPF (.NET)
```powershell
# Commands and bindings
Select-String -Path "sources\*" -Pattern 'ICommand|RelayCommand|DelegateCommand|Command\s*{' -Recurse
# MVVM ViewModels
Select-String -Path "sources\*" -Pattern 'ViewModel|INotifyPropertyChanged|ObservableCollection|BindingContext' -Recurse
```
## 5. Dependency Injection (.NET)
Modern .NET apps use DI extensively. Trace bindings to find implementations:
```powershell
# Service registration
Select-String -Path "sources\*" -Pattern 'services\.Add(Scoped|Singleton|Transient)\s*<' -Recurse
# HTTP client configuration
Select-String -Path "sources\*" -Pattern 'AddHttpClient|BaseAddress|DefaultRequestHeaders' -Recurse
# Interface → implementation
Select-String -Path "sources\*" -Pattern 'services\.Add.*<I\w+,\s*\w+>' -Recurse
# Constructor injection
Select-String -Path "sources\*" -Pattern 'public\s+\w+\(I\w+' -Recurse
```
To trace a call flow through DI:
1. Find where an interface is used (e.g., `IApiService` in a controller)
2. Find the `AddScoped<IApiService, ApiService>` registration
3. Follow `ApiService` to the actual HTTP/API call
## 6. Find Constants and Configuration
### Native
```powershell
# String constants — often reveal URLs, paths, keys
Select-String -Path "decompiled\*" -Pattern '"https?://|"\\\\|"C:\\' -Recurse
# Error messages — useful for understanding control flow
Select-String -Path "strings.txt" -Pattern 'error|failed|invalid|unauthorized|denied' -CaseSensitive:$false
```
### .NET
```powershell
# Configuration access
Select-String -Path "sources\*" -Pattern 'Configuration\[|ConfigurationManager|AppSettings|ConnectionStrings' -Recurse
# Constants
Select-String -Path "sources\*" -Pattern 'const\s+string|static\s+readonly\s+string|BASE_URL|API_KEY|SECRET' -Recurse
# Resource strings
Select-String -Path "sources\*" -Pattern 'Resources\.\w+|ResourceManager' -Recurse
```
## 7. Navigating Stripped/Obfuscated Code
### Native (no debug symbols)
When symbols are stripped, Ghidra generates names like `FUN_00401000`, `DAT_00405000`:
**What you can still use:**
- **Import table** — DLL function names are always readable
- **String literals** — embedded strings survive stripping
- **API call patterns** — sequences of Win32 calls reveal intent
- **Constants** — magic numbers, sizes, flags are preserved
**Strategy:**
1. Start from imports — find calls to network/registry/crypto APIs
2. Cross-reference callers — Ghidra's output shows who calls what
3. Use strings — grep `strings.txt` for URLs, error messages, paths
4. Rename functions — once you understand a function's purpose, rename it in your analysis notes
### .NET obfuscated
**What gets obfuscated:**
- Class names → `a`, `b`, `\u0001`
- Method names → `a()`, `b()`, `\u0002()`
- Field names → random characters
**What does NOT get obfuscated:**
- **.NET framework types** — `HttpClient`, `FileStream`, `Process` keep their names
- **Method signatures** — parameter types from framework classes are preserved
- **String literals** (unless string encryption is used)
- **NuGet package public APIs**`Newtonsoft.Json`, `RestSharp` calls are readable
- **Attributes**`[Serializable]`, `[Route]`, `[HttpGet]` remain
## 8. Tracing a Complete Call Flow: Example
### Example: Finding how an app authenticates
**Native app:**
```
1. dumpbin /imports → finds winhttp.dll imported
2. grep "WinHttpSendRequest" → found in sub_401A00
3. Read sub_401A00 → builds POST request to "/api/auth/login"
4. grep for callers of sub_401A00 → called from sub_401500
5. Read sub_401500 → reads username/password from dialog fields
6. grep for callers of sub_401500 → called from WndProc on WM_COMMAND
7. WM_COMMAND handler checks button ID → "Login" button
```
Result: `Login button → WndProc(WM_COMMAND) → sub_401500 → sub_401A00 → WinHttpSendRequest POST /api/auth/login`
**.NET app:**
```
1. grep for "HttpClient" → found in AuthService.cs
2. Read AuthService.cs → PostAsync("auth/login", credentials)
3. grep for IAuthService usage → injected into LoginViewModel
4. Read LoginViewModel → LoginCommand calls AuthService.LoginAsync()
5. LoginCommand bound to Login button in LoginView.xaml
```
Result: `Login button → LoginViewModel.LoginCommand → AuthService.LoginAsync → HttpClient.PostAsync("auth/login")`
## 9. Tools and Commands Summary
| Goal | Command |
|---|---|
| Find entry points | `Select-String -Path "decompiled\*" -Pattern 'WinMain\|main\|DllMain' -Recurse` |
| Find window procedures | `Select-String -Path "decompiled\*" -Pattern 'WndProc\|WM_COMMAND' -Recurse` |
| Find .NET DI bindings | `Select-String -Path "sources\*" -Pattern 'AddScoped\|AddSingleton\|AddTransient' -Recurse` |
| Find click handlers | `Select-String -Path "sources\*" -Pattern '_Click\|EventHandler\|ICommand' -Recurse` |
| Find constants | `Select-String -Path "sources\*" -Pattern 'const\|BASE_URL\|API_KEY' -CaseSensitive:$false -Recurse` |
| Find usages of a class | `Select-String -Path "sources\*" -Pattern 'ClassName' -Recurse` |
| Find strings containing text | `Select-String -Path "strings.txt" -Pattern '"search text"'` |
| Find network imports | `Select-String -Path "imports.txt" -Pattern 'ws2_32\|winhttp\|wininet'` |

View File

@ -0,0 +1,159 @@
# Ghidra Headless Analyzer CLI Reference
## Overview
Ghidra's Headless Analyzer (`analyzeHeadless.bat` on Windows) runs Ghidra analysis and scripting without the GUI. It imports binaries, performs auto-analysis, and can run custom scripts to export decompiled code.
## Basic Usage
```powershell
& "$env:GHIDRA_INSTALL_DIR\support\analyzeHeadless.bat" <projectDir> <projectName> [OPTIONS]
```
- `<projectDir>` — Directory where the Ghidra project will be created
- `<projectName>` — Name of the Ghidra project
## Key Options
| Option | Description |
|---|---|
| `-import <file>` | Import a binary file into the project |
| `-process <file>` | Process an already-imported file |
| `-postScript <script>` | Run a script after analysis completes |
| `-preScript <script>` | Run a script before analysis |
| `-scriptPath <dir>` | Directory containing your scripts |
| `-deleteProject` | Delete the project after processing |
| `-noanalysis` | Skip auto-analysis (useful if re-running scripts only) |
| `-processor <langID>` | Override architecture detection (e.g., `x86:LE:64:default`) |
| `-analysisTimeoutPerFile <seconds>` | Timeout for analysis per file |
| `-scriptlog <file>` | Write script output to a log file |
| `-overwrite` | Overwrite existing files in the project |
| `-recursive` | Import all files from a directory recursively |
## Common Workflows
### Decompile to C pseudocode (full workflow)
```powershell
$projectDir = "C:\GhidraProjects"
$projectName = "MyProject"
$scriptPath = "${CLAUDE_PLUGIN_ROOT}\skills\windows-reverse-engineering\scripts\ghidra-scripts"
& "$env:GHIDRA_INSTALL_DIR\support\analyzeHeadless.bat" `
$projectDir $projectName `
-import "C:\targets\app.exe" `
-scriptPath $scriptPath `
-postScript "ExportDecompiled.py" `
-deleteProject
```
### Batch import multiple files
```powershell
& "$env:GHIDRA_INSTALL_DIR\support\analyzeHeadless.bat" `
$projectDir $projectName `
-import "C:\targets\" `
-recursive `
-scriptPath $scriptPath `
-postScript "ExportDecompiled.py"
```
### Re-run script without re-analyzing
```powershell
& "$env:GHIDRA_INSTALL_DIR\support\analyzeHeadless.bat" `
$projectDir $projectName `
-process "app.exe" `
-noanalysis `
-scriptPath $scriptPath `
-postScript "ExportDecompiled.py"
```
## Custom Export Scripts
This skill includes `ExportDecompiled.py`, a Jython script that:
1. Decompiles all functions to C pseudocode files
2. Exports the import table
3. Exports the export table (for DLLs)
4. Exports all string references
The script is located at:
```
${CLAUDE_PLUGIN_ROOT}/skills/windows-reverse-engineering/scripts/ghidra-scripts/ExportDecompiled.py
```
### Writing Custom Ghidra Scripts
Ghidra scripts use **Jython (Python 2.7)** with access to the Ghidra API:
```python
# @category Export
# @description Example: list all functions and their addresses
fm = currentProgram.getFunctionManager()
functions = fm.getFunctions(True) # True = forward iteration
for func in functions:
print("{} @ {}".format(func.getName(), func.getEntryPoint()))
```
Key Ghidra API classes:
- `currentProgram` — the loaded binary
- `currentProgram.getFunctionManager()` — access functions
- `currentProgram.getMemory()` — access memory/sections
- `currentProgram.getSymbolTable()` — access symbols
- `currentProgram.getListing()` — access instructions
- `DecompInterface` — decompile functions to C
## Architecture Detection
Ghidra auto-detects the processor for most PE files. Override when needed:
| Architecture | Processor ID |
|---|---|
| x86 32-bit | `x86:LE:32:default` |
| x86 64-bit | `x86:LE:64:default` |
| ARM 32-bit | `ARM:LE:32:v8` |
| ARM64 | `AARCH64:LE:64:v8A` |
## Memory Tuning
For large binaries (>50MB), increase the Java heap:
1. Edit `$env:GHIDRA_INSTALL_DIR\support\analyzeHeadless.bat`
2. Find the `MAXMEM` variable
3. Change from default to: `set MAXMEM=4G` (or more)
Or set via environment variable:
```powershell
$env:_JAVA_OPTIONS = "-Xmx4g"
```
## Output Directory
The `ExportDecompiled.py` script outputs to a directory next to the input file (or as specified by script arguments):
```
<output>/
├── decompiled/ # C pseudocode per function
│ ├── main.c
│ ├── WinMain.c
│ ├── sub_401000.c
│ └── ...
├── imports.txt # DLL imports listing
├── exports.txt # DLL exports listing (if DLL)
├── strings.txt # String references
└── summary.txt # Analysis summary
```
## Troubleshooting
| Problem | Solution |
|---|---|
| `GHIDRA_INSTALL_DIR not set` | Set environment variable to Ghidra directory |
| `Java not found` | Install Java 17+ and ensure it's in PATH |
| `OutOfMemoryError` | Increase `MAXMEM` in analyzeHeadless.bat |
| Script errors | Use `-scriptlog <file>` to capture script output |
| Wrong architecture detected | Use `-processor <langID>` to override |
| Analysis hangs | Use `-analysisTimeoutPerFile 300` to set a 5-minute timeout |

View File

@ -0,0 +1,185 @@
# ilspycmd CLI Reference
## Overview
`ilspycmd` is the command-line interface for ILSpy, the open-source .NET assembly decompiler. It decompiles .NET assemblies (EXE, DLL) to C# source code, including full project reconstruction with `.csproj` files.
## Installation
```powershell
# Requires .NET SDK 6.0+
dotnet tool install -g ilspycmd
# Update to latest
dotnet tool update -g ilspycmd
```
## When to Use ilspycmd vs Ghidra
| Scenario | Recommended |
|---|---|
| .NET Framework (4.x) assembly | ilspycmd |
| .NET Core / .NET 5+ assembly | ilspycmd |
| .NET assembly with WPF/WinForms | ilspycmd |
| Native C/C++ EXE/DLL | Ghidra |
| Mixed-mode assembly (native + managed) | Both — Ghidra for native, ilspycmd for managed |
| Obfuscated .NET (Dotfuscator, ConfuserEx) | de4dot first, then ilspycmd |
| .NET Native / AOT compiled | Ghidra (compiled to native code) |
## Basic Usage
```powershell
ilspycmd [OPTIONS] <assembly>
```
Input can be an `.exe` or `.dll` file containing .NET metadata.
## Key Options
| Option | Description |
|---|---|
| `-p` / `--project` | Decompile to a full C# project (with .csproj file) |
| `-o <dir>` | Output directory for decompiled files |
| `-t <type>` | Decompile a specific type (e.g., `MyApp.MainForm`) |
| `-l` / `--list` | List all types and members in the assembly |
| `--no-dead-code` | Remove unreachable code from output |
| `-r <dir>` | Reference assembly search directory (improves type resolution) |
| `--nested-directories` | Create nested directories matching namespace structure |
| `-lv <version>` | Set the target language version (e.g., `CSharp10_0`) |
## Decompiling Different Targets
### Full project decompilation (recommended)
```powershell
ilspycmd -p -o output_dir MyApp.exe
```
Produces:
- `output_dir/*.cs` — Decompiled C# source files
- `output_dir/*.csproj` — Reconstructed project file
- `output_dir/Properties/` — Assembly info and resources
### Decompile to individual files
```powershell
ilspycmd -o output_dir MyApp.dll
```
Produces C# files without a project structure.
### List all types
```powershell
ilspycmd -l MyApp.exe
```
Useful for identifying namespaces and classes before targeted decompilation.
### Decompile a specific type
```powershell
ilspycmd -t "MyApp.Services.AuthService" MyApp.exe
```
### Decompile with reference resolution
```powershell
ilspycmd -p -o output_dir -r "C:\refs\" MyApp.exe
```
When the assembly references other DLLs, put them in a directory and use `-r` for better type resolution.
## Handling Obfuscated .NET
.NET obfuscators (Dotfuscator, ConfuserEx, Eziriz .NET Reactor, etc.) rename types and members, encrypt strings, add control flow obfuscation, and may add anti-tamper checks.
### Preprocessing with de4dot
```powershell
# Clean the obfuscated assembly first
de4dot ObfuscatedApp.exe -o CleanApp.exe
# Then decompile the cleaned version
ilspycmd -p -o output_dir CleanApp.exe
```
### What de4dot handles
- Renamed types/methods → restored to readable names
- Encrypted strings → decrypted inline
- Proxy delegates → resolved to direct calls
- Dead code from obfuscation → removed
### What remains obfuscated
- Control flow patterns (may still be convoluted)
- Custom protection schemes de4dot doesn't recognize
- Native stub protectors (e.g., .NET Reactor with native mode)
### Manual strategies for obfuscated .NET
1. **String search**: string literals in resources and constants are often preserved
2. **Framework types**: `HttpClient`, `WebRequest`, `SqlConnection` keep their names
3. **Interface names**: public interface names are often preserved for serialization
4. **Attribute values**: `[Route]`, `[HttpGet]`, `[Serializable]` annotations remain readable
## Common Patterns in Decompiled Output
### Dependency Injection (ASP.NET Core)
Look in `Startup.cs` or `Program.cs`:
```csharp
services.AddHttpClient<IApiService, ApiService>(client => {
client.BaseAddress = new Uri("https://api.example.com/v1/");
});
services.AddScoped<IAuthService, AuthService>();
```
### HTTP Clients
```csharp
// HttpClient (modern)
var response = await httpClient.PostAsync("/auth/login", content);
// WebRequest (legacy)
var request = WebRequest.Create("https://api.example.com/data");
// RestSharp
var request = new RestRequest("/users/{id}", Method.Get);
```
### Configuration
```csharp
// appsettings.json values
var apiUrl = Configuration["ApiSettings:BaseUrl"];
var apiKey = Configuration.GetSection("ApiKeys")["Primary"];
```
## Output Structure
When using `-p` (project mode), the output mirrors the original project:
```
output_dir/
├── MyApp.csproj # Reconstructed project file
├── Program.cs # Entry point
├── Properties/
│ └── AssemblyInfo.cs # Assembly metadata
├── Models/
│ ├── User.cs
│ └── LoginRequest.cs
├── Services/
│ ├── AuthService.cs
│ └── ApiService.cs
└── ...
```
## Troubleshooting
| Problem | Solution |
|---|---|
| `ilspycmd: command not found` | Run `dotnet tool install -g ilspycmd` and restart terminal |
| Assembly references not resolved | Use `-r <dir>` to point to referenced DLLs |
| Output has `/* Error */` comments | Assembly may be obfuscated — try de4dot first |
| `BadImageFormatException` | File is not a .NET assembly — use Ghidra instead |
| `FileNotFoundException` for deps | Copy dependency DLLs next to the target assembly |
| Decompiled code won't compile | Expected — decompiled code is for reading, not building |

View File

@ -0,0 +1,264 @@
# Setup Guide: Dependencies for Windows Reverse Engineering
## Java JDK 17+
Ghidra requires Java 17 or later.
### winget (recommended)
```powershell
winget install Microsoft.OpenJDK.17
```
### Chocolatey
```powershell
choco install openjdk17
```
### Manual (Adoptium)
1. Go to <https://adoptium.net/temurin/releases/?version=17>
2. Download the `.msi` installer for your architecture (x64 or ARM64)
3. Run the installer — it adds Java to PATH automatically
### Verify
```powershell
java -version
# Should show version 17.x or higher
```
---
## Ghidra
Ghidra is the NSA's open-source reverse engineering framework. It decompiles native PE binaries to C pseudocode.
### GitHub Releases (recommended)
1. Go to <https://github.com/NationalSecurityAgency/ghidra/releases/latest>
2. Download `ghidra_<version>_PUBLIC_<date>.zip`
3. Extract to a permanent location (e.g., `C:\Tools\Ghidra`)
4. Set the environment variable:
```powershell
# Set for current user permanently
[System.Environment]::SetEnvironmentVariable('GHIDRA_INSTALL_DIR', 'C:\Tools\Ghidra\ghidra_<version>_PUBLIC', 'User')
# Set for current session
$env:GHIDRA_INSTALL_DIR = 'C:\Tools\Ghidra\ghidra_<version>_PUBLIC'
```
### Chocolatey
```powershell
choco install ghidra
```
### Verify
```powershell
# Check the environment variable
$env:GHIDRA_INSTALL_DIR
# Check the headless analyzer
& "$env:GHIDRA_INSTALL_DIR\support\analyzeHeadless.bat" -help
```
> **Note**: On first run, Ghidra may prompt for agreement. The headless analyzer works without a GUI but requires a writable project directory.
---
## ilspycmd (.NET Decompiler)
ilspycmd is the command-line interface for ILSpy, the open-source .NET decompiler. It decompiles .NET assemblies to C# source.
### Prerequisites
Install the .NET SDK (6.0 or later):
```powershell
# Via winget
winget install Microsoft.DotNet.SDK.8
# Via Chocolatey
choco install dotnet-sdk
```
### Install ilspycmd
```powershell
dotnet tool install -g ilspycmd
```
This installs `ilspycmd` as a global .NET tool. The tool is automatically added to PATH.
### Verify
```powershell
ilspycmd --version
```
### Usage
```powershell
# Decompile entire assembly to C# project
ilspycmd -p -o output_dir MyApp.exe
# Decompile to individual C# files (no project)
ilspycmd -o output_dir MyApp.dll
```
---
## strings / strings2 (optional, recommended)
Extract readable ASCII and Unicode strings from binaries. Essential for finding hardcoded URLs, API keys, and error messages.
### SysInternals strings (Microsoft)
```powershell
# Via winget
winget install Microsoft.Sysinternals.Strings
# Or download directly
# https://learn.microsoft.com/en-us/sysinternals/downloads/strings
```
### strings2 (recommended — finds both ASCII and Unicode)
1. Download from <https://github.com/glmcdona/strings2/releases>
2. Extract to a directory in your PATH (e.g., `C:\Tools\strings2\`)
3. Add to PATH:
```powershell
[System.Environment]::SetEnvironmentVariable('PATH', $env:PATH + ';C:\Tools\strings2', 'User')
```
### Verify
```powershell
strings --help
# or
strings2 --help
```
---
## dumpbin (optional)
dumpbin is a CLI tool for inspecting PE headers, imports, exports, and sections. It ships with Visual Studio C++ Build Tools.
> **Important**: dumpbin requires **Visual Studio C++ Build Tools** to be installed. This is a large download (~2-4 GB). If you don't have Visual Studio, consider using Ghidra's PE analysis instead — it extracts the same information.
### Install Visual Studio C++ Build Tools
1. Download from <https://visualstudio.microsoft.com/visual-cpp-build-tools/>
2. In the installer, select **"Desktop development with C++"**
3. Install (requires admin)
### Find dumpbin
After installation, dumpbin is typically at:
```
C:\Program Files\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\<version>\bin\Hostx64\x64\dumpbin.exe
```
To use it, open a **Developer Command Prompt** or **Developer PowerShell**, which adds dumpbin to PATH automatically.
### Verify
```powershell
# From Developer Command Prompt / PowerShell
dumpbin /?
```
### Usage
```powershell
# Show imports
dumpbin /imports MyApp.exe
# Show exports
dumpbin /exports MyLib.dll
# Show headers
dumpbin /headers MyApp.exe
# Show all sections
dumpbin /all MyApp.exe
```
---
## de4dot (optional — .NET deobfuscation)
de4dot is an open-source .NET deobfuscator that can clean up obfuscated assemblies before decompilation.
### Download
1. Go to <https://github.com/de4dot/de4dot/releases>
2. Download the latest release ZIP
3. Extract to `C:\Tools\de4dot\`
4. Add to PATH:
```powershell
[System.Environment]::SetEnvironmentVariable('PATH', $env:PATH + ';C:\Tools\de4dot', 'User')
```
### Usage
```powershell
# Deobfuscate a .NET assembly
de4dot ObfuscatedApp.exe -o CleanApp.exe
# Then decompile the clean version
ilspycmd -p -o output_dir CleanApp.exe
```
---
## Optional Tools
### x64dbg
A free, open-source x86/x64 debugger for Windows. Useful for dynamic analysis.
```powershell
# Via Chocolatey
choco install x64dbg.portable
# Or download from https://x64dbg.com/
```
### PE-bear
A portable PE viewer with a GUI for inspecting headers, sections, and overlays.
Download from <https://github.com/hasherezade/pe-bear/releases>
### Radare2
A powerful command-line reverse engineering framework.
```powershell
choco install radare2
```
---
## Troubleshooting
| Problem | Solution |
|---|---|
| `java: command not found` | Install Java 17+ and ensure it's in PATH |
| `GHIDRA_INSTALL_DIR not set` | Set the environment variable to Ghidra's installation directory |
| `analyzeHeadless` fails to start | Ensure Java 17+ is in PATH and `GHIDRA_INSTALL_DIR` is correct |
| `ilspycmd: command not found` | Run `dotnet tool install -g ilspycmd` and restart your terminal |
| `dotnet: command not found` | Install .NET SDK from https://dotnet.microsoft.com/ |
| Ghidra runs out of memory | Set `JAVA_OPTS="-Xmx4g"` or edit `analyzeHeadless.bat` max heap |
| `dumpbin: command not found` | Open Developer Command Prompt, or install VS C++ Build Tools |
| PowerShell blocks script execution | Run `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned -Force` |
| ilspycmd fails on obfuscated .NET | Run `de4dot` first to clean the assembly, then retry |
| Ghidra decompiler produces `undefined` | Binary may be packed — try unpacking with UPX or manual analysis |

View File

@ -0,0 +1,193 @@
# check-deps.ps1 — Verify dependencies for Windows reverse engineering
# Output includes machine-readable INSTALL_REQUIRED:<dep> and INSTALL_OPTIONAL:<dep> lines.
# Exit code 0 = all required OK, 1 = missing required deps.
$ErrorActionPreference = 'SilentlyContinue'
$RequiredJavaMajor = 17
$Errors = 0
$MissingRequired = @()
$MissingOptional = @()
Write-Host "=== Windows Reverse Engineering: Dependency Check ==="
Write-Host ""
# --- Java ---
$javaOk = $false
$javaCmdExists = Get-Command java -ErrorAction SilentlyContinue
if ($javaCmdExists) {
$javaVersionOutput = & java -version 2>&1 | Select-Object -First 1
$javaVersionStr = [string]$javaVersionOutput
if ($javaVersionStr -match '"(\d+)') {
$javaVersion = [int]$Matches[1]
if ($javaVersion -ge $RequiredJavaMajor) {
Write-Host "[OK] Java $javaVersion detected"
$javaOk = $true
} else {
Write-Host "[WARN] Java detected but version $javaVersion is below $RequiredJavaMajor"
$Errors++
$MissingRequired += 'java'
}
} else {
Write-Host "[WARN] Java detected but could not parse version from: $javaVersionStr"
$Errors++
$MissingRequired += 'java'
}
} else {
Write-Host "[MISSING] Java is not installed or not in PATH"
$Errors++
$MissingRequired += 'java'
}
# --- Ghidra ---
$ghidraOk = $false
$ghidraDir = $env:GHIDRA_INSTALL_DIR
if ($ghidraDir -and (Test-Path "$ghidraDir\support\analyzeHeadless.bat")) {
Write-Host "[OK] Ghidra detected at $ghidraDir"
$ghidraOk = $true
} elseif (Get-Command ghidra -ErrorAction SilentlyContinue) {
Write-Host "[OK] Ghidra detected in PATH"
$ghidraOk = $true
} else {
# Check common installation locations
$ghidraLocations = @(
"$env:ProgramFiles\Ghidra",
"$env:ProgramFiles(x86)\Ghidra",
"$env:USERPROFILE\ghidra",
"C:\Tools\Ghidra",
"C:\ghidra"
)
foreach ($loc in $ghidraLocations) {
$candidates = Get-ChildItem -Path $loc -Directory -Filter "ghidra_*" -ErrorAction SilentlyContinue
if ($candidates) {
$ghidraDir = $candidates | Sort-Object Name -Descending | Select-Object -First 1 -ExpandProperty FullName
if (Test-Path "$ghidraDir\support\analyzeHeadless.bat") {
Write-Host "[OK] Ghidra detected at $ghidraDir"
Write-Host " Hint: Set GHIDRA_INSTALL_DIR=$ghidraDir for faster detection"
$ghidraOk = $true
break
}
}
}
if (-not $ghidraOk) {
Write-Host "[MISSING] Ghidra is not installed or GHIDRA_INSTALL_DIR is not set"
$MissingRequired += 'ghidra'
$Errors++
}
}
# --- ilspycmd ---
$ilspyOk = $false
if (Get-Command ilspycmd -ErrorAction SilentlyContinue) {
$ilspyVersion = & ilspycmd --version 2>&1 | Select-Object -First 1
Write-Host "[OK] ilspycmd detected ($ilspyVersion)"
$ilspyOk = $true
} else {
Write-Host "[MISSING] ilspycmd is not installed (for .NET assembly decompilation)"
# ilspycmd is required if the user wants .NET support, but we only consider
# at least one decompiler (ghidra OR ilspycmd) as strictly required
if (-not $ghidraOk) {
$MissingRequired += 'ilspycmd'
$Errors++
} else {
$MissingOptional += 'ilspycmd'
}
}
# If neither decompiler is available, both are required
if (-not $ghidraOk -and -not $ilspyOk) {
Write-Host ""
Write-Host "[ERROR] No decompiler available. At least one of Ghidra or ilspycmd is required."
}
# --- strings / strings2 ---
$stringsOk = $false
if (Get-Command strings2 -ErrorAction SilentlyContinue) {
Write-Host "[OK] strings2 detected"
$stringsOk = $true
} elseif (Get-Command strings -ErrorAction SilentlyContinue) {
Write-Host "[OK] strings (SysInternals) detected"
$stringsOk = $true
} else {
Write-Host "[MISSING] strings/strings2 not found (optional - extracts embedded strings from binaries)"
$MissingOptional += 'strings'
}
# --- dumpbin ---
$dumpbinOk = $false
if (Get-Command dumpbin -ErrorAction SilentlyContinue) {
Write-Host "[OK] dumpbin detected"
$dumpbinOk = $true
} else {
# Try to find via VS Developer environment
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
if (Test-Path $vswhere) {
$vsInstallPath = & $vswhere -latest -property installationPath 2>$null
if ($vsInstallPath) {
$dumpbinCandidates = Get-ChildItem -Path "$vsInstallPath\VC\Tools\MSVC" -Recurse -Filter "dumpbin.exe" -ErrorAction SilentlyContinue
if ($dumpbinCandidates) {
Write-Host "[OK] dumpbin detected at $($dumpbinCandidates[0].FullName)"
Write-Host " Note: Use Developer Command Prompt for automatic PATH setup"
$dumpbinOk = $true
}
}
}
if (-not $dumpbinOk) {
Write-Host "[MISSING] dumpbin not found (optional - requires Visual Studio C++ Build Tools)"
Write-Host " Install from: https://visualstudio.microsoft.com/visual-cpp-build-tools/"
$MissingOptional += 'dumpbin'
}
}
# --- .NET SDK (for ilspycmd) ---
if (Get-Command dotnet -ErrorAction SilentlyContinue) {
$dotnetVersion = & dotnet --version 2>$null
Write-Host "[OK] .NET SDK $dotnetVersion detected"
} else {
Write-Host "[MISSING] .NET SDK not found (needed to install ilspycmd)"
if (-not $ilspyOk) {
$MissingOptional += 'dotnet-sdk'
}
}
# --- Optional: de4dot ---
if (Get-Command de4dot -ErrorAction SilentlyContinue) {
Write-Host "[OK] de4dot detected (optional - .NET deobfuscation)"
} else {
Write-Host "[MISSING] de4dot not found (optional - .NET deobfuscator for obfuscated assemblies)"
$MissingOptional += 'de4dot'
}
# --- Optional: x64dbg ---
if (Get-Command x64dbg -ErrorAction SilentlyContinue) {
Write-Host "[OK] x64dbg detected (optional)"
} elseif (Test-Path "$env:ProgramFiles\x64dbg\release\x64\x64dbg.exe") {
Write-Host "[OK] x64dbg detected (optional)"
} else {
Write-Host "[MISSING] x64dbg not found (optional - dynamic debugging)"
$MissingOptional += 'x64dbg'
}
# --- Machine-readable summary ---
Write-Host ""
foreach ($dep in $MissingRequired) {
Write-Host "INSTALL_REQUIRED:$dep"
}
foreach ($dep in $MissingOptional) {
Write-Host "INSTALL_OPTIONAL:$dep"
}
Write-Host ""
if ($Errors -gt 0) {
Write-Host "*** $($MissingRequired.Count) required dependency/ies missing. ***"
Write-Host "Run install-dep.ps1 <name> to install, or see references/setup-guide.md."
exit 1
} else {
if ($MissingOptional.Count -gt 0) {
Write-Host "Required dependencies OK. $($MissingOptional.Count) optional dependency/ies missing."
Write-Host "Run install-dep.ps1 <name> to install optional tools."
} else {
Write-Host "All dependencies are installed. Ready to decompile."
}
exit 0
}

View File

@ -0,0 +1,387 @@
# decompile.ps1 — Decompile Windows EXE/DLL/.NET assemblies using Ghidra or ILSpy
#
# Usage: decompile.ps1 [OPTIONS] <file>
#
# Options:
# -Output <dir> Output directory (default: <filename>-decompiled)
# -Engine <engine> Decompiler engine: auto, ghidra, ilspy (default: auto)
# -NoStrings Skip strings extraction (faster)
# -Help Show help message
param(
[Parameter(Position=0)]
[string]$InputFile,
[Alias('o')]
[string]$Output = "",
[ValidateSet('auto', 'ghidra', 'ilspy')]
[string]$Engine = "auto",
[switch]$NoStrings,
[Alias('h')]
[switch]$Help
)
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
function Show-Usage {
@"
Usage: decompile.ps1 [OPTIONS] <file>
Decompile a Windows EXE, DLL, or .NET assembly.
Arguments:
<file> Path to the .exe, .dll, or .sys file
Options:
-Output <dir> Output directory (default: <filename>-decompiled)
-Engine <engine> Decompiler engine: auto, ghidra, ilspy (default: auto)
-NoStrings Skip strings extraction (faster)
-Help Show this help message
Engines:
auto Auto-detect binary type and choose the best engine (default)
ghidra Use Ghidra headless analyzer (native C/C++ binaries)
ilspy Use ilspycmd (for .NET assemblies)
Environment:
GHIDRA_INSTALL_DIR Path to Ghidra installation directory
Examples:
decompile.ps1 MyApp.exe
decompile.ps1 -Engine ilspy MyDotNetApp.dll
decompile.ps1 -Engine ghidra -Output .\analysis NativeApp.exe
decompile.ps1 -NoStrings LargeApp.dll
"@
exit 0
}
if ($Help) { Show-Usage }
# --- Validate input ---
if (-not $InputFile) {
Write-Host "Error: No input file specified." -ForegroundColor Red
Show-Usage
}
if (-not (Test-Path $InputFile)) {
Write-Host "Error: File not found: $InputFile" -ForegroundColor Red
exit 1
}
$InputFileItem = Get-Item $InputFile
$InputFileAbs = $InputFileItem.FullName
$ext = $InputFileItem.Extension.ToLower()
$basename = $InputFileItem.BaseName
if ($ext -notin @('.exe', '.dll', '.sys')) {
Write-Host "Error: Unsupported file type '$ext'. Expected .exe, .dll, or .sys" -ForegroundColor Red
exit 1
}
if (-not $Output) {
$Output = Join-Path (Split-Path $InputFileAbs -Parent) "${basename}-decompiled"
}
# --- Detect binary type ---
function Test-DotNetAssembly {
param([string]$FilePath)
try {
$bytes = [System.IO.File]::ReadAllBytes($FilePath)
# Check MZ header
if ($bytes.Length -lt 64 -or $bytes[0] -ne 0x4D -or $bytes[1] -ne 0x5A) {
return $false
}
# Get PE header offset from 0x3C
$peOffset = [BitConverter]::ToInt32($bytes, 0x3C)
if ($peOffset -le 0 -or ($peOffset + 4) -ge $bytes.Length) {
return $false
}
# Check PE signature
if ($bytes[$peOffset] -ne 0x50 -or $bytes[$peOffset+1] -ne 0x45 -or
$bytes[$peOffset+2] -ne 0x00 -or $bytes[$peOffset+3] -ne 0x00) {
return $false
}
# COFF header starts at peOffset + 4
$coffOffset = $peOffset + 4
$sizeOfOptionalHeader = [BitConverter]::ToUInt16($bytes, $coffOffset + 16)
if ($sizeOfOptionalHeader -eq 0) {
return $false
}
# Optional header starts after COFF header (20 bytes)
$optOffset = $coffOffset + 20
$magic = [BitConverter]::ToUInt16($bytes, $optOffset)
# PE32 (0x10B) or PE32+ (0x20B)
if ($magic -eq 0x10B) {
# PE32: CLI header is data directory index 14, at offset 208 from optional header start
$cliDirOffset = $optOffset + 208
} elseif ($magic -eq 0x20B) {
# PE32+: CLI header is data directory index 14, at offset 224 from optional header start
$cliDirOffset = $optOffset + 224
} else {
return $false
}
if (($cliDirOffset + 8) -gt $bytes.Length) {
return $false
}
# Check if CLR header data directory has a non-zero RVA and size
$cliRva = [BitConverter]::ToUInt32($bytes, $cliDirOffset)
$cliSize = [BitConverter]::ToUInt32($bytes, $cliDirOffset + 4)
return ($cliRva -gt 0 -and $cliSize -gt 0)
} catch {
return $false
}
}
function Get-PeInfo {
param([string]$FilePath)
$info = @{
Architecture = "unknown"
Subsystem = "unknown"
IsDotNet = $false
}
try {
$bytes = [System.IO.File]::ReadAllBytes($FilePath)
$peOffset = [BitConverter]::ToInt32($bytes, 0x3C)
$coffOffset = $peOffset + 4
# Machine type
$machine = [BitConverter]::ToUInt16($bytes, $coffOffset)
switch ($machine) {
0x14C { $info.Architecture = "x86" }
0x8664 { $info.Architecture = "x64" }
0xAA64 { $info.Architecture = "ARM64" }
default { $info.Architecture = "unknown (0x{0:X4})" -f $machine }
}
# Optional header
$optOffset = $coffOffset + 20
$magic = [BitConverter]::ToUInt16($bytes, $optOffset)
if ($magic -eq 0x10B) {
# PE32
$subsystem = [BitConverter]::ToUInt16($bytes, $optOffset + 68)
} elseif ($magic -eq 0x20B) {
# PE32+
$subsystem = [BitConverter]::ToUInt16($bytes, $optOffset + 68)
} else {
$subsystem = 0
}
switch ($subsystem) {
1 { $info.Subsystem = "Native (driver)" }
2 { $info.Subsystem = "GUI" }
3 { $info.Subsystem = "Console" }
default { $info.Subsystem = "unknown ($subsystem)" }
}
$info.IsDotNet = Test-DotNetAssembly $FilePath
} catch {
# Silently fail — info will have defaults
}
return $info
}
# --- Determine engine ---
$peInfo = Get-PeInfo $InputFileAbs
$isDotNet = $peInfo.IsDotNet
Write-Host "=== Decompiling $InputFile ===" -ForegroundColor Cyan
Write-Host "Architecture: $($peInfo.Architecture)"
Write-Host "Subsystem: $($peInfo.Subsystem)"
Write-Host ".NET Assembly: $isDotNet"
Write-Host ""
if ($Engine -eq 'auto') {
if ($isDotNet) {
$Engine = 'ilspy'
Write-Host "Auto-detected: .NET assembly -> using ILSpy" -ForegroundColor Green
} else {
$Engine = 'ghidra'
Write-Host "Auto-detected: Native PE -> using Ghidra" -ForegroundColor Green
}
}
Write-Host "Engine: $Engine"
Write-Host "Output directory: $Output"
Write-Host ""
# --- ILSpy decompilation ---
function Invoke-ILSpy {
if (-not (Get-Command ilspycmd -ErrorAction SilentlyContinue)) {
Write-Host "Error: ilspycmd is not installed. Run: dotnet tool install -g ilspycmd" -ForegroundColor Red
exit 1
}
$sourcesDir = Join-Path $Output "sources"
New-Item -ItemType Directory -Path $sourcesDir -Force | Out-Null
Write-Host "Running: ilspycmd -p -o `"$sourcesDir`" `"$InputFileAbs`"" -ForegroundColor Yellow
& ilspycmd -p -o $sourcesDir $InputFileAbs 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "Warning: ilspycmd exited with code $LASTEXITCODE. Output may be incomplete." -ForegroundColor Yellow
}
# Count output files
if (Test-Path $sourcesDir) {
$csFiles = Get-ChildItem -Path $sourcesDir -Recurse -Filter "*.cs" | Measure-Object
Write-Host ""
Write-Host "C# files decompiled: $($csFiles.Count)" -ForegroundColor Green
# List top-level structure
Write-Host ""
Write-Host "Top-level structure:" -ForegroundColor Cyan
Get-ChildItem -Path $sourcesDir -Depth 1 | ForEach-Object {
$prefix = if ($_.PSIsContainer) { "[DIR] " } else { " " }
Write-Host " $prefix$($_.Name)"
}
}
}
# --- Ghidra decompilation ---
function Invoke-Ghidra {
# Find Ghidra
$ghidraDir = $env:GHIDRA_INSTALL_DIR
if (-not $ghidraDir) {
# Try common locations
$locations = @(
"$env:ProgramFiles\Ghidra",
"$env:USERPROFILE\.local\share\ghidra",
"C:\Tools\Ghidra",
"C:\ghidra"
)
foreach ($loc in $locations) {
$candidates = Get-ChildItem -Path $loc -Directory -Filter "ghidra_*" -ErrorAction SilentlyContinue
if ($candidates) {
$ghidraDir = ($candidates | Sort-Object Name -Descending | Select-Object -First 1).FullName
if (Test-Path "$ghidraDir\support\analyzeHeadless.bat") {
break
}
$ghidraDir = $null
}
}
}
if (-not $ghidraDir -or -not (Test-Path "$ghidraDir\support\analyzeHeadless.bat")) {
Write-Host "Error: Ghidra not found. Set GHIDRA_INSTALL_DIR environment variable." -ForegroundColor Red
exit 1
}
$analyzeHeadless = "$ghidraDir\support\analyzeHeadless.bat"
$ghidraScriptsDir = Join-Path $ScriptDir "ghidra-scripts"
$projectDir = Join-Path $env:TEMP "GhidraProjects"
$projectName = "DecompileProject"
# Create project directory
New-Item -ItemType Directory -Path $projectDir -Force | Out-Null
New-Item -ItemType Directory -Path $Output -Force | Out-Null
Write-Host "Running Ghidra headless analysis..." -ForegroundColor Yellow
Write-Host "Project: $projectDir\$projectName" -ForegroundColor DarkGray
Write-Host "Script: $ghidraScriptsDir\ExportDecompiled.py" -ForegroundColor DarkGray
Write-Host ""
& cmd /c "`"$analyzeHeadless`" `"$projectDir`" `"$projectName`" -import `"$InputFileAbs`" -scriptPath `"$ghidraScriptsDir`" -postScript `"ExportDecompiled.py`" `"$Output`" -deleteProject -overwrite" 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host ""
Write-Host "Warning: Ghidra exited with code $LASTEXITCODE. Output may be incomplete." -ForegroundColor Yellow
}
# Report results
$decompDir = Join-Path $Output "decompiled"
if (Test-Path $decompDir) {
$cFiles = Get-ChildItem -Path $decompDir -Recurse -Filter "*.c" | Measure-Object
Write-Host ""
Write-Host "C pseudocode files: $($cFiles.Count)" -ForegroundColor Green
}
$importsFile = Join-Path $Output "imports.txt"
if (Test-Path $importsFile) {
$importLines = (Get-Content $importsFile | Where-Object { $_ -match '^\s+\w' }).Count
Write-Host "Imported functions: $importLines"
}
$exportsFile = Join-Path $Output "exports.txt"
if (Test-Path $exportsFile) {
$exportLines = (Get-Content $exportsFile | Where-Object { $_ -match '^\w' -and $_ -notmatch '^#' }).Count
Write-Host "Exported functions: $exportLines"
}
$summaryFile = Join-Path $Output "summary.txt"
if (Test-Path $summaryFile) {
Write-Host ""
Write-Host "--- Analysis Summary ---" -ForegroundColor Cyan
Get-Content $summaryFile | Write-Host
}
}
# --- Strings extraction ---
function Invoke-StringsExtraction {
if ($NoStrings) {
Write-Host "Skipping strings extraction (-NoStrings flag set)"
return
}
$stringsOutput = Join-Path $Output "strings.txt"
# Check if strings were already extracted by Ghidra
if (Test-Path $stringsOutput) {
$existingLines = (Get-Content $stringsOutput | Measure-Object).Count
if ($existingLines -gt 5) {
Write-Host "Strings already extracted by decompiler ($existingLines references)"
return
}
}
if (Get-Command strings2 -ErrorAction SilentlyContinue) {
Write-Host "Extracting strings with strings2..."
& strings2 $InputFileAbs > $stringsOutput 2>$null
} elseif (Get-Command strings -ErrorAction SilentlyContinue) {
Write-Host "Extracting strings with SysInternals strings..."
& strings -q -accepteula $InputFileAbs > $stringsOutput 2>$null
} else {
Write-Host "No strings tool available. Skipping strings extraction."
Write-Host "Install strings2 or SysInternals strings for embedded string analysis."
return
}
if (Test-Path $stringsOutput) {
$stringCount = (Get-Content $stringsOutput | Measure-Object).Count
Write-Host "Strings extracted: $stringCount"
}
}
# --- Run ---
switch ($Engine) {
'ilspy' {
Invoke-ILSpy
}
'ghidra' {
Invoke-Ghidra
}
}
Invoke-StringsExtraction
Write-Host ""
Write-Host "=== Decompilation complete ===" -ForegroundColor Green
Write-Host "Output: $Output"

View File

@ -0,0 +1,266 @@
# find-api-calls.ps1 — Search decompiled source for API calls, network endpoints, and secrets
#
# Usage: find-api-calls.ps1 <source-dir> [OPTIONS]
#
# Options:
# --network Search only for network/HTTP patterns
# --registry Search only for registry operations
# --filesystem Search only for file system operations
# --process Search only for process manipulation (injection indicators)
# --crypto Search only for cryptography patterns
# --com Search only for COM/WMI patterns
# --services Search only for Windows service patterns
# --urls Search only for hardcoded URLs and IPs
# --auth Search only for authentication/API key patterns
# --persistence Search only for persistence mechanisms
# --all Search all patterns (default)
# --help Show help message
param(
[Parameter(Position=0)]
[string]$SourceDir,
[switch]$Network,
[switch]$Registry,
[switch]$FileSystem,
[switch]$Process,
[switch]$Crypto,
[switch]$Com,
[switch]$Services,
[switch]$Urls,
[switch]$Auth,
[switch]$Persistence,
[switch]$All,
[Alias('h')]
[switch]$Help
)
$ErrorActionPreference = 'SilentlyContinue'
function Show-Usage {
@"
Usage: find-api-calls.ps1 <source-dir> [OPTIONS]
Search decompiled source (C pseudocode or C# files) for API calls and patterns.
Arguments:
<source-dir> Path to the decompiled sources directory
Options:
--Network Search only for network/HTTP patterns
--Registry Search only for registry operations
--FileSystem Search only for file system operations
--Process Search only for process manipulation (injection indicators)
--Crypto Search only for cryptography patterns
--Com Search only for COM/WMI patterns
--Services Search only for Windows service patterns
--Urls Search only for hardcoded URLs, IPs, and secrets
--Auth Search only for authentication/API key patterns
--Persistence Search only for persistence mechanisms
--All Search all patterns (default)
--Help Show this help message
Output:
Results are printed as file:line:match for easy navigation.
"@
exit 0
}
if ($Help) { Show-Usage }
if (-not $SourceDir) {
Write-Host "Error: No source directory specified." -ForegroundColor Red
Show-Usage
}
if (-not (Test-Path $SourceDir)) {
Write-Host "Error: Directory not found: $SourceDir" -ForegroundColor Red
exit 1
}
# Determine if any specific flag is set
$specificSearch = $Network -or $Registry -or $FileSystem -or $Process -or $Crypto -or $Com -or $Services -or $Urls -or $Auth -or $Persistence
$searchAll = $All -or (-not $specificSearch)
# File extensions to search
$includes = @("*.c", "*.cs", "*.h", "*.cpp", "*.txt")
function Write-Section {
param([string]$Title)
Write-Host ""
Write-Host "==== $Title ====" -ForegroundColor Cyan
Write-Host ""
}
function Search-Pattern {
param(
[string]$Pattern,
[switch]$CaseInsensitive
)
$params = @{
Path = $SourceDir
Pattern = $Pattern
Include = $includes
Recurse = $true
}
if ($CaseInsensitive) {
$params.CaseSensitive = $false
}
$results = Select-String @params 2>$null
if ($results) {
foreach ($r in $results) {
$relPath = $r.Path
try {
$relPath = [System.IO.Path]::GetRelativePath($SourceDir, $r.Path)
} catch { }
Write-Host "${relPath}:$($r.LineNumber):$($r.Line.Trim())"
}
}
}
# =====================================================================
# Search categories
# =====================================================================
# --- Network (Native Win32) ---
if ($searchAll -or $Network) {
Write-Section "WinHTTP"
Search-Pattern 'WinHttpOpen|WinHttpConnect|WinHttpOpenRequest|WinHttpSendRequest|WinHttpReceiveResponse|WinHttpReadData|WinHttpSetOption|WinHttpQueryHeaders'
Write-Section "WinINet"
Search-Pattern 'InternetOpen[AW]?|InternetConnect[AW]?|HttpOpenRequest[AW]?|HttpSendRequest[AW]?|InternetReadFile|InternetCloseHandle|InternetSetOption[AW]?|HttpQueryInfo[AW]?'
Write-Section "Winsock"
Search-Pattern 'WSAStartup|socket\s*\(|connect\s*\(|send\s*\(|recv\s*\(|bind\s*\(|listen\s*\(|accept\s*\(|closesocket|getaddrinfo|gethostbyname|WSASocket|WSASend|WSARecv'
Write-Section ".NET HttpClient"
Search-Pattern 'HttpClient|GetAsync|PostAsync|PutAsync|DeleteAsync|SendAsync|GetStringAsync|GetStreamAsync|IHttpClientFactory|AddHttpClient|CreateClient'
Write-Section ".NET WebRequest (legacy)"
Search-Pattern 'WebRequest|HttpWebRequest|WebClient|DownloadString|DownloadFile|UploadString|UploadFile'
Write-Section ".NET HTTP Request Construction"
Search-Pattern 'HttpRequestMessage|StringContent|JsonContent|FormUrlEncodedContent|MultipartFormDataContent|BaseAddress'
Write-Section "RestSharp / Refit"
Search-Pattern 'RestClient|RestRequest|RestResponse|IRestClient|\[Get\(|\[Post\(|\[Put\(|\[Delete\(|\[Patch\('
}
# --- Registry ---
if ($searchAll -or $Registry) {
Write-Section "Registry (Native)"
Search-Pattern 'RegOpenKey[AW]?(Ex)?|RegCreateKey[AW]?(Ex)?|RegSetValue[AW]?(Ex)?|RegQueryValue[AW]?(Ex)?|RegDeleteKey[AW]?(Ex)?|RegDeleteValue[AW]?|RegEnumKey[AW]?(Ex)?|RegEnumValue[AW]?|RegCloseKey'
Write-Section "Registry (.NET)"
Search-Pattern 'Microsoft\.Win32\.Registry|RegistryKey|OpenSubKey|SetValue|GetValue|CreateSubKey|DeleteSubKey|RegistryHive'
}
# --- File System ---
if ($searchAll -or $FileSystem) {
Write-Section "File System (Native)"
Search-Pattern 'CreateFile[AW]?|ReadFile|WriteFile|DeleteFile[AW]?|CopyFile[AW]?|MoveFile[AW]?(Ex)?|FindFirstFile[AW]?|FindNextFile[AW]?|GetFileAttributes[AW]?|SetFileAttributes[AW]?|CreateDirectory[AW]?|RemoveDirectory[AW]?|GetTempPath|GetTempFileName'
Write-Section "File System (.NET)"
Search-Pattern 'File\.(Read|Write|Append|Copy|Move|Delete|Exists|Open|Create)|Directory\.(Create|Delete|Exists|GetFiles|GetDirectories)|FileStream|StreamReader|StreamWriter|BinaryReader|BinaryWriter|Path\.Combine|Path\.GetTempPath'
}
# --- Process and Thread Manipulation ---
if ($searchAll -or $Process) {
Write-Section "Process Creation"
Search-Pattern 'CreateProcess[AW]?|ShellExecute[AW]?(Ex)?|WinExec|system\s*\('
Write-Section "Process Injection Indicators"
Search-Pattern 'VirtualAlloc(Ex)?|VirtualProtect(Ex)?|WriteProcessMemory|ReadProcessMemory|CreateRemoteThread(Ex)?|NtCreateThreadEx|QueueUserAPC|SetThreadContext|GetThreadContext|SuspendThread|ResumeThread'
Write-Section "DLL Loading"
Search-Pattern 'LoadLibrary[AW]?(Ex)?|GetProcAddress|FreeLibrary|GetModuleHandle[AW]?|GetModuleFileName[AW]?'
Write-Section "Process (.NET)"
Search-Pattern 'Process\.Start|ProcessStartInfo|Process\.GetProcesses|Process\.GetCurrentProcess'
Write-Section "Memory Mapping"
Search-Pattern 'CreateFileMapping[AW]?|MapViewOfFile(Ex)?|OpenFileMapping[AW]?|UnmapViewOfFile'
}
# --- Cryptography ---
if ($searchAll -or $Crypto) {
Write-Section "CryptoAPI (Native)"
Search-Pattern 'CryptAcquireContext|CryptEncrypt|CryptDecrypt|CryptHashData|CryptDeriveKey|CryptGenKey|CryptImportKey|CryptExportKey|CryptGenRandom|CryptCreateHash|CryptSetKeyParam'
Write-Section "BCrypt (Native)"
Search-Pattern 'BCryptOpenAlgorithmProvider|BCryptEncrypt|BCryptDecrypt|BCryptGenerateSymmetricKey|BCryptHash|BCryptCreateHash|BCryptFinishHash|BCryptDeriveKey|BCryptGenerateKeyPair'
Write-Section "Cryptography (.NET)"
Search-Pattern 'System\.Security\.Cryptography|Aes\.|AesManaged|AesCryptoServiceProvider|RSA\.|RSACryptoServiceProvider|SHA256|SHA512|MD5|HMAC|RijndaelManaged|X509Certificate|ProtectedData|DataProtection'
}
# --- COM and WMI ---
if ($searchAll -or $Com) {
Write-Section "COM"
Search-Pattern 'CoCreateInstance|CoInitialize(Ex)?|CoUninitialize|IDispatch|IUnknown|CLSIDFromProgID|ProgIDFromCLSID|CoGetClassObject'
Write-Section "WMI (Native)"
Search-Pattern 'IWbemLocator|IWbemServices|ConnectServer|ExecQuery|ExecMethod'
Write-Section "WMI (.NET)"
Search-Pattern 'ManagementObjectSearcher|ManagementObject|ManagementScope|ObjectQuery|WqlObjectQuery|SelectQuery|ManagementClass'
}
# --- Windows Services ---
if ($searchAll -or $Services) {
Write-Section "Services (Native)"
Search-Pattern 'OpenSCManager[AW]?|CreateService[AW]?|OpenService[AW]?|StartService|ControlService|DeleteService|ChangeServiceConfig[AW]?|QueryServiceStatus(Ex)?|RegisterServiceCtrlHandler(Ex)?|SetServiceStatus|StartServiceCtrlDispatcher'
Write-Section "Services (.NET)"
Search-Pattern 'ServiceBase|ServiceController|ServiceInstaller|ServiceProcessInstaller|OnStart|OnStop|ServiceName|RunAsService'
}
# --- Hardcoded URLs, IPs, and Secrets ---
if ($searchAll -or $Urls) {
Write-Section "Hardcoded URLs (http:// and https://)"
Search-Pattern '"https?://[^"]+'
Write-Section "IP Addresses"
Search-Pattern '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b'
Write-Section "Connection Strings"
Search-Pattern 'Data Source=|Server=|Initial Catalog=|connectionString|ConnectionStrings|Provider=' -CaseInsensitive
Write-Section "File Paths"
Search-Pattern '"[A-Za-z]:\\[^"]+"|"\\\\[^"]+'
}
# --- Authentication and API Keys ---
if ($searchAll -or $Auth) {
Write-Section "Authentication and API Keys"
Search-Pattern 'api[_\-]?key|api[_\-]?secret|auth[_\-]?token|bearer|authorization|x-api-key|client[_\-]?secret|access[_\-]?token|refresh[_\-]?token' -CaseInsensitive
Write-Section "Base URLs and Constants"
Search-Pattern 'BASE_URL|API_URL|SERVER_URL|ENDPOINT|API_BASE|HOST_NAME|ServiceUrl|BaseAddress|ApiEndpoint' -CaseInsensitive
Write-Section "Credentials"
Search-Pattern 'password|passwd|pwd|credential|username|login|authenticate' -CaseInsensitive
}
# --- Persistence Mechanisms ---
if ($searchAll -or $Persistence) {
Write-Section "Registry Run Keys"
Search-Pattern 'CurrentVersion\\Run|CurrentVersion\\RunOnce|CurrentVersion\\RunServices|CurrentVersion\\Policies\\Explorer\\Run'
Write-Section "Scheduled Tasks"
Search-Pattern 'schtasks|ITaskService|ITaskDefinition|TaskScheduler|Register-ScheduledTask|New-ScheduledTask'
Write-Section "Startup Folder"
Search-Pattern 'Startup|shell:startup|Programs\\Startup|Environment\.GetFolderPath.*Startup'
Write-Section "Service Installation"
Search-Pattern 'CreateService|sc\.exe\s+(create|config)|New-Service|Install-Service|RegisterServiceCtrlHandler'
}
Write-Host ""
Write-Host "=== Search complete ===" -ForegroundColor Green

View File

@ -0,0 +1,233 @@
# @category Export
# @description Export decompiled C pseudocode, imports, exports, and strings from a Windows PE binary
# @author Windows Reverse Engineering Skill
#
# This Jython script is designed to be run by Ghidra's Headless Analyzer.
# It decompiles all functions to C pseudocode and exports metadata.
#
# Usage via analyzeHeadless:
# analyzeHeadless.bat <projectDir> <projectName> -import <binary> \
# -scriptPath <this_dir> -postScript ExportDecompiled.py <outputDir>
import os
import sys
from ghidra.app.decompiler import DecompInterface
from ghidra.util.task import ConsoleTaskMonitor
from ghidra.program.model.symbol import SymbolType
# Get output directory from script arguments or use default
args = getScriptArgs()
if args and len(args) > 0:
output_dir = args[0]
else:
# Default: create output next to the analyzed file
prog_name = currentProgram.getName()
base_name = prog_name.rsplit('.', 1)[0] if '.' in prog_name else prog_name
output_dir = os.path.join(os.getcwd(), base_name + "-decompiled")
# Create output subdirectories
decompiled_dir = os.path.join(output_dir, "decompiled")
if not os.path.exists(decompiled_dir):
os.makedirs(decompiled_dir)
print("=== Ghidra Export Script ===")
print("Program: {}".format(currentProgram.getName()))
print("Output directory: {}".format(output_dir))
print("")
# =====================================================================
# 1. Export decompiled C pseudocode for all functions
# =====================================================================
print("--- Decompiling functions ---")
monitor = ConsoleTaskMonitor()
decomp = DecompInterface()
decomp.openProgram(currentProgram)
# Set decompiler options for better output
options = decomp.getOptions()
# Increase timeout for complex functions (60 seconds)
decomp.setSimplificationStyle("decompile")
fm = currentProgram.getFunctionManager()
functions = fm.getFunctions(True) # Forward iteration
func_count = 0
error_count = 0
decompiled_count = 0
for func in functions:
func_count += 1
func_name = func.getName()
entry = func.getEntryPoint()
# Skip thunks and external functions for cleaner output
if func.isThunk():
continue
try:
results = decomp.decompileFunction(func, 60, monitor)
if results and results.decompileCompleted():
decomp_func = results.getDecompiledFunction()
if decomp_func:
c_code = decomp_func.getC()
if c_code:
# Sanitize function name for filename
safe_name = func_name.replace('<', '_').replace('>', '_').replace(':', '_').replace('*', '_').replace('?', '_').replace('"', '_').replace('/', '_').replace('\\', '_').replace('|', '_')
# Add address to avoid name collisions
file_name = "{}_{}.c".format(safe_name, entry.toString())
file_path = os.path.join(decompiled_dir, file_name)
with open(file_path, 'w') as f:
f.write("// Function: {}\n".format(func_name))
f.write("// Address: {}\n".format(entry.toString()))
f.write("// Calling Convention: {}\n".format(func.getCallingConventionName()))
f.write("//\n\n")
f.write(c_code)
decompiled_count += 1
else:
error_count += 1
except Exception as e:
error_count += 1
# Continue on error — don't stop for individual function failures
decomp.dispose()
print("Functions found: {}".format(func_count))
print("Functions decompiled: {}".format(decompiled_count))
print("Errors/timeouts: {}".format(error_count))
print("")
# =====================================================================
# 2. Export import table
# =====================================================================
print("--- Exporting imports ---")
imports_path = os.path.join(output_dir, "imports.txt")
import_count = 0
with open(imports_path, 'w') as f:
f.write("# Import Table for {}\n".format(currentProgram.getName()))
f.write("# Format: DLL :: FunctionName @ Address\n\n")
sym_table = currentProgram.getSymbolTable()
ext_symbols = sym_table.getExternalSymbols()
current_dll = None
for sym in ext_symbols:
if sym.getSymbolType() == SymbolType.FUNCTION:
parent = sym.getParentNamespace()
dll_name = parent.getName() if parent else "UNKNOWN"
func_name = sym.getName()
addr = sym.getAddress()
if dll_name != current_dll:
f.write("\n[{}]\n".format(dll_name))
current_dll = dll_name
f.write(" {} @ {}\n".format(func_name, addr.toString()))
import_count += 1
print("Imports exported: {} functions".format(import_count))
print("")
# =====================================================================
# 3. Export export table (for DLLs)
# =====================================================================
print("--- Exporting exports ---")
exports_path = os.path.join(output_dir, "exports.txt")
export_count = 0
with open(exports_path, 'w') as f:
f.write("# Export Table for {}\n".format(currentProgram.getName()))
f.write("# Format: FunctionName @ Address\n\n")
sym_table = currentProgram.getSymbolTable()
for sym in sym_table.getAllSymbols(True):
if sym.isExternalEntryPoint():
f.write("{} @ {}\n".format(sym.getName(), sym.getAddress().toString()))
export_count += 1
if export_count == 0:
with open(exports_path, 'w') as f:
f.write("# No exports found (this is expected for EXE files)\n")
print("Exports found: {}".format(export_count))
print("")
# =====================================================================
# 4. Export string references
# =====================================================================
print("--- Exporting strings ---")
strings_path = os.path.join(output_dir, "strings.txt")
string_count = 0
with open(strings_path, 'w') as f:
f.write("# String References for {}\n".format(currentProgram.getName()))
f.write("# Format: Address | String\n\n")
listing = currentProgram.getListing()
data_iter = listing.getDefinedData(True)
for data in data_iter:
if monitor.isCancelled():
break
data_type = data.getDataType()
type_name = data_type.getName() if data_type else ""
if "string" in type_name.lower() or "unicode" in type_name.lower():
value = data.getValue()
if value:
val_str = str(value)
# Filter out very short or empty strings
if len(val_str) >= 3:
f.write("{} | {}\n".format(data.getAddress().toString(), val_str))
string_count += 1
print("Strings exported: {}".format(string_count))
print("")
# =====================================================================
# 5. Export summary
# =====================================================================
print("--- Generating summary ---")
summary_path = os.path.join(output_dir, "summary.txt")
with open(summary_path, 'w') as f:
f.write("=== Analysis Summary ===\n\n")
f.write("Program: {}\n".format(currentProgram.getName()))
f.write("Language: {}\n".format(currentProgram.getLanguage().getLanguageDescription().getDescription()))
f.write("Compiler: {}\n".format(currentProgram.getCompilerSpec().getCompilerSpecDescription().getCompilerSpecName()))
f.write("Image Base: {}\n".format(currentProgram.getImageBase().toString()))
f.write("Min Address: {}\n".format(currentProgram.getMinAddress().toString()))
f.write("Max Address: {}\n".format(currentProgram.getMaxAddress().toString()))
f.write("\nFunctions: {}\n".format(func_count))
f.write("Decompiled: {}\n".format(decompiled_count))
f.write("Decompile errors: {}\n".format(error_count))
f.write("Imports: {}\n".format(import_count))
f.write("Exports: {}\n".format(export_count))
f.write("Strings: {}\n".format(string_count))
# List memory blocks / sections
f.write("\n--- Sections ---\n")
memory = currentProgram.getMemory()
for block in memory.getBlocks():
f.write(" {} | Start: {} | Size: {} | Permissions: {}{}{}\n".format(
block.getName(),
block.getStart().toString(),
block.getSize(),
"R" if block.isRead() else "-",
"W" if block.isWrite() else "-",
"X" if block.isExecute() else "-"
))
print("Summary written to {}".format(summary_path))
print("")
print("=== Export complete ===")
print("Output: {}".format(output_dir))

View File

@ -0,0 +1,370 @@
# install-dep.ps1 — Install a single dependency for Windows reverse engineering
# Usage: install-dep.ps1 <dependency>
# Dependencies: java, ghidra, ilspycmd, strings, dumpbin, de4dot, dotnet-sdk
#
# Exit codes:
# 0 — installed successfully
# 1 — installation failed
# 2 — requires manual action (e.g. admin needed but not available)
param(
[Parameter(Mandatory=$true, Position=0)]
[string]$Dependency
)
$ErrorActionPreference = 'Stop'
# --- Detect environment ---
$HasWinget = $null -ne (Get-Command winget -ErrorAction SilentlyContinue)
$HasChoco = $null -ne (Get-Command choco -ErrorAction SilentlyContinue)
$HasDotnet = $null -ne (Get-Command dotnet -ErrorAction SilentlyContinue)
$IsAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
function Write-Info { param([string]$Message) Write-Host "[INFO] $Message" }
function Write-Ok { param([string]$Message) Write-Host "[OK] $Message" }
function Write-Fail { param([string]$Message) Write-Host "[FAIL] $Message" -ForegroundColor Red }
function Write-Manual {
param([string]$Message)
Write-Host "[MANUAL] $Message" -ForegroundColor Yellow
Write-Host " Cannot install automatically. Please install manually and retry." -ForegroundColor Yellow
exit 2
}
function Get-GithubLatestTag {
param([string]$Repo)
try {
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/$Repo/releases/latest" -UseBasicParsing
return $release.tag_name
} catch {
return $null
}
}
function Download-File {
param([string]$Url, [string]$Dest)
Write-Info "Downloading from $Url..."
try {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri $Url -OutFile $Dest -UseBasicParsing
} catch {
Write-Fail "Download failed: $_"
return $false
}
return $true
}
function Add-ToUserPath {
param([string]$Dir)
$currentPath = [System.Environment]::GetEnvironmentVariable('PATH', 'User')
if ($currentPath -notlike "*$Dir*") {
[System.Environment]::SetEnvironmentVariable('PATH', "$currentPath;$Dir", 'User')
$env:PATH = "$env:PATH;$Dir"
Write-Info "Added $Dir to user PATH. Restart your terminal for full effect."
}
}
# =====================================================================
# Dependency installers
# =====================================================================
function Install-Java {
$javaCmdExists = Get-Command java -ErrorAction SilentlyContinue
if ($javaCmdExists) {
$javaVersionOutput = & java -version 2>&1 | Select-Object -First 1
if ([string]$javaVersionOutput -match '"(\d+)') {
$ver = [int]$Matches[1]
if ($ver -ge 17) {
Write-Ok "Java $ver already installed"
return
}
}
}
Write-Info "Installing Java JDK 17+..."
if ($HasWinget) {
Write-Info "Installing via winget..."
& winget install Microsoft.OpenJDK.17 --accept-source-agreements --accept-package-agreements
if ($LASTEXITCODE -eq 0) {
Write-Ok "Java 17 installed via winget"
return
}
Write-Info "winget failed, trying alternatives..."
}
if ($HasChoco) {
Write-Info "Installing via Chocolatey..."
& choco install openjdk17 -y
if ($LASTEXITCODE -eq 0) {
Write-Ok "Java 17 installed via Chocolatey"
return
}
}
Write-Manual "Install Java JDK 17+ from https://adoptium.net/temurin/releases/?version=17"
}
function Install-Ghidra {
# Check if already available
$ghidraDir = $env:GHIDRA_INSTALL_DIR
if ($ghidraDir -and (Test-Path "$ghidraDir\support\analyzeHeadless.bat")) {
Write-Ok "Ghidra already installed at $ghidraDir"
return
}
if ($HasChoco) {
Write-Info "Installing Ghidra via Chocolatey..."
& choco install ghidra -y
if ($LASTEXITCODE -eq 0) {
Write-Ok "Ghidra installed via Chocolatey"
Write-Info "Set GHIDRA_INSTALL_DIR to the Ghidra installation directory."
return
}
Write-Info "Chocolatey install failed, trying direct download..."
}
# Direct download from GitHub
Write-Info "Installing Ghidra from GitHub releases..."
$tag = Get-GithubLatestTag "NationalSecurityAgency/ghidra"
if (-not $tag) {
Write-Manual "Could not determine latest Ghidra version. Download from https://github.com/NationalSecurityAgency/ghidra/releases/latest"
}
$version = $tag -replace '^Ghidra_', '' -replace '_build$', ''
# Try to find the download URL from the release assets
try {
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/NationalSecurityAgency/ghidra/releases/latest" -UseBasicParsing
$asset = $release.assets | Where-Object { $_.name -like "ghidra_*_PUBLIC_*.zip" } | Select-Object -First 1
if (-not $asset) {
Write-Manual "Could not find Ghidra download. Download from https://github.com/NationalSecurityAgency/ghidra/releases/latest"
}
$downloadUrl = $asset.browser_download_url
} catch {
Write-Manual "Could not access GitHub API. Download Ghidra from https://github.com/NationalSecurityAgency/ghidra/releases/latest"
}
$installDir = "$env:USERPROFILE\.local\share\ghidra"
$tmpZip = "$env:TEMP\ghidra-download.zip"
if (-not (Download-File -Url $downloadUrl -Dest $tmpZip)) {
Write-Manual "Download failed. Download manually from $downloadUrl"
}
Write-Info "Extracting Ghidra..."
if (Test-Path $installDir) { Remove-Item -Recurse -Force $installDir }
New-Item -ItemType Directory -Path $installDir -Force | Out-Null
Expand-Archive -Path $tmpZip -DestinationPath $installDir -Force
Remove-Item $tmpZip -Force
# Find the actual Ghidra directory inside the extracted archive
$ghidraSubDir = Get-ChildItem -Path $installDir -Directory -Filter "ghidra_*" | Select-Object -First 1
if ($ghidraSubDir) {
$ghidraPath = $ghidraSubDir.FullName
} else {
$ghidraPath = $installDir
}
# Set environment variable
[System.Environment]::SetEnvironmentVariable('GHIDRA_INSTALL_DIR', $ghidraPath, 'User')
$env:GHIDRA_INSTALL_DIR = $ghidraPath
Write-Ok "Ghidra installed to $ghidraPath"
Write-Info "GHIDRA_INSTALL_DIR set to $ghidraPath"
Write-Info "Restart your terminal for the environment variable to take effect."
}
function Install-IlspyCmd {
if (Get-Command ilspycmd -ErrorAction SilentlyContinue) {
Write-Ok "ilspycmd already installed"
return
}
if (-not $HasDotnet) {
Write-Info ".NET SDK not found. Installing .NET SDK first..."
Install-DotnetSdk
# Re-check
$HasDotnet = $null -ne (Get-Command dotnet -ErrorAction SilentlyContinue)
if (-not $HasDotnet) {
Write-Fail ".NET SDK installation failed. Cannot install ilspycmd."
Write-Manual "Install .NET SDK from https://dotnet.microsoft.com/ then run: dotnet tool install -g ilspycmd"
}
}
Write-Info "Installing ilspycmd via dotnet tool..."
& dotnet tool install -g ilspycmd
if ($LASTEXITCODE -eq 0) {
Write-Ok "ilspycmd installed"
} else {
# May already be installed but older version
& dotnet tool update -g ilspycmd
if ($LASTEXITCODE -eq 0) {
Write-Ok "ilspycmd updated"
} else {
Write-Fail "ilspycmd installation failed."
exit 1
}
}
}
function Install-DotnetSdk {
if ($HasDotnet) {
$ver = & dotnet --version 2>$null
Write-Ok ".NET SDK $ver already installed"
return
}
Write-Info "Installing .NET SDK..."
if ($HasWinget) {
Write-Info "Installing via winget..."
& winget install Microsoft.DotNet.SDK.8 --accept-source-agreements --accept-package-agreements
if ($LASTEXITCODE -eq 0) {
Write-Ok ".NET SDK installed via winget"
return
}
}
if ($HasChoco) {
Write-Info "Installing via Chocolatey..."
& choco install dotnet-sdk -y
if ($LASTEXITCODE -eq 0) {
Write-Ok ".NET SDK installed via Chocolatey"
return
}
}
Write-Manual "Install .NET SDK from https://dotnet.microsoft.com/download"
}
function Install-Strings {
if (Get-Command strings2 -ErrorAction SilentlyContinue) {
Write-Ok "strings2 already installed"
return
}
if (Get-Command strings -ErrorAction SilentlyContinue) {
Write-Ok "strings (SysInternals) already installed"
return
}
# Try winget for SysInternals strings
if ($HasWinget) {
Write-Info "Installing SysInternals Strings via winget..."
& winget install Microsoft.Sysinternals.Strings --accept-source-agreements --accept-package-agreements
if ($LASTEXITCODE -eq 0) {
Write-Ok "SysInternals Strings installed via winget"
return
}
}
# Direct download strings2
Write-Info "Installing strings2 from GitHub..."
$tag = Get-GithubLatestTag "glmcdona/strings2"
if (-not $tag) {
$tag = "v2.0.0"
}
$installDir = "$env:USERPROFILE\.local\share\strings2"
New-Item -ItemType Directory -Path $installDir -Force | Out-Null
$downloadUrl = "https://github.com/glmcdona/strings2/releases/download/$tag/strings2.exe"
if (Download-File -Url $downloadUrl -Dest "$installDir\strings2.exe") {
$binDir = "$env:USERPROFILE\.local\bin"
New-Item -ItemType Directory -Path $binDir -Force | Out-Null
Copy-Item "$installDir\strings2.exe" "$binDir\strings2.exe" -Force
Add-ToUserPath $binDir
Write-Ok "strings2 installed to $binDir"
} else {
Write-Manual "Download strings2 from https://github.com/glmcdona/strings2/releases"
}
}
function Install-Dumpbin {
if (Get-Command dumpbin -ErrorAction SilentlyContinue) {
Write-Ok "dumpbin already installed"
return
}
Write-Host ""
Write-Host "[INFO] dumpbin requires Visual Studio C++ Build Tools." -ForegroundColor Yellow
Write-Host "[INFO] This is a large download (~2-4 GB) and requires admin privileges." -ForegroundColor Yellow
Write-Host ""
Write-Host "To install:" -ForegroundColor Cyan
Write-Host " 1. Download from: https://visualstudio.microsoft.com/visual-cpp-build-tools/" -ForegroundColor Cyan
Write-Host " 2. In the installer, select 'Desktop development with C++'" -ForegroundColor Cyan
Write-Host " 3. After installation, use 'Developer Command Prompt' or 'Developer PowerShell' for dumpbin access" -ForegroundColor Cyan
Write-Host ""
Write-Host "Alternatively, Ghidra can extract the same PE information (imports, exports, headers)." -ForegroundColor Green
Write-Host ""
exit 2
}
function Install-De4dot {
if (Get-Command de4dot -ErrorAction SilentlyContinue) {
Write-Ok "de4dot already installed"
return
}
Write-Info "Installing de4dot from GitHub..."
$tag = Get-GithubLatestTag "de4dot/de4dot"
if (-not $tag) {
Write-Manual "Could not determine latest de4dot version. Download from https://github.com/de4dot/de4dot/releases"
}
$installDir = "$env:USERPROFILE\.local\share\de4dot"
$tmpZip = "$env:TEMP\de4dot-download.zip"
# Find the appropriate asset
try {
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/de4dot/de4dot/releases/latest" -UseBasicParsing
$asset = $release.assets | Where-Object { $_.name -like "*.zip" } | Select-Object -First 1
if (-not $asset) {
Write-Manual "Could not find de4dot download. Download from https://github.com/de4dot/de4dot/releases"
}
$downloadUrl = $asset.browser_download_url
} catch {
Write-Manual "Could not access GitHub API. Download de4dot from https://github.com/de4dot/de4dot/releases"
}
if (-not (Download-File -Url $downloadUrl -Dest $tmpZip)) {
Write-Manual "Download failed. Download manually from $downloadUrl"
}
if (Test-Path $installDir) { Remove-Item -Recurse -Force $installDir }
New-Item -ItemType Directory -Path $installDir -Force | Out-Null
Expand-Archive -Path $tmpZip -DestinationPath $installDir -Force
Remove-Item $tmpZip -Force
# Find de4dot.exe
$de4dotExe = Get-ChildItem -Path $installDir -Recurse -Filter "de4dot.exe" | Select-Object -First 1
if ($de4dotExe) {
$binDir = "$env:USERPROFILE\.local\bin"
New-Item -ItemType Directory -Path $binDir -Force | Out-Null
Copy-Item $de4dotExe.FullName "$binDir\de4dot.exe" -Force
Add-ToUserPath $binDir
Write-Ok "de4dot installed to $binDir"
} else {
Write-Fail "Could not find de4dot.exe in extracted archive."
Write-Manual "Download and extract manually from https://github.com/de4dot/de4dot/releases"
}
}
# =====================================================================
# Dispatch
# =====================================================================
switch ($Dependency.ToLower()) {
'java' { Install-Java }
'ghidra' { Install-Ghidra }
'ilspycmd' { Install-IlspyCmd }
'dotnet-sdk' { Install-DotnetSdk }
'strings' { Install-Strings }
'dumpbin' { Install-Dumpbin }
'de4dot' { Install-De4dot }
default {
Write-Host "Error: Unknown dependency '$Dependency'" -ForegroundColor Red
Write-Host "Available: java, ghidra, ilspycmd, dotnet-sdk, strings, dumpbin, de4dot"
exit 1
}
}