NationalSecurityAgency / ghidra

Ghidra is a software reverse engineering (SRE) framework
https://www.nsa.gov/ghidra
Apache License 2.0
51.62k stars 5.87k forks source link

ud2 x86 instruction is breaking disassembly process #4113

Closed mh4ckt3mh4ckt1c4s closed 2 years ago

mh4ckt3mh4ckt1c4s commented 2 years ago

Describe the bug When opening a binary on Ghidra which contains the ud2 instruction (undefined instruction), the disassembly doesn't go further than this instruction. Ghidra just show an incomplete disassembly and the C code from the decompiler is incomplete too. However, the optcodes are good.

To Reproduce Steps to reproduce the behavior:

  1. Open a binary containing this instruction (I found the bug with the binary from this reverse challenge on HackTheBox (I solved it), the binary is attached below. (I also tested with a custom binary I created, and I encountered the same issue.)
  2. Open the function main
  3. See in the disassembly panel, on address 0x001012e6, that Ghidra didn't disassemble further than the ud2 instruction.
  4. You can compare with the "real" assembly by using objdump -d -M intel <binary> or gdb with disassemble main (both worked for me).

Expected behavior Ghidra disassemble the binary correctly, displaying all the instructions, and the decompiler is able to read the instructions and give a complete output.

Screenshots Capture of failed disassembly by Ghidra image Capture of disassembly using objdump, showing the complete disassembly. You can see that the optcodes are good. image

Attachments The HackTheBox binary with which I first encountered the issue : binary-ud2-issue.zip

Environment (please complete the following information):

pjsoberoi commented 2 years ago

This is very similar to this ticket: https://github.com/NationalSecurityAgency/ghidra/issues/3723.

See in the disassembly panel, on address 0x001012e6, that Ghidra didn't disassemble further than the ud2 instruction.

IMHO that is the correct behavior. You can manually disassemble the bytes after but that shouldn't change the decompilation. You can edit your own x86 slaspec and replace ud2 instruction with a "nop" pcode instruction. This should basically make the decompiler ignore the ud2 instruction. That seems like what you want.

GhidorahRex commented 2 years ago

After reviewing the documentation on the instruction, it appears to be doing the correct thing. The UD2 instruction generates an invalid opcode exception, and the saved instruction pointer is the address of the UD2 instruction, rather than the following one. It should not, without careful consideration, proceed to the following instruction.

mali-arf commented 2 years ago

Hi I am also getting UD2 instructions but I don't know how to replace the opcode UD2 with NOP? (1) I added the following code at the end of Ghidra/Processors/AARCH64/data/languages/AARCH64instructions.sinc file as below:

...
# 66 0F 1F 44
:NotYetImplemented_UD2
is b_0031=0x441F0F66
{
}

} # end with ImmS_ImmR_TestSet=1

(2) deleted the .sla files (3) reload ghidra as ./ghidraRun (4) reanalyzed the attached file (5) the UD2 instruction still appears.

Am I missing something? How can I replace the UD2 with NOP in order to get the correct disassembly of the subsequent instructions? Thanks.

OS: Linux Ubuntu 18.04, kernel version 4.15 generic
Java Version: 11.0.15
Ghidra Version: 10.1.2
Ghidra Origin: Official website

UD2_instr

GhidorahRex commented 2 years ago

Looking at the screenshot it appears you're looking at an x86 binary, but you added the instruction to the end of the ARM64 sleigh code. You need to modify the x86 sleigh file instead. In ia.sinc, search for ":ud2" and you can probably just remove the "goto inst_start;" piece and follow the rest of the directions to get it to continue disassembling.

mali-arf commented 2 years ago

Thank you so much!!! I modified the file Ghidra/Processors/x86/data/languages/ia.sinc from :UD2 is vexMode=0 & byte=0xf; byte=0xb { invalidInstructionException(); goto inst_start; } to :UD2 is vexMode=0 & byte=0xf; byte=0xb { invalidInstructionException();}

reload ghidra and it worked!!! Thanks a lot!