Skip to content

Commit 1366ee7

Browse files
committed
⚡ add funcname analyzer
1 parent 64914c6 commit 1366ee7

File tree

3 files changed

+117
-37
lines changed

3 files changed

+117
-37
lines changed

.project

+17
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,15 @@
1010
<arguments>
1111
</arguments>
1212
</buildCommand>
13+
<buildCommand>
14+
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
15+
<arguments>
16+
</arguments>
17+
</buildCommand>
1318
</buildSpec>
1419
<natures>
1520
<nature>org.eclipse.jdt.core.javanature</nature>
21+
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
1622
</natures>
1723
<linkedResources>
1824
<link>
@@ -21,4 +27,15 @@
2127
<location>/Users/felber/ctf/ghidra_9.0.4</location>
2228
</link>
2329
</linkedResources>
30+
<filteredResources>
31+
<filter>
32+
<id>1631794475296</id>
33+
<name></name>
34+
<type>30</type>
35+
<matcher>
36+
<id>org.eclipse.core.resources.regexFilterMatcher</id>
37+
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
38+
</matcher>
39+
</filter>
40+
</filteredResources>
2441
</projectDescription>

src/main/java/gotools/GoFunctionNameAnalyzer.java

+89-19
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import ghidra.app.util.importer.MessageLog;
77
import ghidra.program.model.address.Address;
88
import ghidra.program.model.address.AddressSetView;
9+
import ghidra.program.model.data.IntegerDataType;
910
import ghidra.program.model.data.StringDataType;
1011
import ghidra.program.model.listing.CodeUnit;
1112
import ghidra.program.model.listing.Data;
@@ -22,14 +23,12 @@
2223

