Ghidra: `endbr` instructions not recognized

Created on 6 Mar 2019  路  3Comments  路  Source: NationalSecurityAgency/ghidra

Describe the bug

The bytes f3 0f 1e fa can not be disassembled into the endbr64 instruction. endbr32 is probably also missing, but I haven't looked for an example.

To Reproduce

Steps to reproduce the behavior:

  1. Import a 64-bit binary on a recent Linux that includes the instructions. I used /bin/ls on Fedora 28.
  2. Scroll to a failure to disassemble the encoding for endbr64.

Expected behavior

The instruction should be disassembled.

Screenshots

fedora_64-bit

The output of objdump -d /bin/ls for comparison:

    3ea0:       f3 0f 1e fa             endbr64 
    3ea4:       41 57                   push   %r15
    3ea6:       41 56                   push   %r14

Environment (please complete the following information):

  • OS: Fedora 28
  • OpenJDK 11
Bug

Most helpful comment

Below are the instructions that Ghidra doesn't seem to be able to disassemble but that objdump does. One variant from each instruction "class" is listed, (for the most part):

0f 01 ca                clac
66 0f ae 38             clflushopt BYTE PTR [eax]
f3 0f ae 30             clrssbsy QWORD PTR [eax]
0f 01 fc                clzero
82 f8 cc                cmp    al,0xcc
82 38 cc                cmp    BYTE PTR [eax],0xcc
0f 01 cf                encls
0f 01 d7                enclu
66 0f 78 c0 cc cc       extrq  xmm0,0xcc,0xcc
0f 37                   getsec
66 0f 3a cf c0 cc       gf2p8affineinvqb xmm0,xmm0,0xcc
66 0f 3a cf 00 cc       gf2p8affineinvqb xmm0,XMMWORD PTR [eax],0xcc
66 0f 3a ce c0 cc       gf2p8affineqb xmm0,xmm0,0xcc
66 0f 3a ce 00 cc       gf2p8affineqb xmm0,XMMWORD PTR [eax],0xcc
66 0f 38 cf c0          gf2p8mulb xmm0,xmm0
66 0f 38 cf 00          gf2p8mulb xmm0,XMMWORD PTR [eax]
f2 0f 78 c0 cc cc       insertq xmm0,xmm0,0xcc,0xcc
0f 01 df                invlpga
66 0f 38 82 00          invpcid eax,[eax]
c5 80 aa aa aa aa       lds    eax,FWORD PTR [eax-0x55555556]
c5 84 00 aa aa aa aa    lds    eax,FWORD PTR [eax+eax*1-0x55555556]
c5 84 40 aa aa aa aa    lds    eax,FWORD PTR [eax+eax*2-0x55555556]
c5 84 80 aa aa aa aa    lds    eax,FWORD PTR [eax+eax*4-0x55555556]
c5 84 c0 aa aa aa aa    lds    eax,FWORD PTR [eax+eax*8-0x55555556]
c5 85 aa aa aa aa       lds    eax,FWORD PTR [ebp-0x55555556]
0f 01 fa                monitorx
f2 0f 2b 00             movntsd QWORD PTR [eax],xmm0
0f 20 00                mov    eax,cr0
0f 22 00                mov    cr0,eax
0f 21 00                mov    eax,db0
0f 23 00                mov    db0,eax
0f 01 fb                mwaitx
f3 0f 1e c8             rdsspd eax
66 0f 3a 15 c0 cc       pextrw eax,xmm0,0xcc
66 0f 3a 15 00 cc       pextrw WORD PTR [eax],xmm0,0xcc
8f c0                   pop    eax
0f 0d 18                prefetch BYTE PTR [eax]
0f 0d 10                prefetchwt1 BYTE PTR [eax]
0f 0d 20                prefetch BYTE PTR [eax]
0f 0d 28                prefetch BYTE PTR [eax]
0f 0d 30                prefetch BYTE PTR [eax]
f3 0f ae e0             ptwrite eax
f3 0f c7 f8             rdpid  eax
0f 01 ee                rdpkru
0f c7 f0                rdrand eax
0f c7 f8                rdseed eax
f3 0f 1e c8             rdsspd eax
0f 01 f9                rdtscp
f3 0f 01 28             rstorssp QWORD PTR [eax]
f3 0f 01 ea             saveprevssp
f3 0f 01 e8             setssbsy
0f 01 de                skinit
0f 01 cb                stac
f6 c8 cc                test   al,0xcc
f6 08 cc                test   BYTE PTR [eax],0xcc
f7 c8 cc cc cc cc       test   eax,0xcccccccc
66 f7 c8 cc cc          test   ax,0xcccc
f7 08 cc cc cc cc       test   DWORD PTR [eax],0xcccccccc
66 f7 08 cc cc          test   WORD PTR [eax],0xcccc
0f ff c0                ud0    eax,eax
0f ff 00                ud0    eax,DWORD PTR [eax]
0f b9 c0                ud1    eax,eax
0f b9 00                ud1    eax,DWORD PTR [eax]
0f 01 d4                vmfunc
0f 01 ef                wrpkru
0f 38 f6 00             wrssd  [eax],eax
c6 f8 cc                xabort 0xcc
c7 f8 dd dd dd dd       xbegin 0xdddfb30c
66 c7 f8 dd dd          xbeginw 0xb319
0f 01 d5                xend
0f c7 18                xrstors [eax]
0f c7 20                xsavec [eax]
0f ae 30                xsaveopt [eax]
0f c7 28                xsaves [eax]
0f 01 d6                xtest

