RedTeam Nexus Labs
Module 22 · Lesson 02 // Binary Analysis Basics

memory concepts

Binary Analysis Basics · CTF

Freereading · 10 min
On this page
LESSON

Overview

When a program runs, its code and data live in memory. To analyze how a binary behaves — especially in reverse-engineering challenges — you need a mental model of how memory is organized. This lesson covers the core memory concepts every analyst relies on: the stack and the heap, addresses, endianness, and the distinction between code and data.

Learning objectives

  • Describe how a process's memory is divided and what the stack and heap are for.
  • Explain what a memory address is and how addresses locate bytes.
  • Define endianness and read a multi-byte value stored in little-endian order.
  • Distinguish executable code from data in memory.

Core concept

A running program is called a process, and the operating system gives each process its own view of memory, addressed as a long sequence of numbered byte-sized slots. That memory is organized into regions with different purposes:

  • Code (text) — the machine instructions, usually read-only and executable.
  • Static/global data — variables that exist for the whole life of the program.
  • Heap — a region for dynamically allocated memory that the program requests as it runs.
  • Stack — a region that tracks function calls, local variables, and return information.

The stack and the heap are the two dynamic regions, and understanding how they differ is central to analyzing program behavior.

How it works

  • Addresses — every byte in a process's memory has a numeric address, written in hexadecimal (for example 0x00401000). An address is simply the location of a byte. Pointers are just values that hold an address. On a 64-bit system addresses are 64 bits wide; on a 32-bit system they are 32 bits wide.
  • The stack — grows and shrinks automatically as functions are called and return. Each function call pushes a stack frame holding its local variables and the return address (where execution resumes when the function finishes). On most common architectures the stack grows downward, from higher addresses toward lower ones. Access is fast and follows a last-in, first-out order.
  • The heap — used for memory whose size or lifetime is not known in advance. The program explicitly requests a block (for example, via an allocator), uses it, and later frees it. The heap is more flexible than the stack but requires the program to manage allocations, and it typically grows in the opposite direction from the stack.
  • Endianness — the order in which the bytes of a multi-byte value are stored. In little-endian order (used by x86 and x86-64), the least significant byte comes first. In big-endian order, the most significant byte comes first. So the 32-bit value 0x12345678 is stored as the bytes 78 56 34 12 in little-endian and 12 34 56 78 in big-endian.
  • Code vs data — the same bytes can be interpreted as instructions or as data depending on context. A region marked executable holds code the CPU will run; other regions hold data. Confusing the two is a classic source of analysis errors, because a disassembler will happily turn data bytes into nonsense "instructions" if pointed at the wrong region.

Practical example

You are inspecting memory in a debugger during an authorized reverse-engineering exercise. At a certain address you see the four bytes 78 56 34 12. Because the target is x86-64 (little-endian), you read them from least significant byte first and reconstruct the 32-bit value 0x12345678. Nearby, you notice a value on the stack that points to an address inside the code region — recognizing it as a saved return address, you now know which function called the current one. By keeping straight what is an address, what is data, and what byte order applies, you correctly interpret the memory instead of misreading it.

Cybersecurity relevance

Memory layout is the foundation of binary exploitation and reverse engineering. The stack's structure — local variables sitting near a saved return address — is exactly what memory-safety bugs like stack buffer overflows target, and understanding it explains why protections such as stack canaries and non-executable stacks exist. Heap behavior underlies another whole class of vulnerabilities. Endianness matters whenever you read raw bytes, craft values, or interpret dumps, and it varies by architecture. The code-versus-data distinction is why defenses mark data regions non-executable. In authorized CTF and lab practice, a correct memory model lets you interpret debugger output accurately and reason about how programs — and their weaknesses — actually work.

Common mistakes

  • Reading multi-byte values in the wrong byte order, forgetting that x86/x86-64 is little-endian.
  • Confusing the stack and the heap — the stack is automatic and call-based; the heap is explicitly allocated and freed.
  • Treating data bytes as code (or vice versa) and misinterpreting a disassembly.
  • Assuming the stack grows upward — on common architectures it grows toward lower addresses.

Key takeaways

  • A process's memory is divided into code, static data, heap, and stack regions.
  • The stack is automatic and holds stack frames (locals plus return addresses); the heap is explicitly allocated for dynamic memory.
  • An address is the numeric location of a byte; endianness is the byte order of multi-byte values, and x86/x86-64 is little-endian (0x12345678 stored as 78 56 34 12).
  • The same bytes are code or data depending on context and region permissions.

Check your understanding

  • On a little-endian system, what 32-bit value do the bytes 78 56 34 12 represent?
  • What is the difference between the stack and the heap, and what does a stack frame contain?
FINISH THIS LESSON

Sign in to save your progress.