Few days ago I was inspecting a malware using my disassembler, and I stumbled on this piece of code:
I use “!?!?!” string for undefined/reserved opcode. I had some problems testing reserved opcodes so I decided to check this case carefully. The first check is given by a comparative method, I loaded the malware into IDA. Look here:
The first thing I thought of was: “Damn, there’s a bug inside my disasm engine”.
I took a look at the printed version of my “Intel® IA-32 Architectures Software Developer’s Manual – Volume 2B: Instruction Set Reference, N-Z”. According to one-byte opcode map, C6 opcode is defined as a “Grp 11 (1A) – MOV”.
What does it mean?
The opcode can’t give me the exact meaning of the instruction. I need some extra information, which are given by the opcode extension: ModR/M byte (0x22 in the example). To retrieve the necessary information about this opcode I have to check a new table: “Opcode Extensions for One- and Two-byte Opcodes by Group Number”. I’m interested in row denoted as Group_11:
This is only a part of the entire table, it shows the header and the row of the group I’m focused on.
ModR/M byte is divided into 3 parts: mod, nnn and r/m.
0x22 = 00100010b
mod = 00 (bit 7, 6)
nnn = 100 (bit 5, 4, 3)
r/m = 010 (bit 2,1,0)
These numbers help you to locate the right instruction definition into the opcode extension’s table. To make things short, nnn value identifies the right cell to pick out. In this case 100b points to a blank cell, what does it mean?
According to Intel manual: “All blanks in all opcode maps are reserved and must not be used. Do not depend on the operation of undefined or reserved opcodes“.
Is it really an invalid instruction? All my initial investigations were done using the printed version of the Intel manual, and since of I had found some errors in it I decided to look at the most recent online version.
This new check doesn’t change anything, seems like IDA is able to disassemble an invalid instruction. Weird.
Now the question is: is this a bug or do they (IDA’s developers) know how to handle undocumented opcodes? To answer this question I have two options:
1. try loading the malware into some more disassemblers
2. try stepping the instruction using a debugger
Option number 1
The result is the same, it’s an invalid instruction.
Option number 2
This is the last check I did. I wrote a new exe file including an instruction with C6 opcode in it. The program is really simple and the source is right here:
.text:00401000 BA B2 10 40 00 mov edx, offset word_4010B2
.text:00401005 C6 22 FB mov byte ptr [edx], 0FBh
.text:00401008 6A 00 push 0
.text:0040100A 68 1D 30 40 00 push offset Caption
.text:0040100F 68 55 30 40 00 push offset Text
.text:00401014 6A 00 push 0
.text:00401016 E8 91 00 00 00 call MessageBoxA
.text:0040101B C3 retn
According to Ida it should move a byte inside 0x4010B2 address (it has full access) showing a simple messagebox, nothing more. Unfortunately the result is not the same.
If you run the file without a debugger it crashes and the classic error box appears. Spying inside the message error’s box I see that the error occours at offset 0x1005, C6 opcode!
If you run the file with Ollydbg you’ll get almost the same result, the debugger stops signalling the error “Illegal instruction” at 0x401005. Again, C6 opcode!
If you run the file using IDA’s debugger you’ll get a simple warning: “An attempt was mode to execute an illegal instruction (0x401005)”. After that you’ll get a sequence of error boxes, seems like Ida’s debugger is not fully able to handle execution of illegal instruction…this is another story, btw.
I did some more test and seems like the problem occours with all the *blank cells*; I tried with all the possible C6 combinations and with some different opcodes too. The result is always the same, Ida shows a disassembled instruction which is totally wrong!!!
I tried reading Ida’s help file but there was no mention about the problem, I don’t think there’s an hidden option to set. I tried googling without luck. Due to this fact I’m not 100% sure but… I think it’s a bug!