Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to detect the CPU architecture from machine code?

Let's say that there are 2 possible architectures, ARM and x86. Is there a way to detect what system the code is running on, to achieve something like this from assembly/machine code?

if (isArm)
    jmp to arm machine code
if (isX86)
    jmp to x86 machine code

I know that ARM machine code differs from x86 machine code significantly. What I'm thinking about is some well crafted assembly instructions that would result in the same binary machine code.

like image 837
Tibi Avatar asked Jun 27 '16 13:06

Tibi


2 Answers

Assuming you have already taken care of all other differences1 and you are left with writing a small polyglot trampoline, you can use these opcodes:

EB 02 00 EA

Which, when put at address 0, for ARM (non thumb), translates into:

00000000: b 0xbb4
00000004: ...

But for x86 (real mode), translates to:

0000:0000 jmp 04h
0000:0002 add dl, ch
0000:0004 ...

You can then put more elaborate x86 code at address 04h and ARM code at address 0bb4h.

Of course, when relocating the base address, make sure to relocate the jump targets too.


1 For example, ARM starts at address 0 while x86 starts at address 0fffffff0h, so you need a specific hardware/firmware support to abstract the boot address.

like image 102
Margaret Bloom Avatar answered Nov 09 '22 02:11

Margaret Bloom


http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0363g/Beijdcef.html

https://electronics.stackexchange.com/a/232934

How to setup ARM interrupt vector table branches in C or inline assembly?

http://osnet.cs.nchu.edu.tw/powpoint/Embedded94_1/Chapter%207%20ARM%20Exceptions.pdf

ARM Undefined Instruction error

ARM assembly is not my area of expertise, but I have programmed a lot in x86 assembly. I remember I had this same question as homework back in college. The solution I found was interrupt 06h (http://webpages.charter.net/danrollins/techhelp/0103.HTM , https://es.wikipedia.org/wiki/Llamada_de_interrupci%C3%B3n_del_BIOS#Tabla_de_interrupciones). This interrupt is fired everytime the microprocessor tries to execute an unknown instruction ("invalid opcode").

8086 gets stucked when an invalid opcode is found, because the IP (instruction pointer) returns to the same invalid instruction, where it tries to re-execute it, this loop stucks the execution of the program.

Starting with 80286 interrupt 06h is fired, so the programmer can handle the invalid opcode cases.

Interrupt 06h helps to detect the CPU architecture, by simply trying to execute an x64 opcode, if interrrupt 06h is fired, the CPU did not recognize it, so it is x86, otherwise it is x64.

This technique can be also used to detect the type of microprocessor :

  • Try to execute a 80286 instruction, if interrupt 06h is not fired, CPU is, at least, 8286.
  • Try to execute a 80386 instruction, if interrupt 06h is not fired, CPU is, at least, 8386.
  • And so on...

http://mtech.dk/thomsen/program/ioe.php

https://software.intel.com/en-us/articles/introduction-to-x64-assembly

like image 36
Jose Manuel Abarca Rodríguez Avatar answered Nov 09 '22 02:11

Jose Manuel Abarca Rodríguez