Skip to content

Commit 6b404af

Browse files
sandhrabinowargio
authored andcommitted
Diff documentation (#61)
* Adding rz-diff documentation with examples and changing iS output for Sections * remove spaces * Add -S option * Resolve suggestions * Resolve suggestions * remove diff definition
1 parent 616cabd commit 6b404af

2 files changed

Lines changed: 232 additions & 94 deletions

File tree

Lines changed: 193 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,217 @@
1-
# Binary Diffing
1+
# Rz-Diff (binary and text diffing utility)
22

3-
This section is based on the http://rizin.today article "[binary diffing](https://rizinorg.github.io/blog/posts/binary-diffing/)"
3+
## Distance
44

5-
Without any parameters, `rz-diff` by default shows what bytes are changed and their corresponding offsets:
5+
For bulk processing, you may want to have a higher-level overview of differences.
6+
7+
The `-d` option serves to calculate the distance between the two binaries using either myers algorithm or the levenshtein algorithm.
8+
9+
```
10+
-d --------> myers (myers algorithm)
11+
|----> leven (levenshtein algorithm)
12+
```
13+
14+
### Myers algorithm:
15+
16+
In the [Myers](https://epubs.siam.org/doi/10.1137/S0097539794264810) algorithm for edit distance, the cost of an insertion or deletion is 1 and the cost of a replacement is 2.
17+
The theorem leads directly to an O(k) algorithm for incrementally computing a new solution from an old one, as contrasts the O(k2 ) time required to compute a solution from scratch.
18+
Thus the algorithm performs well when the two strings are similar.
19+
20+
`rz-diff -d myers /bin/true /bin/false`
21+
22+
output:
23+
```
24+
similarity: 0.974
25+
distance: 2046
26+
```
27+
28+
### Levenshtein distance:
29+
30+
[Levenshtein](https://en.wikipedia.org/wiki/Levenshtein_distance) distance is a string metric for measuring the difference between two sequences. Informally, the Levenshtein distance between two words is the minimum number of single-character edits (insertions, deletions or substitutions) required to change one word into the other.
31+
32+
`rz-diff -d leven /bin/true /bin/false`
33+
34+
output:
35+
```
36+
similarity: 0.974
37+
distance: 2046
38+
```
39+
40+
## Hexadecimal Diffing:
41+
42+
`-H` The hexadecimal displays the hexdump of file0 vs file1 in a side-by-side window. Navigational keys allows easily parsing through the hexdump of the files individually.
43+
44+
- `1` and `2` : to move to the next or previous page.
45+
- `Z` and `A` : allows parsing forward and backward through file0, byte by byte.
46+
- `C` and `D` : allows parsing forward and backward through file1, byte by byte.
47+
- `G` and `B` : seeks the end and beginning of the files.
48+
- `N` and `M` : takes you to the Next and the Previous differing byte in the files respectively.
49+
- `/\` and `\/` : parsing both binaries simultaneously, 16 bytes a time.
50+
- `<` and `>` : parsing both binaries simultaneously, by 1 byte.
51+
- `: <seek address in hex/decimal>` : seeks the address provided and bring the window to start dump from the seeked address.
52+
- `?` : shows the help screen in the visual mode which can be exited with 'q'/esc keys.
53+
54+
The bytes that differ are: `rz-diff -H /bin/true /bin/false`
55+
56+
```
57+
.---------- [ 0 | 9958]( true )-------------------------------------------------------------------- [ 0 | 9958]( false )---------------------------------------------------------.
58+
| 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F |
59+
|0x0000000000000000 | 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 | .ELF............ | 0x0000000000000000 | 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 | .ELF............ |
60+
|0x0000000000000010 | 03 00 3e 00 01 00 00 00 10 26 00 00 00 00 00 00 | ..>......&...... | 0x0000000000000010 | 03 00 3e 00 01 00 00 00 20 26 00 00 00 00 00 00 | ..>..... &...... |
61+
|0x0000000000000020 | 40 00 00 00 00 00 00 00 d8 91 00 00 00 00 00 00 | @............... | 0x0000000000000020 | 40 00 00 00 00 00 00 00 d8 91 00 00 00 00 00 00 | @............... |
62+
|0x0000000000000030 | 00 00 00 00 40 00 38 00 0d 00 40 00 1e 00 1d 00 | ....@.8...@..... | 0x0000000000000030 | 00 00 00 00 40 00 38 00 0d 00 40 00 1e 00 1d 00 | ....@.8...@..... |
63+
|0x0000000000000040 | 06 00 00 00 04 00 00 00 40 00 00 00 00 00 00 00 | ........@....... | 0x0000000000000040 | 06 00 00 00 04 00 00 00 40 00 00 00 00 00 00 00 | ........@....... |
64+
|0x0000000000000050 | 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 | @.......@....... | 0x0000000000000050 | 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 | @.......@....... |
65+
|0x0000000000000060 | d8 02 00 00 00 00 00 00 d8 02 00 00 00 00 00 00 | ................ | 0x0000000000000060 | d8 02 00 00 00 00 00 00 d8 02 00 00 00 00 00 00 | ................ |
66+
|0x0000000000000070 | 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00 | ................ | 0x0000000000000070 | 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00 | ................ |
67+
|0x0000000000000080 | 18 03 00 00 00 00 00 00 18 03 00 00 00 00 00 00 | ................ | 0x0000000000000080 | 18 03 00 00 00 00 00 00 18 03 00 00 00 00 00 00 | ................ |
68+
|0x0000000000000090 | 18 03 00 00 00 00 00 00 1c 00 00 00 00 00 00 00 | ................ | 0x0000000000000090 | 18 03 00 00 00 00 00 00 1c 00 00 00 00 00 00 00 | ................ |
69+
70+
...
71+
|0x00000000000002f0 | 30 9c 00 00 00 00 00 00 30 9c 00 00 00 00 00 00 | 0.......0....... | 0x00000000000002f0 | 30 9c 00 00 00 00 00 00 30 9c 00 00 00 00 00 00 | 0.......0....... |
72+
|0x0000000000000300 | d0 03 00 00 00 00 00 00 d0 03 00 00 00 00 00 00 | ................ | 0x0000000000000300 | d0 03 00 00 00 00 00 00 d0 03 00 00 00 00 00 00 | ................ |
73+
`------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------'
74+
1 2 -/+0x320 | Z A file0 +/-1 | C D file1 +/-1 | G B end/begin | N M next/prev | \//\ +/-16 | < > +/-1 | : seek
75+
76+
```
77+
78+
`-S` mode allows you to adjust the window size of the hexadecimal view to your preference.
79+
Minimmum: `W = 120 H = 20`
80+
81+
Example : `rz-diff -HS 120x20 /bin/true /bin/false`
82+
83+
### File Type Based Diffing
84+
85+
`t` option computes the difference between two files based on its type.
86+
87+
```
88+
-t --------> bytes (raw bytes in the files)
89+
|----> lines (compares text files)
90+
|----> functions (compares functions found in the files)
91+
|----> classes (compares classes found in the files)
92+
|----> command (compares command output returned when executed)
93+
|----> entries (compares entries found in the files)
94+
|----> fields (compares fields found in the files)
95+
|----> graphs (compares 2 functions and outputs in graphviz/dot format)
96+
|----> format (compares text files)
97+
|----> imports (compares imports found in the files)
98+
|----> libraries (compares libraries found in the files)
99+
|----> sections (compares sections found in the files)
100+
|----> strings (compares sections found in the files)
101+
|----> symbols (compares symbols found in the files)
102+
103+
```
104+
105+
### Diffing ASCII-text files:
106+
107+
` $ rz-diff -t lines genuine cracked`
6108
```
7-
$ rz-diff genuine cracked
8-
0x000081e0 85c00f94c0 => 9090909090 0x000081e0
9-
0x0007c805 85c00f84c0 => 9090909090 0x0007c805
109+
--- genuine
110+
+++ cracked
111+
@@ -1,1 +1,1 @@
112+
-hello1234567890
113+
+1234567890hello
114+
```
115+
116+
### Diffing functions in binaries:
117+
118+
It this mode, it will give you three columns for all functions: "First file offset", "Percentage of matching" and "Second file offset".
119+
120+
` $ rz-diff -t functions /bin/true /bin/false`
10121

11-
$ rz-asm -d 85c00f94c0
12-
test eax, eax
13-
sete al
14122
```
15-
Notice how the two jumps are nop'ed.
123+
sym.imp.__fprintf_chk 11 0x00000000000024e0 | MATCH (1.000000) | 0x00000000000024e0 11 sym.imp.__fprintf_chk
124+
sym.imp.mbsinit 11 0x00000000000024f0 | MATCH (1.000000) | 0x00000000000024f0 11 sym.imp.mbsinit
125+
sym.imp.iswprint 11 0x0000000000002500 | MATCH (1.000000) | 0x0000000000002500 11 sym.imp.iswprint
126+
sym.imp.__ctype_b_loc 11 0x0000000000002510 | MATCH (1.000000) | 0x0000000000002510 11 sym.imp.__ctype_b_loc
127+
fcn.00002640 34 0x0000000000002640 | UNMATCH (0.058824) | 0x0000000000002650 34 fcn.00002650
128+
fcn.00002700 840 0x0000000000002700 | UNMATCH (0.221163) | 0x0000000000002710 840 fcn.00002710
129+
fcn.00002b30 176 0x0000000000002b30 | UNMATCH (0.173077) | 0x0000000000002b40 176 fcn.00002b40
130+
fcn.00002bf0 208 0x0000000000002bf0 | SIMILAR (0.961538) | 0x0000000000002c00 208 fcn.00002c00
131+
fcn.00002cd0 4627 0x0000000000002cd0 | SIMILAR (0.993949) | 0x0000000000002ce0 4627 fcn.00002ce0
132+
```
133+
134+
### Diffing classes in binaries:
135+
136+
`rz-diff -t functions /bin/true /bin/false`
16137

17-
For bulk processing, you may want to have a higher-level overview of differences. This is why rizin is able to compute the distance and the percentage of similarity between two files with the `-s` option:
18138
```
19-
$ rz-diff -s /bin/true /bin/false
20-
similarity: 0.97
21-
distance: 743
139+
--- /bin/true
140+
+++ /bin/false
22141
```
23142

24-
If you want more concrete data, it's also possible to count the differences, with the `-c` option:
143+
### Commands
144+
145+
146+
### Diffing entries in binaries
147+
148+
`rz-diff -t entries /bin/true /bin/false`
149+
25150
```
26-
$ rz-diff -c genuine cracked
27-
2
151+
--- /bin/true
152+
+++ /bin/false
153+
@@ -1,3 +1,3 @@
154+
-virt: 0x00000000000026f0 phys: 0x00000000000026f0 entry init
155+
-virt: 0x00000000000026b0 phys: 0x00000000000026b0 entry fini
156+
-virt: 0x0000000000002610 phys: 0x0000000000002610 entry program
157+
+virt: 0x0000000000002700 phys: 0x0000000000002700 entry init
158+
+virt: 0x00000000000026c0 phys: 0x00000000000026c0 entry fini
159+
+virt: 0x0000000000002620 phys: 0x0000000000002620 entry program
160+
28161
```
29162

30-
If you are unsure whether you are dealing with similar binaries, with `-C` flag you can check there are matching functions. It this mode, it will give you three columns for all functions: "First file offset", "Percentage of matching" and "Second file offset".
163+
### Diffing fields in binaries:
164+
165+
`rz-diff -t fields /bin/true /bin/false `
31166

32167
```
33-
$ rz-diff -C /bin/false /bin/true
34-
entry0 0x4013e8 | MATCH (0.904762) | 0x4013e2 entry0
35-
sym.imp.__libc_start_main 0x401190 | MATCH (1.000000) | 0x401190 sym.imp.__libc_start_main
36-
fcn.00401196 0x401196 | MATCH (1.000000) | 0x401196 fcn.00401196
37-
fcn.0040103c 0x40103c | MATCH (1.000000) | 0x40103c fcn.0040103c
38-
fcn.00401046 0x401046 | MATCH (1.000000) | 0x401046 fcn.00401046
39-
fcn.000045e0 24 0x45e0 | UNMATCH (0.916667) | 0x45f0 24 fcn.000045f0
40-
...
168+
--- /bin/true
169+
+++ /bin/false
41170
```
42-
Moreover, we can ask rz-diff to perform analysis first - adding `-A` option will run `aaa` on the binaries.
43-
And we can specify binaries architecture for this analysis too using
171+
172+
### Diffing sections in binaries:
173+
174+
`rz-diff -t sections /bin/true /bin/false`
175+
44176
```
45-
$ rz-diff -AC -a x86 /bin/true /bin/false | grep UNMATCH
46-
[x] Analyze all flags starting with sym. and entry0 (aa)
47-
[x] Analyze len bytes of instructions for references (aar)
48-
[x] Analyze function calls (aac)
49-
[ ] [*] Use -AA or aaaa to perform additional experimental analysis.
50-
[x] Constructing a function name for fcn.* and sym.func.* functions (aan))
51-
[x] Analyze all flags starting with sym. and entry0 (aa)
52-
[x] Analyze len bytes of instructions for references (aar)
53-
[x] Analyze function calls (aac)
54-
[ ] [*] Use -AA or aaaa to perform additional experimental analysis.
55-
[x] Constructing a function name for fcn.* and sym.func.* functions (aan))
56-
sub.fileno_500 86 0x4500 | UNMATCH (0.965116) | 0x4510 86 sub.fileno_510
57-
sub.__freading_4c0 59 0x44c0 | UNMATCH (0.949153) | 0x44d0 59 sub.__freading_4d0
58-
sub.fileno_440 120 0x4440 | UNMATCH (0.200000) | 0x4450 120 sub.fileno_450
59-
sub.setlocale_fa0 64 0x3fa0 | UNMATCH (0.104651) | 0x3fb0 64 sub.setlocale_fb0
60-
fcn.00003a50 120 0x3a50 | UNMATCH (0.125000) | 0x3a60 120 fcn.00003a60
177+
178+
--- /bin/true
179+
+++ /bin/false
61180
```
62181

63-
And now a cool feature : rizin supports graph-diffing, à la [DarunGrim](http://www.darungrim.org/), with the `-g` option. You can either give it a symbol name, of specify two offsets, if the function you want to diff is named differently in compared files. For example, `rz-diff -md -g main /bin/true /bin/false | xdot -` will show differences in `main()` function of Unix `true` and `false` programs. You can compare it to `rz-diff -md -g main /bin/false /bin/true | xdot -` (Notice the order of the arguments) to get the two versions.
64-
This is the result:
182+
### Diffing strings in binaries:
65183

66-
![/bin/true vs /bin/false](img/true_false2.png)
184+
`rz-diff -t strings /bin/true /bin/false`
67185

68-
Parts in yellow indicate that some offsets do not match. The grey piece means a perfect match. The orange one highlights a strong difference. If you look closely, you will see that the left part of the picture has `mov eax, 0x1; pop rbx; pop rbp; ret`, while the right one has `xor edx, edx; pop rbx; pop rbp; ret`.
186+
```
187+
--- /bin/true
188+
+++ /bin/false
189+
@@ -11,7 +11,7 @@
190+
Written by %s, %s, %s,\n%s, %s, %s, %s,\nand %s.\n
191+
Copyright %s %d Free Software Foundation, Inc.
192+
--help display this help and exit\n
193+
-Exit with a status code indicating success.
194+
+Exit with a status code indicating failure.
195+
Written by %s, %s, %s,\n%s, %s, %s, and %s.\n
196+
Written by %s, %s, %s,\n%s, %s, and %s.\n
197+
https://www.gnu.org/software/coreutils/
198+
@@ -51,7 +51,7 @@
199+
--help
200+
ASCII
201+
POSIX
202+
+false
203+
shell
204+
%s\n\n
205+
8.30
206+
-true
69207
70-
Binary diffing is an important feature for reverse engineering. It can be used to analyze [security updates](https://en.wikipedia.org/wiki/Patch_Tuesday), infected binaries, firmware changes and more...
208+
```
71209

72-
We have only shown the code analysis diffing functionality, but rizin supports additional types of diffing between two binaries: at byte level, deltified similarities, and more to come.
210+
### Diffing symbols in binaries:
73211

74-
We have plans to implement more kinds of bindiffing algorithms into rizin, and why not, add support for ASCII art graph diffing and better integration with the rest of the toolkit.
212+
`rz-diff -t symbols /bin/true /bin/false`
75213

214+
```
215+
--- /bin/true
216+
+++ /bin/false
217+
```

src/tools/rz-diff/intro.md

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,44 @@
44

55
```
66
$ rz-diff -h
7-
Usage: rz-diff [-abBcCdjrspOxuUvV] [-A[A]] [-g sym] [-m graph_mode][-t %] [file] [file]
8-
-a [arch] specify architecture plugin to use (x86, arm, ..)
9-
-A [-A] run aaa or aaaa after loading each binary (see -C)
10-
-b [bits] specify register size for arch (16 (thumb), 32, 64, ..)
11-
-B output in binary diff (GDIFF)
12-
-c count of changes
13-
-C graphdiff code (columns: off-A, match-ratio, off-B) (see -A)
14-
-d use delta diffing
15-
-D show disasm instead of hexpairs
16-
-e [k=v] set eval config var value for all RzCore instances
17-
-g [sym|off1,off2] graph diff of given symbol, or between two offsets
18-
-G [cmd] run an rizin command on every RzCore instance created
19-
-i diff imports of target files (see -u, -U and -z)
20-
-j output in json format
21-
-n print bare addresses only (diff.bare=1)
22-
-m [aditsjJ] choose the graph output mode
23-
-O code diffing with opcode bytes only
24-
-p use physical addressing (io.va=0)
25-
-q quiet mode (disable colors, reduce output)
26-
-r output in rizin commands
27-
-s compute edit distance (no substitution, Eugene W. Myers' O(ND) diff algorithm)
28-
-ss compute Levenshtein edit distance (substitution is allowed, O(N^2))
29-
-S [name] sort code diff (name, namelen, addr, size, type, dist) (only for -C or -g)
30-
-t [0-100] set threshold for code diff (default is 70%)
31-
-x show two column hexdump diffing
32-
-X show two column hexII diffing
33-
-u unified output (---+++)
34-
-U unified output using system 'diff'
35-
-v show version information
36-
-V be verbose (current only for -s)
37-
-z diff on extracted strings
38-
-Z diff code comparing zignatures
39-
40-
Graph Output formats: (-m [mode])
41-
<blank/a> Ascii art
42-
s rizin commands
43-
d Graphviz dot
44-
g Graph Modelling Language (gml)
45-
j json
46-
J json with disarm
47-
k SDB key-value
48-
t Tiny ascii art
49-
i Interactive ascii art
7+
Usage: rz-diff [options] <file0> <file1>
8+
-a [arch] specify architecture plugin to use (x86, arm, ..)
9+
-b [bits] specify register size for arch (16 (thumb), 32, 64, ..)
10+
-d [algo] compute edit distance based on the choosen algorithm:
11+
myers | Eugene W. Myers' O(ND) algorithm (no substitution)
12+
leven | Levenshtein O(N^2) algorithm (with substitution)
13+
-H hexadecimal visual mode
14+
-h this help message
15+
-j json output
16+
-q quite output
17+
-v show version information
18+
-A compare virtual and physical addresses
19+
-C disable colors
20+
-T show timestamp information
21+
-S [WxH] sets the width and height of the terminal for visual mode
22+
-0 [cmd] input for file0 when option -t 'commands' is given.
23+
the same value will be set for file1, if -1 is not set.
24+
-1 [cmd] input for file1 when option -t 'commands' is given.
25+
-t [type] compute the difference between two files based on its type:
26+
bytes | compares raw bytes in the files (only for small files)
27+
lines | compares text files
28+
functions | compares functions found in the files
29+
classes | compares classes found in the files
30+
command | compares command output returned when executed in both files
31+
| requires -0 <cmd> and -1 <cmd> is optional
32+
entries | compares entries found in the files
33+
fields | compares fields found in the files
34+
graphs | compares 2 functions and outputs in graphviz/dot format
35+
| requires -0 <fcn name|offset> and -1 <fcn name|offset> is optional
36+
imports | compares imports found in the files
37+
libraries | compares libraries found in the files
38+
sections | compares sections found in the files
39+
strings | compares strings found in the files
40+
symbols | compares symbols found in the files
41+
palette colors can be changed by adding the following lines
42+
inside the $HOME/.rizinrc file
43+
ec diff.unknown blue | offset color
44+
ec diff.match green | match color
45+
ec diff.unmatch red | mismatch color
5046
```
5147

0 commit comments

Comments
 (0)