Skip to content

Commit f6ea905

Browse files
committed
Binary Rewriting *WITH* Control-Flow Recovery
This change makes it possible to rewrite binaries using Control-Flow Recovery (CFR). To enable, simply pass "-X" to E9Tool: $ ./e9tool -X ... This will enable a heuristic-based CFR analysis in E9Patch, and the binary will be rewritten using this information. Without the "-X", the binary will be rewritten without CFR, which is the classic E9Patch mode. PROS (with -X): - The rewritten binary will be much faster - The patching coverage will be much higher - The rewriting speed will be improved CONS (with -X): - If the heuristic-based CFR is inaccurate, the rewritten binary may be broken/buggy. Thus, the -X mode provides much weaker guarantees. That said, the CFR analysis is designed to be an overapproximation that should work for all binaries compiled with standard compilers such as gcc or clang. The CFR does *NOT* assume disassembly/symbols and can handle classic problems like data-in-code. It appears to work for most binaries. (The only incompatible binary found thus far is E9Patch itself, which contains code that delibrately attempts to confuse CFR analysis). Whether the performance vs. accuracy trade-off is acceptable depends on the application. The -X mode is generally much faster, and closes the performance gap with inline-based binary rewriting tools like RetroWrite. Internally, CFR enables a new rewriting tactic "T0" that batches together instructions that are not jump targets into a single trampoline. This significantly improves locality and reduces jumps, improving performance. This also improves patching coverage, since instruction batches are easier to patch, and generally do not need to rely on instruction punning.
1 parent 35d1059 commit f6ea905

16 files changed

Lines changed: 1122 additions & 232 deletions

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CXXFLAGS = -std=c++11 -Wall -Wno-reorder -fPIC -pie -march=native \
55
-DVERSION=$(shell cat VERSION)
66

77
E9PATCH_OBJS=\
8+
src/e9patch/e9CFR.o \
89
src/e9patch/e9alloc.o \
910
src/e9patch/e9api.o \
1011
src/e9patch/e9elf.o \
@@ -54,6 +55,9 @@ tool.debug: $(E9TOOL_OBJS)
5455
$(CXX) $(CXXFLAGS) $(E9TOOL_OBJS) -o e9tool libZydis.a \
5556
-Wl,--dynamic-list=src/e9tool/e9tool.syms -ldl
5657

58+
tool.clean:
59+
rm -rf $(E9TOOL_OBJS) e9tool
60+
5761
loader_elf:
5862
$(CXX) -std=c++11 -Wall -fno-stack-protector -Wno-unused-function -fPIC \
5963
-Os -c src/e9patch/e9loader_elf.cpp
@@ -71,6 +75,6 @@ src/e9patch/e9elf.o: loader_elf
7175
src/e9patch/e9pe.o: loader_pe
7276

7377
clean:
74-
rm -rf $(E9PATCH_OBJS) $(E9TOOL_OBJS) e9tool.o e9patch e9tool a.out \
78+
rm -rf $(E9PATCH_OBJS) e9patch \
7579
src/e9patch/e9loader.c e9loader.out e9loader.o e9loader.bin
7680

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.0.0-rc2
1+
1.0.0-CFR

build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ EOF
8787
fi
8888

8989
echo -e "${GREEN}$0${OFF}: building e9patch and e9tool..."
90-
make clean
90+
make tool.clean clean
9191
make -j `nproc` tool release
9292

9393
echo -e "${GREEN}$0${OFF}: done...!"

doc/e9patch.1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ The final phase prints the physical memory utilization:
4242
.PP
4343

4444
.SH OPTIONS
45+
.IP "\fB\-OCFR\fR[=\fI\,false\/\fR]" 4
46+
Enables [disables] heuristic-based "Control-Flow Recovery"
47+
(CRF) analysis and related optimizations. This usually makes
48+
the rewritten binary much faster, but may introduce rewriting
49+
bugs if the built-in CRF analysis is inaccurate.
50+
.br
51+
Default: \fBfalse\fR (disabled)
4552
.IP "\fB\-Oepilogue\fR=\fI\,N\/\fR" 4
4653
Append a epilogue of up to N instructions to the end of each
4754
trampoline. This may enhance \fB\-Opeephole\fR.

doc/e9tool.1

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@ Insert a trap (int3) instruction at the corresponding
205205
trampoline entry. This can be used for debugging with gdb.
206206
.IP "\fB\-\-version\fR" 4
207207
Print the version and exit.
208+
.IP "\fB\-X\fR" 4
209+
Enables binary rewriting "with" control-flow recovery. This
210+
usually makes the rewritten binary much faster, but may
211+
introduce rewriting bugs if the built-in recovery analysis is
212+
inaccurate.
208213
.SH "SEE ALSO"
209214
\fIe9patch\fR(1), \fIe9compile\fR(1), \fIe9afl\fR(1), \fIredfat\fR(1)
210215
.SH AUTHOR

0 commit comments

Comments
 (0)