diff --git a/.gitignore b/.gitignore index 85dd180..b484c6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,9 @@ ### OpenSHC +*.7z +*.sarif +*.bin +/tmp + build-*/ build/ _build/ diff --git a/convert3.py b/convert3.py new file mode 100644 index 0000000..99cb920 --- /dev/null +++ b/convert3.py @@ -0,0 +1,124 @@ +from typing import List +from skink.architecture.enums import Enum, EnumResult +from skink.export.project.project import Project +from skink.export.project.collection import ExportedContentCollection, ExportContents +from skink.architecture.structs.struct import Struct +from skink.architecture.unions.union import Union +from skink.architecture.functionsignatures import FunctionSignature +from skink.architecture.typedefs import Typedef +from skink.sarif.datatypes.DataTypeResult import DataTypeResult +from skink.sarif.datatypes.FunctionSignatureResult import FunctionSignatureResult +from skink.sarif.datatypes.UnionResult import UnionResult +from skink.sarif.BasicResult import BasicResult +from skink.sarif.datatypes.TypedefResult import TypedefResult +import logging + +from skink.export.classes.collect import collect_classes, collect_namespaced_functions +import pathlib +from skink.export.styles.style3.exporter import Exporter, BinaryContext, TransformationRules, FileRules + +from skink.export.context import DEFAULT, Context +ctx: Context = DEFAULT.copy() # type: ignore +ctx.class_rules.suffix = "" +ctx.struct_rules.suffix = "" +ctx.include.file_extension = "" + + +import argparse +parser = argparse.ArgumentParser() +parser.add_argument("--sarif", required=False, default="Stronghold Crusader.exe.all.sarif") +parser.add_argument("--clear-cache", required=False, action='store_true', default=False) +parser.add_argument("--output-dir", required=False, default='src') +parser.add_argument("--verbose", default=False, action='store_true') +args = parser.parse_args() + +if args.verbose: + logging.getLogger().setLevel(logging.DEBUG) + +if args.clear_cache: + if pathlib.Path(".cached-symbols.bin").exists(): + pathlib.Path(".cached-symbols.bin").unlink() + if pathlib.Path(".cached-objs.bin").exists(): + pathlib.Path(".cached-objs.bin").unlink() + +project = Project(args.sarif, cache_objects=True, cache_symbols_to_path=".cached-symbols.bin") + +# TODO: permit_overwrite = False +logging.log(logging.INFO, "processing all symbol results") +project.process_all_symbol_results(log_progress=1000, store_symbol_result=True, permit_overwrite=True) +logging.log(logging.INFO, "processing all symbol results: finished") + +# objs_i = 0 +# for _ in project.yield_raw_objects(): +# objs_i += 1 +# print(objs_i) +import pickle +if pathlib.Path(".cached-objs.bin").exists() == False: + logging.log(logging.INFO, "finding all by location") + objs: List[BasicResult] = [] + objs_i = 0 + for obj in project.find_all_by_location(location="/_HoldStrong", recursive=True, lookup_lsymbols=True): + objs_i += 1 + print(f"{objs_i}\t\t{obj.ruleId}") + objs.append(obj) + logging.log(logging.INFO, "finding all by location: finished") + with open(".cached-objs.bin", 'wb') as f: + pickle.dump(file=f, obj=objs) +else: + with open(".cached-objs.bin", 'rb') as f: + objs = pickle.load(file=f) + +logging.log(logging.INFO, "collecting classes") +clsses = list(collect_classes(objs)) +logging.log(logging.INFO, "collecting classes: finished") + +logging.log(logging.INFO, "collecting namespaced functions") +namespaced_functions = list(collect_namespaced_functions(objs)) +logging.log(logging.INFO, "collecting namespaced functions: finished") + +bc = BinaryContext(hash="3BB0A8C1", abbreviation="SHC", reccmp_binary="STRONGHOLDCRUSADER") +exporter = Exporter(binary_context=bc, transformation_rules=TransformationRules(use_regex = True, regex={"_HoldStrong": "OpenSHC"}), expose_original_methods=True, + file_rules = FileRules(one_file_per_function=True, one_file_per_method=True)) + +collection = ExportedContentCollection(ignore_duplicates=True) + +collection.add(*exporter.export_helpers()) + +for cls in clsses: + collection.add(*exporter.export_class(cls)) + +for ns in namespaced_functions: + collection.add(*exporter.export_namespace(ns)) + +collection.add(exporter.export_addresses(project.yield_objects())) + +class_paths = set(cls.location(ctx) for cls in clsses) + +for obj in objs: + if isinstance(obj, DataTypeResult): + if obj.message.text == "DT.Struct": + global S + s = Struct(obj) + if s.name == "GameSynchronyState": + S = s + if s.path(ctx) not in class_paths: + collection.add(exporter.export_struct(s)) + elif isinstance(obj, EnumResult): + e = Enum(obj) + if e.er.properties.additionalProperties.size == 4: + collection.add(exporter.export_enum(e)) + else: + collection.add(*exporter.export_sized_enum(e)) + elif isinstance(obj, UnionResult): + e = Union(obj) + collection.add(exporter.export_union(e)) + elif isinstance(obj, FunctionSignatureResult): + fsr = FunctionSignature(obj) + collection.add(exporter.export_function_signature(fsr)) + elif isinstance(obj, TypedefResult): + td = Typedef(obj) + if "*" in td.name: + continue + collection.add(exporter.export_typedef(td)) + +collection.write_to_disk(pathlib.Path(args.output_dir), overwrite_all=True) diff --git a/reccmp/.gitignore b/reccmp/.gitignore new file mode 100644 index 0000000..53005d2 --- /dev/null +++ b/reccmp/.gitignore @@ -0,0 +1,4 @@ +reccmp-build.yml + +*.txt +*.json diff --git a/src/precomp/.gitignore b/src/precomp/.gitignore new file mode 100644 index 0000000..b4bdc95 --- /dev/null +++ b/src/precomp/.gitignore @@ -0,0 +1 @@ +addresses-SHC-3BB0A8C1.hpp \ No newline at end of file diff --git a/src/precomp/common.h b/src/precomp/common.hpp similarity index 80% rename from src/precomp/common.h rename to src/precomp/common.hpp index 8f5a1cf..801fb06 100644 --- a/src/precomp/common.h +++ b/src/precomp/common.hpp @@ -1,7 +1,9 @@ -#pragma once +/** + AUTO_GENERATED: DO NOT TOUCH THIS FILE + path: 'precomp/common.hpp' +*/ -#define MAP_XY_LIMIT 400 -#define MAP_XY_LIMIT_INCLUSIVE 399 +#pragma once namespace Ghidra { typedef void* pointer; @@ -11,7 +13,7 @@ typedef unsigned char undefined; // typedef unsigned char bool; typedef unsigned char byte; typedef unsigned int dword; -// typedef unsigned long long GUID; // different then the Windows one? +// typedef unsigned long long GUID; typedef pointer32 ImageBaseOffset32; typedef long long longlong; @@ -23,13 +25,13 @@ typedef unsigned long ulong; typedef unsigned long long ulonglong; typedef unsigned char undefined1; typedef unsigned short undefined2; -typedef unsigned int undefined3; +typedef unsigned char undefined3[3]; typedef unsigned int undefined4; typedef unsigned long long undefined6; typedef unsigned long long undefined8; typedef unsigned short ushort; // typedef short wchar_t; typedef unsigned short word; -} // namespace Ghidra +} using namespace Ghidra; diff --git a/src/precomp/pch.h b/src/precomp/pch.h index 39742ad..f08522a 100644 --- a/src/precomp/pch.h +++ b/src/precomp/pch.h @@ -3,9 +3,11 @@ #pragma once +#include "addresses-SHC-3BB0A8C1.hpp" +#include "polyfills/assertion.h" #include "CompileMacros.h" #include "FunctionResolver.h" #include "StructResolver.h" #include "TypeUtility.h" -#include "common.h" +#include "common.hpp" #include "framework.h" diff --git a/src/precomp/polyfills/assertion.h b/src/precomp/polyfills/assertion.h new file mode 100644 index 0000000..e225c55 --- /dev/null +++ b/src/precomp/polyfills/assertion.h @@ -0,0 +1,7 @@ +/** + AUTO_GENERATED: DO NOT TOUCH THIS FILE + path: 'util/assertion.h' +*/ + +#define static_assert_cpp98(condition) typedef int _static_assert_cpp98_obj[(condition) ? 1 : -1]; +#define static_assert_cpp98_obj(condition, obj) typedef int _static_assert_cpp98 ## _ ## obj[(condition) ? 1 : -1]; \ No newline at end of file