Altering x86 Instruction
Altering x86 Instruction
Alexander Krog
▶ Vulnerability researcher at Vectorize
▶ CTF player (Kalmarunionen)
▶ email: alexander.dalsgaard.krog@proton.me
▶ Discord: @zanderdk
Alexander Skovsende
▶ Grad student at Danish Technical University
▶ CTF player (Kalmarunionen)
Architectural Crash Course
Architectural Crash Course
What/Why is Microcode?
Official Updates
▶ Applied by kernel/firmware
▶ Signed & encrypted by Intel
Microcode ROM/RAM
Example
xadd instruction
▶ Add and exchange registers
Registers
▶ Normal registers
▶ 16 tmp registers
▶ 8 tmp floating point registers
▶ System register
▶ Ucode state register
Micro Architecture - Memory
Normal Memory
▶ Virtual access to RAM
▶ Physical access to RAM
Ucode memory
▶ Data RAM for data
▶ 0x100 qword
Micro Architecture - Misc
1. p
▶ present flag
2. src
▶ is a uaddr » 1
3. dst
▶ is a uaddr » 1
Match & Patch
Match & Patch
Dynamic Inspection
How can we change micro code?
How can we change micro code?
Microcode Access
▶ Requires Red Unlock
▶ Intel debug instructions
ME-Exploit
▶ Vulnerability found in Intel Management Engine by Positive Technologies
▶ Red Unlock
▶ Intel Debug Instructions
Pre-built flash Image
▶ Lib-Micro
▶ Assembler for microcode
▶ Dynamic or Statically linked Linux library
▶ https://github.com/zanderdk/lib-micro
Lib-Micro
void yolo(void) {
ucode_t ucode_patch[] = {
{ //0x7da0
MOVE_DSZ64_DI(TMP0, 0x1337),
MOVE_DSZ64_DI(RBX, 0xdead),
MOVE_DSZ64_DR(RAX, TMP0), END_SEQWORD
}
};
patch_ucode(0x7da0, ucode_patch, ARRAY_SZ(ucode_patch));
hook_match_and_patch(0, 0x0740 /* sysexitq xlat */ , 0x7da0);
}
Disappearing Microcode Changes
IN AL, DX
▶ Significantly bigger than other port io instructions
▶ Re-apply microcode update from Intel
Patch
▶ Abusing for fuzzing and tracing
▶ Patched out using rom -> rom match & patch
Syscall Instruction
▶ Jumps to kernel space
▶ Kernel handles requested syscall
▶ rcx contains userspace return address
Backdoor
Pseudocode
if (RAX != SYS_write || mem[RSI+0x100] != 0xd00df00d) {
goto normal_syscall;
}
~
~
~
~
~
~
~
~
~
~
~
Backdoor
Pseudocode
if (RAX != SYS_write || mem[RSI+0x100] != 0xd00df00d) {
goto normal_syscall;
}
mem[RSI+0x100] = RIP; // save state
mem[RSI+0x108] = RAX;
mem[RSI+0x110] = RDI;
mem[RSI+0x118] = RSI;
mem[RSI+0x120] = RDX;
~
~
~
~
~
~
Backdoor
Pseudocode
if (RAX != SYS_write || mem[RSI+0x100] != 0xd00df00d) {
goto normal_syscall;
}
mem[RSI+0x100] = RIP; // save state
mem[RSI+0x108] = RAX;
mem[RSI+0x110] = RDI;
mem[RSI+0x118] = RSI;
mem[RSI+0x120] = RDX;
RCX = RSI + 0x130;
~
~
~
~
~
Backdoor
Pseudocode
if (RAX != SYS_write || mem[RSI+0x100] != 0xd00df00d) {
goto normal_syscall;
}
mem[RSI+0x100] = RIP; // save state
mem[RSI+0x108] = RAX;
mem[RSI+0x110] = RDI;
mem[RSI+0x118] = RSI;
mem[RSI+0x120] = RDX;
RCX = RSI + 0x130;
RAX = SYS_mprotect;
RDI = RSI & ~0xfff;
RSI = 0x2000;
RDX = 0x7;
goto normal_syscall;
Backdoor
Userspace Code
▶ fork
▶ Parent process
▶ Restore from saved context
▶ Saved from microcode
▶ Continue normal execution
▶ Child process
▶ Do the evil e.g. pop calc
Reversing a CPU
Reversing Instruction Set
Future work
▶ Find bug in CPU
▶ Help from intel thanks
▶ Red Unlock from software
Thanks and Acknowledgment:
Thanks
▶ Kalmarunionen
Acknowledgment
▶ Mark Ermolov et. al.
▶ Positive Technologies
▶ CustomProcessingUnit - Pietro Borrello
Questions?