Skip to content

Commit e58f96b

Browse files
committed
initial commit
0 parents  commit e58f96b

File tree

3 files changed

+164
-0
lines changed

3 files changed

+164
-0
lines changed

Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "dump-diff"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
capstone = "0.12.0"
8+
clap = { version = "4.5.4", features = ["derive"] }
9+
clap-num = "1.1.1"

readme.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# dump-diff
2+
3+
Crude diff tools for assembly binary blobs
4+
5+
## usage
6+
7+
```console
8+
Usage: dump-diff [OPTIONS] --target <TARGET> --current <CURRENT> --addr <ADDR> --arch <ARCH> --mode <MODE>
9+
10+
Options:
11+
-t, --target <TARGET> Target
12+
-c, --current <CURRENT> Current
13+
-x, --addr <ADDR> Address
14+
-a, --arch <ARCH> Architecture
15+
-m, --mode <MODE> Mode
16+
-e, --endianness <ENDIANNESS> Endianness
17+
-h, --help Print help
18+
```
19+
20+
- TARGET: the target binary
21+
- CURRENT: your current compiled code
22+
- ADDR: the (virtual) memory address where the code is located at.
23+
- ARCH: the [architecture](https://docs.rs/capstone/latest/capstone/enum.Arch.html)
24+
- MODE: the [mode](https://docs.rs/capstone/latest/capstone/enum.Mode.html)
25+
- ENDIANNESS: big or little (defaults: little)
26+
27+
⚠️ WARNING ⚠️ The tool doesn't check the arch/mode tuple, so you can ask for ARM64 + RiscV64 (and it will panic).
28+
29+
## Example
30+
31+
```console
32+
$ dump-diff -t target.bin -c current.bin -x 0x821843e8 -a ppc -m mode32 -e big
33+
mflr r12 mflr r12
34+
stw r12, -8(r1) stw r12, -8(r1)
35+
std r30, -0x18(r1) std r30, -0x18(r1)
36+
std r31, -0x10(r1) std r31, -0x10(r1)
37+
stfd f31, -0x20(r1) stfd f31, -0x20(r1)
38+
stwu r1, -0x80(r1) stwu r1, -0x80(r1)
39+
lfs f31, 0x54(r3) mr r31, r3 <===========
40+
mr r31, r3 mr r30, r4 <===========
41+
mr r30, r4 lfs f31, 0x54(r31) <===========
42+
bl 0x8210fb68 bl 0x8210fb68
43+
extsh r11, r30 extsh r11, r30
44+
lis r10, -0x7dff lis r10, -0x7dff
45+
std r11, 0x50(r1) std r11, 0x50(r1)
46+
lfd f0, 0x50(r1) lfd f0, 0x50(r1)
47+
fcfid f0, f0 fcfid f0, f0
48+
lis r9, -0x7e00 lis r9, -0x7e00
49+
frsp f12, f0 frsp f12, f0
50+
lfd f0, -0x3fb0(r10) lfd f0, -0x3fb0(r10)
51+
lfs f13, 0x1580(r9) lfs f13, 0x1580(r9)
52+
fmuls f12, f1, f12 fmuls f12, f1, f12
53+
fmsub f0, f12, f0, f31 fnmsub f0, f12, f0, f31 <===========
54+
frsp f0, f0 frsp f0, f0
55+
fcmpu cr6, f0, f13 fcmpu cr6, f0, f13
56+
blt cr6, 0x82184450 blt cr6, 0x82184450
57+
fsubs f0, f0, f13 fsubs f0, f0, f13
58+
b 0x82184464 b 0x82184464
59+
lis r11, -0x7e00 lis r11, -0x7e00
60+
lfs f12, 0x7a0(r11) lfs f12, 0x7a0(r11)
61+
fcmpu cr6, f0, f12 fcmpu cr6, f0, f12
62+
bge cr6, 0x82184464 bge cr6, 0x82184464
63+
fadds f0, f0, f13 fadds f0, f0, f13
64+
stfs f0, 0x54(r31) stfs f0, 0x54(r31)
65+
addi r1, r1, 0x80 addi r1, r1, 0x80
66+
lwz r12, -8(r1) lwz r12, -8(r1)
67+
mtlr r12 mtlr r12
68+
lfd f31, -0x20(r1) lfd f31, -0x20(r1)
69+
ld r30, -0x18(r1) ld r30, -0x18(r1)
70+
ld r31, -0x10(r1) ld r31, -0x10(r1)
71+
blr blr
72+
```

src/main.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use std::io::Read;
2+
use std::fs::File;
3+
use clap::Parser;
4+
use clap_num::maybe_hex;
5+
use capstone::prelude::*;
6+
7+
/// Compare compiled assembly
8+
#[derive(Parser, Debug)]
9+
#[command(author = None, version = None, about = None, long_about = None)]
10+
struct Args {
11+
/// Target
12+
#[arg(short, long)]
13+
target: String,
14+
15+
/// Current
16+
#[arg(short, long)]
17+
current: String,
18+
19+
/// Address
20+
#[arg(short='x', long, value_parser=maybe_hex::<u32>)]
21+
addr: u32,
22+
23+
/// Architecture
24+
#[arg(short, long)]
25+
arch: capstone::Arch,
26+
27+
/// Mode
28+
#[arg(short, long)]
29+
mode: capstone::Mode,
30+
31+
/// Endianness
32+
#[arg(short, long)]
33+
endianness: Option<capstone::Endian>,
34+
}
35+
36+
const ALIGNMENT: usize = 30;
37+
fn main() {
38+
let args = Args::parse();
39+
40+
let cs = Capstone::new_raw(args.arch, args.mode, capstone::NO_EXTRA_MODE, args.endianness).expect("Can't create capstone engine");
41+
42+
let current = disassemble(&cs, &args.current, args.addr);
43+
let target = disassemble(&cs, &args.target, args.addr);
44+
let min_size = std::cmp::min(current.len(), target.len());
45+
let max_size = std::cmp::max(current.len(), target.len());
46+
47+
for i in 0..min_size {
48+
print!("{}{}{}", current[i], " ".repeat(ALIGNMENT - current[i].len()), target[i]);
49+
if current[i] != target[i] {
50+
print!("{}<===========", " ".repeat(ALIGNMENT - target[i].len()));
51+
}
52+
println!("");
53+
}
54+
55+
for i in min_size..max_size {
56+
if current.len() < min_size {
57+
print!("{}{}", current[i], " ".repeat(ALIGNMENT - current[i].len()));
58+
} else {
59+
print!("{}", " ".repeat(ALIGNMENT));
60+
}
61+
if target.len() < min_size {
62+
print!("{}", target[i]);
63+
}
64+
println!("");
65+
}
66+
}
67+
68+
fn disassemble(cs: &Capstone, file: &str, vram: u32) -> Vec<String> {
69+
let mut f = File::open(file).unwrap();
70+
let mut buffer = Vec::new();
71+
f.read_to_end(&mut buffer).unwrap();
72+
73+
let insns = cs.disasm_all(&buffer, vram as u64).expect("Failed to disassemble");
74+
75+
let mut insts = vec![];
76+
for i in insns.as_ref() {
77+
let op_str = i.op_str().unwrap_or("");
78+
let inst = i.mnemonic().unwrap();
79+
insts.push(format!("{inst} {op_str}"));
80+
}
81+
82+
insts
83+
}

0 commit comments

Comments
 (0)