L04 · Numbers, the Toolchain, and 32-bit C Memory Layout

CS 161, Lesson 4, in 50 slides and code mode. It covers binary, hexadecimal, and two's-complement representation, the toolchain that turns source into a running process, the ELF sections (supplemental), and the four-section 32-bit C memory layout - code, static, heap, and stack - with the direction each one grows. It is anchored to textbook sections 2.1 to 2.3, and all conversions were verified.

Subject: Computer Security · 49 slides · code lesson

Open the interactive version of this deck · Homework for this lesson

What this lesson covers

The lesson, slide by slide

1. From Bytes to a Running Process

Title

CS 161 · Lesson 4 of 45 · Systems unit begins

binary & hex · two's complement · the toolchain · 32-bit memory layout

2. By the end of this lesson you can…

Objectives

  1. Convert fluently between binary, hex, and decimal, and read a hex memory dump nibble-by-nibble.
  2. Represent negative integers in two's complement and predict the 32-bit bit pattern of −1.
  3. Order the toolchain stages from source to process and say what each one resolves.
  4. Place a C variable into the correct memory section (code/static/heap/stack) from its declaration.
  5. State the grow directions of the stack and heap and why the stack growing down matters for the rest of the unit.

3. What survived from L03 · Threat Modeling (STRIDE/DFD) + TCB & TOCTTOU Labs?

Warm-up

Discussion prompt

Before we open L04 · Numbers, the Toolchain, and 32-bit C Memory Layout: without looking back, what was the main idea of L03 · Threat Modeling (STRIDE/DFD) + TCB & TOCTTOU Labs, and what could you do by the end of it that you could not do before?

Hint: One sentence for the idea, one for the skill. If the second one is blank, that is the part to revisit.

Answer:

CS 161, Lesson 3 and Quiz 3, in 48 slides. It covers structured threat modeling with STRIDE and data-flow diagrams, marked as supplemental, then a TCB-identification exercise from section 1.12 and the classic access()/open() symlink TOCTTOU lab from section 1.13. It applies all 13 principles from Lessons 1 and 2.

4. We are on a 32-bit system from here on

Concept

The textbook fixes this convention: 'unless otherwise stated we'll be using 32-bit systems.' That means 4-byte words, addresses from 0x00000000 to 0xFFFFFFFF, and the registers eip/ebp/esp (next lesson).

SystemAddress sizeAddress space
32-bit (this course)32 bits = 4 bytes2^32 bytes = 4 GiB
64-bit (real machines)64 bits = 8 bytes2^64 bytes

Every offset we compute in Weeks 2–5 assumes 4-byte words. Memorize that now — it's the #1 source of wrong exam answers when students drift to 64-bit.

5. Fill in: Address size for We are on a 32-bit system from here on

Comparison

Comparison matrix

From We are on a 32-bit system from here on: refill the Address size column from what you know. The rest of the table is as it appeared.

SystemAddress sizeAddress space
32-bit (this course)32 bits = 4 bytes2^32 bytes = 4 GiB
64-bit (real machines)64 bits = 8 bytes2^64 bytes

6. Numbers & Hex

Section

Part 1 · §2.1

7. One hex digit = one nibble = 4 bits

Concept

Hex is base-16. Each digit 0–F encodes exactly 4 bits, so two hex digits = one byte. That is the entire reason memory dumps use hex — one byte is always two clean characters.

binary   hex   decimal
0000      0      0
1010      A     10
1111      F     15
10110101  B5    181
BinaryGroup into nibblesHexDecimal
101101011011 | 0101B5181
001010100010 | 10102A42
111111111111 | 1111FF255

8. What each one costs: One hex digit = one nibble = 4 bits

Trade off

Comparison matrix

From One hex digit = one nibble = 4 bits: every row here is a choice with a cost. Fill the Decimal column, then say which row you would actually pick and what you give up for it.

BinaryGroup into nibblesHexDecimal
101101011011 | 0101B5181
001010100010 | 10102A42
111111111111 | 1111FF255

9. What has to happen first: Convert 0b10110101 by hand

Ranking

Put in order

Put the moves of Convert 0b10110101 by hand into the order they have to happen.

  1. Sum the set bits
  2. Group into nibbles for hex
  3. Check by reversing

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. 128 + 32 + 16 + 4 + 1 = 181. Only the columns with a 1 contribute.

