The Zlob malware contains lots of bogus API calls to hinder analysis. This blag post describes how to use a script in Ghidra to automate the process of patching out those calls with  While one might think that in the screenshot above, the selection in the disassembly has a lenght of 6 and ranges from 0x10003a34 to 0x10003a3a (exclusively) it is in fact three selections, each of length 1 starting at
While one might think that in the screenshot above, the selection in the disassembly has a lenght of 6 and ranges from 0x10003a34 to 0x10003a3a (exclusively) it is in fact three selections, each of length 1 starting at 
						
				
						
										
										
			NOP instructions.
The malware employs some basic obfuscation techniques, one of which is performing lots of API calls without side effects. This makes both the disassembly as well as the decompile view hard to read. The following excerpts where take from a random sample belonging to this family (SHA256 hash 0b38ca277bbb042d43bd1f17c4e424e167020883526eb2527ba929b2f0990a8f):
ff d5 | CALL EBP=>KERNEL32.DLL::GetCurrentThreadId
ff d5 | CALL EBP=>KERNEL32.DLL::GetCurrentThreadId
ff d6 | CALL ESI=>KERNEL32.DLL::GetLastError      
ff d7 | CALL EDI=>KERNEL32.DLL::GetConsoleCP      
ff d6 | CALL ESI=>KERNEL32.DLL::GetLastError      
ff d6 | CALL ESI=>KERNEL32.DLL::GetLastError      
ff d6 | CALL ESI=>KERNEL32.DLL::GetLastError      
ff d7 | CALL EDI=>KERNEL32.DLL::GetConsoleCP      
ff d6 | CALL ESI=>KERNEL32.DLL::GetLastError      
ff d7 | CALL EDI=>KERNEL32.DLL::GetConsoleCP      
ff d6 | CALL ESI=>KERNEL32.DLL::GetLastError      
GetCurrentThreadId();
GetCurrentThreadId();
GetLastError();
GetConsoleCP();
GetLastError();
GetLastError();
GetLastError();
GetConsoleCP();
GetLastError();
GetConsoleCP();
GetLastError();
[...]
NOP instruction (0x90) but this is a more than tedious process (it would be even more tedious to right click into the Listing view and select "Patch Instruction"). Let's write a handy script to automate this:
public void run() throws Exception {
    if (currentSelection != null) {
        AddressRangeIterator addressRanges = currentSelection.getAddressRanges(true);
        for (AddressRange addressRange : addressRanges) {
            nopOut(addressRange.getMinAddress(), addressRange.getLength());
        }
    }
}
private void nopOut(Address addressStart, long length) throws CancelledException, MemoryAccessException {
    clearListing(addressStart, addressStart.add(length));
    for (int i = 0; i < length; i++) {
        Address address = addressStart.add(i);
        setByte(address, (byte) 0x90);
    }
    disassemble(addressStart);
}
NOP.
## A tiny plot-twist
Since selecting calls in the decompile view will also highlight disassembly, one might think that you can as easily select region of the decompile view, execute the same script and come to the same result. Sadly this is not the case: If you select a line in the decompile view, the corresponding selection in the disassembly will always only have length 1. 
 While one might think that in the screenshot above, the selection in the disassembly has a lenght of 6 and ranges from 0x10003a34 to 0x10003a3a (exclusively) it is in fact three selections, each of length 1 starting at
While one might think that in the screenshot above, the selection in the disassembly has a lenght of 6 and ranges from 0x10003a34 to 0x10003a3a (exclusively) it is in fact three selections, each of length 1 starting at 0x10003a34, 0x10003a36 and, 0x10003a38. Executing the above script will hence result in the byte sequence 90 d3 90 d3 90 d3 which cannot even be disassembled.
So let's not pass in addressRange.getLength() into the nopOut function but instead extend the length such that the last instruction is always included completely:
/**
 * Searchers backwards for the last assembly instruction and returns the length
 * of the address range, potentially extended to fully include this last
 * instruction.
 */
private long assemblyAlignedLength(AddressRange addressRange) {
	long length = addressRange.getLength();
	for (int i = 1; i <= MAX_ASSEMBLY_INSTRUCTION_LENGTH; i++) {
		Instruction instruction = getInstructionAt(addressRange.getMinAddress().add(length - i));
		if (instruction != null) {
			return length + (instruction.getLength() - i);
		}
	}
	return length;
}
nts.java script on github!
Edit (2023-10-01): F2 is not correct, Ctrl-Shift-G it is.
3 Replies to “Programmatically NOP the Current Selection in Ghidra”