x64dbg
在数据窗口中,地址后面的数据默认以低位到高位的顺序排列。而在堆栈窗口中,数据以从高位到地位的顺序显示。
寻址
[立即数]
读取内存的值:
1
2
|
MOV EAX, DWORD PTR DS:[0x13FFC4]
MOV EAX, DWORD PTR DS:[0x13FFC8]
|
向内存中写入数据:
1
2
|
MOV DWORD PTR DS:[0x13FFC4], EAX
MOV DWORD PTR DS:[0x13FFC8], EAX
|
获取内存地址
1
2
|
LEA EAX, DWORD PTR DS:[0x13FFC4]
LEA EAX, DWORD PTR DS:[ESP+8]
|
LEA: Load Effective Address,加载有效地址
[reg]
读取内存的值:
1
2
|
MOV ECX, 0x13FFC4
MOV EAX, DWORD PTR DS:[ECX]
|
读取ECX中存储的数据并将其看作内存地址编号进行读取。
向内存中写入数据:
1
2
|
MOV EDX, 0x13FFC4
MOV DWORD PTR DS:[EDX], 0x12345678
|
获取内存地址:
1
2
|
LEA EAX, DWORD PTR DS:[EDX]
MOV EAX, DWORD PTR DS:[EDX]
|
[reg + 立即数]
读取内存的值:
1
2
|
MOV ECX, 0x13FFC4
MOV EAX, DWORD PTR DS:[ECX+4]
|
向内存中写入数据:
1
2
|
MOV EDX, 0x13FFC4
MOV DWORD PTR DS:[EDX+0xC], 0x12345678
|
获取内存地址:
1
2
|
LEA EAX, DWORD PTR DS:[EDX+4]
MOV EAX, DWORD PTR DS:[EDX+4]
|
[reg + reg*{1,2,4,8}]
读取内存的值:
1
2
3
|
MOV EAX, 13FFC4
MOV ECX, 2
MOV EDX, DWORD PTR DS:[EAX+ECX*4]
|
向内存中写入数据:
1
2
3
|
MOV EAX, 13FFC4
MOV ECX, 2
MOV DWORD PTR DS:[EAX+ECX*4], 87654321
|
获取内存地址:
1
|
LEA EAX, DWORD PTR DS:[EAX+ECX*4]
|
[reg + reg*{1,2,4,8} + 立即数]
读取内存的值:
1
2
3
|
MOV EAX, 13FFC4
MOV ECX, 2
MOV EDX, DWORD PTR DS:[EAX+ECX*4+4]
|
向内存中写入数据:
1
2
3
|
MOV EAX, 13FFC4
MOV ECX, 2
MOV DWORD PTR DS:[EAX+ECX*4+4], 87654321
|
获取内存地址:
1
|
LEA EAX, DWORD PTR DS:[EAX+ECX*4+2]
|
堆栈
获取堆栈中的地址可以通过栈顶或栈底地址+偏移量的方式读取。
堆栈适合临时存储大量的数据,便于查找。
栈底的值恒定,栈顶根据内存使用情况变化。
模拟堆栈实现
此处模拟以高地址向低地址扩展(Windows)为例。
写入模拟(压栈/入栈)
假设EBX为栈底,EDX为栈顶:
1
2
|
MOV EBX, 0x12FFE0
MOV EDX, 0x12FFE0
|
向内存中存值:
1
|
MOV DWORD PTR DS:[EDX-4], 0xAAAAAAAA
|
更新栈顶位置:
也可以先改动栈顶位置,再写入值:
1
2
3
|
;也可以使用LEA更新栈顶位置
LEA EDX, DWORD PTR DS:[EDX-4]
MOV DWORD PTR DS:[EDX], 0xBBBBBBBB
|
读取模拟
1
2
3
4
|
;以栈底为基准
MOV ESI, DWORD PTR DS:[EBX-8]
;以栈顶为基准
MOV ESI, DWORD PTR DS:[EDX+8]
|
出栈模拟
以栈顶为基准,取一个双字,取出后将栈顶移动(恢复到原来的位置)。
PUSH/POP
一般,ESP为栈顶、EBP为栈底。
可以使用PUSH命令,向栈顶压入数据并移动栈顶。
1
2
3
4
5
6
7
8
9
|
PUSH 0x12345678
PUSH EAX
;PUSH 不能压入8位的值
;PUSH AX栈顶将只移动2个单位的
PUSH AX
;压入内存的值
PUSH DWORD PTR DS:[0x12FFBA]
;压入16位的内存值栈顶将只移动2个单位
PUSH WORD PTR DS:[0x12FFBA]
|
可以使用POP命令,读取并移动栈顶。
1
2
3
|
POP EAX
;弹出16位数据到EAX,栈顶移动2个单位
POP AX
|
PUSHAD/POPAD
把寄存器的值全部压入/弹出内存。
PUSHAD = Push All Data
POPAD = Pop All Data