0

I want to write some assembly code that can find out whether it runs in an x86 or x64 binary (The reason I want to do such a weird thing is that I will inject this code in any given binary, and when the code runs, it will determine which kind of system call it should do and run that part of the code. Nothing malicious, just a "hello world" before passing to the actual entry point as an exercise).

Anyway, one 'solution' I thought of was as follows:

  • read the stack pointer to general-purpose register X
  • push 0
  • read the stack pointer to GP register Y
  • subtract Y from X (store result in X)
  • pop to Y (to fix the stack)
  • X has size of register, behave accordingly

This is the closest I could get:

0:  54                      push   rsp
1:  54                      push   rsp
2:  5b                      pop    rbx
3:  58                      pop    rax
4:  48 29 d8                sub    rax,rbx <---
7:  83 f8 08                cmp    eax,0x8
a:  74 ??                   je     64_bit_code_addr

This produces the same bytes for x86, except for that 0x48 at address 0x4. How can I write that instruction in an architecture-independent way? Or what other solution can I have to achieve this effect?

(Please do not present out-of-the-box solutions, such as "you can determine the class of an executable by checking EI_CLASS offset of an ELF file" etc.)

kubuzetto
  • 1,046
  • 1
  • 12
  • 31
  • The shortest way to implement your idea of checking the stack increment would be `mov eax, esp` / `push rbp` / `sub eax, esp` / `cmp eax, 4` / `je mode_32bit`. This still works if the low 32 of RSP wrap around. You could save the CMP by starting with `lea eax, [rsp-4]`, and just testing ZF after the SUB. As a bonus, now your function has already saved a register on the stack to free it up for use. But see also this duplicate which uses the same idea as Harold's answer. – Peter Cordes Aug 29 '16 at 01:11

1 Answers1

2

It can be much simpler, using that REX.W in 32bit code is a DEC:

48 90

Which in 64bit code is:

rex.w nop   ; still a nop

and in 32bit code:

dec eax
nop

Put something like xor eax, eax before it, of course.

harold
  • 61,398
  • 6
  • 86
  • 164