Skip to content

Euarno/DecHint

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DecHint

Hex-Rays pseudocode expression simplification hints — a non-invasive annotation plugin for IDA Pro.

中文文档

Version 1.1.0 · IDA Pro 9.x + Hex-Rays · IDAPython 3.x


What It Does

DecHint walks the Hex-Rays ctree (expression AST) of a decompiled function, matches every sub-expression against a library of algebraic simplification rules, and surfaces the results as pseudocode comments and an interactive report dialog — without ever modifying the decompilation itself.

  • ❌ Does not alter the IDA database or the decompiled output
  • ✅ All suggestions are displayed as removable [DH]-prefixed comments
  • ✅ Conservative by design — false negatives over false positives

Installation

Copy the entire dechint/ folder into IDA's plugins directory:

<IDA_INSTALL>/plugins/dechint/

IDA 9.x automatically discovers ida-plugin.json inside sub-directories and loads the plugin on startup. No manual registration required.

Directory Structure

dechint/
├── ida-plugin.json              # IDA 9.x plugin descriptor
├── dechint_entry.py             # Entry point (PLUGIN_ENTRY)
├── __init__.py
├── LICENSE                      # MIT License
├── README.md                    # This file (English)
├── README_CN.md                 # 中文文档
├── dh_core/
│   ├── plugin.py                # plugin_t + action registration + UI hooks
│   ├── analyzer.py              # 4-layer analysis pipeline (Match → Normalize → Conflict Resolution → Render)
│   ├── rules.py                 # Rule engine — 35 simplification rules
│   ├── expr_utils.py            # Expression helpers (type checks, structural matching, pretty-print, side-effect analysis)
│   ├── models.py                # Data models (RewriteHint, confidence levels)
│   ├── settings.py              # Runtime settings
│   └── comment_writer.py        # Write hints as pseudocode comments via treeloc_t
└── dh_ui/
    ├── report_window.py          # PyQt5 report dialog with checkboxes
    └── settings_dialog.py        # PyQt5 settings dialog

Usage

Quick Start

  1. Open a binary in IDA and press F5 to decompile a function.
  2. Press Ctrl+Shift+H (or Edit → Plugins → DecHint) to analyze.
  3. An interactive report table pops up with all detected simplifications.
  4. Check the hints you want, then click "Write Selected" to insert them as pseudocode comments.

Right-Click Menu

In any pseudocode view, right-click to find the DecHint/ submenu:

Action Description
Analyze Current Function Run analysis & open the report (Ctrl+Shift+H)
Settings… Open the settings dialog

Report Dialog Features

  • Checkbox per row — select which hints to write as comments
  • Filter by confidence — toggle Safe / Conditional visibility
  • Text search — filter by rule name, expression text, etc.
  • Write Selected / Write All / Clear Comments buttons
  • Double-click any row to jump to that address in IDA
  • Copy results to clipboard
  • Refresh to re-analyze without reopening

Settings

Option Default Description
Show safe rules Display results from safe (always-valid) rules
Show conditional rules Display results from conditional rules
Show candidate rules Display low-confidence candidates
Max hints per line 2 Cap hints written to a single pseudocode line

Analysis Pipeline

The analyzer uses a 4-layer pipeline:

Layer Purpose
1. Match Full scan — every rule runs on every expression node. No early break.
2. Normalize Deduplicate exact copies (same address + rule + rewrite text).
3. Conflict Resolution Per-address: larger expression span wins → safe beats conditional → higher priority wins → substring subsumption across all addresses.
4. Render Two outputs: report (near-full list for the dialog) and comments (strict conflict-resolved subset for writing).

Rules (35 total)

Safe Rules — always valid

