INTEL TYPE: High-Level vs. Low-Level Architecture

OBJECTIVE: Understand the abstraction layers between source code and machine execution.

0x01: The Source of the Binary

Software starts as Source Code. While developers use various languages (Python for ML, JavaScript for Web), the world of systems software and high-performance applications is dominated by C and C++. These languages are flexible enough to build everything from device drivers to web browsers.

However, the CPU is “language blind.” It cannot read C++ code. It requires a Compiler (like GCC or G++) to translate those abstract concepts into the specific machine instructions that the processor understands.

0x02: High-Level vs. Low-Level

The choice between high-level and low-level languages is a trade-off between Abstraction and Control.

  • High-Level (C/C++): Programmers use “human-ish” logic like if-else and while loops. The compiler handles the “grunt work” of deciding which registers to use or where to store variables in memory.
  • Low-Level (Assembly): Strongly coupled to a specific CPU (like ARM or x86). It gives the programmer total control over every instruction and memory cycle.

0x03: Why Use Assembly?

In an era of powerful compilers, why would anyone write in Assembly? In reverse engineering, we often find assembly used for:

  • Exploitation: Writing “Shellcode” for buffer overflows.
  • Performance: Hand-tuning critical library functions like memcpy.
  • Hardware Access: Writing OS kernels or firmware bootloaders that interact directly with CPU internals.

0x04: The Interactive Mission (Assembly Use-Case Matcher)

Test your knowledge of when an operator should drop from C++ into raw Assembly. Match the Scenario to the Justification.

[FIELD_LOGIC_TEST_v1.0]
SCENARIO: You are developing an exploit for a legacy system and need to inject code that executes directly in a small memory buffer without standard library support.

0x05: Cross-Compiling for Other Architectures

One of the primary advantages of high-level languages like C/C++ is Portability. The source code is not locked to one specific processor. However, your development machine (likely x86_64) is different from your target machine (likely ARM64).

To bridge this gap, we use a Cross-Compiler. This is a version of GCC that runs on one architecture but produces binaries for another.

Common Cross-Compilers for ARM:

  • gcc-aarch64-linux-gnu: For 64-bit ARM Linux.
  • gcc-arm-linux-gnueabihf: For 32-bit ARM Linux.

0x06: Target Verification

Once a binary is compiled, how do we know it’s actually an ARM binary and not an x86 one? We use the file command. This utility reads the ELF Header and tells us exactly what kind of “beast” we are dealing with.

user@ocsaly:~$ file example.so
example.so: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV)

As a Reverse Engineer, this is your first step in Reconnaissance. Before you open a debugger, you must know the bitness (32 vs 64) and the architecture (ARM vs x86).

0x07: Interactive Mission (The Architecture Identifier)

In this mission, you will simulate the file command. Analyze the provided “System Hex Dump” and identify which architecture the binary was compiled for.

[BINARY_RECON_v1.0]
7F 45 4C 46 02 01 01 00 00 00 00 00 00 00 00 00
02 00 B7 00 01 00 00 00 10 10 40 00 00 00 00 00

MISSION: Identify the architecture. Hint: Look for the Machine ID (Offset 0x12). B7 stands for AArch64 (ARM64).

0x08: Final Mission Task

Current Objective: Install the ARM cross-compiler on your machine using:

sudo apt-get install gcc-aarch64-linux-gnu

Compile the “Hello” program from today’s lecture using the cross-compiler and verify the output with the file command. If the result shows ARM aarch64, you have successfully prepared your environment for Phase 4: Advanced ARM Exploitation.