Accessing memory

Pwncollege

You can move data between registers and memory with mov!

This will load the 64-bit value stored at memory address 0x12345 into rbx:

mov rax, 0x12345  
mov rbx, [rax]

This will store the 64-bit value in rbx into memory at address 0x133337:

mov rax, 0x133337  
mov [rax], rbx

This is equivalent to push rcx:

sub rsp, 8
mov [rsp], rcx

Each addressed memory location contains one byte.

An 8-byte write at address 0x133337 will write to addresses 0x133337 through 0x13333f.

[!NOTE] How does this differ on macOS? macOS is still byte-addressable, so an 8-byte store at 0x133337 does touch 0x133337–0x13333F, but the Mach VM enforces permissions on 4 KB pages, not individual bytes.

Pointers 

By containing the memory address, rax is a pointer that points to the data we want to access! 

When you use a register like rax to hold a memory address, and then you use [rax] to get the value at that address, you’re doing what’s called dereferencing a pointer.

Earlier, you used rax to hold a memory address and then used [rax] to get the value stored there — that’s called dereferencing.

The cool part is: you don’t have to use rax. You can use any register to hold an address, and you can even overwrite that same register with the value from the address it points to.

Example

mov [133700], 42      ; Store the number 42 at memory address 0x133700
mov rax, 133700       ; rax now holds the address 0x133700
mov rax, [rax]        ; rax now holds the value at that address — 42

So rax first had an address, and then we replaced it with the value at that address. That’s totally allowed.

Throughout this snippet, rax goes from being used as a pointer to being used to hold the data that’s been read from memory.