From a74cf7bbfc588e2b39fe0f603849af9705219fe5 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Thu, 11 Jul 2024 10:30:46 +0300 Subject: [PATCH 01/34] fix: addition of project resources to .gitignore Signed-off-by: VyacheslavIurevich --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 9ac2dd8..cea3aab 100644 --- a/.gitignore +++ b/.gitignore @@ -161,3 +161,7 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +# Our app resources +*.rep +*.gpr +resources/out \ No newline at end of file From 78378e52f70124096ca9d1325deb57daa49662a2 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Thu, 11 Jul 2024 16:22:12 +0300 Subject: [PATCH 02/34] feat: addition of function runtime checker Signed-off-by: VyacheslavIurevich --- src/function_in_runtime.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/function_in_runtime.py diff --git a/src/function_in_runtime.py b/src/function_in_runtime.py new file mode 100644 index 0000000..8ea4441 --- /dev/null +++ b/src/function_in_runtime.py @@ -0,0 +1,11 @@ +'''Check if input function is in runtime''' + +#pylint: disable=wrong-import-order +import pyhidra # pylint: disable=import-error +pyhidra.start() +#from ghidra.program.model.listing import Function pylint: disable=import-error + +def function_in_runtime(function): + '''All runtime functions' names do start with _ ''' + function_name = function.getName() + return function_name.startswith('_') From 81033d8e6b264738b67f250a31dc8b60b6a79276 Mon Sep 17 00:00:00 2001 From: Sarapulov Vasilii Date: Thu, 11 Jul 2024 17:23:12 +0300 Subject: [PATCH 03/34] feat: addtion of function write program data types --- resources/in/test.out | Bin 0 -> 15960 bytes src/code_receiving.py | 32 ++++++++++++++++++++++++++++++++ src/write_program_data_types | 17 +++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 resources/in/test.out create mode 100644 src/code_receiving.py create mode 100644 src/write_program_data_types diff --git a/resources/in/test.out b/resources/in/test.out new file mode 100644 index 0000000000000000000000000000000000000000..68211d92a68d4d85172085d5867536c6aeed533b GIT binary patch literal 15960 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 Date: Thu, 11 Jul 2024 23:19:52 +0300 Subject: [PATCH 04/34] feat: addition of function PLT checker Signed-off-by: VyacheslavIurevich --- src/function_is_plt.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/function_is_plt.py diff --git a/src/function_is_plt.py b/src/function_is_plt.py new file mode 100644 index 0000000..c864c0e --- /dev/null +++ b/src/function_is_plt.py @@ -0,0 +1,26 @@ +'''Check if input function is PLT jump''' + +#pylint: disable=wrong-import-order +import pyhidra # pylint: disable=import-error +from elftools.elf.elffile import ELFFile # pylint: disable=import-error +pyhidra.start() + +def get_got_bounds(path): + '''Get GOT section addresses bounds''' + elffile = ELFFile(path) + section = elffile.get_section_by_name('.got') + return section.header.sh_addr, section.header.sh_addr + section.header.sh_size - 2 + +def function_is_plt(function, program, path): + '''Check if input function is PLT jump''' + listing = program.getListing() + body = function.getBody() + for address in body.getAddresses(True): + code_unit = str(listing.getCodeUnitAt(address)) + if code_unit.startswith("JMP qword ptr"): + words = code_unit.split() + address_str = words[-1][1:-1] # removing [] + address = int(address_str, 16) + got_start, got_end = get_got_bounds(path) + return got_start <= address - 16 ** 5 <= got_end + return False From 92ba7615070987bdfd57df453fa809cc43c97590 Mon Sep 17 00:00:00 2001 From: Sarapulov Vasilii Date: Thu, 11 Jul 2024 23:42:24 +0300 Subject: [PATCH 05/34] fix: file closing Signed-off-by: Sarapulov Vasilii --- src/code_receiving.py | 32 -------------------------------- src/write_program_data_types | 17 ----------------- src/write_program_data_types.py | 14 ++++++++++++++ 3 files changed, 14 insertions(+), 49 deletions(-) delete mode 100644 src/code_receiving.py delete mode 100644 src/write_program_data_types create mode 100644 src/write_program_data_types.py diff --git a/src/code_receiving.py b/src/code_receiving.py deleted file mode 100644 index 9951878..0000000 --- a/src/code_receiving.py +++ /dev/null @@ -1,32 +0,0 @@ -'''Receiving decompiled code from Ghidra API via pyhidra''' -#pylint: disable=wrong-import-position -import pyhidra # pylint: disable=import-error -pyhidra.start() -import ghidra # pylint: disable=import-error -from java.io import File # pylint: disable=import-error - -def receive_code(binary_file_path, output_file_path): - '''Receiving decompiled code''' - with pyhidra.open_program(binary_file_path) as flat_api: - program = flat_api.getCurrentProgram() - dtm = program.getDataTypeManager() - ifc = ghidra.app.decompiler.DecompInterface() - ifc.openProgram(program) - print(ghidra.app.util.exporter.getFakeCTypeDefinitions(dtm.getDataOrganization())) - # for i in data_type.getDataOrganization(): - # print(i) - # for f in program.getFunctionManager().getFunctions(True): - # print(f, f.getBody()) - # print() - # results = ifc.decompileFunction(f, 0, flat_api.monitor) - # print(results.getDecompiledFunction().getC()) - - # listing = program.getListing() - # for i in listing.getCodeUnits(True): - # print(i) - # exporter = ghidra.app.util.exporter.CppExporter() - - # f = File(output_file_path) - # exporter.export(f, program, None, flat_api.monitor) - -receive_code("resources/in/test.out", "resources/out/test.c") diff --git a/src/write_program_data_types b/src/write_program_data_types deleted file mode 100644 index 03c78f5..0000000 --- a/src/write_program_data_types +++ /dev/null @@ -1,17 +0,0 @@ -'''Dumping program data types''' -#pylint: disable=wrong-import-position -import pyhidra # pylint: disable=import-error -pyhidra.start() -import ghidra # pylint: disable=import-error -from java.io import File, PrintWriter # pylint: disable=import-error - -def write_program_data_types(file, monitor): - """Dumping program data types""" - dtm = program.getDataTypeManager() - cfile_writer = PrintWriter(file) - data_type_writer = ghidra.program.model.data.DataTypeWriter(dtm, cfile_writer, True) - data_type_writer.write(dtm, monitor) -with pyhidra.open_program("resources/in/test.out") as flat_api: - program = flat_api.getCurrentProgram() - f = File("resources/out/test1.c") - write_program_data_types(f, flat_api.monitor) diff --git a/src/write_program_data_types.py b/src/write_program_data_types.py new file mode 100644 index 0000000..a5edce7 --- /dev/null +++ b/src/write_program_data_types.py @@ -0,0 +1,14 @@ +'''Dumping program data types''' +#pylint: disable=wrong-import-position +import pyhidra # pylint: disable=import-error +pyhidra.start() +import ghidra # pylint: disable=import-error +from java.io import PrintWriter # pylint: disable=import-error + +def write_program_data_types(program, file, monitor): + """Dumping program data types""" + dtm = program.getDataTypeManager() + c_file_writer = PrintWriter(file) + data_type_writer = ghidra.program.model.data.DataTypeWriter(dtm, c_file_writer, False) + data_type_writer.write(dtm, monitor) + c_file_writer.close() From 3362f6896f21c8f0b18c779bd1af8e9324c22503 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Fri, 12 Jul 2024 09:57:33 +0300 Subject: [PATCH 06/34] feat: addition of image base instead of const Signed-off-by: VyacheslavIurevich --- src/function_is_plt.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/function_is_plt.py b/src/function_is_plt.py index c864c0e..f882fbf 100644 --- a/src/function_is_plt.py +++ b/src/function_is_plt.py @@ -7,12 +7,15 @@ def get_got_bounds(path): '''Get GOT section addresses bounds''' - elffile = ELFFile(path) - section = elffile.get_section_by_name('.got') - return section.header.sh_addr, section.header.sh_addr + section.header.sh_size - 2 + with open(path, "rb") as file: + elf = ELFFile(file) + section = elf.get_section_by_name('.got') + return section.header.sh_addr, section.header.sh_addr + section.header.sh_size - 2 -def function_is_plt(function, program, path): +def function_is_plt(function, path): '''Check if input function is PLT jump''' + program = function.getProgram() + image_base = int(str(program.getImageBase()), 16) listing = program.getListing() body = function.getBody() for address in body.getAddresses(True): @@ -22,5 +25,5 @@ def function_is_plt(function, program, path): address_str = words[-1][1:-1] # removing [] address = int(address_str, 16) got_start, got_end = get_got_bounds(path) - return got_start <= address - 16 ** 5 <= got_end + return got_start <= address - image_base <= got_end return False From fbf6e95e670fa91f803d31396c15652c4ce520de Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Fri, 12 Jul 2024 10:03:20 +0300 Subject: [PATCH 07/34] fix: move GOT bounds parsing out of cycle Signed-off-by: VyacheslavIurevich --- src/function_is_plt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/function_is_plt.py b/src/function_is_plt.py index f882fbf..0b67932 100644 --- a/src/function_is_plt.py +++ b/src/function_is_plt.py @@ -18,12 +18,12 @@ def function_is_plt(function, path): image_base = int(str(program.getImageBase()), 16) listing = program.getListing() body = function.getBody() + got_start, got_end = get_got_bounds(path) for address in body.getAddresses(True): code_unit = str(listing.getCodeUnitAt(address)) if code_unit.startswith("JMP qword ptr"): words = code_unit.split() address_str = words[-1][1:-1] # removing [] address = int(address_str, 16) - got_start, got_end = get_got_bounds(path) return got_start <= address - image_base <= got_end return False From bbf181d76733dab5b141d18b421b05006d241918 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Fri, 12 Jul 2024 10:12:58 +0300 Subject: [PATCH 08/34] fix: restructuring of all modules (putting into one file) Signed-off-by: VyacheslavIurevich --- src/function_in_runtime.py | 11 ----------- src/{function_is_plt.py => tools.py} | 23 +++++++++++++++++++---- src/write_program_data_types.py | 14 -------------- 3 files changed, 19 insertions(+), 29 deletions(-) delete mode 100644 src/function_in_runtime.py rename src/{function_is_plt.py => tools.py} (55%) delete mode 100644 src/write_program_data_types.py diff --git a/src/function_in_runtime.py b/src/function_in_runtime.py deleted file mode 100644 index 8ea4441..0000000 --- a/src/function_in_runtime.py +++ /dev/null @@ -1,11 +0,0 @@ -'''Check if input function is in runtime''' - -#pylint: disable=wrong-import-order -import pyhidra # pylint: disable=import-error -pyhidra.start() -#from ghidra.program.model.listing import Function pylint: disable=import-error - -def function_in_runtime(function): - '''All runtime functions' names do start with _ ''' - function_name = function.getName() - return function_name.startswith('_') diff --git a/src/function_is_plt.py b/src/tools.py similarity index 55% rename from src/function_is_plt.py rename to src/tools.py index 0b67932..ef66c28 100644 --- a/src/function_is_plt.py +++ b/src/tools.py @@ -1,9 +1,16 @@ -'''Check if input function is PLT jump''' +'''Tools for checking functions and exporting decompiled program to a .c file''' -#pylint: disable=wrong-import-order -import pyhidra # pylint: disable=import-error -from elftools.elf.elffile import ELFFile # pylint: disable=import-error +#pylint: disable=wrong-import-order, wrong-import-position, import-error +from elftools.elf.elffile import ELFFile +import pyhidra pyhidra.start() +from ghidra.program.model.data import DataTypeWriter +from java.io import PrintWriter + +def function_in_runtime(function): + '''Check if input function is from C Runtime''' + function_name = function.getName() + return function_name.startswith('_') def get_got_bounds(path): '''Get GOT section addresses bounds''' @@ -27,3 +34,11 @@ def function_is_plt(function, path): address = int(address_str, 16) return got_start <= address - image_base <= got_end return False + +def write_program_data_types(program, file, monitor): + """Dumping program data types""" + dtm = program.getDataTypeManager() + c_file_writer = PrintWriter(file) + data_type_writer = DataTypeWriter(dtm, c_file_writer, False) + data_type_writer.write(dtm, monitor) + c_file_writer.close() diff --git a/src/write_program_data_types.py b/src/write_program_data_types.py deleted file mode 100644 index a5edce7..0000000 --- a/src/write_program_data_types.py +++ /dev/null @@ -1,14 +0,0 @@ -'''Dumping program data types''' -#pylint: disable=wrong-import-position -import pyhidra # pylint: disable=import-error -pyhidra.start() -import ghidra # pylint: disable=import-error -from java.io import PrintWriter # pylint: disable=import-error - -def write_program_data_types(program, file, monitor): - """Dumping program data types""" - dtm = program.getDataTypeManager() - c_file_writer = PrintWriter(file) - data_type_writer = ghidra.program.model.data.DataTypeWriter(dtm, c_file_writer, False) - data_type_writer.write(dtm, monitor) - c_file_writer.close() From 097bc76a0797c6cab32e4adedbff2b604bd93698 Mon Sep 17 00:00:00 2001 From: Sarapulov Vasilii Date: Fri, 12 Jul 2024 12:34:18 +0300 Subject: [PATCH 09/34] feat: addtion of postprocessor logic Signed-off-by: Sarapulov Vasilii --- src/function_in_runtime.py | 11 --------- src/main.py | 27 +++++++++++++++++++-- src/tools.py | 43 +++++++++++++++++++++++++++++++++ src/write_program_data_types.py | 14 ----------- 4 files changed, 68 insertions(+), 27 deletions(-) delete mode 100644 src/function_in_runtime.py create mode 100644 src/tools.py delete mode 100644 src/write_program_data_types.py diff --git a/src/function_in_runtime.py b/src/function_in_runtime.py deleted file mode 100644 index 8ea4441..0000000 --- a/src/function_in_runtime.py +++ /dev/null @@ -1,11 +0,0 @@ -'''Check if input function is in runtime''' - -#pylint: disable=wrong-import-order -import pyhidra # pylint: disable=import-error -pyhidra.start() -#from ghidra.program.model.listing import Function pylint: disable=import-error - -def function_in_runtime(function): - '''All runtime functions' names do start with _ ''' - function_name = function.getName() - return function_name.startswith('_') diff --git a/src/main.py b/src/main.py index a8322d9..ecb3b1b 100644 --- a/src/main.py +++ b/src/main.py @@ -1,3 +1,26 @@ -"""Simple program""" +"""Postprocessor main""" -print("Hello world") +#pylint: disable=wrong-import-position +import pyhidra # pylint: disable=import-error +pyhidra.start() +import ghidra # pylint: disable=import-error +from java.io import File, PrintWriter # pylint: disable=import-error +import tools # pylint: disable=import-error + +def export_c_code(binary_file_path, output_file_path): + '''Exporting c code to a file''' + with pyhidra.open_program(binary_file_path) as flat_api: + program = flat_api.getCurrentProgram() + ifc = ghidra.app.decompiler.DecompInterface() + ifc.openProgram(program) + f = File(output_file_path) + c_file_writer = PrintWriter(f) + tools.write_program_data_types(program, c_file_writer, flat_api.monitor) + for function in program.getFunctionManager().getFunctions(True): + if tools.exclude_function(function, binary_file_path): + continue + results = ifc.decompileFunction(function, 0, flat_api.monitor) + c_file_writer.println(results.getDecompiledFunction().getC()) + c_file_writer.close() + +export_c_code("resources/in/test.out", "resources/out/test.c") diff --git a/src/tools.py b/src/tools.py new file mode 100644 index 0000000..59379ea --- /dev/null +++ b/src/tools.py @@ -0,0 +1,43 @@ +'''Tools for checking functions and exporting decompiled program to a .c file''' + +#pylint: disable=wrong-import-order, wrong-import-position, import-error +from elftools.elf.elffile import ELFFile +from ghidra.program.model.data import DataTypeWriter + +def function_in_runtime(function): + '''Check if input function is from C Runtime''' + function_name = function.getName() + return function_name.startswith('_') + +def get_got_bounds(path): + '''Get GOT section addresses bounds''' + with open(path, "rb") as file: + elf = ELFFile(file) + section = elf.get_section_by_name('.got') + return section.header.sh_addr, section.header.sh_addr + section.header.sh_size - 2 + +def function_is_plt(function, path): + '''Check if input function is PLT jump''' + program = function.getProgram() + image_base = int(str(program.getImageBase()), 16) + listing = program.getListing() + body = function.getBody() + got_start, got_end = get_got_bounds(path) + for address in body.getAddresses(True): + code_unit = str(listing.getCodeUnitAt(address)) + if code_unit.startswith("JMP qword ptr"): + words = code_unit.split() + address_str = words[-1][1:-1] # removing [] + address = int(address_str, 16) + return got_start <= address - image_base <= got_end + return False + +def write_program_data_types(program, c_file_writer, monitor): + """Dumping program data types""" + dtm = program.getDataTypeManager() + data_type_writer = DataTypeWriter(dtm, c_file_writer, False) + data_type_writer.write(dtm, monitor) + +def exclude_function(function, binary_file_path): + """Dumping program data types""" + return function_in_runtime(function) or function_is_plt(function, binary_file_path) diff --git a/src/write_program_data_types.py b/src/write_program_data_types.py deleted file mode 100644 index a5edce7..0000000 --- a/src/write_program_data_types.py +++ /dev/null @@ -1,14 +0,0 @@ -'''Dumping program data types''' -#pylint: disable=wrong-import-position -import pyhidra # pylint: disable=import-error -pyhidra.start() -import ghidra # pylint: disable=import-error -from java.io import PrintWriter # pylint: disable=import-error - -def write_program_data_types(program, file, monitor): - """Dumping program data types""" - dtm = program.getDataTypeManager() - c_file_writer = PrintWriter(file) - data_type_writer = ghidra.program.model.data.DataTypeWriter(dtm, c_file_writer, False) - data_type_writer.write(dtm, monitor) - c_file_writer.close() From a426a6b858a1afc0a09c54f889551437df40490f Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Fri, 12 Jul 2024 15:51:01 +0300 Subject: [PATCH 10/34] feat: addition of new logic of PLT checking Signed-off-by: VyacheslavIurevich --- src/tools.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/tools.py b/src/tools.py index ef66c28..a3a448c 100644 --- a/src/tools.py +++ b/src/tools.py @@ -1,7 +1,6 @@ '''Tools for checking functions and exporting decompiled program to a .c file''' #pylint: disable=wrong-import-order, wrong-import-position, import-error -from elftools.elf.elffile import ELFFile import pyhidra pyhidra.start() from ghidra.program.model.data import DataTypeWriter @@ -12,27 +11,24 @@ def function_in_runtime(function): function_name = function.getName() return function_name.startswith('_') -def get_got_bounds(path): - '''Get GOT section addresses bounds''' - with open(path, "rb") as file: - elf = ELFFile(file) - section = elf.get_section_by_name('.got') - return section.header.sh_addr, section.header.sh_addr + section.header.sh_size - 2 +def address_to_int(address): + '''Address is a number in hex''' + return int(str(address), 16) -def function_is_plt(function, path): +def function_is_plt(function): '''Check if input function is PLT jump''' program = function.getProgram() - image_base = int(str(program.getImageBase()), 16) listing = program.getListing() body = function.getBody() - got_start, got_end = get_got_bounds(path) + min_address = address_to_int(body.getMinAddress()) + max_address = address_to_int(body.getMaxAddress()) for address in body.getAddresses(True): code_unit = str(listing.getCodeUnitAt(address)) if code_unit.startswith("JMP qword ptr"): words = code_unit.split() - address_str = words[-1][1:-1] # removing [] - address = int(address_str, 16) - return got_start <= address - image_base <= got_end + jmp_address = address_to_int(words[-1][1:-1]) # [1:-1] is to remove [] from address + if not min_address <= jmp_address <= max_address: + return True return False def write_program_data_types(program, file, monitor): From fd61c5d0c28e5d65e1e0e8d15666458e6440b129 Mon Sep 17 00:00:00 2001 From: Sarapulov Vasilii Date: Fri, 12 Jul 2024 23:13:53 +0300 Subject: [PATCH 11/34] feat: new postprocessor logic Signed-off-by: Sarapulov Vasilii --- .vscode/tasks.json | 28 ++++++++++++++++++++++++++++ resources/in/bmp-header.out | Bin 0 -> 16552 bytes src/main.py | 15 +++++++++++---- src/tools.py | 7 ++++++- 4 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 .vscode/tasks.json create mode 100755 resources/in/bmp-header.out diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..08d9005 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc build active file", + "command": "/usr/bin/gcc", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/resources/in/bmp-header.out b/resources/in/bmp-header.out new file mode 100755 index 0000000000000000000000000000000000000000..23ddd4715d4a8892c6c43e6f9a54cb8f1457bc1c GIT binary patch literal 16552 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 literal 0 HcmV?d00001 diff --git a/src/main.py b/src/main.py index ecb3b1b..4a40105 100644 --- a/src/main.py +++ b/src/main.py @@ -3,23 +3,30 @@ #pylint: disable=wrong-import-position import pyhidra # pylint: disable=import-error pyhidra.start() -import ghidra # pylint: disable=import-error from java.io import File, PrintWriter # pylint: disable=import-error +from ghidra.app.decompiler import DecompileOptions # pylint: disable=import-error +from ghidra.app.decompiler import DecompInterface # pylint: disable=import-error import tools # pylint: disable=import-error def export_c_code(binary_file_path, output_file_path): '''Exporting c code to a file''' with pyhidra.open_program(binary_file_path) as flat_api: program = flat_api.getCurrentProgram() - ifc = ghidra.app.decompiler.DecompInterface() - ifc.openProgram(program) + + options = DecompileOptions() + options.grabFromProgram(program) + + decompiler = DecompInterface() + decompiler.setOptions(options) + decompiler.openProgram(program) + f = File(output_file_path) c_file_writer = PrintWriter(f) tools.write_program_data_types(program, c_file_writer, flat_api.monitor) for function in program.getFunctionManager().getFunctions(True): if tools.exclude_function(function, binary_file_path): continue - results = ifc.decompileFunction(function, 0, flat_api.monitor) + results = decompiler.decompileFunction(function, 0, flat_api.monitor) c_file_writer.println(results.getDecompiledFunction().getC()) c_file_writer.close() diff --git a/src/tools.py b/src/tools.py index 59379ea..c58bda6 100644 --- a/src/tools.py +++ b/src/tools.py @@ -40,4 +40,9 @@ def write_program_data_types(program, c_file_writer, monitor): def exclude_function(function, binary_file_path): """Dumping program data types""" - return function_in_runtime(function) or function_is_plt(function, binary_file_path) + entry_point = function.getEntryPoint() + code_unit_at = function.getProgram().getListing().getCodeUnitAt(entry_point) + return \ + function_in_runtime(function) or \ + function_is_plt(function, binary_file_path) or \ + code_unit_at.getMnemonicString() == "??" From af98895994a2959a7b0f9f9dff26132f0e43018e Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Fri, 12 Jul 2024 23:25:28 +0300 Subject: [PATCH 12/34] fix: removal of file path in exclude_function call Signed-off-by: VyacheslavIurevich --- src/main.py | 2 +- src/tools.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main.py b/src/main.py index 4a40105..906aa0f 100644 --- a/src/main.py +++ b/src/main.py @@ -24,7 +24,7 @@ def export_c_code(binary_file_path, output_file_path): c_file_writer = PrintWriter(f) tools.write_program_data_types(program, c_file_writer, flat_api.monitor) for function in program.getFunctionManager().getFunctions(True): - if tools.exclude_function(function, binary_file_path): + if tools.exclude_function(function): continue results = decompiler.decompileFunction(function, 0, flat_api.monitor) c_file_writer.println(results.getDecompiledFunction().getC()) diff --git a/src/tools.py b/src/tools.py index 4de97a1..b6ef8ec 100644 --- a/src/tools.py +++ b/src/tools.py @@ -5,7 +5,6 @@ import pyhidra pyhidra.start() from ghidra.program.model.data import DataTypeWriter -from java.io import PrintWriter def function_in_runtime(function): '''Check if input function is from C Runtime''' @@ -16,7 +15,7 @@ def address_to_int(address): '''Address is a number in hex''' return int(str(address), 16) -ef function_is_plt(function): +def function_is_plt(function): '''Check if input function is PLT jump''' program = function.getProgram() listing = program.getListing() From 2896b82b4b1bb60c947fd4945e1e84a966ff8297 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Fri, 12 Jul 2024 23:28:01 +0300 Subject: [PATCH 13/34] feat: addition of .vscode/ and .idea/ to .gitignore Signed-off-by: VyacheslavIurevich --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index cea3aab..2719157 100644 --- a/.gitignore +++ b/.gitignore @@ -164,4 +164,7 @@ cython_debug/ # Our app resources *.rep *.gpr -resources/out \ No newline at end of file +resources/out + +.vscode/ +.idea/ \ No newline at end of file From f39f9d2567db98f62c8499258dc1d6f1adc9e6ea Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Fri, 12 Jul 2024 23:30:01 +0300 Subject: [PATCH 14/34] fix: deletion of .vscode/ Signed-off-by: VyacheslavIurevich --- .vscode/tasks.json | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 .vscode/tasks.json diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 08d9005..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "tasks": [ - { - "type": "cppbuild", - "label": "C/C++: gcc build active file", - "command": "/usr/bin/gcc", - "args": [ - "-fdiagnostics-color=always", - "-g", - "${file}", - "-o", - "${fileDirname}/${fileBasenameNoExtension}" - ], - "options": { - "cwd": "${fileDirname}" - }, - "problemMatcher": [ - "$gcc" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "detail": "Task generated by Debugger." - } - ], - "version": "2.0.0" -} \ No newline at end of file From 1262532b39d6678809ea6384620ab8095d527b4f Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Fri, 12 Jul 2024 23:39:35 +0300 Subject: [PATCH 15/34] fix: reformatting of the code and other files Signed-off-by: VyacheslavIurevich --- .githooks/pre-commit | 1 - .github/workflows/pylint.yml | 1 - .gitignore | 2 +- CONTRIBUTING.md | 1 - LICENSE | 1 - README.md | 1 - src/main.py | 16 +++++++++------- src/tools.py | 17 +++++++++++------ 8 files changed, 21 insertions(+), 19 deletions(-) diff --git a/.githooks/pre-commit b/.githooks/pre-commit index eebf3f9..c733190 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -7,4 +7,3 @@ if [[ $pylint_check_status -ne 0 ]]; then else exit 0 fi - diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index b6430bf..4e6008d 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -25,4 +25,3 @@ jobs: - name: Analysing the code with pylint run: | pylint $(git ls-files '*.py') - diff --git a/.gitignore b/.gitignore index 2719157..dc005bd 100644 --- a/.gitignore +++ b/.gitignore @@ -167,4 +167,4 @@ cython_debug/ resources/out .vscode/ -.idea/ \ No newline at end of file +.idea/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b10a981..08902e4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,4 +13,3 @@ git config --local core.hooksPath .githooks/ 8. Your naming of commits and pull requests must be logical and reasonable. 9. Please use "git commit -s" option. 10. If you are in doubt what to do, it's better to text developers. - diff --git a/LICENSE b/LICENSE index 701456c..6c3fe91 100644 --- a/LICENSE +++ b/LICENSE @@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/README.md b/README.md index 8dc97cb..c444e37 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,3 @@ This console app provides ability to postprocess code, which is decompiled via G # Team * Vyacheslav Kochergin. [GitHub](https://github.com/VyacheslavIurevich), [Contact](https://t.me/se4life). * Vasilii Sarapulov. [GitHub](https://github.com/Sarapulov-Vas), [Contact](https://t.me/sarpaulov). - diff --git a/src/main.py b/src/main.py index 906aa0f..fe79fba 100644 --- a/src/main.py +++ b/src/main.py @@ -1,15 +1,16 @@ """Postprocessor main""" -#pylint: disable=wrong-import-position -import pyhidra # pylint: disable=import-error +# pylint: disable=wrong-import-position, import-error +import pyhidra pyhidra.start() -from java.io import File, PrintWriter # pylint: disable=import-error -from ghidra.app.decompiler import DecompileOptions # pylint: disable=import-error -from ghidra.app.decompiler import DecompInterface # pylint: disable=import-error -import tools # pylint: disable=import-error +from java.io import File, PrintWriter +from ghidra.app.decompiler import DecompileOptions +from ghidra.app.decompiler import DecompInterface +import tools + def export_c_code(binary_file_path, output_file_path): - '''Exporting c code to a file''' + """Exporting c code to a file""" with pyhidra.open_program(binary_file_path) as flat_api: program = flat_api.getCurrentProgram() @@ -30,4 +31,5 @@ def export_c_code(binary_file_path, output_file_path): c_file_writer.println(results.getDecompiledFunction().getC()) c_file_writer.close() + export_c_code("resources/in/test.out", "resources/out/test.c") diff --git a/src/tools.py b/src/tools.py index b6ef8ec..3e2b844 100644 --- a/src/tools.py +++ b/src/tools.py @@ -1,22 +1,25 @@ -'''Tools for checking functions and exporting decompiled program to a .c file''' +"""Tools for checking functions and exporting decompiled program to a .c file""" -#pylint: disable=wrong-import-order, wrong-import-position, import-error +# pylint: disable=wrong-import-order, wrong-import-position, import-error import pyhidra pyhidra.start() from ghidra.program.model.data import DataTypeWriter + def function_in_runtime(function): - '''Check if input function is from C Runtime''' + """Check if input function is from C Runtime""" function_name = function.getName() return function_name.startswith('_') + def address_to_int(address): - '''Address is a number in hex''' + """Address is a number in hex""" return int(str(address), 16) + def function_is_plt(function): - '''Check if input function is PLT jump''' + """Check if input function is PLT jump""" program = function.getProgram() listing = program.getListing() body = function.getBody() @@ -26,17 +29,19 @@ def function_is_plt(function): code_unit = str(listing.getCodeUnitAt(address)) if code_unit.startswith("JMP qword ptr"): words = code_unit.split() - jmp_address = address_to_int(words[-1][1:-1]) # [1:-1] is to remove [] from address + jmp_address = address_to_int(words[-1][1:-1]) # [1:-1] is to remove [] from address if not min_address <= jmp_address <= max_address: return True return False + def write_program_data_types(program, c_file_writer, monitor): """Dumping program data types""" dtm = program.getDataTypeManager() data_type_writer = DataTypeWriter(dtm, c_file_writer, False) data_type_writer.write(dtm, monitor) + def exclude_function(function): """Dumping program data types""" entry_point = function.getEntryPoint() From 9618eae2e83fe5c4fc03f6796199f00cacb49316 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Sat, 13 Jul 2024 21:30:31 +0300 Subject: [PATCH 16/34] feat: addition of replace_types function to tools.py Signed-off-by: VyacheslavIurevich --- src/main.py | 11 +++++++---- src/tools.py | 29 +++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/main.py b/src/main.py index fe79fba..bfd9ff4 100644 --- a/src/main.py +++ b/src/main.py @@ -2,10 +2,10 @@ # pylint: disable=wrong-import-position, import-error import pyhidra + pyhidra.start() from java.io import File, PrintWriter -from ghidra.app.decompiler import DecompileOptions -from ghidra.app.decompiler import DecompInterface +from ghidra.app.decompiler import DecompileOptions, DecompInterface import tools @@ -23,13 +23,16 @@ def export_c_code(binary_file_path, output_file_path): f = File(output_file_path) c_file_writer = PrintWriter(f) + c_file_writer.println("#include ") tools.write_program_data_types(program, c_file_writer, flat_api.monitor) for function in program.getFunctionManager().getFunctions(True): if tools.exclude_function(function): continue results = decompiler.decompileFunction(function, 0, flat_api.monitor) - c_file_writer.println(results.getDecompiledFunction().getC()) + function_code = results.getDecompiledFunction().getC() + function_code_replaced_types = tools.replace_types(function_code) + c_file_writer.println(function_code_replaced_types) c_file_writer.close() -export_c_code("resources/in/test.out", "resources/out/test.c") +export_c_code("resources/in/bmp-header.out", "resources/out/test.c") diff --git a/src/tools.py b/src/tools.py index 3e2b844..1c6a2c5 100644 --- a/src/tools.py +++ b/src/tools.py @@ -2,10 +2,25 @@ # pylint: disable=wrong-import-order, wrong-import-position, import-error +from collections import OrderedDict import pyhidra + pyhidra.start() from ghidra.program.model.data import DataTypeWriter +TYPES_TO_REPLACE = OrderedDict(byte="unsigned char", + dwfenc="unsigned char", + dword="unsigned int", + qword="unsigned long", + word="unsigned short", + uint="unsigned int", + undefined1="uint8_t", + undefined2="uint16_t", + undefined4="uint32_t", + undefined8="uint64_t", + undefined="unsigned int" + ) + def function_in_runtime(function): """Check if input function is from C Runtime""" @@ -46,7 +61,13 @@ def exclude_function(function): """Dumping program data types""" entry_point = function.getEntryPoint() code_unit_at = function.getProgram().getListing().getCodeUnitAt(entry_point) - return \ - function_in_runtime(function) or \ - function_is_plt(function) or \ - code_unit_at.getMnemonicString() == "??" + return function_in_runtime(function) \ + or function_is_plt(function) \ + or code_unit_at.getMnemonicString() == "??" + + +def replace_types(function_code): + """Replacing all Ghidra types with types from intttypes.h""" + for old_type, new_type in TYPES_TO_REPLACE.items(): + function_code = function_code.replace(old_type, new_type) + return function_code From 8d7030c4cbe01b6c228fd593a4d982c935013311 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Sat, 13 Jul 2024 21:32:44 +0300 Subject: [PATCH 17/34] fix: docstring patch Signed-off-by: VyacheslavIurevich --- src/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools.py b/src/tools.py index 1c6a2c5..862e95f 100644 --- a/src/tools.py +++ b/src/tools.py @@ -67,7 +67,7 @@ def exclude_function(function): def replace_types(function_code): - """Replacing all Ghidra types with types from intttypes.h""" + """Replacing all Ghidra types with types from intttypes.h and standart C types""" for old_type, new_type in TYPES_TO_REPLACE.items(): function_code = function_code.replace(old_type, new_type) return function_code From a94bbb55ac8b6ea7ef7c137cf8bd3c7d3354dbae Mon Sep 17 00:00:00 2001 From: Sarapulov Vasilii Date: Mon, 15 Jul 2024 15:41:36 +0300 Subject: [PATCH 18/34] feat: addition of data types analyzer Signed-off-by: Sarapulov Vasilii --- src/main.py | 9 ++++++--- src/tools.py | 7 +++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main.py b/src/main.py index bfd9ff4..c967047 100644 --- a/src/main.py +++ b/src/main.py @@ -8,12 +8,12 @@ from ghidra.app.decompiler import DecompileOptions, DecompInterface import tools +LIBRARY_LIST = ["stdio.h", "stdlib.h", "inttypes.h"] def export_c_code(binary_file_path, output_file_path): """Exporting c code to a file""" with pyhidra.open_program(binary_file_path) as flat_api: program = flat_api.getCurrentProgram() - options = DecompileOptions() options.grabFromProgram(program) @@ -23,8 +23,9 @@ def export_c_code(binary_file_path, output_file_path): f = File(output_file_path) c_file_writer = PrintWriter(f) - c_file_writer.println("#include ") - tools.write_program_data_types(program, c_file_writer, flat_api.monitor) + for lib in LIBRARY_LIST: + c_file_writer.println(f"#include <{lib}>") + tools.write_program_data_types(program, c_file_writer, flat_api.monitor, LIBRARY_LIST) for function in program.getFunctionManager().getFunctions(True): if tools.exclude_function(function): continue @@ -33,6 +34,8 @@ def export_c_code(binary_file_path, output_file_path): function_code_replaced_types = tools.replace_types(function_code) c_file_writer.println(function_code_replaced_types) c_file_writer.close() + decompiler.closeProgram() + decompiler.dispose() export_c_code("resources/in/bmp-header.out", "resources/out/test.c") diff --git a/src/tools.py b/src/tools.py index 862e95f..c707597 100644 --- a/src/tools.py +++ b/src/tools.py @@ -50,10 +50,13 @@ def function_is_plt(function): return False -def write_program_data_types(program, c_file_writer, monitor): +def write_program_data_types(program, c_file_writer, monitor, library_list): """Dumping program data types""" dtm = program.getDataTypeManager() - data_type_writer = DataTypeWriter(dtm, c_file_writer, False) + data_type_writer = DataTypeWriter(dtm, c_file_writer,) + for data_type in dtm.getAllDataTypes(): + if data_type.getPathName().split('/')[1] in library_list: + dtm.remove(data_type, monitor) data_type_writer.write(dtm, monitor) From d1fb14354cbaf5d792b3a90d556e7fefad5be337 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Mon, 15 Jul 2024 16:06:31 +0300 Subject: [PATCH 19/34] fix: formatting fix Signed-off-by: VyacheslavIurevich --- src/main.py | 1 + src/tools.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.py b/src/main.py index c967047..9424fe4 100644 --- a/src/main.py +++ b/src/main.py @@ -10,6 +10,7 @@ LIBRARY_LIST = ["stdio.h", "stdlib.h", "inttypes.h"] + def export_c_code(binary_file_path, output_file_path): """Exporting c code to a file""" with pyhidra.open_program(binary_file_path) as flat_api: diff --git a/src/tools.py b/src/tools.py index c707597..cbbb655 100644 --- a/src/tools.py +++ b/src/tools.py @@ -53,7 +53,7 @@ def function_is_plt(function): def write_program_data_types(program, c_file_writer, monitor, library_list): """Dumping program data types""" dtm = program.getDataTypeManager() - data_type_writer = DataTypeWriter(dtm, c_file_writer,) + data_type_writer = DataTypeWriter(dtm, c_file_writer, ) for data_type in dtm.getAllDataTypes(): if data_type.getPathName().split('/')[1] in library_list: dtm.remove(data_type, monitor) From 7103492b0b4372aab7300d26e134528cacc9dc87 Mon Sep 17 00:00:00 2001 From: Sarapulov Vasilii Date: Mon, 15 Jul 2024 21:50:52 +0300 Subject: [PATCH 20/34] fix: correction of data type unloading Signed-off-by: Sarapulov Vasilii --- src/main.py | 4 ++-- src/tools.py | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main.py b/src/main.py index c967047..727141b 100644 --- a/src/main.py +++ b/src/main.py @@ -25,7 +25,7 @@ def export_c_code(binary_file_path, output_file_path): c_file_writer = PrintWriter(f) for lib in LIBRARY_LIST: c_file_writer.println(f"#include <{lib}>") - tools.write_program_data_types(program, c_file_writer, flat_api.monitor, LIBRARY_LIST) + tools.write_program_data_types(program, c_file_writer, flat_api.monitor) for function in program.getFunctionManager().getFunctions(True): if tools.exclude_function(function): continue @@ -38,4 +38,4 @@ def export_c_code(binary_file_path, output_file_path): decompiler.dispose() -export_c_code("resources/in/bmp-header.out", "resources/out/test.c") +export_c_code("/home/sarapulov-vasilii/Downloads/bmp_viewer", "resources/out/test.c") diff --git a/src/tools.py b/src/tools.py index c707597..ad132c1 100644 --- a/src/tools.py +++ b/src/tools.py @@ -50,14 +50,17 @@ def function_is_plt(function): return False -def write_program_data_types(program, c_file_writer, monitor, library_list): +def write_program_data_types(program, c_file_writer, monitor): """Dumping program data types""" dtm = program.getDataTypeManager() - data_type_writer = DataTypeWriter(dtm, c_file_writer,) + data_type_writer = DataTypeWriter(dtm, c_file_writer) + data_type_list = [] for data_type in dtm.getAllDataTypes(): - if data_type.getPathName().split('/')[1] in library_list: - dtm.remove(data_type, monitor) - data_type_writer.write(dtm, monitor) + if ".h" not in data_type.getPathName().split('/')[1]: + data_type_list.append(data_type) + + data_type_writer.write(data_type_list, monitor) + dtm.close() def exclude_function(function): From be6befbd87c5a434d89af391d12e8f60b452cca6 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Mon, 15 Jul 2024 22:08:32 +0300 Subject: [PATCH 21/34] fix: path fix + formatting Signed-off-by: VyacheslavIurevich --- src/main.py | 2 +- src/tools.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main.py b/src/main.py index c22a618..65eb49b 100644 --- a/src/main.py +++ b/src/main.py @@ -39,4 +39,4 @@ def export_c_code(binary_file_path, output_file_path): decompiler.dispose() -export_c_code("/home/sarapulov-vasilii/Downloads/bmp_viewer", "resources/out/test.c") +export_c_code("resources/int/bmp-header.out", "resources/out/test.c") diff --git a/src/tools.py b/src/tools.py index ad132c1..2506e91 100644 --- a/src/tools.py +++ b/src/tools.py @@ -58,7 +58,6 @@ def write_program_data_types(program, c_file_writer, monitor): for data_type in dtm.getAllDataTypes(): if ".h" not in data_type.getPathName().split('/')[1]: data_type_list.append(data_type) - data_type_writer.write(data_type_list, monitor) dtm.close() From 24333d39e02fc50e5150dff18fce1b802c364e20 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Mon, 15 Jul 2024 22:21:39 +0300 Subject: [PATCH 22/34] fix: main typo fix Signed-off-by: VyacheslavIurevich --- src/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.py b/src/main.py index 65eb49b..4ffb580 100644 --- a/src/main.py +++ b/src/main.py @@ -39,4 +39,4 @@ def export_c_code(binary_file_path, output_file_path): decompiler.dispose() -export_c_code("resources/int/bmp-header.out", "resources/out/test.c") +export_c_code("resources/in/bmp-header.out", "resources/out/test.c") From 8e16641b2205a1b32cf2367ff7047a1799d60343 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Tue, 16 Jul 2024 10:17:31 +0300 Subject: [PATCH 23/34] fix: removal of all types except uint from TYPES_TO_REPLACE Signed-off-by: VyacheslavIurevich --- src/tools.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/tools.py b/src/tools.py index 2506e91..292e853 100644 --- a/src/tools.py +++ b/src/tools.py @@ -8,18 +8,7 @@ pyhidra.start() from ghidra.program.model.data import DataTypeWriter -TYPES_TO_REPLACE = OrderedDict(byte="unsigned char", - dwfenc="unsigned char", - dword="unsigned int", - qword="unsigned long", - word="unsigned short", - uint="unsigned int", - undefined1="uint8_t", - undefined2="uint16_t", - undefined4="uint32_t", - undefined8="uint64_t", - undefined="unsigned int" - ) +TYPES_TO_REPLACE = OrderedDict(uint="unsigned int") def function_in_runtime(function): From cdbc9416075ae1ed3c8935ca31f48ca0fbbb3f93 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Tue, 16 Jul 2024 12:05:04 +0300 Subject: [PATCH 24/34] feat: implementation of concat dumping to code file Signed-off-by: VyacheslavIurevich --- src/main.py | 4 ++++ src/tools.py | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/main.py b/src/main.py index 4ffb580..71c0d02 100644 --- a/src/main.py +++ b/src/main.py @@ -27,12 +27,16 @@ def export_c_code(binary_file_path, output_file_path): for lib in LIBRARY_LIST: c_file_writer.println(f"#include <{lib}>") tools.write_program_data_types(program, c_file_writer, flat_api.monitor) + used_concats = set() for function in program.getFunctionManager().getFunctions(True): if tools.exclude_function(function): continue results = decompiler.decompileFunction(function, 0, flat_api.monitor) function_code = results.getDecompiledFunction().getC() function_code_replaced_types = tools.replace_types(function_code) + if "CONCAT" in function_code_replaced_types: + used_concats = \ + tools.put_concat(c_file_writer, function_code_replaced_types, used_concats) c_file_writer.println(function_code_replaced_types) c_file_writer.close() decompiler.closeProgram() diff --git a/src/tools.py b/src/tools.py index 292e853..da52d85 100644 --- a/src/tools.py +++ b/src/tools.py @@ -3,23 +3,28 @@ # pylint: disable=wrong-import-order, wrong-import-position, import-error from collections import OrderedDict +from math import floor, log2 import pyhidra pyhidra.start() from ghidra.program.model.data import DataTypeWriter TYPES_TO_REPLACE = OrderedDict(uint="unsigned int") +CONCAT_LEN = 6 # = len("CONCAT") +BYTE_SIZE = 8 +HEX_BASE = 16 +RUNTIME_PREFIX = '_' def function_in_runtime(function): """Check if input function is from C Runtime""" function_name = function.getName() - return function_name.startswith('_') + return function_name.startswith(RUNTIME_PREFIX) def address_to_int(address): """Address is a number in hex""" - return int(str(address), 16) + return int(str(address), HEX_BASE) def function_is_plt(function): @@ -65,3 +70,31 @@ def replace_types(function_code): for old_type, new_type in TYPES_TO_REPLACE.items(): function_code = function_code.replace(old_type, new_type) return function_code + + +def get_nearest_lower_power_2(num): + """Rounds a number to nearest lower power of 2""" + return 2 ** floor(log2(num)) + + +def put_concat(file_writer, function_code, used_concats): + """Puts CONCATXY functions into C code""" + concat_cnt = function_code.count("CONCAT") + concat_idx = 0 + for _ in range(concat_cnt): + concat_idx = function_code.find("CONCAT", concat_idx) + CONCAT_LEN + first_size = int(function_code[concat_idx]) + second_size = int(function_code[concat_idx + 1]) + if (first_size, second_size) in used_concats: + continue + first_inttype_size = get_nearest_lower_power_2(first_size * BYTE_SIZE) + second_inttype_size = get_nearest_lower_power_2(second_size * BYTE_SIZE) + concat_name = f"unsigned long CONCAT{first_size}{second_size}" + concat_args = f"(uint{first_inttype_size}_t a, uint{second_inttype_size}_t b)\n" + concat_body = \ + f"return ((unsigned long)b) | (unsigned long)a << ({second_size} * {BYTE_SIZE});" + concat_signature = concat_name + concat_args + concat_function = concat_signature + '{' + '\n' + '\t' + concat_body + '\n' + '}' + '\n' + file_writer.println(concat_function) + used_concats.add((first_size, second_size)) + return used_concats From b1c5a0fe51472812102339ac13cbef7499aea123 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Tue, 16 Jul 2024 13:24:49 +0300 Subject: [PATCH 25/34] feat: addition of signatures printing Signed-off-by: VyacheslavIurevich --- src/main.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main.py b/src/main.py index 71c0d02..a46b028 100644 --- a/src/main.py +++ b/src/main.py @@ -27,17 +27,23 @@ def export_c_code(binary_file_path, output_file_path): for lib in LIBRARY_LIST: c_file_writer.println(f"#include <{lib}>") tools.write_program_data_types(program, c_file_writer, flat_api.monitor) - used_concats = set() + functions_code = [] for function in program.getFunctionManager().getFunctions(True): if tools.exclude_function(function): continue results = decompiler.decompileFunction(function, 0, flat_api.monitor) - function_code = results.getDecompiledFunction().getC() + decompiled_function = results.getDecompiledFunction() + function_signature = decompiled_function.getSignature() + function_code = decompiled_function.getC() function_code_replaced_types = tools.replace_types(function_code) - if "CONCAT" in function_code_replaced_types: + functions_code.append(function_code_replaced_types) + c_file_writer.println(function_signature + '\n') + used_concats = set() + for function_code in functions_code: + if "CONCAT" in function_code: used_concats = \ - tools.put_concat(c_file_writer, function_code_replaced_types, used_concats) - c_file_writer.println(function_code_replaced_types) + tools.put_concat(c_file_writer, function_code, used_concats) + c_file_writer.println(function_code) c_file_writer.close() decompiler.closeProgram() decompiler.dispose() From 06d57814e998d8e3ed6b0aae68fab5edf151a490 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Tue, 16 Jul 2024 13:25:13 +0300 Subject: [PATCH 26/34] fix: addition of pylint option Signed-off-by: VyacheslavIurevich --- src/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.py b/src/main.py index a46b028..388490f 100644 --- a/src/main.py +++ b/src/main.py @@ -1,6 +1,6 @@ """Postprocessor main""" -# pylint: disable=wrong-import-position, import-error +# pylint: disable=wrong-import-position, import-error, too-many-locals import pyhidra pyhidra.start() From 1232a9dd747086780cb48492bc84e77c0cab63f1 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Tue, 16 Jul 2024 14:59:56 +0300 Subject: [PATCH 27/34] feat: addition of signature types replacement, new types added to TYPES_TO_REPLACE Signed-off-by: VyacheslavIurevich --- src/main.py | 3 ++- src/tools.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main.py b/src/main.py index 388490f..0796630 100644 --- a/src/main.py +++ b/src/main.py @@ -34,10 +34,11 @@ def export_c_code(binary_file_path, output_file_path): results = decompiler.decompileFunction(function, 0, flat_api.monitor) decompiled_function = results.getDecompiledFunction() function_signature = decompiled_function.getSignature() + function_signature_replaced_types = tools.replace_types(function_signature) function_code = decompiled_function.getC() function_code_replaced_types = tools.replace_types(function_code) functions_code.append(function_code_replaced_types) - c_file_writer.println(function_signature + '\n') + c_file_writer.println(function_signature_replaced_types + '\n') used_concats = set() for function_code in functions_code: if "CONCAT" in function_code: diff --git a/src/tools.py b/src/tools.py index da52d85..9d863d2 100644 --- a/src/tools.py +++ b/src/tools.py @@ -9,7 +9,9 @@ pyhidra.start() from ghidra.program.model.data import DataTypeWriter -TYPES_TO_REPLACE = OrderedDict(uint="unsigned int") +TYPES_TO_REPLACE = OrderedDict(uint="unsigned int", \ + ushort = "unsigned short", \ + ulong = "unsigned long") CONCAT_LEN = 6 # = len("CONCAT") BYTE_SIZE = 8 HEX_BASE = 16 From 0fa5ba54b425cd58ec2884c3f60aa22072bf5ba6 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Tue, 16 Jul 2024 15:14:52 +0300 Subject: [PATCH 28/34] fix: restructuring of code Signed-off-by: VyacheslavIurevich --- src/main.py | 65 ++++++++++++++++++++++++++++++---------------------- src/tools.py | 6 ++--- 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/main.py b/src/main.py index 0796630..7bfbde9 100644 --- a/src/main.py +++ b/src/main.py @@ -1,6 +1,6 @@ """Postprocessor main""" -# pylint: disable=wrong-import-position, import-error, too-many-locals +# pylint: disable=wrong-import-position, import-error import pyhidra pyhidra.start() @@ -11,43 +11,52 @@ LIBRARY_LIST = ["stdio.h", "stdlib.h", "inttypes.h"] +def init_decompiler(program): + """Decompiler initialization""" + options = DecompileOptions() + options.grabFromProgram(program) + decompiler = DecompInterface() + decompiler.setOptions(options) + decompiler.openProgram(program) + return decompiler + + +def put_functions(program, file_writer, monitor): + """Puts all functions and their signatures into C code file""" + decompiler = init_decompiler(program) + functions_code = [] + for function in program.getFunctionManager().getFunctions(True): + if tools.exclude_function(function): + continue + results = decompiler.decompileFunction(function, 0, monitor) + decompiled_function = results.getDecompiledFunction() + function_signature = decompiled_function.getSignature() + function_signature_replaced_types = tools.replace_types(function_signature) + function_code = decompiled_function.getC() + function_code_replaced_types = tools.replace_types(function_code) + functions_code.append(function_code_replaced_types) + file_writer.println(function_signature_replaced_types + '\n') + used_concats = set() + for function_code in functions_code: + if "CONCAT" in function_code: + used_concats = \ + tools.put_concat(file_writer, function_code, used_concats) + file_writer.println(function_code) + decompiler.closeProgram() + decompiler.dispose() + + def export_c_code(binary_file_path, output_file_path): """Exporting c code to a file""" with pyhidra.open_program(binary_file_path) as flat_api: program = flat_api.getCurrentProgram() - options = DecompileOptions() - options.grabFromProgram(program) - - decompiler = DecompInterface() - decompiler.setOptions(options) - decompiler.openProgram(program) - f = File(output_file_path) c_file_writer = PrintWriter(f) for lib in LIBRARY_LIST: c_file_writer.println(f"#include <{lib}>") tools.write_program_data_types(program, c_file_writer, flat_api.monitor) - functions_code = [] - for function in program.getFunctionManager().getFunctions(True): - if tools.exclude_function(function): - continue - results = decompiler.decompileFunction(function, 0, flat_api.monitor) - decompiled_function = results.getDecompiledFunction() - function_signature = decompiled_function.getSignature() - function_signature_replaced_types = tools.replace_types(function_signature) - function_code = decompiled_function.getC() - function_code_replaced_types = tools.replace_types(function_code) - functions_code.append(function_code_replaced_types) - c_file_writer.println(function_signature_replaced_types + '\n') - used_concats = set() - for function_code in functions_code: - if "CONCAT" in function_code: - used_concats = \ - tools.put_concat(c_file_writer, function_code, used_concats) - c_file_writer.println(function_code) + put_functions(program, c_file_writer, flat_api.monitor) c_file_writer.close() - decompiler.closeProgram() - decompiler.dispose() export_c_code("resources/in/bmp-header.out", "resources/out/test.c") diff --git a/src/tools.py b/src/tools.py index 9d863d2..00c795f 100644 --- a/src/tools.py +++ b/src/tools.py @@ -9,9 +9,9 @@ pyhidra.start() from ghidra.program.model.data import DataTypeWriter -TYPES_TO_REPLACE = OrderedDict(uint="unsigned int", \ - ushort = "unsigned short", \ - ulong = "unsigned long") +TYPES_TO_REPLACE = OrderedDict(uint="unsigned int", + ushort="unsigned short", + ulong="unsigned long") CONCAT_LEN = 6 # = len("CONCAT") BYTE_SIZE = 8 HEX_BASE = 16 From c2f3475451212ddd5be8396f7ebd92554d744237 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Tue, 16 Jul 2024 20:50:33 +0300 Subject: [PATCH 29/34] feat: addition of mergeable.yml Signed-off-by: VyacheslavIurevich --- .github/mergeable.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .github/mergeable.yml diff --git a/.github/mergeable.yml b/.github/mergeable.yml new file mode 100644 index 0000000..788aca1 --- /dev/null +++ b/.github/mergeable.yml @@ -0,0 +1,9 @@ +version: 2 +mergeable: + - when: pull_request.* + name: 'Check PR description' + validate: + - do: description + no_empty: + enabled: true + message: Description matter and should not be empty. Provide detail with **what** was changed, **why** it was changed, and **how** it was changed. From 27138e510ae7760993b4839c76d4bcb4b53bc672 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Tue, 16 Jul 2024 21:07:50 +0300 Subject: [PATCH 30/34] feat: README.md patch Signed-off-by: VyacheslavIurevich --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index c444e37..0a0aad4 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,13 @@ This console app provides ability to postprocess code, which is decompiled via G # Team * Vyacheslav Kochergin. [GitHub](https://github.com/VyacheslavIurevich), [Contact](https://t.me/se4life). * Vasilii Sarapulov. [GitHub](https://github.com/Sarapulov-Vas), [Contact](https://t.me/sarpaulov). +# Technologies used +* [Python 3.12](https://www.python.org/) +* [pyhidra](https://github.com/dod-cyber-crime-center/pyhidra) +* [Pylint](https://www.pylint.org/) +# Project status +In development. +# Contributing +See [CONTRIBUTING.md](./CONTRIBUTING.md) +# License +See [LICENSE](./LICENSE) From e257610f69c2d954ad420a500e70404c028080c6 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Tue, 16 Jul 2024 21:14:47 +0300 Subject: [PATCH 31/34] feat: addition of pylint badge Signed-off-by: VyacheslavIurevich --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0a0aad4..2850f4f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ # recompilation_postprocessor +![Pylint](https://github.com/VyacheslavIurevich/recompilation_postprocessor/actions/workflows/pylint.yml/badge.svg) + This console app provides ability to postprocess code, which is decompiled via Ghidra, to make it buildable. # Team * Vyacheslav Kochergin. [GitHub](https://github.com/VyacheslavIurevich), [Contact](https://t.me/se4life). From 71a6e180c6705d5e20bcd613a3aa9b5f08c67347 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Tue, 16 Jul 2024 22:57:14 +0300 Subject: [PATCH 32/34] feat: addition of stack protection removal Signed-off-by: VyacheslavIurevich --- src/main.py | 8 +++--- src/tools.py | 77 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/main.py b/src/main.py index 7bfbde9..ba60e29 100644 --- a/src/main.py +++ b/src/main.py @@ -31,11 +31,11 @@ def put_functions(program, file_writer, monitor): results = decompiler.decompileFunction(function, 0, monitor) decompiled_function = results.getDecompiledFunction() function_signature = decompiled_function.getSignature() - function_signature_replaced_types = tools.replace_types(function_signature) + function_signature_processed = tools.replace_types(function_signature) function_code = decompiled_function.getC() - function_code_replaced_types = tools.replace_types(function_code) - functions_code.append(function_code_replaced_types) - file_writer.println(function_signature_replaced_types + '\n') + function_code_processed = tools.handle_function(function_code) + functions_code.append(function_code_processed) + file_writer.println(function_signature_processed + '\n') used_concats = set() for function_code in functions_code: if "CONCAT" in function_code: diff --git a/src/tools.py b/src/tools.py index 00c795f..6d61342 100644 --- a/src/tools.py +++ b/src/tools.py @@ -16,6 +16,13 @@ BYTE_SIZE = 8 HEX_BASE = 16 RUNTIME_PREFIX = '_' +PLT_INSTRUCTION = "JMP qword ptr" +STACK_PROTECTOR_VARIABLE = "in_FS_OFFSET" + + +def address_to_int(address): + """Address is a number in hex""" + return int(str(address), HEX_BASE) def function_in_runtime(function): @@ -24,11 +31,6 @@ def function_in_runtime(function): return function_name.startswith(RUNTIME_PREFIX) -def address_to_int(address): - """Address is a number in hex""" - return int(str(address), HEX_BASE) - - def function_is_plt(function): """Check if input function is PLT jump""" program = function.getProgram() @@ -38,7 +40,7 @@ def function_is_plt(function): max_address = address_to_int(body.getMaxAddress()) for address in body.getAddresses(True): code_unit = str(listing.getCodeUnitAt(address)) - if code_unit.startswith("JMP qword ptr"): + if code_unit.startswith(PLT_INSTRUCTION): words = code_unit.split() jmp_address = address_to_int(words[-1][1:-1]) # [1:-1] is to remove [] from address if not min_address <= jmp_address <= max_address: @@ -46,10 +48,19 @@ def function_is_plt(function): return False -def write_program_data_types(program, c_file_writer, monitor): +def exclude_function(function): + """Dumping program data types""" + entry_point = function.getEntryPoint() + code_unit_at = function.getProgram().getListing().getCodeUnitAt(entry_point) + return function_in_runtime(function) \ + or function_is_plt(function) \ + or code_unit_at.getMnemonicString() == "??" + + +def write_program_data_types(program, file_writer, monitor): """Dumping program data types""" dtm = program.getDataTypeManager() - data_type_writer = DataTypeWriter(dtm, c_file_writer) + data_type_writer = DataTypeWriter(dtm, file_writer) data_type_list = [] for data_type in dtm.getAllDataTypes(): if ".h" not in data_type.getPathName().split('/')[1]: @@ -58,20 +69,36 @@ def write_program_data_types(program, c_file_writer, monitor): dtm.close() -def exclude_function(function): - """Dumping program data types""" - entry_point = function.getEntryPoint() - code_unit_at = function.getProgram().getListing().getCodeUnitAt(entry_point) - return function_in_runtime(function) \ - or function_is_plt(function) \ - or code_unit_at.getMnemonicString() == "??" - - -def replace_types(function_code): +def replace_types(code): """Replacing all Ghidra types with types from intttypes.h and standart C types""" for old_type, new_type in TYPES_TO_REPLACE.items(): - function_code = function_code.replace(old_type, new_type) - return function_code + code = code.replace(old_type, new_type) + return code + + +def remove_stack_protection(code): + """Removal of stack protection from code""" + lines = code.split('\n') + for num, line in enumerate(lines): + if STACK_PROTECTOR_VARIABLE in line: + # if we have "if ..." with in_FS_OFFSET checking + # we must remove all "if" block - 4 lines (with ghidra comment) + if "if" in line: + lines.pop(num + 3) + lines.pop(num + 2) + lines.pop(num + 1) + lines.pop(num) + new_code = '\n'.join(lines) + return new_code + + +def handle_function(code): + """Handling function code""" + code_replaced_types = replace_types(code) + if STACK_PROTECTOR_VARIABLE not in code_replaced_types: + return code_replaced_types + code_removed_stack_protection = remove_stack_protection(code_replaced_types) + return code_removed_stack_protection def get_nearest_lower_power_2(num): @@ -79,14 +106,14 @@ def get_nearest_lower_power_2(num): return 2 ** floor(log2(num)) -def put_concat(file_writer, function_code, used_concats): +def put_concat(file_writer, code, used_concats): """Puts CONCATXY functions into C code""" - concat_cnt = function_code.count("CONCAT") + concat_cnt = code.count("CONCAT") concat_idx = 0 for _ in range(concat_cnt): - concat_idx = function_code.find("CONCAT", concat_idx) + CONCAT_LEN - first_size = int(function_code[concat_idx]) - second_size = int(function_code[concat_idx + 1]) + concat_idx = code.find("CONCAT", concat_idx) + CONCAT_LEN + first_size = int(code[concat_idx]) + second_size = int(code[concat_idx + 1]) if (first_size, second_size) in used_concats: continue first_inttype_size = get_nearest_lower_power_2(first_size * BYTE_SIZE) From 92f8b17f7f6f2abcf0ece4f77577ac57172b9f42 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Wed, 17 Jul 2024 16:16:43 +0300 Subject: [PATCH 33/34] feat: addition of project folder removal Signed-off-by: VyacheslavIurevich --- src/main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main.py b/src/main.py index ba60e29..d4a29c3 100644 --- a/src/main.py +++ b/src/main.py @@ -1,6 +1,7 @@ """Postprocessor main""" # pylint: disable=wrong-import-position, import-error +from shutil import rmtree import pyhidra pyhidra.start() @@ -57,6 +58,8 @@ def export_c_code(binary_file_path, output_file_path): tools.write_program_data_types(program, c_file_writer, flat_api.monitor) put_functions(program, c_file_writer, flat_api.monitor) c_file_writer.close() + project_folder = str(flat_api.getProjectRootFolder())[:-2] # last two symbols are :/ + rmtree(f"resources/in/{project_folder}") export_c_code("resources/in/bmp-header.out", "resources/out/test.c") From fb585956ede8a974733767c12e0abf3f5ea75649 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Thu, 18 Jul 2024 15:00:20 +0300 Subject: [PATCH 34/34] feat: addition of new stack protector case removal Signed-off-by: VyacheslavIurevich --- resources/in/calculator | Bin 0 -> 25496 bytes resources/in/integrate_sin | Bin 0 -> 16488 bytes src/tools.py | 18 +++++++++++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100755 resources/in/calculator create mode 100755 resources/in/integrate_sin diff --git a/resources/in/calculator b/resources/in/calculator new file mode 100755 index 0000000000000000000000000000000000000000..aefa10bb81701786cf5271c898bbcd0004b77afe GIT binary patch literal 25496 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 literal 0 HcmV?d00001 diff --git a/resources/in/integrate_sin b/resources/in/integrate_sin new file mode 100755 index 0000000000000000000000000000000000000000..421ae382de13f89b5b776313bba2d822c37df50c GIT binary patch literal 16488 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 mSptmft}NB@Bu$W!e&TY@