One of the most useful features in OFRAK is the powerful PatchMaker library, providing capabilities to build and inject C source code into existing binaries. OFRAK’s FunctionReplacementModifier provides an easy-to-use API that leverages the PatchMaker to replace one or more functions in a binary. This post will walk through how this works.
Consider the following program, validate_input.c
, which rejects any input that contains the character “}”:
int validate_input(char* user_input){
int i = 0;
while(user_input[i]){
if (user_input[i] == '}'){
return 0;
}
i++;
}
return 1;
}
int main(int argc, char** argv){
char* input = argv[1];
if (validate_input(input)){
printf("Input accepted!\n");
return 0;
}else{
printf("Input rejected!\n");
return 1;
}
}
We can build this program and quickly validate that it works as expected:
>> gcc -o validate_input validate_input.c
>> ./validate_input "input1"
Input accepted!
>> ./validate_input "input}1"
Input rejected!
>>
Now let’s imagine that, for whatever reason, we need to change this program such that “}” is valid input if it is escaped with a backslash (the Voldemort of ASCII characters – never literally type it out unless absolutely necessary). Why does the customer need “}” in their input sometimes? Don’t ask me, I’m just the engineer.
A typical forward-engineering solution would involve updating the validate_input
inside of our source file to something like this:
int validate_input(char* user_input){
int i = 0;
while(user_input[i]){
if (user_input[i] == '}'){
// If this is the first character (no prev char) or the prev char is NOT backslash, fail validation
if (i == 0 || user_input[i-1] != '\\') return 0;
}
i++;
}
return 1;
}
Next, the forward-engineer would recompile the program.
Consider, however, that you need to apply this patch with the constraint that you cannot recompile the entire program (maybe you don’t have the complete source code or toolchains needed to recompile, or just do not want to). How might you approach this?
Maybe you are an assembly whiz and enjoy writing, injecting, and debugging shellcode. For the non-masochists, however, OFRAK’s FunctionReplacementModifier
allows us to easily take the above C patch (let’s call it validate_input_patch.c
) and inject it into the binary without recompiling the entire binary or needing access to source code.
The OFRAK script to do this is pretty straightforward! The FunctionReplacementModifier takes a handful of arguments that are easy to summarize:
The script looks like this:
from ofrak import *
from ofrak.core import *
from ofrak_patch_maker.toolchain.model import *
from ofrak_patch_maker.toolchain.gnu_x64 import *
import ofrak_angr
async def main(ofrak_context, input_file):
target_binary = await ofrak_context.create_root_resource_from_file(input_file)
await target_binary.unpack_recursively()
await target_binary.run(
FunctionReplacementModifier,
FunctionReplacementModifierConfig(
SourceBundle.slurp("patch_src"),
{"validate_input": "validate_input_patch.c"},
ToolchainConfig(
file_format=BinFileType.ELF,
force_inlines=False,
relocatable=False,
no_std_lib=False,
no_jump_tables=True,
no_bss_section=True,
compiler_optimization_level=CompilerOptimizationLevel.SPACE,
),
GNU_X86_64_LINUX_EABI_10_3_0_Toolchain,
)
)
await target_binary.flush_to_disk(input_file + ".patched")
o = OFRAK()
o.discover(ofrak_angr)
o.run(main, "validate_input")
This script takes a few seconds to run. As described previously, OFRAK will unpack and analyze the target (in this case using the angr backend), then build the patch, find the existing validate_input
function, and overwrite it with our patch. Just to encourage you to give it a try as much as possible, we’ll leave out the oh-so-exciting payoff of the expected output from the patched binary. Actually applying and running the patch is left as an exercise to the reader.
We’ll leave you with a little bit of food for thought as well:
main
function instead of validate_input
?main
and validate_input
? Is it even still the same program? Has science gone too far? (This is a philosophical question, but not a rhetorical one. Discuss.)Sal Stolfo was an original founding member of Red Balloon Security, Inc.
© 2022 Red Balloon Security.
All Rights Reserved.
Contact us now to discover more about Red Balloon Security’s range of solutions and services or to arrange a demonstration.
Reach out to learn more about our embedded security offering and to schedule a demo.
Reach out to learn more about our embedded security offering and to schedule a demo.
Reach out to learn more about our embedded security offering and to schedule a demo.
Reach out to learn more about our embedded security offering and to schedule a demo.