逆向03:内存地址与堆栈

x64dbg

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
SUB EDX, 4

也可以先改动栈顶位置,再写入值:

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


Built with Hugo
主题 StackJimmy 设计