88 lines
2.9 KiB
Java
88 lines
2.9 KiB
Java
/* ###
|
|
* IP: GHIDRA
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
// Search for the start of X86 relative call instructions, look at the potential target and
|
|
// and if the function is valid, then disassemble and create a function at the target.
|
|
//
|
|
// Your mileage may vary! This should only be run after existing code has been found.
|
|
// The results should be checked for validity.
|
|
// @category Analysis
|
|
|
|
import ghidra.app.script.GhidraScript;
|
|
import ghidra.app.util.PseudoDisassembler;
|
|
import ghidra.app.util.PseudoInstruction;
|
|
import ghidra.program.model.address.*;
|
|
import ghidra.program.model.listing.CodeUnit;
|
|
import ghidra.program.model.listing.Instruction;
|
|
|
|
public class FindX86RelativeCallsScript extends GhidraScript {
|
|
|
|
@Override
|
|
public void run() throws Exception {
|
|
|
|
Address addr = currentProgram.getMemory().getMinAddress();
|
|
PseudoDisassembler pdis = new PseudoDisassembler(currentProgram);
|
|
|
|
AddressSetView execSet = currentProgram.getMemory().getExecuteSet();
|
|
AddressSet disSet = new AddressSet();
|
|
|
|
while (addr != null) {
|
|
addr = this.find(addr, (byte) 0xe8);
|
|
if (addr == null) {
|
|
break;
|
|
}
|
|
|
|
if (execSet.isEmpty() || execSet.contains(addr)) {
|
|
CodeUnit cu = currentProgram.getListing().getUndefinedDataAt(addr);
|
|
if (cu != null) {
|
|
PseudoInstruction instr = pdis.disassemble(addr);
|
|
|
|
Address target = instr.getAddress(0);
|
|
|
|
if (currentProgram.getMemory().contains(target) &&
|
|
(execSet.isEmpty() || execSet.contains(target))) {
|
|
// println ("e8 call " + addr + " -> " + target);
|
|
|
|
// also disassemble from this call.
|
|
// This will only get a partial function, so maybe it would be better not to do this
|
|
if (currentProgram.getFunctionManager().getFunctionAt(target) != null) {
|
|
disassemble(addr);
|
|
disSet.add(addr);
|
|
}
|
|
|
|
// There should be more checks done here on the validity.
|
|
// maybe does the potential function at target start like other functions
|
|
// that have already been defined.
|
|
Instruction realinstr =
|
|
currentProgram.getListing().getInstructionAt(target);
|
|
if (realinstr == null) {
|
|
boolean isvalid = pdis.isValidSubroutine(target, true);
|
|
if (isvalid) {
|
|
// println(" found");
|
|
disassemble(target);
|
|
disSet.add(target);
|
|
createFunction(target, null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
addr = addr.add(1);
|
|
}
|
|
|
|
show("X86 Relative Calls", disSet);
|
|
}
|
|
}
|