In this post we will try to understand the memory more. From here we will be able tweak some parameters and obtain more information regarding how we can assigne values into the memory which we have allocated and then try to access them via pointer and dereference.

If we lookinto the code below, we can see that we have mapped a memory location at 0x404000 and we have called it my memory. And from the starting point of the memory location, we have assigned some sequential values so that we can identify what are the values we are looking at when it is displayed.

from qiling import Qiling # import
from qiling.const import QL_VERBOSE
from pwn import *


code=asm("""
mov rax, qword ptr [rdi+ 0xe]
""",  arch = 'amd64', os = 'linux')
ql = Qiling(code=code, archtype='x8664', ostype='Linux', verbose=QL_VERBOSE.DISASM)

ql.mem.map(0x404000//4096*4096, 4096, info="my_area")
ql.mem.write(0x404000, b'\x01\x02\x03\x04\x05\x06\x07\x08')
ql.mem.write(0x404008, b'\xa1\xb2\xc3\xef\x11\x12\x13\x14')

# we can also use pwntools to convert a value to raw bytes.
# In [21]: p64(0x3)
# Out[21]: b'\x03\x00\x00\x00\x00\x00\x00\x00'

ql.mem.write(0x40400e, b'\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8')
ql.mem.write(0x404018, b'\x41\x42\x43\x44\x45\x46\x47\x48')
ql.mem.write(0x404020, b'\x51\x52\x53\x54\x55\x56\x57\x58')
ql.arch.regs.write("rdi", 0x404000)

ql.run()
print("rax is: " + str(ql.arch.regs.read("rax")) + " hex => " + hex(ql.arch.regs.read("rax")))
print("rdi is: " + str(ql.arch.regs.read("rdi")) + " hex => " + hex(ql.arch.regs.read("rdi")))
print("result: r13 is: " + str(ql.arch.regs.read("r13")))


==> 
rax is: 14467750880663028417 hex => 0xc8c7c6c5c4c3c2c1

Using the assembly code mov rax, qword ptr [rdi+ 0xe] we tell that get qwordsized data from the location rdi (which has been assigned 0x404000) and 0xe bytes away from rdi. As expected we can see our intended value in the output.

We will be able to access other values as well and view them if we change values from 0xe to something else.