mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-31 19:15:53 +08:00
GP-3952 Updated the script categories to simplify and reduce the number of folders.
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
//Annotates an HFS+ attributes b-Tree file.
|
||||
//@category iOS
|
||||
//@category Apple.iOS
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.util.bin.*;
|
||||
@@ -180,7 +180,8 @@ public class BTreeAnnotationScript extends GhidraScript {
|
||||
return data;
|
||||
}
|
||||
|
||||
private Data createBTreeHeaderRecord(Program program, BTreeHeaderRecord headerRecord, int offset)
|
||||
private Data createBTreeHeaderRecord(Program program, BTreeHeaderRecord headerRecord,
|
||||
int offset)
|
||||
throws Exception {
|
||||
Address address = toAddr(offset);
|
||||
DataType dataType = headerRecord.toDataType();
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
//This script cleans up the disassembly for kext files by locating "Bad Instruction" bookmarks caused by incorrectly defined data in valid code flows.
|
||||
//@author
|
||||
//@category iOS
|
||||
//@category Apple.iOS
|
||||
//@keybinding
|
||||
//@menupath
|
||||
//@toolbar
|
||||
@@ -56,7 +56,7 @@ public class BadInstructionCleanup extends GhidraScript {
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanup(Address ba) throws Exception {
|
||||
public void cleanup(Address ba) throws Exception {
|
||||
|
||||
Program p = currentProgram;
|
||||
BookmarkManager bmgr = p.getBookmarkManager();
|
||||
@@ -79,8 +79,9 @@ public void cleanup(Address ba) throws Exception {
|
||||
Address paddr = listing.getInstructionBefore(ba).getAddress();
|
||||
RegisterValue rv;
|
||||
if (paddr != null) {
|
||||
rv = p.getProgramContext().getRegisterValue(contextReg,
|
||||
paddr);
|
||||
rv = p.getProgramContext()
|
||||
.getRegisterValue(contextReg,
|
||||
paddr);
|
||||
p.getProgramContext().setRegisterValue(ba, ba_end, rv);
|
||||
}
|
||||
}
|
||||
@@ -89,13 +90,14 @@ public void cleanup(Address ba) throws Exception {
|
||||
Function f = getFunctionBefore(ba);
|
||||
if (f != null) {
|
||||
CreateFunctionCmd cf = new CreateFunctionCmd(f.getName(), f
|
||||
.getEntryPoint(), null, f.getSymbol().getSource(),
|
||||
true, true);
|
||||
.getEntryPoint(),
|
||||
null, f.getSymbol().getSource(),
|
||||
true, true);
|
||||
cf.applyTo(p);
|
||||
}
|
||||
bmgr.removeBookmark(bm);
|
||||
bmgr.setBookmark(ba, "Analysis", "Cleanup",
|
||||
"Converted invalid pointer to code");
|
||||
"Converted invalid pointer to code");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
* 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.
|
||||
*/
|
||||
//@category iOS
|
||||
//@category Apple.iOS
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
//Processes Mach-O BIND information.
|
||||
//@category Mac OS X
|
||||
//@category Apple.Mac OS X
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
@@ -35,28 +35,29 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
File file = new File( currentProgram.getExecutablePath() );
|
||||
if ( !file.exists() ) {
|
||||
file = askFile( "Please select original file used to import this program:", "Original File" );
|
||||
File file = new File(currentProgram.getExecutablePath());
|
||||
if (!file.exists()) {
|
||||
file = askFile("Please select original file used to import this program:",
|
||||
"Original File");
|
||||
}
|
||||
if (file == null) {
|
||||
popup("File cannot be null");
|
||||
return;
|
||||
}
|
||||
if ( !file.exists() ) {
|
||||
popup( "Cannot find original binary at \n" + file.getAbsolutePath() );
|
||||
if (!file.exists()) {
|
||||
popup("Cannot find original binary at \n" + file.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
ByteProvider provider = new RandomAccessByteProvider( file ) ;
|
||||
ByteProvider provider = new RandomAccessByteProvider(file);
|
||||
try {
|
||||
MachHeader header = new MachHeader(provider);
|
||||
header.parse();
|
||||
List<DyldInfoCommand> commands = header.getLoadCommands( DyldInfoCommand.class );
|
||||
for ( DyldInfoCommand command : commands ) {
|
||||
if ( monitor.isCancelled() ) {
|
||||
List<DyldInfoCommand> commands = header.getLoadCommands(DyldInfoCommand.class);
|
||||
for (DyldInfoCommand command : commands) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
processCommand( header, provider, command );
|
||||
processCommand(header, provider, command);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -64,37 +65,39 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
}
|
||||
}
|
||||
|
||||
private void processCommand( MachHeader header, ByteProvider provider, DyldInfoCommand command ) throws Exception {
|
||||
private void processCommand(MachHeader header, ByteProvider provider, DyldInfoCommand command)
|
||||
throws Exception {
|
||||
|
||||
BindState bind = new BindState();
|
||||
bind.header = header;
|
||||
|
||||
try {
|
||||
boolean done = false;
|
||||
|
||||
byte [] commandBytes = provider.readBytes( command.getBindOffset(), command.getBindSize() );
|
||||
ByteArrayInputStream byteServer = new ByteArrayInputStream( commandBytes );
|
||||
|
||||
while ( !done ) {
|
||||
byte[] commandBytes =
|
||||
provider.readBytes(command.getBindOffset(), command.getBindSize());
|
||||
ByteArrayInputStream byteServer = new ByteArrayInputStream(commandBytes);
|
||||
|
||||
if ( monitor.isCancelled() ) {
|
||||
while (!done) {
|
||||
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
int value = byteServer.read();
|
||||
|
||||
if ( value == -1 ) {
|
||||
if (value == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
byte b = (byte) value;
|
||||
|
||||
int opcode = b & DyldInfoCommandConstants.BIND_OPCODE_MASK;
|
||||
int opcode = b & DyldInfoCommandConstants.BIND_OPCODE_MASK;
|
||||
int immediate = b & DyldInfoCommandConstants.BIND_IMMEDIATE_MASK;
|
||||
|
||||
switch ( opcode ) {
|
||||
switch (opcode) {
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_ADD_ADDR_ULEB: {
|
||||
bind.segmentOffset += uleb128( byteServer );
|
||||
bind.segmentOffset += uleb128(byteServer);
|
||||
break;
|
||||
}
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_DO_BIND: {
|
||||
@@ -104,18 +107,20 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
}
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: {
|
||||
bind.doBind();
|
||||
bind.segmentOffset += ( immediate * currentProgram.getDefaultPointerSize() ) + currentProgram.getDefaultPointerSize();
|
||||
bind.segmentOffset += (immediate * currentProgram.getDefaultPointerSize()) +
|
||||
currentProgram.getDefaultPointerSize();
|
||||
break;
|
||||
}
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: {
|
||||
bind.doBind();
|
||||
bind.segmentOffset += uleb128( byteServer ) + currentProgram.getDefaultPointerSize();
|
||||
bind.segmentOffset +=
|
||||
uleb128(byteServer) + currentProgram.getDefaultPointerSize();
|
||||
break;
|
||||
}
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: {
|
||||
long count = uleb128( byteServer );
|
||||
long skip = uleb128( byteServer );
|
||||
for ( int i = 0 ; i < count ; ++i ) {
|
||||
long count = uleb128(byteServer);
|
||||
long skip = uleb128(byteServer);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
bind.doBind();
|
||||
bind.segmentOffset += skip + currentProgram.getDefaultPointerSize();
|
||||
}
|
||||
@@ -126,41 +131,43 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
break;
|
||||
}
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_SET_ADDEND_SLEB: {
|
||||
bind.addend = sleb128( byteServer );
|
||||
bind.addend = sleb128(byteServer);
|
||||
break;
|
||||
}
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: {
|
||||
bind.libraryOrdinal = immediate;
|
||||
bind.fromDylib = getOrdinalName( bind );
|
||||
bind.fromDylib = getOrdinalName(bind);
|
||||
break;
|
||||
}
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: {
|
||||
bind.libraryOrdinal = (int) uleb128( byteServer );
|
||||
bind.fromDylib = getOrdinalName( bind );
|
||||
bind.libraryOrdinal = (int) uleb128(byteServer);
|
||||
bind.fromDylib = getOrdinalName(bind);
|
||||
break;
|
||||
}
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: {
|
||||
//the special ordinals are negative numbers
|
||||
if ( immediate == 0 ) {
|
||||
if (immediate == 0) {
|
||||
bind.libraryOrdinal = 0;
|
||||
}
|
||||
else {
|
||||
byte signExtended = (byte) ( DyldInfoCommandConstants.BIND_OPCODE_MASK | immediate );
|
||||
byte signExtended =
|
||||
(byte) (DyldInfoCommandConstants.BIND_OPCODE_MASK | immediate);
|
||||
bind.libraryOrdinal = signExtended;
|
||||
}
|
||||
bind.fromDylib = getOrdinalName( bind );
|
||||
bind.fromDylib = getOrdinalName(bind);
|
||||
break;
|
||||
}
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: {
|
||||
bind.segmentIndex = immediate;
|
||||
bind.segmentStartAddress = getSegmentStartAddress( bind );
|
||||
bind.segmentName = getSegmentName( bind );
|
||||
bind.segmentOffset = uleb128( byteServer );
|
||||
bind.segmentStartAddress = getSegmentStartAddress(bind);
|
||||
bind.segmentName = getSegmentName(bind);
|
||||
bind.segmentOffset = uleb128(byteServer);
|
||||
break;
|
||||
}
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: {
|
||||
bind.symbolName = readString( byteServer );
|
||||
if ( ( immediate & DyldInfoCommandConstants.BIND_SYMBOL_FLAGS_WEAK_IMPORT ) != 0 ) {
|
||||
bind.symbolName = readString(byteServer);
|
||||
if ((immediate &
|
||||
DyldInfoCommandConstants.BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) {
|
||||
bind.weak = true;
|
||||
}
|
||||
else {
|
||||
@@ -170,51 +177,51 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
}
|
||||
case DyldInfoCommandConstants.BIND_OPCODE_SET_TYPE_IMM: {
|
||||
bind.type = immediate;
|
||||
bind.typeName = getTypeName( bind );
|
||||
bind.typeName = getTypeName(bind);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
popup( "unknown bind opcode " + Integer.toHexString( opcode ) );
|
||||
popup("unknown bind opcode " + Integer.toHexString(opcode));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String readString( ByteArrayInputStream byteServer ) {
|
||||
private String readString(ByteArrayInputStream byteServer) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
while ( !monitor.isCancelled() ) {
|
||||
while (!monitor.isCancelled()) {
|
||||
int value = byteServer.read();
|
||||
if ( value == -1 ) {
|
||||
if (value == -1) {
|
||||
break;
|
||||
}
|
||||
byte b = (byte) value;
|
||||
if ( b == '\0' ) {
|
||||
if (b == '\0') {
|
||||
break;
|
||||
}
|
||||
buffer.append( (char) ( b & 0xff ) );
|
||||
buffer.append((char) (b & 0xff));
|
||||
}
|
||||
System.out.println( buffer.toString() );
|
||||
System.out.println(buffer.toString());
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private long getSegmentStartAddress( BindState bind ) {
|
||||
List<SegmentCommand> segments = bind.header.getLoadCommands( SegmentCommand.class );
|
||||
SegmentCommand segment = segments.get( bind.segmentIndex );
|
||||
private long getSegmentStartAddress(BindState bind) {
|
||||
List<SegmentCommand> segments = bind.header.getLoadCommands(SegmentCommand.class);
|
||||
SegmentCommand segment = segments.get(bind.segmentIndex);
|
||||
return segment.getVMaddress();
|
||||
}
|
||||
|
||||
private String getSegmentName( BindState bind ) {
|
||||
List<SegmentCommand> segments = bind.header.getLoadCommands( SegmentCommand.class );
|
||||
SegmentCommand segment = segments.get( bind.segmentIndex );
|
||||
private String getSegmentName(BindState bind) {
|
||||
List<SegmentCommand> segments = bind.header.getLoadCommands(SegmentCommand.class);
|
||||
SegmentCommand segment = segments.get(bind.segmentIndex);
|
||||
return segment.getSegmentName();
|
||||
}
|
||||
|
||||
private String getTypeName( BindState bind ) {
|
||||
switch ( bind.type ) {
|
||||
private String getTypeName(BindState bind) {
|
||||
switch (bind.type) {
|
||||
case DyldInfoCommandConstants.BIND_TYPE_POINTER: {
|
||||
return "pointer";
|
||||
}
|
||||
@@ -225,11 +232,11 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
return "text_pcrel32";
|
||||
}
|
||||
}
|
||||
throw new RuntimeException( "unknown type: " + Integer.toHexString( bind.type ) );
|
||||
throw new RuntimeException("unknown type: " + Integer.toHexString(bind.type));
|
||||
}
|
||||
|
||||
private String getOrdinalName( BindState bind ) {
|
||||
switch ( bind.libraryOrdinal ) {
|
||||
private String getOrdinalName(BindState bind) {
|
||||
switch (bind.libraryOrdinal) {
|
||||
case DyldInfoCommandConstants.BIND_SPECIAL_DYLIB_SELF: {
|
||||
return "this-image";
|
||||
}
|
||||
@@ -240,14 +247,15 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
return "flat-namespace";
|
||||
}
|
||||
}
|
||||
if ( bind.libraryOrdinal < DyldInfoCommandConstants.BIND_SPECIAL_DYLIB_FLAT_LOOKUP ) {
|
||||
return "unknown special ordinal" + Integer.toHexString( bind.libraryOrdinal );
|
||||
if (bind.libraryOrdinal < DyldInfoCommandConstants.BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
|
||||
return "unknown special ordinal" + Integer.toHexString(bind.libraryOrdinal);
|
||||
}
|
||||
List<DynamicLibraryCommand> dylibCommands = bind.header.getLoadCommands( DynamicLibraryCommand.class );
|
||||
if ( bind.libraryOrdinal > dylibCommands.size() ) {
|
||||
return "library ordinal out of range" + Integer.toHexString( bind.libraryOrdinal );
|
||||
List<DynamicLibraryCommand> dylibCommands =
|
||||
bind.header.getLoadCommands(DynamicLibraryCommand.class);
|
||||
if (bind.libraryOrdinal > dylibCommands.size()) {
|
||||
return "library ordinal out of range" + Integer.toHexString(bind.libraryOrdinal);
|
||||
}
|
||||
DynamicLibraryCommand dylibCommand = dylibCommands.get( bind.libraryOrdinal - 1 );
|
||||
DynamicLibraryCommand dylibCommand = dylibCommands.get(bind.libraryOrdinal - 1);
|
||||
DynamicLibrary dynamicLibrary = dylibCommand.getDynamicLibrary();
|
||||
LoadCommandString name = dynamicLibrary.getName();
|
||||
return name.getString();
|
||||
@@ -256,15 +264,15 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
/**
|
||||
* Unsigned Little-endian Base-128
|
||||
*/
|
||||
private long uleb128( ByteArrayInputStream byteServer ) throws Exception {
|
||||
private long uleb128(ByteArrayInputStream byteServer) throws Exception {
|
||||
long result = 0;
|
||||
int bit = 0;
|
||||
int bit = 0;
|
||||
|
||||
while ( !monitor.isCancelled() ) {
|
||||
while (!monitor.isCancelled()) {
|
||||
|
||||
int value = byteServer.read();
|
||||
|
||||
if ( value == -1 ) {
|
||||
if (value == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -272,16 +280,16 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
|
||||
long slice = b & 0x7f;
|
||||
|
||||
if ( ( b & 0x80 ) == 0x80 ) {//if upper bit is set
|
||||
if ( bit >= 64 || slice << bit >> bit != slice ) {//then left shift and right shift
|
||||
throw new RuntimeException( "uleb128 too big" );
|
||||
if ((b & 0x80) == 0x80) {//if upper bit is set
|
||||
if (bit >= 64 || slice << bit >> bit != slice) {//then left shift and right shift
|
||||
throw new RuntimeException("uleb128 too big");
|
||||
}
|
||||
}
|
||||
|
||||
result |= ( slice << bit );
|
||||
result |= (slice << bit);
|
||||
bit += 7;
|
||||
|
||||
if ( ( b & 0x80 ) == 0 ) {//if upper bit NOT set, then we are done
|
||||
if ((b & 0x80) == 0) {//if upper bit NOT set, then we are done
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -291,23 +299,23 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
/**
|
||||
* Signed Little-endian Base-128
|
||||
*/
|
||||
private long sleb128( ByteArrayInputStream byteServer ) throws Exception {
|
||||
private long sleb128(ByteArrayInputStream byteServer) throws Exception {
|
||||
long result = 0;
|
||||
int bit = 0;
|
||||
while ( !monitor.isCancelled() ) {
|
||||
int bit = 0;
|
||||
while (!monitor.isCancelled()) {
|
||||
|
||||
int value = byteServer.read();
|
||||
|
||||
if ( value == -1 ) {
|
||||
if (value == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
byte nextByte = (byte) value;
|
||||
|
||||
result |= ( ( nextByte & 0x7f ) << bit );
|
||||
result |= ((nextByte & 0x7f) << bit);
|
||||
bit += 7;
|
||||
|
||||
if ( ( nextByte & 0x80 ) == 0 ) {
|
||||
if ((nextByte & 0x80) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -339,51 +347,51 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
|
||||
String sectionName = "no section";
|
||||
List<Section> sections = header.getAllSections();
|
||||
for ( Section section : sections ) {
|
||||
for (Section section : sections) {
|
||||
long start = section.getAddress();
|
||||
long end = section.getAddress() + section.getSize();
|
||||
if ( sectionAddress.getOffset() >= start && sectionAddress.getOffset() < end ) {
|
||||
long end = section.getAddress() + section.getSize();
|
||||
if (sectionAddress.getOffset() >= start && sectionAddress.getOffset() < end) {
|
||||
sectionName = section.getSectionName();
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File( fromDylib );
|
||||
File file = new File(fromDylib);
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append( segmentName );
|
||||
buffer.append( ' ' );
|
||||
buffer.append( ' ' );
|
||||
buffer.append(segmentName);
|
||||
buffer.append(' ');
|
||||
buffer.append(' ');
|
||||
buffer.append(StringUtilities.pad(sectionName, ' ', -20));
|
||||
buffer.append( ' ' );
|
||||
buffer.append( ' ' );
|
||||
buffer.append( sectionAddress );
|
||||
buffer.append( ' ' );
|
||||
buffer.append( ' ' );
|
||||
buffer.append( typeName );
|
||||
buffer.append( ' ' );
|
||||
buffer.append( ' ' );
|
||||
buffer.append( weak );
|
||||
buffer.append( ' ' );
|
||||
buffer.append( ' ' );
|
||||
buffer.append( addend );
|
||||
buffer.append( ' ' );
|
||||
buffer.append( ' ' );
|
||||
buffer.append(' ');
|
||||
buffer.append(' ');
|
||||
buffer.append(sectionAddress);
|
||||
buffer.append(' ');
|
||||
buffer.append(' ');
|
||||
buffer.append(typeName);
|
||||
buffer.append(' ');
|
||||
buffer.append(' ');
|
||||
buffer.append(weak);
|
||||
buffer.append(' ');
|
||||
buffer.append(' ');
|
||||
buffer.append(addend);
|
||||
buffer.append(' ');
|
||||
buffer.append(' ');
|
||||
buffer.append(StringUtilities.pad(file.getName(), ' ', -20));
|
||||
buffer.append( ' ' );
|
||||
buffer.append( ' ' );
|
||||
buffer.append( symbolName );
|
||||
buffer.append( ' ' );
|
||||
buffer.append( ' ' );
|
||||
buffer.append(' ');
|
||||
buffer.append(' ');
|
||||
buffer.append(symbolName);
|
||||
buffer.append(' ');
|
||||
buffer.append(' ');
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
void doBind() throws Exception {
|
||||
monitor.setMessage( "Performing bind: " + symbolName );
|
||||
monitor.setMessage("Performing bind: " + symbolName);
|
||||
|
||||
SymbolIterator symbolIterator = currentProgram.getSymbolTable().getSymbols( symbolName );
|
||||
SymbolIterator symbolIterator = currentProgram.getSymbolTable().getSymbols(symbolName);
|
||||
|
||||
if ( !symbolIterator.hasNext() ) {
|
||||
printerr( "Not found: " + symbolName );
|
||||
if (!symbolIterator.hasNext()) {
|
||||
printerr("Not found: " + symbolName);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -391,22 +399,25 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||
|
||||
long offset = symbol.getAddress().getOffset();
|
||||
|
||||
DataConverter converter = DataConverter.getInstance(currentProgram.getLanguage().isBigEndian());
|
||||
DataConverter converter =
|
||||
DataConverter.getInstance(currentProgram.getLanguage().isBigEndian());
|
||||
|
||||
if ( currentProgram.getDefaultPointerSize() == 8 ) {
|
||||
setBytes( getAddress(), converter.getBytes( offset ) );
|
||||
if (currentProgram.getDefaultPointerSize() == 8) {
|
||||
setBytes(getAddress(), converter.getBytes(offset));
|
||||
}
|
||||
else {
|
||||
setBytes( getAddress(), converter.getBytes( (int)offset ) );
|
||||
setBytes(getAddress(), converter.getBytes((int) offset));
|
||||
}
|
||||
|
||||
Reference reference = currentProgram.getReferenceManager().addMemoryReference( getAddress(), symbol.getAddress(), RefType.READ, SourceType.IMPORTED, 0 );
|
||||
currentProgram.getReferenceManager().setPrimary( reference, true );
|
||||
Reference reference = currentProgram.getReferenceManager()
|
||||
.addMemoryReference(getAddress(), symbol.getAddress(), RefType.READ,
|
||||
SourceType.IMPORTED, 0);
|
||||
currentProgram.getReferenceManager().setPrimary(reference, true);
|
||||
}
|
||||
|
||||
Address getAddress() {
|
||||
long result = segmentStartAddress + segmentOffset;//TODO
|
||||
Address sectionAddress = toAddr( result & 0xffffffffL );
|
||||
Address sectionAddress = toAddr(result & 0xffffffffL);
|
||||
return sectionAddress;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
//Pulls symbol name through pointer references.
|
||||
//@category Mac OS X
|
||||
//@category Apple.Mac OS X
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -97,8 +97,9 @@ public class PointerPullerScript extends GhidraScript {
|
||||
}
|
||||
Namespace nameSpace = getNamespace(null, nameSpaceName);
|
||||
if (nameSpace == null) {
|
||||
nameSpace = currentProgram.getSymbolTable().createNameSpace(null, nameSpaceName,
|
||||
SourceType.ANALYSIS);
|
||||
nameSpace = currentProgram.getSymbolTable()
|
||||
.createNameSpace(null, nameSpaceName,
|
||||
SourceType.ANALYSIS);
|
||||
}
|
||||
return nameSpace;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
//@category References
|
||||
//@category
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -23,31 +22,31 @@ import ghidra.program.model.listing.CodeUnit;
|
||||
import ghidra.program.model.listing.Listing;
|
||||
import ghidra.program.model.symbol.*;
|
||||
|
||||
|
||||
public class RemoveAllOffcutReferencesScript extends GhidraScript {
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
Listing listing = currentProgram.getListing();
|
||||
ReferenceManager referenceManager = currentProgram.getReferenceManager();
|
||||
AddressIterator iterator = referenceManager.getReferenceDestinationIterator(currentProgram.getMinAddress(), true);
|
||||
AddressIterator iterator =
|
||||
referenceManager.getReferenceDestinationIterator(currentProgram.getMinAddress(), true);
|
||||
while (iterator.hasNext()) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
Address address = iterator.next();
|
||||
CodeUnit codeUnit = listing.getCodeUnitContaining(address);
|
||||
if (codeUnit != null) {
|
||||
if (!codeUnit.getMinAddress().equals(address)) {
|
||||
monitor.setMessage("Removing offcut reference at "+address);
|
||||
ReferenceIterator referencesTo = referenceManager.getReferencesTo(address);
|
||||
while (referencesTo.hasNext()) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
Reference reference = referencesTo.next();
|
||||
referenceManager.delete(reference);
|
||||
}
|
||||
Address address = iterator.next();
|
||||
CodeUnit codeUnit = listing.getCodeUnitContaining(address);
|
||||
if (codeUnit != null) {
|
||||
if (!codeUnit.getMinAddress().equals(address)) {
|
||||
monitor.setMessage("Removing offcut reference at " + address);
|
||||
ReferenceIterator referencesTo = referenceManager.getReferencesTo(address);
|
||||
while (referencesTo.hasNext()) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
Reference reference = referencesTo.next();
|
||||
referenceManager.delete(reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-15
@@ -1,13 +1,12 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* 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.
|
||||
@@ -15,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
//Removes any offcut references to the current code unit.
|
||||
//@category References
|
||||
//@category
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -29,38 +28,38 @@ public class RemoveOffcutReferenceToCurrentInstructionScript extends GhidraScrip
|
||||
|
||||
Instruction instruction = getInstructionAt(currentAddress);
|
||||
|
||||
if ( instruction != null ) {
|
||||
removeReferences( instruction );
|
||||
if (instruction != null) {
|
||||
removeReferences(instruction);
|
||||
}
|
||||
|
||||
Data data = getDataAt(currentAddress);
|
||||
|
||||
if ( data != null ) {
|
||||
removeReferences( data );
|
||||
if (data != null) {
|
||||
removeReferences(data);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeReferences(CodeUnit codeUnit) {
|
||||
Address address = currentAddress.add( 1 );
|
||||
Address address = currentAddress.add(1);
|
||||
|
||||
while ( address.compareTo( codeUnit.getMaxAddress() ) <= 0) {
|
||||
while (address.compareTo(codeUnit.getMaxAddress()) <= 0) {
|
||||
|
||||
if ( monitor.isCancelled() ) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
Reference [] referencesTo = getReferencesTo(address);
|
||||
Reference[] referencesTo = getReferencesTo(address);
|
||||
|
||||
for ( Reference reference : referencesTo ) {
|
||||
for (Reference reference : referencesTo) {
|
||||
|
||||
if ( monitor.isCancelled() ) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
removeReference(reference);
|
||||
}
|
||||
|
||||
address = address.add( 1 );
|
||||
address = address.add(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+44
-41
@@ -1,13 +1,12 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* 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.
|
||||
@@ -16,7 +15,7 @@
|
||||
*/
|
||||
//Resolves relative references computed off EBX.
|
||||
//This will resolve references to strings in the "__cstring" section.
|
||||
//@category Mac OS X
|
||||
//@category Apple.Mac OS X
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -38,19 +37,19 @@ public class ResolveReferencesRelativeToEbxScript extends GhidraScript {
|
||||
|
||||
FunctionIterator functions = currentProgram.getListing().getFunctions(true);
|
||||
|
||||
while ( functions.hasNext() ) {
|
||||
while (functions.hasNext()) {
|
||||
|
||||
if ( monitor.isCancelled() ) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
Function function = functions.next();
|
||||
|
||||
monitor.setMessage( function.getName() );
|
||||
monitor.setMessage(function.getName());
|
||||
|
||||
loopOverInstructionsInFunction( function );
|
||||
loopOverInstructionsInFunction(function);
|
||||
|
||||
function = getFunctionAfter( function );
|
||||
function = getFunctionAfter(function);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,49 +58,53 @@ public class ResolveReferencesRelativeToEbxScript extends GhidraScript {
|
||||
|
||||
long ebx = -1;
|
||||
|
||||
InstructionIterator instructions = currentProgram.getListing().getInstructions( function.getBody(), true ) ;
|
||||
InstructionIterator instructions =
|
||||
currentProgram.getListing().getInstructions(function.getBody(), true);
|
||||
|
||||
while ( instructions.hasNext() ) {
|
||||
while (instructions.hasNext()) {
|
||||
|
||||
Instruction instruction = instructions.next();
|
||||
|
||||
if ( monitor.isCancelled() ) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ebx == -1 ) {
|
||||
ebx = getValueForEBX( instruction );
|
||||
if (ebx == -1) {
|
||||
ebx = getValueForEBX(instruction);
|
||||
}
|
||||
|
||||
if ( ebx == -1 ) {
|
||||
if (ebx == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0 ; i < instruction.getNumOperands() ; ++i ) {
|
||||
for (int i = 0; i < instruction.getNumOperands(); ++i) {
|
||||
|
||||
Object [] opObjects = instruction.getOpObjects(i);
|
||||
Object[] opObjects = instruction.getOpObjects(i);
|
||||
|
||||
if ( opObjects.length == 2 ) {
|
||||
if (opObjects.length == 2) {
|
||||
|
||||
if (opObjects[ 0 ] instanceof Scalar && opObjects[ 1 ] instanceof Register ) {
|
||||
if (opObjects[0] instanceof Scalar && opObjects[1] instanceof Register) {
|
||||
|
||||
Scalar scalar = (Scalar) opObjects[ 0 ];
|
||||
Scalar scalar = (Scalar) opObjects[0];
|
||||
|
||||
Register register = (Register) opObjects[ 1 ];
|
||||
Register register = (Register) opObjects[1];
|
||||
|
||||
if ( register.equals( EBX ) ) {
|
||||
if (register.equals(EBX)) {
|
||||
|
||||
Address address = toAddr( (ebx + scalar.getUnsignedValue()) & Conv.INT_MASK );
|
||||
Address address =
|
||||
toAddr((ebx + scalar.getUnsignedValue()) & Conv.INT_MASK);
|
||||
|
||||
if ( isValid( address ) ) {
|
||||
if (isValid(address)) {
|
||||
|
||||
removeReferencesFrom(instruction);
|
||||
|
||||
Reference reference = createMemoryReference( instruction, 1, address, RefType.DATA );
|
||||
Reference reference =
|
||||
createMemoryReference(instruction, 1, address, RefType.DATA);
|
||||
|
||||
setReferencePrimary( reference );
|
||||
setReferencePrimary(reference);
|
||||
|
||||
println( "Creating reference from " + instruction.getMinAddress() + " to " + address );
|
||||
println("Creating reference from " + instruction.getMinAddress() +
|
||||
" to " + address);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,43 +115,43 @@ public class ResolveReferencesRelativeToEbxScript extends GhidraScript {
|
||||
|
||||
private boolean isValid(Address address) {
|
||||
|
||||
Instruction instruction = getInstructionContaining( address );
|
||||
if ( instruction != null ) {
|
||||
Instruction instruction = getInstructionContaining(address);
|
||||
if (instruction != null) {
|
||||
Address min = instruction.getMinAddress();
|
||||
if ( address.compareTo( min ) > 0 ) {
|
||||
if (address.compareTo(min) > 0) {
|
||||
return false; //off-cut
|
||||
}
|
||||
}
|
||||
|
||||
Data data = getDataContaining( address );
|
||||
if ( data != null ) {
|
||||
Data data = getDataContaining(address);
|
||||
if (data != null) {
|
||||
Address min = data.getMinAddress();
|
||||
if ( address.compareTo( min ) > 0 ) {
|
||||
if (address.compareTo(min) > 0) {
|
||||
return false; //off-cut
|
||||
}
|
||||
}
|
||||
|
||||
return currentProgram.getMemory().contains( address );
|
||||
return currentProgram.getMemory().contains(address);
|
||||
}
|
||||
|
||||
private void removeReferencesFrom(Instruction instruction) {
|
||||
Reference [] referencesFrom = instruction.getReferencesFrom();
|
||||
Reference[] referencesFrom = instruction.getReferencesFrom();
|
||||
for (Reference reference : referencesFrom) {
|
||||
removeReference( reference );
|
||||
removeReference(reference);
|
||||
}
|
||||
}
|
||||
|
||||
private long getValueForEBX(Instruction instruction) {
|
||||
|
||||
if ( instruction.getMnemonicString().equals( "CALL" ) ) {
|
||||
if (instruction.getMnemonicString().equals("CALL")) {
|
||||
|
||||
Address nextInstructionAddress = instruction.getMaxAddress().add( 1 );
|
||||
Address nextInstructionAddress = instruction.getMaxAddress().add(1);
|
||||
|
||||
Reference [] referencesFrom = instruction.getReferencesFrom();
|
||||
Reference[] referencesFrom = instruction.getReferencesFrom();
|
||||
|
||||
if ( referencesFrom.length == 1) {
|
||||
if (referencesFrom.length == 1) {
|
||||
|
||||
if ( referencesFrom[0].getToAddress().equals( nextInstructionAddress ) ) {
|
||||
if (referencesFrom[0].getToAddress().equals(nextInstructionAddress)) {
|
||||
|
||||
return nextInstructionAddress.getOffset();
|
||||
}
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
//Upgrade DEX program(s) that have function prototypes layed down prior to Ghidra 7.1
|
||||
//@category Upgrade
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.framework.model.*;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.data.FunctionDefinitionDataType;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.util.exception.*;
|
||||
|
||||
/**
|
||||
* There was a major rearrangement of registers in the Dalvik.slaspec from 7.0 -> 7.1 which invalidates function prototypes
|
||||
* laid down by "Android DEX Header Format" analyzer. This script repairs the prototypes to match the new register layout
|
||||
* If run with a Program already up, the script will make all the changes, letting the user decide if they want to
|
||||
* save (or undo) the changes. If the script is run from an empty code browser, it will search for all Dalvik programs
|
||||
* in the current project and automatically upgrade and save the function prototypes.
|
||||
*
|
||||
*/
|
||||
public class UpgradeDexToGhidra71Script extends GhidraScript {
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
|
||||
if ( currentProgram != null ) {
|
||||
processProgram(currentProgram);
|
||||
return;
|
||||
}
|
||||
|
||||
PluginTool tool = state.getTool();
|
||||
Project project = tool.getProject();
|
||||
ProjectData projectData = project.getProjectData();
|
||||
DomainFolder rootFolder = projectData.getRootFolder();
|
||||
recurseProjectFolder( rootFolder );
|
||||
}
|
||||
|
||||
private void recurseProjectFolder( DomainFolder domainFolder ) throws Exception {
|
||||
DomainFile[] files = domainFolder.getFiles();
|
||||
for ( DomainFile domainFile : files ) {
|
||||
monitor.checkCancelled();
|
||||
try {
|
||||
processDomainFile( domainFile );
|
||||
} catch(Exception ex) {
|
||||
printerr(ex.getMessage());
|
||||
}
|
||||
}
|
||||
DomainFolder[] folders = domainFolder.getFolders();
|
||||
for ( DomainFolder folder : folders ) {
|
||||
monitor.checkCancelled();
|
||||
recurseProjectFolder( folder );
|
||||
}
|
||||
}
|
||||
|
||||
private void processDomainFile(DomainFile domainFile ) throws Exception {
|
||||
Map<String, String> metadata = domainFile.getMetadata();
|
||||
if (metadata == null) {
|
||||
return;
|
||||
}
|
||||
String formatString = metadata.get("Executable Format");
|
||||
if (formatString == null) {
|
||||
return;
|
||||
}
|
||||
if (!formatString.equals("Dalvik Executable (DEX)")) {
|
||||
return;
|
||||
}
|
||||
DomainObject domainObject = domainFile.getDomainObject(this, true, true, monitor);
|
||||
try {
|
||||
Program program = (Program) domainObject;
|
||||
processProgram(program);
|
||||
saveProgram(program);
|
||||
} finally {
|
||||
domainObject.release(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void processProgram(Program program) throws CancelledException {
|
||||
println("Updating program: "+program.getName());
|
||||
int id = program.startTransaction("Update DEX parameters");
|
||||
boolean success = false;
|
||||
try {
|
||||
for (Function func : program.getFunctionManager().getFunctions(true)) {
|
||||
monitor.checkCancelled();
|
||||
processFunction(func);
|
||||
}
|
||||
success = true;
|
||||
} finally {
|
||||
program.endTransaction(id, success);
|
||||
}
|
||||
}
|
||||
|
||||
private void processFunction(Function func) {
|
||||
monitor.setMessage("Updating: "+func.getName());
|
||||
FunctionDefinitionDataType sig = new FunctionDefinitionDataType(func,false);
|
||||
try {
|
||||
sig.setCallingConvention(CompilerSpec.CALLING_CONVENTION_stdcall);
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
func.setCustomVariableStorage(false);
|
||||
ApplyFunctionSignatureCmd cmd = new ApplyFunctionSignatureCmd(func.getEntryPoint(),sig,SourceType.ANALYSIS);
|
||||
cmd.applyTo(func.getProgram());
|
||||
|
||||
Program program = func.getProgram();
|
||||
Language language = program.getLanguage();
|
||||
AddressSpace registerSpace = program.getAddressFactory().getRegisterSpace();
|
||||
Variable[] localVariables = func.getLocalVariables();
|
||||
|
||||
for (Variable var : localVariables) {
|
||||
Varnode varnode = var.getFirstStorageVarnode();
|
||||
if (!varnode.isRegister()) {
|
||||
continue;
|
||||
}
|
||||
if (varnode.getOffset() >= 0x1000)
|
||||
{
|
||||
continue; // Already converted
|
||||
}
|
||||
long offset = varnode.getOffset() + 0x1000 - 8;
|
||||
int size = varnode.getSize();
|
||||
Register localRegister = language.getRegister(registerSpace, offset, size);
|
||||
try {
|
||||
LocalVariableImpl newlocal = new LocalVariableImpl( var.getName(), 0, var.getDataType(), localRegister, func.getProgram() );
|
||||
func.removeVariable(var);
|
||||
func.addLocalVariable(newlocal, SourceType.ANALYSIS);
|
||||
} catch (InvalidInputException e) {
|
||||
} catch (DuplicateNameException e) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user