Taking advantage of Intel's messup to obfuscate your code 10-16-2017, 03:14 AM
#1
The method was discussed at Blackhat 2017 (https://www.youtube.com/watch?v=KrksBdWcZgQ) so I can't take credit for it, but I still think it's very interesting and useful. Quite surprisingly, I haven't seen a lot of malware capitalize on this yet.
Basically, this researcher decided to look for undocumented opcodes and quirks in x86 processors. He found a lot of opcodes that weren't documented, and he also discovered a good number of bugs in disassembly software.
In x86, you can prepend 0x66 to jmp (0xe8) or call (0xe9), which supposedly changes the size of the address. AMD processors and disassemblers obey this, but Intel processors ignore it. This discontinuity between what the disassembler says and what Intel does allows you to make the disassembly different from the code that's being executed.
I'm going to use the same example as in the other thread:
So this is the code before the modification. We put a nop before the jump so we have space to work.
When we replace the nop with 0x66, the disassembly changes.
Now, it tells us that we are going to 0x5bc (a completely irrelevant address that doesn't mean shit). But when I run this executable on my intel processor, there is no such error.
Here, the effect is reduced to not being able to follow the code. But what if instead of 0x0000 I had a different instruction? What if it's 3 bytes? Then all of the disassembly until the end of the function is incorrect. Maybe even more if it fails to read ret as its own instruction.
The only drawback of this is that AMD processors will obey the instruction and the code will blow up. For this reason, I suggest you implement a processor checker function that would only run your obfuscated code if the processor is intel.
Anyways, here is how you can set this up on every jump instruction of a particular C file:
And there you go. Now open up your file in a disassembler and look at your function. Expect most of your calls and jumps to point to nowhere. Definitely different from what the code actually does when you run it.
This guys fuzzing methodology for documenting missing opcodes was just fantastic. Depth-first is really clever. Here is the link his sandsifter tool
https://github.com/xoreaxeaxeax/sandsift.../sifter.py
Basically, this researcher decided to look for undocumented opcodes and quirks in x86 processors. He found a lot of opcodes that weren't documented, and he also discovered a good number of bugs in disassembly software.
In x86, you can prepend 0x66 to jmp (0xe8) or call (0xe9), which supposedly changes the size of the address. AMD processors and disassemblers obey this, but Intel processors ignore it. This discontinuity between what the disassembler says and what Intel does allows you to make the disassembly different from the code that's being executed.
I'm going to use the same example as in the other thread:
So this is the code before the modification. We put a nop before the jump so we have space to work.
Code:
│       0x00400acb    90       nop
│     ┌─< 0x00400acc    e98d000000   jmp 0x400b5eWhen we replace the nop with 0x66, the disassembly changes.
Code:
│    └─< 0x00400acb    66e98d00    jmp 0xb5c
│      0x00400acf    0000      add byte [rax], alNow, it tells us that we are going to 0x5bc (a completely irrelevant address that doesn't mean shit). But when I run this executable on my intel processor, there is no such error.
Here, the effect is reduced to not being able to follow the code. But what if instead of 0x0000 I had a different instruction? What if it's 3 bytes? Then all of the disassembly until the end of the function is incorrect. Maybe even more if it fails to read ret as its own instruction.
The only drawback of this is that AMD processors will obey the instruction and the code will blow up. For this reason, I suggest you implement a processor checker function that would only run your obfuscated code if the processor is intel.
Anyways, here is how you can set this up on every jump instruction of a particular C file:
Code:
gcc -S <your C file>.c
sed -e 's/\tjmp/\t.byte 0x66\n\tjmp/g' -e 's/\tcall/\t.byte 0x66\n\tcall/g' <your C file>.s -i
gcc <obfuscation options etc..> -static <your .s files>And there you go. Now open up your file in a disassembler and look at your function. Expect most of your calls and jumps to point to nowhere. Definitely different from what the code actually does when you run it.
This guys fuzzing methodology for documenting missing opcodes was just fantastic. Depth-first is really clever. Here is the link his sandsifter tool
https://github.com/xoreaxeaxeax/sandsift.../sifter.py
GPG key:
https://pgp.mit.edu/pks/lookup?op=get&se...B335BFCADA
Sig:
D96D 0220 0E13 CE13 8C6C Â D697 F68B 0EB3 35BF CADA
https://pgp.mit.edu/pks/lookup?op=get&se...B335BFCADA
Sig:
D96D 0220 0E13 CE13 8C6C Â D697 F68B 0EB3 35BF CADA

![[+]](https://sinister.ly/images/modern/collapse_collapsed.png)
