Rule Pattern Simplifies To
div-mul-mod-identity a*(x/a) + x%a x
sub-div-mul-to-mod x - (x/a)*a x % a
base-plus-div-mul-mod base + a*(x/a) + x%a base + x
nested-mod-identity ((x%a)/b)*b + (x%a)%b x % a
redundant-cast (T)(T)x (T)x
linear-index-normalize N*((x%M)/N) + (x%M)%N x % M
array-index-simplify arr[complex_index] arr[simplified]
add-zero x + 0 x
mul-one x * 1 x
xor-self x ^ x 0
sub-self x - x 0
double-neg -(-x) x
double-bnot ~(~x) x
or-self x | x x
and-self x & x x
shift-by-zero x << 0 / x >> 0 x
and-all-ones x & 0xFFFFFFFF x
xor-zero x ^ 0 x
or-zero x | 0 x
xor-all-ones x ^ 0xFF…F ~x

Conditional Rules — require assumptions

Rule Pattern Simplifies To Assumption
mul-zero x * 0 0 No side effects
and-zero x & 0 0 No side effects
or-all-ones x | 0xFF…F 0xFF…F No side effects
mul-pow2-to-shift x * 2^k x << k Integer equivalence
div-pow2-to-shift x / 2^k x >> k Unsigned / non-negative
mod-pow2-to-and x % 2^k x & (2^k-1) Unsigned / non-negative
and-to-mod-pow2 x & (2^k-1) x % 2^k Readability
twos-complement-add-normalize x + 0x61C88647 x - 0x9E3779B9 uint32 two's complement
twos-complement-sub-normalize x - 0xFFFFFFFF x + 1 uint32 two's complement
shift-mask-explain (x >> k) << k x & ~mask Shift-mask equivalence
sub-shift-mask-to-mod x - ((x>>k)<<k) x % 2^k Unsigned / non-negative
mul-neg-one x * 0xFF…F -x Two's complement
add-neg-const x + 0xFFFFFFFC x - 4 Two's complement
add-self x + x x << 1 Equivalence
shl-one-to-pow2 1 << k 2^k Readability

Comment Format

Comments injected into pseudocode are prefixed with [DH] for easy identification and bulk removal:

// [DH] dword_51A0[((8 * ((v3 % 64) / 8)) + ((v3 % 64) % 8))]
// [DH]   =>  dword_51A0[v3 % 64]
// [DH]   [safe] rule: array-index-simplify
// [DH] (x + 0x61C88647)
// [DH]   =>  (x - 0x9E3779B9)
// [DH]   assume: uint32 two's complement
// [DH]   [conditional] rule: twos-complement-add-normalize

The Clear Comments button removes all [DH]-prefixed lines without touching user-written comments.


Technical Notes

Comment Placement (treeloc_t)

Hex-Rays pseudocode comments are placed via cfunc_t.set_user_cmt(treeloc_t, text).

  • Normal statement lines (ending with ;): positioned using get_line_item() → ptail.loc.
  • Control-structure heads (if / while / for / switch): a parent-aware CV_PARENTS visitor builds an expr_ea → enclosing control cinsn_t map, then uses treeloc_t { insn.ea, ITP_BLOCK1 } — the same coordinate IDA uses when users press / to comment.

Expression Equality

exprs_equal() performs structural comparison with commutative awareness — for operators like +, *, &, |, ^, it also checks the swapped operand order.

Side-Effect Analysis

is_side_effect_free() recursively checks whether an expression contains calls, assignments, or pre/post-increment operations. Rules like mul-zero and and-zero use this to decide between SAFE and CONDITIONAL confidence.


Known Limitations

  1. Single-function, single-expression scope — no inter-procedural analysis
  2. Type inference depends on Hex-Rays — missing types may prevent some conditional rules from firing
  3. Settings are session-only (not persisted across IDA restarts)

License

MIT License — Copyright © 2026 Euarno

About

A non-invasive IDA Pro plugin that analyzes Hex-Rays pseudocode ctree AST and surfaces algebraic expression simplification hints as comments and an interactive report. 35 rules, 4-layer pipeline, zero database modification.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages