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 touch0x133337–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.