push指令
比如push ebp就是把ebp的值放在esp所指的地方,然后esp-4(32位,以下均为32位)。
pop指令
pop ebp就是把esp所指的地方的值给ebp,然后esp+4
call指令
call函数的时候,把eip的下一行存到esp所指的位置,然后esp-4
leave指令
leave指令可以等价于mov esp,ebp;pop ebp
ret指令
等价于pop eip
调试例子
下载:https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/stackoverflow/ret2text/bamboofox-ret2text/ret2text
该程序来自于ctfwiki中的基本ROP-ret2text
直接使用pwndbg启动起来,一直ni到我们需要的,比如call puts函数:
此时的esp为0xffffcf90
,ebp为0xffffd018
,我们si进去:
执行完call后,此时的esp为0xffffcf8c
,esp指向的值为0x80486a7
,ebp保持不变。
未执行call前,eip的下一行为0x80486a7
,执行call时,将eip的下一行即0x80486a7
给esp所指向的值,然后esp-4(0xffffcf90-4=0xffffcf8c
)。
接下来ni到push 0x18
:
要执行push 0x18
,push就是把要push的东西给esp所指向的值,然后esp-4,所以指向完push 0x1
后,esp会变为0xffffcf88
,而esp所指向的值会变为0x18
:
接下来再看push eax
:
eax的值为0x0
,esp的值为0xffffcf84
,push就是把要push的东西给esp所指向的值,然后esp-4,所以esp所指向的值会变为0x0
,esp变为0xffffcf84-4=0xffffcf80
:
再ni到pop edx
:
pop某个东西就是把esp所指向的值给这个东西,esp再加4,此时为pop edx
,就是把esp当前所指向的值0xf7e1f9c4
给edx,esp-4=0xffffcf78+4=0xffffcf7c
,如下图:
此时的edx变为0xf7e1f9c4
,esp变为0xffffcf7c
。接着向下看:
ret就是相当于pop eip,要执行ret 0xc
的话,eip接下来会变为esp所指向的值0xf7c73200
,esp会变为0xffffcf7c+0xc+4=0xffffcf8c
(如果没有0xc的话,就不用加)如下图:
直接finish出来,去找最后的leave:
leave就是等价于mov esp,ebp;pop ebp
先来看当前的:esp为0xffffcf90
,ebp为0xffffd018
,可以先用telescope 0xffffd018
找一下ebp所指向的值:
由于由于leave相当于一次执行两步,先来分析mov esp,ebp
,执行完这个后,esp会变为0xffffd018
,此时再pop ebp
,就是把esp所指向的值(0x0)给ebp,然后esp+4变为0xffffd018+4=0xffffd01c
:
可以看到,ebp变为0,esp变为0xffffd01c
。调试分析结束,由于我也刚学不久,如果有错误的地方,大佬勿喷。