Here are 5 bytes you you can use to detect the architecture you're on:
_shellcode: xor ecx, ecx ; set ecx to 0 db 0x41 ; x86 opcode for: inc ecx loop x64_code ; ecx now -1 in x64, we jmp x86_code: ; use fs segment ; ret x64_code: ; use gs segment
Those familiar with x64 assembly should recognize that the 0x40-0x50 range is often used as a prefix for an instruction. We can use this subtle difference to confuse the processor. In this case, if running in x64, the inc ecx opcode becomes a prefix for the loop. The loop instruction decrements ecx by one, and if ecx is not equal to 0 it will jump to the given label.
I used db 0x41 instead of inc ecx in the source code, since nasm uses a modern 2-byte instruction to prevent this ambiguity when we actually want the 1-byte increment. Here are the different outputs, which clearly show what is going on:
x86
"\x31\xc9" /* xor %ecx,%ecx */ "\x41" /* inc %ecx */ "\xe2\x01" /* loop x64_code */ <-- ecx = 0, no jmp
x64
"\x31\xc9" /* xor %ecx,%ecx */ "\x41\xe2\x01" /* rex.B loop x64_code */ <-- ecx = -1, jmp
No comments :
Post a Comment