Also, the following disassembled differently than with objdump:

f3 0f ae e8             incsspd eax
^^^ Disassembled in Ghidra as LFENCE

f2 0f 79 c0             insertq xmm0,xmm0
^^^ Disassembled in Ghidra as VMWRITE

f3 0f ae 20             ptwrite DWORD PTR [eax]
^^^ Disassembled in Ghidra as XSAVE

Not included in the list are several *FENCE instructions that aren't decoded correctly by objdump or Ghirda (but that should be valid, based on the spec), and several of the NOP variants which Ghidra doesn't disassemble correctly. Also, my script doesn't currently output any AVX/SSE instructions.

This ticket is related to #22

All 3 comments

I can confirm that endbr32 and endbr64 don't disassemble.

I have a script that aims to generate interesting variations of every possible x86 instruction for testing disassemblers for things like this. From loading the binary from that into Ghidra, it looks like there may be several other unsupported instructions as well. When I get a chance I'll look through the other disassembly failure cases and post back with ones that aren't just the result of bugs in my script. :)

It might be a nice exercise to add them. endbr32/endbr64 are especially easy because they have no semantics (i.e. are nops). Adding them should just be a matter of plugging in the right bits into the x86 processor SLEIGH (which is even automatically compiled for you).

Below are the instructions that Ghidra doesn't seem to be able to disassemble but that objdump does. One variant from each instruction "class" is listed, (for the most part):

