Compare commits
2 Commits
88d10a9a2e
...
433d76fb73
Author | SHA1 | Date |
---|---|---|
|
433d76fb73 | |
|
a4b12ba2f4 |
|
@ -0,0 +1,3 @@
|
||||||
|
[*.java]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
|
@ -6,4 +6,30 @@
|
||||||
#include "gh_structs.h"
|
#include "gh_structs.h"
|
||||||
#include "gh_global.h"
|
#include "gh_global.h"
|
||||||
|
|
||||||
|
template<size_t Offset, size_t Size>
|
||||||
|
struct Field {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t Size>
|
||||||
|
struct _FieldBinderSizeTraits {
|
||||||
|
using type = undefined;
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct _FieldBinderSizeTraits<4> {
|
||||||
|
using type = undefined4;
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct _FieldBinderSizeTraits<2> {
|
||||||
|
using type = undefined2;
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct _FieldBinderSizeTraits<3> {
|
||||||
|
using type = undefined3;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t Offset, size_t Size>
|
||||||
|
inline uint32_t& operator+(const char* str, Field<Offset, Size> offset) {
|
||||||
|
return *(_FieldBinderSizeTraits<Size>*)(str + offset);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* B8D59B54_1674_4C0F_AA2C_611385FF5D03 */
|
#endif /* B8D59B54_1674_4C0F_AA2C_611385FF5D03 */
|
||||||
|
|
|
@ -1,14 +1,26 @@
|
||||||
#ifndef A523F6DB_0645_4DEB_8AEB_3792CB732B49
|
#ifndef A523F6DB_0645_4DEB_8AEB_3792CB732B49
|
||||||
#define A523F6DB_0645_4DEB_8AEB_3792CB732B49
|
#define A523F6DB_0645_4DEB_8AEB_3792CB732B49
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#else
|
||||||
|
#include "../win32_shim.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/proc.h>
|
||||||
|
#endif
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
// Fallback to int if type is not annotated
|
// Fallback to int if type is not annotated
|
||||||
// typedef int64_t undefined;
|
// typedef int64_t undefined;
|
||||||
typedef uint32_t undefined4;
|
typedef uint32_t undefined4;
|
||||||
typedef uint16_t undefined2;
|
typedef uint16_t undefined2;
|
||||||
|
struct undefined3 {
|
||||||
|
uint8_t _0;
|
||||||
|
uint8_t _1;
|
||||||
|
uint8_t _2;
|
||||||
|
};
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
typedef byte undefined1;
|
typedef byte undefined1;
|
||||||
// typedef uint64_t uint;
|
// typedef uint64_t uint;
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
#ifndef F69A0336_B517_4804_B49B_F4FBE6691DDB
|
||||||
|
#define F69A0336_B517_4804_B49B_F4FBE6691DDB
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef const char* LPCSTR;
|
||||||
|
typedef const wchar_t* LPCWSTR;
|
||||||
|
typedef char* LPSTR;
|
||||||
|
typedef wchar_t* LPWSTR;
|
||||||
|
typedef void* LPVOID;
|
||||||
|
typedef const void* LPCVOID;
|
||||||
|
typedef unsigned long DWORD;
|
||||||
|
typedef unsigned short WORD;
|
||||||
|
typedef unsigned char BYTE;
|
||||||
|
typedef int32_t LONG;
|
||||||
|
typedef uint32_t ULONG;
|
||||||
|
typedef int32_t BOOL;
|
||||||
|
typedef uint32_t UINT;
|
||||||
|
typedef char CHAR;
|
||||||
|
|
||||||
|
typedef void* HANDLE;
|
||||||
|
typedef void* HMODULE;
|
||||||
|
typedef void* HINSTANCE;
|
||||||
|
typedef void* HWND;
|
||||||
|
typedef void* HDC;
|
||||||
|
typedef void* HGLRC;
|
||||||
|
typedef void* HMENU;
|
||||||
|
typedef void* HBITMAP;
|
||||||
|
typedef void* HBRUSH;
|
||||||
|
typedef void* HFONT;
|
||||||
|
typedef void* HPEN;
|
||||||
|
typedef void* HRGN;
|
||||||
|
typedef void* HICON;
|
||||||
|
typedef void* HCURSOR;
|
||||||
|
typedef void* HACCEL;
|
||||||
|
typedef void* HRSRC;
|
||||||
|
typedef void* HGLOBAL;
|
||||||
|
typedef void* HLOCAL;
|
||||||
|
typedef void* HKEY;
|
||||||
|
typedef void* PHKEY;
|
||||||
|
typedef DWORD* LPDWORD;
|
||||||
|
typedef BYTE* LPBYTE;
|
||||||
|
typedef int32_t LSTATUS;
|
||||||
|
|
||||||
|
typedef struct tagRECT {
|
||||||
|
LONG left;
|
||||||
|
LONG top;
|
||||||
|
LONG right;
|
||||||
|
LONG bottom;
|
||||||
|
} RECT;
|
||||||
|
|
||||||
|
inline void GetWindowsDirectoryA(char* lpBuffer, DWORD nSize) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LPSTR GetCommandLineA() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void GetPrivateProfileStringA(LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpBuffer, DWORD nSize, LPCSTR lpFileName) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LSTATUS RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, DWORD samDesired, PHKEY phkResult) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LSTATUS RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LSTATUS RegCloseKey(HKEY hKey) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* F69A0336_B517_4804_B49B_F4FBE6691DDB */
|
|
@ -10,10 +10,14 @@ import java.util.HashSet;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Dictionary;
|
import java.util.Dictionary;
|
||||||
|
|
||||||
|
import ghidra.app.decompiler.ClangFieldToken;
|
||||||
import ghidra.app.decompiler.ClangLine;
|
import ghidra.app.decompiler.ClangLine;
|
||||||
|
import ghidra.app.decompiler.ClangSyntaxToken;
|
||||||
import ghidra.app.decompiler.ClangToken;
|
import ghidra.app.decompiler.ClangToken;
|
||||||
import ghidra.app.decompiler.DecompileResults;
|
import ghidra.app.decompiler.DecompileResults;
|
||||||
import ghidra.app.decompiler.PrettyPrinter;
|
import ghidra.app.decompiler.PrettyPrinter;
|
||||||
|
@ -24,7 +28,6 @@ import ghidra.program.model.data.BitFieldDataType;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.DataTypeComponent;
|
import ghidra.program.model.data.DataTypeComponent;
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
import ghidra.program.model.data.DataTypeManager;
|
||||||
import re3lib.DataTypeWriter;
|
|
||||||
import ghidra.program.model.data.PointerDataType;
|
import ghidra.program.model.data.PointerDataType;
|
||||||
import ghidra.program.model.data.ProgramBasedDataTypeManager;
|
import ghidra.program.model.data.ProgramBasedDataTypeManager;
|
||||||
import ghidra.program.model.data.Structure;
|
import ghidra.program.model.data.Structure;
|
||||||
|
@ -76,7 +79,8 @@ public class Decompile extends GhidraScript {
|
||||||
if (comment != null && comment.contains("Library Function")) {
|
if (comment != null && comment.contains("Library Function")) {
|
||||||
println("Adding library function " + function.getName() + " to blacklist");
|
println("Adding library function " + function.getName() + " to blacklist");
|
||||||
println("ac:" + functionAddrBlackList.size() + " jj:"
|
println("ac:" + functionAddrBlackList.size() + " jj:"
|
||||||
+ functionAddrBlackList.contains(function.getEntryPoint()) + " " + function.getEntryPoint());
|
+ functionAddrBlackList.contains(function.getEntryPoint()) + " "
|
||||||
|
+ function.getEntryPoint());
|
||||||
isIgnoredFunction = true;
|
isIgnoredFunction = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +145,8 @@ public class Decompile extends GhidraScript {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static final Pattern fieldAccessRegex = Pattern.compile("^_([0-9]+)_([0-9]+)_$");
|
||||||
|
|
||||||
void decompileFunction(Hashtable<String, GlobalRec> outGlobalSymbols, Function function)
|
void decompileFunction(Hashtable<String, GlobalRec> outGlobalSymbols, Function function)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
String fileName = sanitizeFunctionName(function.getName()) + ".cxx";
|
String fileName = sanitizeFunctionName(function.getName()) + ".cxx";
|
||||||
|
@ -182,8 +188,50 @@ public class Decompile extends GhidraScript {
|
||||||
for (int i = 0; i < line.getIndent(); i++) {
|
for (int i = 0; i < line.getIndent(); i++) {
|
||||||
codeWriter.write(' ');
|
codeWriter.write(' ');
|
||||||
}
|
}
|
||||||
for (int t = 0; t < line.getNumTokens(); t++) {
|
|
||||||
ClangToken token = line.getToken(t);
|
List<ClangToken> tokens = new ArrayList<>();
|
||||||
|
// Parse preliminary line tokens
|
||||||
|
for (int i = 0; i < line.getNumTokens(); i++) {
|
||||||
|
ClangToken token = line.getToken(i);
|
||||||
|
if (!token.getText().isEmpty())
|
||||||
|
tokens.add(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preprocess tokens
|
||||||
|
boolean prevDot = false;
|
||||||
|
for (int t = 0; t < tokens.size(); t++) {
|
||||||
|
ClangToken token = tokens.get(t);
|
||||||
|
|
||||||
|
boolean thisDot = false;
|
||||||
|
// println("Token: " + token.toString());
|
||||||
|
if (token.toString().equals(".")) {
|
||||||
|
// println("Found dot: " + token.toString() + " - " + token.getClass());
|
||||||
|
thisDot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevDot) {
|
||||||
|
// println("Possible field access: " + token.getText());
|
||||||
|
if (token instanceof ClangSyntaxToken) {
|
||||||
|
// Parse _4_4_ sub-access using regex
|
||||||
|
String text = token.getText();
|
||||||
|
Matcher matcher = fieldAccessRegex.matcher(text);
|
||||||
|
if (matcher.matches()) {
|
||||||
|
int offset = Integer.parseInt(matcher.group(1));
|
||||||
|
int size = Integer.parseInt(matcher.group(2));
|
||||||
|
// println("MATCHED: " + token.getText() + " - " + token.getSyntaxType() + " - " + token.getVarnode() + " - "
|
||||||
|
// + token.getPcodeOp());
|
||||||
|
|
||||||
|
// Replace tokens with + Field<offset, size>
|
||||||
|
ClangToken replacement = new ClangToken(token.Parent(), " + Field<" + offset + ", " + size + ">()");
|
||||||
|
tokens.remove(t);
|
||||||
|
tokens.remove(t - 1);
|
||||||
|
tokens.add(t - 1, replacement);
|
||||||
|
t--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract memory references
|
||||||
HighSymbol gsym = token.getHighSymbol(highFunction);
|
HighSymbol gsym = token.getHighSymbol(highFunction);
|
||||||
if (gsym != null) {
|
if (gsym != null) {
|
||||||
var symStorage = gsym.getStorage();
|
var symStorage = gsym.getStorage();
|
||||||
|
@ -197,27 +245,11 @@ public class Decompile extends GhidraScript {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address.isMemoryAddress()) {
|
if (address.isMemoryAddress()) {
|
||||||
// println("Memory: " + token.toString() + " - " + gsym.getName() + " - " +
|
|
||||||
// address);
|
|
||||||
// boolean defined = address.isConstantAddress();
|
|
||||||
// Symbol symAtAddr = getSymbolAt(address);
|
|
||||||
// if (defined && symAtAddr != null) {
|
|
||||||
// } else {
|
|
||||||
// // println("NOT FULLY DEFINED: " + address + " - " + symAtAddr);
|
|
||||||
// // defined = false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
outGlobalSymbols.put(gsym.getName(), new GlobalRec(gsym, address));
|
outGlobalSymbols.put(gsym.getName(), new GlobalRec(gsym, address));
|
||||||
} else {
|
}
|
||||||
// println("Unknown: " + token.toString() + " - " + gsym.getName() + " - " +
|
|
||||||
// address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// println("CONST: " + token.toString() + " - " + gsym.getName());
|
// Extract external function calls
|
||||||
// println(
|
|
||||||
// "Token: " + token.toString() + " - " + gsym.getName() + " - " +
|
|
||||||
// symStorage.getSerializationString());
|
|
||||||
}
|
|
||||||
PcodeOp op = token.getPcodeOp();
|
PcodeOp op = token.getPcodeOp();
|
||||||
if (op != null && op.getOpcode() == PcodeOp.CALL) {
|
if (op != null && op.getOpcode() == PcodeOp.CALL) {
|
||||||
// println("PcodeOp: " + op.toString() + " - " + op.getInput(0).toString());
|
// println("PcodeOp: " + op.toString() + " - " + op.getInput(0).toString());
|
||||||
|
@ -230,11 +262,18 @@ public class Decompile extends GhidraScript {
|
||||||
// println("Adding header: " + calledFunction + " / " +
|
// println("Adding header: " + calledFunction + " / " +
|
||||||
// calledFunction.getSignature().getPrototypeString(true));
|
// calledFunction.getSignature().getPrototypeString(true));
|
||||||
headers.add("extern " + calledFunction.getSignature().getPrototypeString(true)
|
headers.add("extern " + calledFunction.getSignature().getPrototypeString(true)
|
||||||
+ "; // " + calledFunction.getEntryPoint() + " // " + calledFunction.getName());
|
+ "; // " + calledFunction.getEntryPoint() + " // "
|
||||||
|
+ calledFunction.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
prevDot = thisDot;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print tokens
|
||||||
|
for (int t = 0; t < tokens.size(); t++) {
|
||||||
|
ClangToken token = tokens.get(t);
|
||||||
codeWriter.write(token.toString());
|
codeWriter.write(token.toString());
|
||||||
}
|
}
|
||||||
codeWriter.write('\n');
|
codeWriter.write('\n');
|
||||||
|
@ -387,7 +426,8 @@ public class Decompile extends GhidraScript {
|
||||||
if (dt instanceof Structure || dt instanceof TypedefDataType) {
|
if (dt instanceof Structure || dt instanceof TypedefDataType) {
|
||||||
if (typeBlacklist.contains(dt.getDisplayName()))
|
if (typeBlacklist.contains(dt.getDisplayName()))
|
||||||
continue;
|
continue;
|
||||||
println("Adding: " + dt.getDisplayName() + " - " + dt.getClass().getSimpleName());
|
// println("Adding: " + dt.getDisplayName() + " - " +
|
||||||
|
// dt.getClass().getSimpleName());
|
||||||
filteredTypes.add(dt);
|
filteredTypes.add(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,7 +439,8 @@ public class Decompile extends GhidraScript {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
try (PrintWriter writer = new PrintWriter(new File(RecompileConfig.INSTANCE.outputDir, "gh_structs.h"), "UTF-8")) {
|
try (PrintWriter writer = new PrintWriter(new File(RecompileConfig.INSTANCE.outputDir, "gh_structs.h"),
|
||||||
|
"UTF-8")) {
|
||||||
headerGuardPre(writer, "STRUCTS");
|
headerGuardPre(writer, "STRUCTS");
|
||||||
writer.println("// AUTO-GENERATED FILE ");
|
writer.println("// AUTO-GENERATED FILE ");
|
||||||
writer.println("#include <gh_struct_binder.h>");
|
writer.println("#include <gh_struct_binder.h>");
|
||||||
|
|
Loading…
Reference in New Issue