x/arch/x86/x86asm: x86 64-bit immediate argument integer overflow #45052
Labels
NeedsInvestigation
Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone
What version of Go are you using (
go version
)?Note: My go module imported
arch
versioned atv0.0.0-20210308155006-05f8f0431f72
.Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
I am writing a "shellcode" parser that takes raw binary, or a C-style hex array and converts it into human-readable disassembly like the Unix
objdump
utility. While experimenting with some sample shellcode, I found that this x86_64 sample produced an instruction with an argument that differed from the comments and the output ofobjdump
.The instruction in question:
objdump's interpretation:
A sample Go program, and its interpretation:
What did you expect to see?
I expected the immediate argument to the
mov
to be0xfee1dead
.What did you see instead?
The immediate argument to the
mov
is-0x11e2153
(0xFFFFFFFFFEE1DEAD
).Debugging and thoughts
I should start by stating that my knowledge of x86 is... limited. So, I apologize in advance for misusing any terminology. I am going off what I already know, some Googling, and code comments.
I did attempt to understand what exactly is going on in the
x86asm
library. My first thought is maybe this is not even a bug? The value in question overflows a signed 32-bit integer... But this is 64-bit assembly.Following the
x86asm.Decode
function through a debugger, we end up in thedecode1
function indecode.go
. Its documentation mentions that itmimic[s] bugs (or at least unique features) of GNU libopcodes as used by objdump
. So, is this data even being interpreted correctly in the first place?That said, @rsc's comment regarding 64-bit support on line 242 states:
... so, perhaps I am already setting my expectations a bit high :) The comment dates back to ~2014. Maybe it no longer applies?
In
decode1
, we end up in a loop on line 468. Its job appears to be decoding op code bytes. On the sixth iteration, we end up in a switch statement case on line 1046. Apparently, the op code is interpreted asxArgImm32
. The code in this case converts the localimm
variable (anint64
) to anint32
, and then converts this new value to anImm
, which is a type alias forint64
. It then assigns it to index 1 of theArgs
field of theInst
object being constructed:The resulting value is
-18751827
(0xFFFFFFFFFEE1DEAD
).I wonder if the op code was interpreted incorrectly? The subsequent
xArgImm64
case does the right thing (not convertingimm
to anint32
), and this is 64-bit code.Thank you for reading!
The text was updated successfully, but these errors were encountered: