{
	"id": "91482815-b3d3-41f9-aff2-2adf58bbcfed",
	"created_at": "2026-04-06T00:20:54.695324Z",
	"updated_at": "2026-04-10T03:21:50.242664Z",
	"deleted_at": null,
	"sha1_hash": "7b0d6b9c172da618dc7ce0f26fd9e449f82dc709",
	"title": "Programmatically NOP the Current Selection in Ghidra – nullteilerfrei",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 213274,
	"plain_text": "Programmatically NOP the Current Selection in Ghidra –\r\nnullteilerfrei\r\nBy born\r\nPublished: 2023-10-01 · Archived: 2026-04-05 23:02:59 UTC\r\nmalware-analysis, technology 2020-08-23\r\nThe Zlob malware contains lots of bogus API calls to hinder analysis. This blag post describes how to use a script\r\nin Ghidra to automate the process of patching out those calls with NOP instructions.\r\nThe malware employs some basic obfuscation techniques, one of which is performing lots of API calls without\r\nside effects. This makes both the disassembly as well as the decompile view hard to read. The following excerpts\r\nwhere take from a random sample belonging to this family (SHA256 hash\r\n0b38ca277bbb042d43bd1f17c4e424e167020883526eb2527ba929b2f0990a8f ):\r\nff d5 | CALL EBP=\u003eKERNEL32.DLL::GetCurrentThreadId\r\nff d5 | CALL EBP=\u003eKERNEL32.DLL::GetCurrentThreadId\r\nff d6 | CALL ESI=\u003eKERNEL32.DLL::GetLastError\r\nff d7 | CALL EDI=\u003eKERNEL32.DLL::GetConsoleCP\r\nff d6 | CALL ESI=\u003eKERNEL32.DLL::GetLastError\r\nff d6 | CALL ESI=\u003eKERNEL32.DLL::GetLastError\r\nff d6 | CALL ESI=\u003eKERNEL32.DLL::GetLastError\r\nff d7 | CALL EDI=\u003eKERNEL32.DLL::GetConsoleCP\r\nff d6 | CALL ESI=\u003eKERNEL32.DLL::GetLastError\r\nff d7 | CALL EDI=\u003eKERNEL32.DLL::GetConsoleCP\r\nff d6 | CALL ESI=\u003eKERNEL32.DLL::GetLastError\r\nAnd the corresponding decompile view:\r\nGetCurrentThreadId();\r\nGetCurrentThreadId();\r\nGetLastError();\r\nGetConsoleCP();\r\nGetLastError();\r\nGetLastError();\r\nGetLastError();\r\nGetConsoleCP();\r\nGetLastError();\r\nGetConsoleCP();\r\nhttps://blag.nullteilerfrei.de/2020/08/23/programmatically-nop-the-current-selection-in-ghidra/\r\nPage 1 of 3\n\nGetLastError();\r\n[...]\r\nYou can \"just\" hit Ctrlf+Shift+G after selecting every call (and the following byte) to replace it with the NOP\r\ninstruction ( 0x90 ) but this is a more than tedious process (it would be even more tedious to right click into the\r\nListing view and select \"Patch Instruction\"). Let's write a handy script to automate this:\r\npublic void run() throws Exception {\r\n if (currentSelection != null) {\r\n AddressRangeIterator addressRanges = currentSelection.getAddressRanges(true);\r\n for (AddressRange addressRange : addressRanges) {\r\n nopOut(addressRange.getMinAddress(), addressRange.getLength());\r\n }\r\n }\r\n}\r\nprivate void nopOut(Address addressStart, long length) throws CancelledException, MemoryAccessException {\r\n clearListing(addressStart, addressStart.add(length));\r\n for (int i = 0; i \u003c length; i++) {\r\n Address address = addressStart.add(i);\r\n setByte(address, (byte) 0x90);\r\n }\r\n disassemble(addressStart);\r\n}\r\nIf you assign this script to the keyboard shortcut Ctrl-Alt-Shift-N for example, you can just select regions of\r\ndisassembly and hit that combination to replace everything with NOP .\r\nA tiny plot-twist\r\nSince selecting calls in the decompile view will also highlight disassembly, one might think that you can as easily\r\nselect region of the decompile view, execute the same script and come to the same result. Sadly this is not the\r\ncase: If you select a line in the decompile view, the corresponding selection in the disassembly will always only\r\nhave length 1.\r\nhttps://blag.nullteilerfrei.de/wp-content/uploads/2020/08/disassembly-selection-1024x212.png 1024w,\r\nhttps://blag.nullteilerfrei.de/wp-content/uploads/2020/08/disassembly-selection-300x62.png 300w,\r\nhttps://blag.nullteilerfrei.de/2020/08/23/programmatically-nop-the-current-selection-in-ghidra/\r\nPage 2 of 3\n\nhttps://blag.nullteilerfrei.de/wp-content/uploads/2020/08/disassembly-selection-768x159.png 768w,\r\nhttps://blag.nullteilerfrei.de/wp-content/uploads/2020/08/disassembly-selection.png 1313w\" sizes=\"(max-width:\r\n1024px) 100vw, 1024px\"\u003e\r\nWhile one might think that in the screenshot above, the selection in the disassembly has a lenght of 6 and ranges\r\nfrom 0x10003a34 to 0x10003a3a (exclusively) it is in fact three selections, each of length 1 starting at\r\n0x10003a34 , 0x10003a36 and, 0x10003a38 . Executing the above script will hence result in the byte sequence\r\n90 d3 90 d3 90 d3 which cannot even be disassembled.\r\nSo let's not pass in addressRange.getLength() into the nopOut function but instead extend the length such that\r\nthe last instruction is always included completely:\r\n/**\r\n * Searchers backwards for the last assembly instruction and returns the length\r\n * of the address range, potentially extended to fully include this last\r\n * instruction.\r\n */\r\nprivate long assemblyAlignedLength(AddressRange addressRange) {\r\n long length = addressRange.getLength();\r\n for (int i = 1; i \u003c= MAX_ASSEMBLY_INSTRUCTION_LENGTH; i++) {\r\n Instruction instruction = getInstructionAt(addressRange.getMinAddress().add(length - i));\r\n if (instruction != null) {\r\n return length + (instruction.getLength() - i);\r\n }\r\n }\r\n return length;\r\n}\r\nYou can find the complete nts.java script on github!\r\nEdit (2023-10-01): F2 is not correct, Ctrl-Shift-G it is.\r\nSource: https://blag.nullteilerfrei.de/2020/08/23/programmatically-nop-the-current-selection-in-ghidra/\r\nhttps://blag.nullteilerfrei.de/2020/08/23/programmatically-nop-the-current-selection-in-ghidra/\r\nPage 3 of 3",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://blag.nullteilerfrei.de/2020/08/23/programmatically-nop-the-current-selection-in-ghidra/"
	],
	"report_names": [
		"programmatically-nop-the-current-selection-in-ghidra"
	],
	"threat_actors": [],
	"ts_created_at": 1775434854,
	"ts_updated_at": 1775791310,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/7b0d6b9c172da618dc7ce0f26fd9e449f82dc709.pdf",
		"text": "https://archive.orkl.eu/7b0d6b9c172da618dc7ce0f26fd9e449f82dc709.txt",
		"img": "https://archive.orkl.eu/7b0d6b9c172da618dc7ce0f26fd9e449f82dc709.jpg"
	}
}