10. Convert 0b10110101 by hand

Worked example

  1   0   1   1   0   1   0   1
128  64  32  16   8   4   2   1

Sum the set bits

Why: 128 + 32 + 16 + 4 + 1 = 181. Only the columns with a 1 contribute.

Group into nibbles for hex

Why: 1011 = B (11), 0101 = 5. So 0b10110101 = 0xB5.

FormValue
binary10110101
hex0xB5
decimal181

Check by reversing

Why: 0xB5 = 11×16 + 5 = 176 + 5 = 181. Agrees — conversion verified.

11. Watch it run: Convert 0b10110101 by hand

Pattern

Step through it

Step through Convert 0b10110101 by hand one row at a time. What is driving the change, and what would the row after the last one be?

  1. Step 1: Form is binary
  2. Step 2: Form is hex
  3. Step 3: Form is decimal

12. Two's complement: how negatives are stored

Concept

A signed 32-bit int stores negatives in two's complement: to get −x, invert all bits of x and add 1. The top bit is the sign.

 1  = 0x00000001
~1  = 0xFFFFFFFE   (invert)
+1  = 0xFFFFFFFF   (add one)  =>  -1
Value32-bit hexNote
00x00000000all zeros
-10xFFFFFFFFall ones
INT_MAX0x7FFFFFFFsign bit 0, rest 1 = 2147483647
INT_MIN0x80000000sign bit 1, rest 0 = -2147483648

13. Fill in: Note for Two's complement: how negatives are stored

Comparison

Comparison matrix

From Two's complement: how negatives are stored: refill the Note column from what you know. The rest of the table is as it appeared.

Value32-bit hexNote
00x00000000all zeros
-10xFFFFFFFFall ones
INT_MAX0x7FFFFFFFsign bit 0, rest 1 = 2147483647
INT_MIN0x80000000sign bit 1, rest 0 = -2147483648

14. Something is wrong here: signed vs unsigned reading of the same bytes

Anomaly

Predict first

A student writes this, and it looks reasonable:

The 4 bytes 0xFFFFFFFF are in memory.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: Reads the bits as unsigned without checking the variable's type — the same bits mean different numbers.

The 4 bytes 0xFFFFFFFF are in memory.

Why: Reads the bits as unsigned without checking the variable's type — the same bits mean different numbers.

15. Trap: signed vs unsigned reading of the same bytes

Trap

The trap

The 4 bytes 0xFFFFFFFF are in memory.

Assume they always mean 4,294,967,295

Why: Reads the bits as unsigned without checking the variable's type — the same bits mean different numbers.

The fix

The 4 bytes 0xFFFFFFFF are in memory.

Read them as the TYPE says: signed int → −1, unsigned int → 4,294,967,295

Why: Bits carry no sign on their own; the declared type decides interpretation. This exact ambiguity becomes the integer-conversion bug in Lesson 9.

16. Break it on purpose: signed vs unsigned reading of the same bytes

Break the constraint

Discussion prompt

The rule this trap just fixed:

Bits carry no sign on their own; the declared type decides interpretation. This exact ambiguity becomes the integer-conversion bug in Lesson 9.

Now break it on purpose. Build a case that violates it and follow the consequences until something visibly fails. Where does the failure first show up — and would you have noticed it if you had not been looking?

Hint: The dangerous rules are the ones whose violation still produces an answer. If yours fails loudly, try to find one that fails quietly.

Answer:

Reads the bits as unsigned without checking the variable's type — the same bits mean different numbers.

17. The Toolchain

Section

Part 2 · §2.2

18. Source becomes a process in stages

Concept

C does not run directly. A pipeline transforms text into a running process, and each stage has one job.

