/* ### * 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. */ // This script searches for image base offset references of size 32 and 64 to the current cursor // location. This script only works on programs of size 32 and 64. The results are both printed to // the console and are presented in a table with two tabs, one for each size. To apply data types to // undefined ones that are found simply select the desired ones from the table then drag either the // ImageBaseOffset32 or ImageBaseOffset64 data type, whichever is applicable, onto the selection in // the listing from the Data Type Manager. // //@category Search import ghidra.app.script.GhidraScript; import ghidra.program.model.address.*; import ghidra.util.exception.CancelledException; public class SearchForImageBaseOffsetsScript extends GhidraScript { static final int POINTER_BYTE_LEN_64BIT = 8; static final int POINTER_BYTE_LEN_32BIT = 4; static final byte BYTE_MASK = (byte) 0xff; static final int BITS_PER_BYTE = 8; @Override public void run() throws Exception { if (currentProgram == null) { println("No open program"); return; } long defaultPointerSize = currentProgram.getDefaultPointerSize(); if (defaultPointerSize != 4 && defaultPointerSize != 8) { println("This script only works on 32 or 64 bit programs"); return; } Address imageBase = currentProgram.getImageBase(); boolean isBigEndian = currentProgram.getMemory().isBigEndian(); long currentAddressOffset = currentAddress.getOffset(); long imageBaseOffset = imageBase.getOffset(); long currentAddressIbo = currentAddressOffset - imageBaseOffset; byte searchBytes[] = createSearchArray(currentAddressIbo, POINTER_BYTE_LEN_64BIT, isBigEndian); println("searching for possible ibo64 references to " + currentAddress.toString() + " ..."); AddressSet ibo64refs = searchForByteArray(searchBytes); printAddresses(ibo64refs); searchBytes = createSearchArray(currentAddressIbo, POINTER_BYTE_LEN_32BIT, isBigEndian); println("searching for possible ibo32 references to " + currentAddress.toString() + " ..."); AddressSet ibo32refs = searchForByteArray(searchBytes); printAddresses(ibo32refs); show("64-bit ImageBaseOffset References", ibo64refs); show("32-bit ImageBaseOffset References", ibo32refs); } /** * Method to return an appropriate sized and endian-ordered byte array out of the given long value * @param value the given value * @param numBytes the number of bytes to copy into the array * @return the appropriate sized and endian-ordered byte array for the given value * @throws CancelledException if cancelled */ private byte[] createSearchArray(long value, int numBytes, boolean isBigEndian) throws CancelledException { if (isBigEndian) { return createBigEndianByteArray(value, numBytes); } return createLittleEndianByteArray(value, numBytes); } /** * Method to create a little endian ordered byte array out of the given long value * @param value the given value * @param numBytes the number of bytes to copy into the array * @return the little endian byte array for the given value * @throws CancelledException if cancelled */ private byte[] createLittleEndianByteArray(long value, int numBytes) throws CancelledException { byte byteArray[] = new byte[numBytes]; for (int i = 0; i < numBytes; i++) { monitor.checkCancelled(); byteArray[i] = (byte) (value >> (BITS_PER_BYTE * i) & BYTE_MASK); } return byteArray; } /** * Method to create a big endian byte array out of the given long value * @param value the given value * @param numBytes the number of bytes to copy into the array * @return the big endian byte array for the given value * @throws CancelledException if cancelled */ private byte[] createBigEndianByteArray(long value, int numBytes) throws CancelledException { byte byteArray[] = new byte[numBytes]; for (int i = 0; i < numBytes; i++) { monitor.checkCancelled(); byteArray[i] = (byte) (value >> (8 * (numBytes - (i + 1))) & 0xff); } return byteArray; } /** * Method to search for the given byte array and print the address(es) where it is found * @param byteArray the given byte array * @throws CancelledException if cancelled */ private AddressSet searchForByteArray(byte[] byteArray) throws CancelledException { AddressSet addressSet = new AddressSet(); Address start = currentProgram.getMinAddress(); Address found = find(start, byteArray); while (found != null) { monitor.checkCancelled(); addressSet.add(found); start = found.add(1); found = find(start, byteArray); } return addressSet; } private void printAddresses(AddressSet addressSet) throws CancelledException { AddressIterator addresses = addressSet.getAddresses(true); while (addresses.hasNext()) { monitor.checkCancelled(); Address address = addresses.next(); println(address.toString()); } } }