ModRM / SIB REX.___ global tables lazy binding different types of VMs - interface : system / process / language - implementatoin: - emulation (giant if/else) - binary translation (compile machine code to new machine code) - native / trap-and-emulate (rely on HW triggering OS code on "special" things) - counterexample: POPF used to act differently in kernel/user ... but not by triggering OS in earlier x86 antidebugging - breakpoints addq --> addq subq --> int $2 // encoding: 0xCC -- "jump to debugger and save old address" loop:xorq --> xorq je loop - counter-strategy: look for 0xCC ("jump to debugger") - read the machine code --- add it and see if it's the same as before - counter-counter-straegy: replace the "jump if being debugged" with nop - single-stepping jmpq *4(%rax,%rbx,8) - hardware support: x86 - "TF flag" --> call debugger after every instruction - counter strategies: - mess with the TF flag (but debugger gets control before change) - mess with the place where debugger calls go (also works for breakpoints) - tell OS "Hey, let me handle debugger calls on myself!" - countercountermeasure: debugger/OS blocks those callls x86 segmentation - modern memory protection - "page tables" (late in 3330) - OS sets a mapping from program addresses to real addresses including invalid regions, holes, etc. - historic memory protection: segmentatoin - x86 supported it very early - and still does --- and it's mandatory - every memory accesses uses a "segment #" (from instruction) - table (segment #, base address, limit) - "real memory address acccesed": program address + base address (before page tables) - access is okay if program address <= limit - modern OSs: almost all segment table entries are (segment #, 0, MAX_VALUE) one exception: thread-local storage (segment #, pointer to storage, MAX_VALUE)` "extra pointer register" %fs or %gs (contain segment #s) typically assigned to thread-local storage using %fs or %gs: mov %fs:0x28, %rax # access 0x28 using segment # %fs, move to %rax assembly RE