┏━━┓
BACK
┗━━┛
╔══════════════════════════════════════════════════════════════════════════════════╗
║ 16-07-2026 ║
║ A Small Obfuscation Detour ║
║ ║
╠══-----==[ Contents ]==---------------------------------------------------------══╣
║ ║
║ 1: brief recap of lock instruction ║
║ 2: some ret manipulation ║
║ ║
╚══════════════════════════════════════════════════════════════════════════════════╝
╔══════════════════════════════════════════════════════════════════════════════════╗
╠══-----==[ 1 ]==----------------------------------------------------------------══╣
║ ║
║ Once again, it has been a while. With a view to breaking the silence, a short ║
║ exploration into messing with *insert disassembler of choice*. ║
║ ║
║ The idea came from toying with illegal instructions, and the way it appears to ║
║ mess with disassembler heuristics (as per this throwaway comment on a previous ║
║ post) ║
║ ║
║ Again, we shall be working with assembly since that gives us the granular ║
║ control I need, plus it's what I am comfortable with ║
║ ║
║ If we have an instruction that triggers a SigIll (via the #UD xor exception): ║
╠══------------------------------------------------------------------------------══╣
║ lock xor rax, rbx ║
╠══------------------------------------------------------------------------------══╣
║ ║
║ and we force gcc to compile that instruction using: ║
║ ║
╠══------------------------------------------------------------------------------══╣
║ .byte 0xF0, 0x48, 0x31, 0xD8 # bytecode for [lock xor rax, rbx] ║
╠══------------------------------------------------------------------------------══╣
║ ║
║ we can make a small program, and insert our instruction bytes some way through: ║
║ ║
╠══------------------------------------------------------------------------------══╣
║ _start: ║
║ ║
║ xor rax, rax ║
║ mov rax, 0x1 ║
║ mov rax, 0x2 ║
║ ║
║ .byte 0xF0, 0x48, 0x31, 0xD8 ║
║ ║
║ mov rax, 0x3 ║
║ mov rax, 0x4 ║
║ mov rax, 0x5 ║
╠══------------------------------------------------------------------------------══╣
║ ║
║ again, there are some hoops we have to jump through to compile this to a working ║
║ executable under the ever suspicious auspices of gcc, I'll put the commands here ║
║ as henceforth a script will be doing this for me - which means I'll forget them ║
║ in short order ║
║ ║
║ gcc -c -g -o testprogram.o testprogram.s ║
║ gcc -nostdlib -no-pie -o testprogram testprogram.o ║
║ ║
║ syntax for buildfile: ./build.sh -filename- (minus extension, expects .s) ║
║ ║
║ once compiled, we can plug the resulting executable into binay ninja and see ║
║ what the disassembler spits back out: ║
║ ║
╠══------------------------------------------------------------------------------══╣
║ _start: ║
║ ║
║ xor rax, rax ║
║ mov rax, 0x1 ║
║ mov rax, 0x2 ║
║ ?? ║
║ H1\xd8H\xc7\xc0\x03\x00\x00\x00H\xc7\xc0\x04 ║
║ \x00\x00\x00H\xc7\xc0\x05\x00\x00\x00 ║
╠══------------------------------------------------------------------------------══╣
║ ║
║ It seems that the moment the disassembler hits the illegal instruction, it no ║
║ longer continues the code flow, since, it its opinion, execution would never ║
║ reach those opcodes (which is true) ║
║ ║
║ both ghidra and IDA (the free version, I’m not a millionaire) do much the same. ║
║ This is not particularly useful unless we can actually get the unreadable ║
║ instructions to execute. The obvious way to do this is set a label after the ║
║ bytes, and then jump over the bytes to that label. Unfortunately, this is far ║
║ too obvious and the disassembler will just follow that jump and neatly display ║
║ our "obfuscated" code ║
║ ║
║ So we have a new objective, somehow redirect code flow past these bytes in a way ║
║ that can't be obviously detected ║
║ ║
╠══════════════════════════════════════════════════════════════════════════════════╣
╠══-----==[ 2 ]==----------------------------------------------------------------══╣
║ ║
║ A while ago, 0xnubb made a blog post about some malware he was disassembling, ║
║ and, after I pinged him a message, we had some back-and-forth taking a deeper ║
║ look at floxiv ║
║ ║
║ Putting aside the function of the malware for the moment, the primary way floxiv ║
║ obfuscates control flow is through ret manipulation. Adding x bytes to the ║
║ return address such that when the function calls ret, we are dumped back into ║
║ the control flow having skipped over x bytes of machine code. One such function, ║
║ in its most simple form, may look something like: ║
║ ║
╠══------------------------------------------------------------------------------══╣
║ _skip_4: ║
║ pop rax ║
║ add rax, 4 ║
║ push rax ║
║ ret ║
╠══------------------------------------------------------------------------------══╣
║ ║
║ We can use this to obfuscate our path over the illegal instruction as such: ║
║ ║
╠══------------------------------------------------------------------------------══╣
║ _start: ║
║ xor rax, rax ║
║ ┌──────────────────────────────┐ ║
║ | call _skip_4 ├───[ our obfuscation package ║
║ | .byte 0xF0, 0x48, 0x31, 0xD8 | ║
║ └──────────────────────────────┘ ║
║ xor rax, 0xdead ║
╠══------------------------------------------------------------------------------══╣
║ ║
║ The part after our obfuscation isn't disassembled by binja, as it is deemed ║
║ "unreachable". I'm not sure what the application for this type of obfuscation ║
║ could serve, considering it is focused at the reverse engineering step, though ║
║ I'm sure it has some use. So the xor rax, 0xdead is "hidden" to a static ║
║ reverse engineer ║
║ ║
║ Originally this blog post went into a multitude of different ways that I tried ║
║ to execute the code after our obfuscation block, but it lost it's focus and ║
║ there were several large assumptions I made about disassemblers and their ║
║ process that rendered those investigations moot (at least for a reader). These ║
║ snippets will eventually be masticated and regurgitated into a future blogpost ║
║ on other obfuscation processes! ║
║ ║
║ CWW out ║
╚══════════════════════════════════════════════════════════════════════════════════╝
┏━━┓
BACK
┗━━┛