2324
public class GoFunctionNameAnalyzer extends AnalyzerBase {
2425
public GoFunctionNameAnalyzer() {
25-
super("Go Function Name Analyzer", "Recovers function names in go binaries.",
26-
AnalyzerType.BYTE_ANALYZER);
26+
super("Go Function Name Analyzer", "Recovers function names in go binaries.", AnalyzerType.BYTE_ANALYZER);
2727
setPriority(AnalysisPriority.DATA_TYPE_PROPOGATION.before());
2828
}
2929

3030
@Override
31-
public boolean added(Program p, AddressSetView set, TaskMonitor monitor, MessageLog log)
32-
throws CancelledException {
31+
public boolean added(Program p, AddressSetView set, TaskMonitor monitor, MessageLog log) throws CancelledException {
3332
MemoryBlock gopcln;
3433
try {
3534
gopcln = getGopclntab(p);
@@ -48,23 +47,28 @@ public boolean added(Program p, AddressSetView set, TaskMonitor monitor, Message
4847

4948
private void recoverGoFunctions(Program p, TaskMonitor m, MessageLog log, MemoryBlock gopc)
5049
throws MemoryAccessException {
50+
// TODO this only works for 64bit binaries
5151
long pointerSize = 8;
5252
Address a = gopc.getStart();
5353
int goVersionMagic = p.getMemory().getInt(a);
54-
a.add(8);
54+
try {
55+
createData(p, a, new IntegerDataType());
56+
} catch (Exception e) {
57+
log.appendException(e);
58+
}
59+
a = a.add(pointerSize);
60+
5561
// https://github.com/golang/go/blob/release-branch.go1.16/src/debug/gosym/pclntab.go#L169
5662
if (goVersionMagic == 0xfffffffb) {
57-
getInformation12(p, m, log, a, pointerSize);
58-
}
59-
else {
60-
getInformation116(p, m, log, a, pointerSize);
63+
getInformation12(p, m, log, gopc, a, pointerSize);
64+
} else {
65+
getInformation116(p, m, log, gopc, a, pointerSize);
6166
}
6267
}
63-
}
64-
// TODO this only works for 64bit binaries
65-
}
66-
private void getInformation12(Program p, TaskMonitor m, MessageLog log, MemoryBlock gopc, Address a, long pointerSize){
67-
// skip unimportant header
68+
69+
private void getInformation12(Program p, TaskMonitor m, MessageLog log, MemoryBlock gopc, Address a, long pointerSize)
70+
throws MemoryAccessException {
71+
// skip unimportant header
6872
long size = p.getMemory().getLong(a);
6973
a = a.add(pointerSize);
7074
for (int i = 0; i < size; i++) {
@@ -95,11 +99,78 @@ private void getInformation12(Program p, TaskMonitor m, MessageLog log, MemoryBl
9599
continue;
96100
}
97101
if (f == null) {
98-
CreateFunctionCmd cmd =
99-
new CreateFunctionCmd(functionName, funcPointer, null, SourceType.ANALYSIS);
102+
CreateFunctionCmd cmd = new CreateFunctionCmd(functionName, funcPointer, null, SourceType.ANALYSIS);
103+
if (!cmd.applyTo(p, m)) {
104+
log.appendMsg(
105+
String.format("Unable to create function at %s, (expected %s)\n", d.getAddress(), d.getValue()));
106+
}
107+
continue;
108+
} else if (f.getName().equals(functionName)) {
109+
continue;
110+
}
111+
try {
112+
f.setName(functionName, SourceType.ANALYSIS);
113+
p.getListing().setComment(funcPointer, CodeUnit.EOL_COMMENT, "from gotool");
114+
} catch (DuplicateNameException | InvalidInputException e) {
115+
log.appendException(e);
116+
continue;
117+
}
118+
}
119+
}
120+
121+
private void getInformation116(Program p, TaskMonitor m, MessageLog log, MemoryBlock gopc, Address a,
122+
long pointerSize) throws MemoryAccessException {
123+
Address funcDataTable, currentFuncTable;
124+
long size = p.getMemory().getLong(a);
125+
a = a.add(pointerSize * 2);
126+
long funcNameTableOffset = p.getMemory().getLong(a);
127+
a = a.add(pointerSize * 4);
128+
long funcDataTableOffset = p.getMemory().getLong(a);
129+
funcDataTable = gopc.getStart().add(funcDataTableOffset);
130+
currentFuncTable = gopc.getStart().add(funcDataTableOffset);
131+
132+
for (int i = 0; i < size; i++) {
133+
long funcEntryPoint, funcDataOffset;
134+
int funcNameOffset;
135+
try {
136+
funcEntryPoint = p.getMemory().getLong(currentFuncTable);
137+
currentFuncTable = currentFuncTable.add(pointerSize);
138+
139+
funcDataOffset = p.getMemory().getLong(currentFuncTable);
140+
currentFuncTable = currentFuncTable.add(pointerSize);
141+
142+
funcNameOffset = p.getMemory().getInt(funcDataTable.add(funcDataOffset + pointerSize));
143+
} catch (Exception e) {
144+
log.appendException(e);
145+
continue;
146+
}
147+
148+
Address namePointer = gopc.getStart().add(funcNameTableOffset + funcNameOffset);
149+
Data d;
150+
try {
151+
d = createData(p, namePointer, new StringDataType());
152+
p.getListing().setComment(namePointer, CodeUnit.EOL_COMMENT, d.getValue().toString());
153+
} catch (Exception e) {
154+
log.appendException(e);
155+
continue;
156+
}
157+
Address funcPointer = p.getAddressFactory().getDefaultAddressSpace().getAddress(funcEntryPoint);
158+
Function f = p.getFunctionManager().getFunctionAt(funcPointer);
159+
String functionName = (String) (d.getValue());
160+
if (functionName.startsWith("type..") || functionName.endsWith(".")) {
161+
// TODO what to do with it?
162+
p.getListing().setComment(funcPointer, CodeUnit.EOL_COMMENT, functionName);
163+
continue;
164+
}
165+
if (gopc.contains(funcPointer)) {
166+
log.appendMsg(String.format("skipped %s because it is in the section", functionName));
167+
continue;
168+
}
169+
if (f == null) {
170+
CreateFunctionCmd cmd = new CreateFunctionCmd(functionName, funcPointer, null, SourceType.ANALYSIS);
100171
if (!cmd.applyTo(p, m)) {
101-
log.appendMsg(String.format(
102-
"Unable to create function at %s, (expected %s)\n", d.getAddress(), d.getValue()));
172+
log.appendMsg(
173+
String.format("Unable to create function at %s, (expected %s)\n", d.getAddress(), d.getValue()));
103174
}
104175
continue;
105176
} else if (f.getName().equals(functionName)) {
@@ -113,5 +184,4 @@ private void getInformation12(Program p, TaskMonitor m, MessageLog log, MemoryBl
113184
}
114185
}
115186
}
116-
private void getInformation116(){}
117187
}

src/main/java/gotools/GoReturntypeAnalyzer.java

+11-18
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,12 @@
2323
import ghidra.program.model.data.DataType;
2424
import ghidra.program.model.data.StructureDataType;
2525
import ghidra.program.model.data.Undefined8DataType;
26-
import ghidra.program.model.listing.*;
2726
import ghidra.program.model.listing.Function;
2827
import ghidra.program.model.listing.Parameter;
2928
import ghidra.program.model.listing.ParameterImpl;
3029
import ghidra.program.model.listing.Program;
3130
import ghidra.program.model.listing.Variable;
3231
import ghidra.program.model.listing.VariableStorage;
33-
import ghidra.program.model.symbol.*;
3432
import ghidra.program.model.symbol.RefType;
3533
import ghidra.program.model.symbol.Reference;
3634
import ghidra.program.model.symbol.ReferenceManager;
@@ -55,8 +53,7 @@ public GoReturntypeAnalyzer() {
5553
}
5654

5755
@Override
58-
public boolean added(Program p, AddressSetView set, TaskMonitor monitor, MessageLog log)
59-
throws CancelledException {
56+
public boolean added(Program p, AddressSetView set, TaskMonitor monitor, MessageLog log) throws CancelledException {
6057
this.detectReturnTypes(p, monitor, log);
6158
return true;
6259
}
@@ -73,11 +70,11 @@ private void detectReturnTypes(Program p, TaskMonitor m, MessageLog log, Functio
7370
int minWrite = Integer.MAX_VALUE;
7471
m.setMessage(String.format("return type analysis of %s", f.getName()));
7572
if (!f.getName().contains("main.A")) {
76-
//return;
73+
// return;
7774
}
7875
try {
7976
f.setCallingConvention("go__stdcall");
80-
//f.setCallingConvention("unknown");
77+
// f.setCallingConvention("unknown");
8178
} catch (InvalidInputException e) {
8279
log.appendException(e);
8380
}
@@ -113,8 +110,7 @@ private void detectReturnTypes(Program p, TaskMonitor m, MessageLog log, Functio
113110
numberOfRet = (maxWrite - minWrite) / pointerSize + 1;
114111
}
115112
if (totalArgReturnVals > 10) {
116-
log.appendMsg(String.format(
117-
"Skipped function %s because it has %d arguments", f.getName(), totalArgReturnVals));
113+
log.appendMsg(String.format("Skipped function %s because it has %d arguments", f.getName(), totalArgReturnVals));
118114
return;
119115
}
120116
long numberOfArgs = totalArgReturnVals - numberOfRet;
@@ -131,11 +127,9 @@ private void detectReturnTypes(Program p, TaskMonitor m, MessageLog log, Functio
131127
if (params != null && params.length > i) {
132128
newParams.add(params[i]);
133129
} else {
134-
VariableStorage v =
135-
f.getCallingConvention().getArgLocation(i, params, new Undefined8DataType(), p);
130+
VariableStorage v = f.getCallingConvention().getArgLocation(i, params, new Undefined8DataType(), p);
136131
try {
137-
Variable var =
138-
new ParameterImpl(null, new Undefined8DataType(), v, p, SourceType.ANALYSIS);
132+
Variable var = new ParameterImpl(null, new Undefined8DataType(), v, p, SourceType.ANALYSIS);
139133
newParams.add(var); // TODO why so complicated?!
140134
} catch (InvalidInputException e) {
141135
log.appendException(e);
@@ -144,8 +138,8 @@ private void detectReturnTypes(Program p, TaskMonitor m, MessageLog log, Functio
144138
}
145139
}
146140
try {
147-
f.replaceParameters(newParams, Function.FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,
148-
false, SourceType.ANALYSIS);
141+
f.replaceParameters(newParams, Function.FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, false,
142+
SourceType.ANALYSIS);
149143
} catch (DuplicateNameException | InvalidInputException e) {
150144
log.appendException(e);
151145
return;
@@ -166,8 +160,7 @@ private void detectReturnTypes(Program p, TaskMonitor m, MessageLog log, Functio
166160
f.setReturn(t, new VariableStorage(p, minWrite, t.getLength()), SourceType.IMPORTED);
167161
break;
168162
default:
169-
StructureDataType s =
170-
new StructureDataType(String.format("ret_%d", f.getSymbol().getID()), 0);
163+
StructureDataType s = new StructureDataType(String.format("ret_%d", f.getSymbol().getID()), 0);
171164
for (int i = 0; i < numberOfRet; i++) {
172165
s.add(new Undefined8DataType());
173166
}
@@ -179,7 +172,7 @@ private void detectReturnTypes(Program p, TaskMonitor m, MessageLog log, Functio
179172
log.appendException(e);
180173
}
181174
}
182-
System.out.printf("Function %s has %d arguments and %d return values. Max offset: %d\n",
183-
f.getName(), numberOfArgs, numberOfRet, maxOffset);
175+
System.out.printf("Function %s has %d arguments and %d return values. Max offset: %d\n", f.getName(), numberOfArgs,
176+
numberOfRet, maxOffset);
184177
}
185178
}

0 commit comments

Comments
 (0)