0f 01 ca                clac
66 0f ae 38             clflushopt BYTE PTR [eax]
f3 0f ae 30             clrssbsy QWORD PTR [eax]
0f 01 fc                clzero
82 f8 cc                cmp    al,0xcc
82 38 cc                cmp    BYTE PTR [eax],0xcc
0f 01 cf                encls
0f 01 d7                enclu
66 0f 78 c0 cc cc       extrq  xmm0,0xcc,0xcc
0f 37                   getsec
66 0f 3a cf c0 cc       gf2p8affineinvqb xmm0,xmm0,0xcc
66 0f 3a cf 00 cc       gf2p8affineinvqb xmm0,XMMWORD PTR [eax],0xcc
66 0f 3a ce c0 cc       gf2p8affineqb xmm0,xmm0,0xcc
66 0f 3a ce 00 cc       gf2p8affineqb xmm0,XMMWORD PTR [eax],0xcc
66 0f 38 cf c0          gf2p8mulb xmm0,xmm0
66 0f 38 cf 00          gf2p8mulb xmm0,XMMWORD PTR [eax]
f2 0f 78 c0 cc cc       insertq xmm0,xmm0,0xcc,0xcc
0f 01 df                invlpga
66 0f 38 82 00          invpcid eax,[eax]
c5 80 aa aa aa aa       lds    eax,FWORD PTR [eax-0x55555556]
c5 84 00 aa aa aa aa    lds    eax,FWORD PTR [eax+eax*1-0x55555556]
c5 84 40 aa aa aa aa    lds    eax,FWORD PTR [eax+eax*2-0x55555556]
c5 84 80 aa aa aa aa    lds    eax,FWORD PTR [eax+eax*4-0x55555556]
c5 84 c0 aa aa aa aa    lds    eax,FWORD PTR [eax+eax*8-0x55555556]
c5 85 aa aa aa aa       lds    eax,FWORD PTR [ebp-0x55555556]
0f 01 fa                monitorx
f2 0f 2b 00             movntsd QWORD PTR [eax],xmm0
0f 20 00                mov    eax,cr0
0f 22 00                mov    cr0,eax
0f 21 00                mov    eax,db0
0f 23 00                mov    db0,eax
0f 01 fb                mwaitx
f3 0f 1e c8             rdsspd eax
66 0f 3a 15 c0 cc       pextrw eax,xmm0,0xcc
66 0f 3a 15 00 cc       pextrw WORD PTR [eax],xmm0,0xcc
8f c0                   pop    eax
0f 0d 18                prefetch BYTE PTR [eax]
0f 0d 10                prefetchwt1 BYTE PTR [eax]
0f 0d 20                prefetch BYTE PTR [eax]
0f 0d 28                prefetch BYTE PTR [eax]
0f 0d 30                prefetch BYTE PTR [eax]
f3 0f ae e0             ptwrite eax
f3 0f c7 f8             rdpid  eax
0f 01 ee                rdpkru
0f c7 f0                rdrand eax
0f c7 f8                rdseed eax
f3 0f 1e c8             rdsspd eax
0f 01 f9                rdtscp
f3 0f 01 28             rstorssp QWORD PTR [eax]
f3 0f 01 ea             saveprevssp
f3 0f 01 e8             setssbsy
0f 01 de                skinit
0f 01 cb                stac
f6 c8 cc                test   al,0xcc
f6 08 cc                test   BYTE PTR [eax],0xcc
f7 c8 cc cc cc cc       test   eax,0xcccccccc
66 f7 c8 cc cc          test   ax,0xcccc
f7 08 cc cc cc cc       test   DWORD PTR [eax],0xcccccccc
66 f7 08 cc cc          test   WORD PTR [eax],0xcccc
0f ff c0                ud0    eax,eax
0f ff 00                ud0    eax,DWORD PTR [eax]
0f b9 c0                ud1    eax,eax
0f b9 00                ud1    eax,DWORD PTR [eax]
0f 01 d4                vmfunc
0f 01 ef                wrpkru
0f 38 f6 00             wrssd  [eax],eax
c6 f8 cc                xabort 0xcc
c7 f8 dd dd dd dd       xbegin 0xdddfb30c
66 c7 f8 dd dd          xbeginw 0xb319
0f 01 d5                xend
0f c7 18                xrstors [eax]
0f c7 20                xsavec [eax]
0f ae 30                xsaveopt [eax]
0f c7 28                xsaves [eax]
0f 01 d6                xtest

Also, the following disassembled differently than with objdump:

f3 0f ae e8             incsspd eax
^^^ Disassembled in Ghidra as LFENCE

f2 0f 79 c0             insertq xmm0,xmm0
^^^ Disassembled in Ghidra as VMWRITE

f3 0f ae 20             ptwrite DWORD PTR [eax]
^^^ Disassembled in Ghidra as XSAVE

Not included in the list are several *FENCE instructions that aren't decoded correctly by objdump or Ghirda (but that should be valid, based on the spec), and several of the NOP variants which Ghidra doesn't disassemble correctly. Also, my script doesn't currently output any AVX/SSE instructions.

This ticket is related to #22

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tzizi picture tzizi  路  17Comments

ghost picture ghost  路  29Comments

cattrace picture cattrace  路  20Comments

dw picture dw  路  20Comments

astrelsky picture astrelsky  路  16Comments