xorpd assembly riddle 0x06

xorpd has some riddle-like pieces of assembly code here. In this post, I’ll analyze this one.

May I present you the code:

not      rax
inc rax
neg rax

Line 1: not rax

This op flips every single bit for the rax register, simple as that. This performs a bitwise not operation as you’d expect.

; Some examples to illustrate not's behavior:mov rax, 0x0
not rax
; Here rax = 0xffffffffffffffff
not rax
; Here rax = 0x0
mov rax, 0x00ff005500aa
; Now rax = 0x00ff005500aa
not rax
; Finally, rax here is equal to 0xffffff00ffaaff55

Line 2: inc rax

Even simpler than the last line, this one just increments rax by 1:

mov rax, 0x0
inc rax
; Here rax = 0x0000000000000001
mov rax, 0xffffffffffffffff
inc rax
; Here rax = 0x0

Line 3: neg rax

Now, here’s where the riddle unfolds: the neg op calculates the two’s complement… How? May you ask

Well, it turns out the two’s complement of a given value X can be obtained by performing a bitwise not operation on X, then adding one to the previous result:

mov  rax, X
not rax
inc rax
; rax = X's two's complement
====================================================================mov rax, X
neg rax
; rax = X's two's complement

Conclusion

If we run the instructions from the riddle in the presented order rax’s value wouldn't be changed after all as we would be doing something like:

let n = 0x55
n = twosComplement(twosComplement(n))
print(n) // yields "0x55"

By applying the two’s complement twice they cancel each other and we end up with the original value. This riddle shows us how the two’s complement is calculated and how it can be reversed!


syscall59

Shellcode for the masses

Syscall59 — by Alan Vivona

Written by

Twitter: @syscall59 | medium.syscall59.com | syscall59@protonmail.com

syscall59

syscall59

Shellcode for the masses