source.c
  -> preprocessor   (expand #include, #define)
  -> compiler       (C -> assembly)
  -> assembler      (assembly -> object file, raw bytes)
  -> linker         (resolve symbols across .o + libraries)
  -> executable
  -> loader         (map into virtual memory)
  -> process
StageInput → OutputResolves
Preprocessortext → textmacros, includes
CompilerC → assemblysyntax, types, codegen
Assemblerasm → object (.o)mnemonics → machine bytes
Linker.o + libs → execross-file symbol addresses
Loaderexe → processmap sections into memory

19. Break it if you can: Source becomes a process in stages

Counterexample

Discussion prompt

C does not run directly. A pipeline transforms text into a running process, and each stage has one job.

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

20. Why the linker is its own stage

Intuition

The compiler sees one file at a time. When main.c calls helper() defined in util.c, the compiler emits a placeholder — it cannot know helper's final address.

The linker sees all the object files at once and patches every placeholder to a real address (symbol resolution). That's why a missing function is a link error, not a compile error.

Ask yourself: if you get 'undefined reference to helper', which stage failed — and which stage was perfectly happy?

21. By analogy: Why the linker is its own stage

Analogy

Discussion prompt

Explain Why the linker is its own stage by analogy to something with no Computer Security in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.

Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.

Answer:

The compiler sees one file at a time. When main.c calls helper() defined in util.c, the compiler emits a placeholder — it cannot know helper's final address.

22. ⊕ ELF sections (real-world detail)

Concept

⊕ Supplemental — beyond the textbook's four-section model. A real ELF executable splits the program's static parts into named sections:

SectionHoldsWritable?
.textmachine codeno (executable)
.rodatastring literals, const datano
.datainitialized globals/staticsyes
.bsszero-initialized globals/staticsyes (no file bytes)

The exam-relevant model is still the book's four regions (next part). Know .text/.data/.bss/.rodata for real binaries, but don't expect them on a CS 161 stack diagram.

23. What each one costs: ⊕ ELF sections (real-world detail)

Trade off

Comparison matrix

From ⊕ ELF sections (real-world detail): every row here is a choice with a cost. Fill the Holds column, then say which row you would actually pick and what you give up for it.

SectionHoldsWritable?
.textmachine codeno (executable)
.rodatastring literals, const datano
.datainitialized globals/staticsyes
.bsszero-initialized globals/staticsyes (no file bytes)

24. C Memory Layout

Section

Part 3 · §2.3

25. Four regions, low address to high

Concept

At runtime the OS hands the process one contiguous address space. The book divides it into four regions, lowest address to highest:

RegionHoldsGrows
Codeexecutable instructionsfixed
Staticglobals, static vars, constantsfixed
Heapmalloc'd dataUP ↑ (toward higher addr)
Stacklocals, call framesDOWN ↓ (toward lower addr)

Heap and stack grow toward each other from opposite ends of the space. The stack starts high and grows down; the heap starts low and grows up.

26. Which is which, by Grows

Discrimination

Sort into buckets

Sort these by Grows, from memory, without looking back at Four regions, low address to high. Telling them apart on the spot is the skill; the table is only where the answer happens to be written down.

fixed
Code; Static
UP ↑ (toward higher addr)
Heap
DOWN ↓ (toward lower addr)
Stack
g1
Grows is "fixed" for Code, Static — that is what the table on "Four regions, low address to high" records, and it is the single property separating this group from the rest.
g2
Grows is "UP ↑ (toward higher addr)" for Heap — that is what the table on "Four regions, low address to high" records, and it is the single property separating this group from the rest.
g3
Grows is "DOWN ↓ (toward lower addr)" for Stack — that is what the table on "Four regions, low address to high" records, and it is the single property separating this group from the rest.

27. What has to happen first: Place each variable in its region

Ranking

Put in order

Put the moves of Place each variable in its region into the order they have to happen.

  1. g and s → static region
  2. the literal "hi" → static (read-only); the pointer msg → wherever msg is declared
  3. Verify the split

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. Globals and statics live for the whole program, so they sit in the fixed static section (g initialized, s zero-initialized).

28. Place each variable in its region

Worked example

int g = 7;              // A
static int s;           // B
const char *msg = "hi"; // C: pointer + literal

void f(void) {
    int local;          // D
    int *p = malloc(16); // E: pointer D-area, block heap
}

g and s → static region

Why: Globals and statics live for the whole program, so they sit in the fixed static section (g initialized, s zero-initialized).

the literal "hi" → static (read-only); the pointer msg → wherever msg is declared

Why: String literals are constants in static/.rodata; the pointer variable itself follows its own scope.

VarDeclared asRegion
gglobal intstatic
sstatic intstatic
"hi"string literalstatic (read-only)
localfunction localstack
*p blockmalloc(16)heap

Verify the split

Why: local and the pointer p sit on the stack; only the 16 bytes from malloc live on the heap. The pointer is on the stack; the pointee is on the heap — a distinction we exploit in Lesson 10.

29. Fill in: Region for Place each variable in its region

Comparison

Comparison matrix

From Place each variable in its region: refill the Region column from what you know. The rest of the table is as it appeared.

VarDeclared asRegion
gglobal intstatic
sstatic intstatic
"hi"string literalstatic (read-only)
localfunction localstack
*p blockmalloc(16)heap

30. Why 'stack grows down' is the whole game

Intuition

Each new function call allocates its frame at a lower address than its caller. So a local buffer sits at a lower address than the saved return address that lives above it.

But a write into that buffer (e.g. copying a string) moves from low to high addresses — upward, toward the return address. Growth direction (down) and write direction (up) are opposite. Hold that thought: it is the buffer overflow in one sentence.

Ask yourself: if locals are below the return address and writes go upward, what does an over-long write eventually reach?

31. Where does each piece belong: L04 · Numbers, the Toolchain, and 32-bit C…

Sorting

Sort into buckets

These are the pieces of L04 · Numbers, the Toolchain, and 32-bit C Memory Layout, out of order. Put each one back under the part of the lesson it belongs to.

Numbers & Hex
One hex digit = one nibble = 4 bits; Convert 0b10110101 by hand; Two's complement: how negatives are stored
The Toolchain
Source becomes a process in stages; Why the linker is its own stage; ⊕ ELF sections (real-world detail)
C Memory Layout
Four regions, low address to high; Place each variable in its region; Why 'stack grows down' is the whole game
s1
Numbers & Hex is where L04 · Numbers, the Toolchain, and 32-bit C Memory Layout puts One hex digit = one nibble = 4 bits, Convert 0b10110101 by hand, Two's complement: how negatives are stored. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s2
The Toolchain is where L04 · Numbers, the Toolchain, and 32-bit C Memory Layout puts Source becomes a process in stages, Why the linker is its own stage, ⊕ ELF sections (real-world detail). Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s3
C Memory Layout is where L04 · Numbers, the Toolchain, and 32-bit C Memory Layout puts Four regions, low address to high, Place each variable in its region, Why 'stack grows down' is the whole game. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.

32. Something is wrong here: 'grows down' means writes go to lower addresses

Anomaly

Predict first

A student writes this, and it looks reasonable:

A buffer is filled by copying bytes into it.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: Conflates frame ALLOCATION direction with data WRITE direction — they are not the same thing.

A buffer is filled by copying bytes into it.

Why: Conflates frame ALLOCATION direction with data WRITE direction — they are not the same thing.

33. Trap: 'grows down' means writes go to lower addresses

Trap

The trap

A buffer is filled by copying bytes into it.

Assume bytes are written from high address to low because 'the stack grows down'

Why: Conflates frame ALLOCATION direction with data WRITE direction — they are not the same thing.

The fix

A buffer is filled by copying bytes into it.

Frames are allocated downward, but bytes are written upward (low → high) within the buffer

Why: §2.3: allocating a new frame decrements the pointer (down), but a string copy fills buf[0], buf[1], … at increasing addresses (up). The overflow reaches the return address precisely because writes go up.

34. Which of these survive contact with L04 · Numbers, the Toolchain, and 32-bit C…?

Two truths and a lie

Sort into buckets

Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.

Holds up
Every offset we compute in Weeks 2–5 assumes 4-byte words. Memorize that now — it's the #1 source of wrong exam answers when students drift to 64-bit.; A signed 32-bit int stores negatives in two's complement: to get −x, invert all bits of x and add 1. The top bit is the sign.; C does not run directly. A pipeline transforms text into a running process, and each stage has one job.
Breaks
The 4 bytes 0xFFFFFFFF are in memory.; A buffer is filled by copying bytes into it.
sound
These are stated as this lesson states them — each one survives the edge cases L04 · Numbers, the Toolchain, and 32-bit C Memory Layout puts it through.
flawed
Each of these is lifted from a trap in this deck: reasonable-sounding, and wrong in a way that only shows up once you rely on it.

35. Virtual addresses, briefly

Concept

Every process believes it owns the full 0x00000000–0xFFFFFFFF space. The OS gives each one that illusion via virtual memory — two processes can both 'have' address 0x08048000 mapped to different physical RAM.

We treat addresses as virtual throughout this unit; the physical mapping (CS 61C / 162) doesn't change any exploit arithmetic.

36. Break it if you can: Virtual addresses, briefly

Counterexample

Discussion prompt

We treat addresses as virtual throughout this unit; the physical mapping (CS 61C / 162) doesn't change any exploit arithmetic.

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

37. Rebuild the recipe: The Lesson-4 recipe

Ranking

Put in order

These are the steps of The Lesson-4 recipe, scrambled. Put them back in order before the next slide shows you.

  1. Hex ↔ binary: split every byte into two nibbles; each hex digit = 4 bits.
  2. Negatives: invert + 1; −1 is all-ones (0xFFFFFFFF) in 32 bits.
  3. Same bits, two meanings: signed vs unsigned is a TYPE decision.
  4. Toolchain order: preprocess → compile → assemble → link → load.
  5. Place a variable: lifetime/scope decides region — globals & statics & literals → static; locals → stack; malloc → heap.
  6. Directions: stack allocates DOWN, heap allocates UP, but byte writes within a buffer go UP.

Why: This is the order the recipe itself gives. Recalling the sequence without the slide in front of you is the difference between recognising the method and being able to run it — most of what goes wrong in practice is a step done out of turn.

38. The Lesson-4 recipe

Pattern

  1. Hex ↔ binary: split every byte into two nibbles; each hex digit = 4 bits.
  2. Negatives: invert + 1; −1 is all-ones (0xFFFFFFFF) in 32 bits.
  3. Same bits, two meanings: signed vs unsigned is a TYPE decision.
  4. Toolchain order: preprocess → compile → assemble → link → load.
  5. Place a variable: lifetime/scope decides region — globals & statics & literals → static; locals → stack; malloc → heap.
  6. Directions: stack allocates DOWN, heap allocates UP, but byte writes within a buffer go UP.

39. Where does it stop working: The Lesson-4 recipe

Edge cases

Discussion prompt

The Lesson-4 recipe works on the cases you have just seen. Push it to the edge: what is the most degenerate input it still handles — empty, zero, one item, everything equal — and what is the first case where it stops being true? Name the case, not just "it breaks".

Hint: Try the smallest legal input, then the largest, then the one where two things collide. Methods are specified at their edges; the middle takes care of itself.

Answer:

  1. Hex ↔ binary: split every byte into two nibbles; each hex digit = 4 bits.
  2. Negatives: invert + 1; −1 is all-ones (0xFFFFFFFF) in 32 bits.
  3. Same bits, two meanings: signed vs unsigned is a TYPE decision.
  4. Toolchain order: preprocess → compile → assemble → link → load.
  5. Place a variable: lifetime/scope decides region — globals & statics & literals → static; locals → stack; malloc → heap.
  6. Directions: stack allocates DOWN, heap allocates UP, but byte writes within a buffer go UP.

40. Checkpoint 1 — read the bytes

Check

A 32-bit signed int variable holds the bytes 0xFFFFFFFF. Solve on paper first.

Check your understanding

What value does it hold, and why?

  • A. −1, because two's complement makes all-ones the representation of −1. (correct)
  • B. 4,294,967,295, because that is what 0xFFFFFFFF equals.
  • C. 0, because the bits cancel out.
  • D. 2,147,483,647, because that is the largest int.

Answer: A

Why: For a signed 32-bit int, 0xFFFFFFFF is two's-complement −1 (invert 1 → 0xFFFFFFFE, add 1 → 0xFFFFFFFF). The unsigned reading would be 4,294,967,295, but the type here is signed.

Why B tempts people
That is the UNSIGNED interpretation; the variable is declared signed, so the top bit is a sign bit.
Why C tempts people
All-ones is not zero; zero is 0x00000000. The bits do not cancel.
Why D tempts people
INT_MAX is 0x7FFFFFFF (sign bit 0). 0xFFFFFFFF has the sign bit set, so it is negative.

41. Rule out three: Checkpoint 2 — which stage failed?

Elimination

Eliminate the wrong options

Which toolchain stage produced this error?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. The preprocessor, because the header wasn't expanded.
  • B. The compiler, because main.c has a type error.
  • C. The linker, because no object file provides helper's address.
  • D. The loader, because helper isn't mapped into memory.

Survives elimination: C

Why: The declaration satisfied the compiler (it knew helper's signature), so compilation succeeded. The error appears when the linker tries to resolve the call to a definition across all object files and finds none — a classic link-time symbol-resolution failure.

42. Checkpoint 2 — which stage failed?

Check

Your build prints: 'undefined reference to helper'. helper() is declared in a header and called in main.c, but never defined anywhere.

Check your understanding

Which toolchain stage produced this error?

  • A. The preprocessor, because the header wasn't expanded.
  • B. The compiler, because main.c has a type error.
  • C. The linker, because no object file provides helper's address. (correct)
  • D. The loader, because helper isn't mapped into memory.

Answer: C

Why: The declaration satisfied the compiler (it knew helper's signature), so compilation succeeded. The error appears when the linker tries to resolve the call to a definition across all object files and finds none — a classic link-time symbol-resolution failure.

Why A tempts people
The header expanded fine; a declaration is present. The problem is a missing definition, found later.
Why B tempts people
The compiler was satisfied by the declaration — that's exactly why the error slips to link time.
Why D tempts people
The loader never runs; there is no executable yet because linking failed first.

43. Rule out three: Checkpoint 3 — direction reasoning

Elimination

Eliminate the wrong options

The stack 'grows down,' so in which direction do the copied bytes land, and what do they threaten?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. Downward to lower addresses, threatening the heap.
  • B. Upward to higher addresses, threatening the saved return address above buf.
  • C. They stay within buf; C prevents writing past index 7.
  • D. Randomly, depending on the allocator.

Survives elimination: B

Why: Frame allocation goes down, but a string copy fills buf[0], buf[1], … at increasing addresses — upward. Since the saved return address sits above buf, a long-enough copy overwrites it. That is the entire mechanism of the stack overflow in Lesson 8.

44. Checkpoint 3 — direction reasoning

Check

A local char buf[8] is filled by copying a long string into it.

Check your understanding

The stack 'grows down,' so in which direction do the copied bytes land, and what do they threaten?

  • A. Downward to lower addresses, threatening the heap.
  • B. Upward to higher addresses, threatening the saved return address above buf. (correct)
  • C. They stay within buf; C prevents writing past index 7.
  • D. Randomly, depending on the allocator.

Answer: B

Why: Frame allocation goes down, but a string copy fills buf[0], buf[1], … at increasing addresses — upward. Since the saved return address sits above buf, a long-enough copy overwrites it. That is the entire mechanism of the stack overflow in Lesson 8.

Why A tempts people
Allocation goes down, but data is written upward; and the heap is at the opposite end of the address space, not just below the stack.
Why C tempts people
C performs no automatic bounds checking — writing buf[8] and beyond is exactly what's allowed and dangerous.
Why D tempts people
A sequential copy is deterministic and goes strictly upward; nothing random about it.

45. Misconceptions to drop now

Concept

46. Synthesis — the foundation for the exploits ahead

Concept

47. Primary sources & where to read more

Concept

48. Connect it up: L04 · Numbers, the Toolchain, and 32-bit C Memory Layout

Connect it up

Draw it

One page, no notation unless you need it: draw how these connect — Numbers & Hex · The Toolchain · C Memory Layout. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.

49. Recap — Lesson 4

Recap

You can convert across bases, read signed vs unsigned bits, order the toolchain, place any variable in its region, and explain why the stack growing down sets up every overflow to come.

Idea§Keep this
Hex nibble2.11 hex digit = 4 bits
Two's complement2.1−1 = 0xFFFFFFFF (32-bit)
Toolchain2.2Missing function = LINK error
Memory regions2.3Globals→static, locals→stack, malloc→heap
Directions2.3Alloc down, writes up

Sources

  1. CS 161 Computer Security Textbook §2.1 (Number representation), §2.2 (Compiler/Assembler/Linker/Loader), §2.3 (C memory layout) — Wagner, Weaver, Kao, Shakir, Law & Ngai, UC Berkeley — 'unless otherwise stated we'll be using 32-bit systems'
  2. Tool Interface Standard (TIS) Executable and Linking Format (ELF) Specification v1.2 — TIS Committee, 1995 — .text/.data/.bss/.rodata section semantics (⊕ supplemental)
  3. Computer Systems: A Programmer's Perspective, ch. 7 (Linking) — Bryant & O'Hallaron — symbol resolution and the static link step (⊕ background)

Want this taught 1-on-1? Alexander tutors Computer Security — $55/session, free consultation.

Book on Wyzant · Text (657) 465-8108