mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-24 03:01:15 +07:00
update stack
This commit is contained in:
parent
9d54f09cdd
commit
4052ac215e
@ -80,55 +80,55 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
使用 gdb 查看对应的汇编代码:
|
||||
使用 gdb 查看对应的汇编代码,这里我们给出了详细的注释:
|
||||
```text
|
||||
gdb-peda$ disassemble main
|
||||
Dump of assembler code for function main:
|
||||
0x00000563 <+0>: lea ecx,[esp+0x4]
|
||||
0x00000567 <+4>: and esp,0xfffffff0
|
||||
0x0000056a <+7>: push DWORD PTR [ecx-0x4]
|
||||
0x0000056d <+10>: push ebp
|
||||
0x0000056e <+11>: mov ebp,esp
|
||||
0x00000570 <+13>: push ebx
|
||||
0x00000563 <+0>: lea ecx,[esp+0x4] ;将 esp+0x4 的地址传给 ecx
|
||||
0x00000567 <+4>: and esp,0xfffffff0 ;栈 16 字节对齐
|
||||
0x0000056a <+7>: push DWORD PTR [ecx-0x4] ;ecx-0x4,即原 esp 强制转换为双字数据后压入栈中
|
||||
0x0000056d <+10>: push ebp ;保存调用 main() 函数之前的 ebp,由于在 _start 中将 ebp 清零了,这里的 ebp=0x0
|
||||
0x0000056e <+11>: mov ebp,esp ;把调用 main() 之前的 esp 作为当前栈帧的 ebp
|
||||
0x00000570 <+13>: push ebx ;ebx、ecx 入栈
|
||||
0x00000571 <+14>: push ecx
|
||||
0x00000572 <+15>: sub esp,0x10
|
||||
0x00000575 <+18>: call 0x440 <__x86.get_pc_thunk.bx>
|
||||
0x0000057a <+23>: add ebx,0x1a86
|
||||
0x00000580 <+29>: mov DWORD PTR [ebp-0x10],0x1
|
||||
0x00000587 <+36>: mov DWORD PTR [ebp-0xc],0x2
|
||||
0x0000058e <+43>: push DWORD PTR [ebp-0xc]
|
||||
0x00000591 <+46>: push DWORD PTR [ebp-0x10]
|
||||
0x00000594 <+49>: call 0x53d <add>
|
||||
0x00000572 <+15>: sub esp,0x10 ;为局部变量 a、b 分配空间并做到 16 字节对齐
|
||||
0x00000575 <+18>: call 0x440 <__x86.get_pc_thunk.bx> ;调用 <__x86.get_pc_thunk.bx> 函数,将 esp 强制转换为双字数据后保存到 ebx
|
||||
0x0000057a <+23>: add ebx,0x1a86 ;ebx+0x1a86
|
||||
0x00000580 <+29>: mov DWORD PTR [ebp-0x10],0x1 ;a 第二个入栈所以保存在 ebp-0x10 的位置,此句即 a=1
|
||||
0x00000587 <+36>: mov DWORD PTR [ebp-0xc],0x2 ;b 第一个入栈所以保存在 ebp-0xc 的位置,此句即 b=2
|
||||
0x0000058e <+43>: push DWORD PTR [ebp-0xc] ;将 b 压入栈中
|
||||
0x00000591 <+46>: push DWORD PTR [ebp-0x10] ;将 a 压入栈中
|
||||
0x00000594 <+49>: call 0x53d <add> ;调用 add() 函数,返回值保存在 eax 中
|
||||
0x00000599 <+54>: add esp,0x8
|
||||
0x0000059c <+57>: sub esp,0x8
|
||||
0x0000059f <+60>: push eax
|
||||
0x000005a0 <+61>: lea eax,[ebx-0x19b0]
|
||||
0x000005a6 <+67>: push eax
|
||||
0x000005a7 <+68>: call 0x3d0 <printf@plt>
|
||||
0x000005ac <+73>: add esp,0x10
|
||||
0x000005af <+76>: mov eax,0x0
|
||||
0x000005b4 <+81>: lea esp,[ebp-0x8]
|
||||
0x000005b7 <+84>: pop ecx
|
||||
0x0000059f <+60>: push eax ;eax 入栈
|
||||
0x000005a0 <+61>: lea eax,[ebx-0x19b0] ;ebx-0x19b0 的地址保存到 eax,该地址处保存字符串 "%d\n"
|
||||
0x000005a6 <+67>: push eax ;eax 入栈
|
||||
0x000005a7 <+68>: call 0x3d0 <printf@plt> ;调用 printf() 函数
|
||||
0x000005ac <+73>: add esp,0x10 ;调整栈顶指针 esp,删除 add() 和 printf() 的参数
|
||||
0x000005af <+76>: mov eax,0x0 ;eax=0x0
|
||||
0x000005b4 <+81>: lea esp,[ebp-0x8] ;ebp-0x8 的地址保存到 esp
|
||||
0x000005b7 <+84>: pop ecx ;弹栈恢复 ecx、ebx、ebp
|
||||
0x000005b8 <+85>: pop ebx
|
||||
0x000005b9 <+86>: pop ebp
|
||||
0x000005ba <+87>: lea esp,[ecx-0x4]
|
||||
0x000005bd <+90>: ret
|
||||
0x000005ba <+87>: lea esp,[ecx-0x4] ;ecx-0x4 的地址保存到 esp
|
||||
0x000005bd <+90>: ret ;返回
|
||||
End of assembler dump.
|
||||
gdb-peda$ disassemble add
|
||||
Dump of assembler code for function add:
|
||||
0x0000053d <+0>: push ebp
|
||||
0x0000053e <+1>: mov ebp,esp
|
||||
0x00000540 <+3>: sub esp,0x10
|
||||
0x00000543 <+6>: call 0x5be <__x86.get_pc_thunk.ax>
|
||||
0x00000548 <+11>: add eax,0x1ab8
|
||||
0x0000054d <+16>: mov eax,DWORD PTR [ebp+0x8]
|
||||
0x00000550 <+19>: mov DWORD PTR [ebp-0x8],eax
|
||||
0x00000553 <+22>: mov eax,DWORD PTR [ebp+0xc]
|
||||
0x00000556 <+25>: mov DWORD PTR [ebp-0x4],eax
|
||||
0x00000559 <+28>: mov edx,DWORD PTR [ebp-0x8]
|
||||
0x0000055c <+31>: mov eax,DWORD PTR [ebp-0x4]
|
||||
0x0000055f <+34>: add eax,edx
|
||||
0x00000561 <+36>: leave
|
||||
0x0000053d <+0>: push ebp ;保存调用 add() 函数之前的 ebp
|
||||
0x0000053e <+1>: mov ebp,esp ;把调用 add() 之前的 esp 作为当前栈帧的 ebp
|
||||
0x00000540 <+3>: sub esp,0x10 ;为局部变量 x、y 分配空间并做到 16 字节对齐
|
||||
0x00000543 <+6>: call 0x5be <__x86.get_pc_thunk.ax> ;调用 <__x86.get_pc_thunk.ax> 函数,将 esp 强制转换为双字数据后保存到 eax
|
||||
0x00000548 <+11>: add eax,0x1ab8 ;eax+0x1ab8
|
||||
0x0000054d <+16>: mov eax,DWORD PTR [ebp+0x8] ;将 ebp+0x8 的数据 0x1 传送到 eax,ebp+0x4 为函数返回地址
|
||||
0x00000550 <+19>: mov DWORD PTR [ebp-0x8],eax ;保存 eax 的值 0x1 到 ebp-0x8 的位置
|
||||
0x00000553 <+22>: mov eax,DWORD PTR [ebp+0xc] ;将 ebp+0xc 的数据 0x2 传送到 eax
|
||||
0x00000556 <+25>: mov DWORD PTR [ebp-0x4],eax ;保存 eax 的值 0x2 到 ebp-0x4 的位置
|
||||
0x00000559 <+28>: mov edx,DWORD PTR [ebp-0x8] ;取出 ebp-0x8 的值 0x1 到 edx
|
||||
0x0000055c <+31>: mov eax,DWORD PTR [ebp-0x4] ;取出 ebp-0x4 的值 0x2 到 eax
|
||||
0x0000055f <+34>: add eax,edx ;eax+edx
|
||||
0x00000561 <+36>: leave ;返回,相当于 mov esp,ebp; pop ebp;
|
||||
0x00000562 <+37>: ret
|
||||
End of assembler dump.
|
||||
```
|
||||
@ -136,27 +136,27 @@ End of assembler dump.
|
||||
```text
|
||||
gdb-peda$ disassemble _start
|
||||
Dump of assembler code for function _start:
|
||||
0x00000400 <+0>: xor ebp,ebp
|
||||
0x00000402 <+2>: pop esi
|
||||
0x00000403 <+3>: mov ecx,esp
|
||||
0x00000405 <+5>: and esp,0xfffffff0
|
||||
0x00000408 <+8>: push eax
|
||||
0x00000400 <+0>: xor ebp,ebp ;清零 ebp,表示下面的 main() 函数栈帧中 ebp 保存的上一级 ebp 为 0x00000000
|
||||
0x00000402 <+2>: pop esi ;弹栈设置 esi
|
||||
0x00000403 <+3>: mov ecx,esp ;暂时保存当前的 esp
|
||||
0x00000405 <+5>: and esp,0xfffffff0 ;栈 16 字节对齐
|
||||
0x00000408 <+8>: push eax ;eax、esp、edx 入栈
|
||||
0x00000409 <+9>: push esp
|
||||
0x0000040a <+10>: push edx
|
||||
0x0000040b <+11>: call 0x432 <_start+50>
|
||||
0x00000410 <+16>: add ebx,0x1bf0
|
||||
0x00000416 <+22>: lea eax,[ebx-0x19d0]
|
||||
0x0000040b <+11>: call 0x432 <_start+50> ;先将下一条指令地址 0x00000410 压栈,设置 esp 指向它,再调用 0x00000432 处的指令
|
||||
0x00000410 <+16>: add ebx,0x1bf0 ;ebx+0x1bf0
|
||||
0x00000416 <+22>: lea eax,[ebx-0x19d0] ;取 <__libc_csu_fini> 地址传给 eax,然后压栈
|
||||
0x0000041c <+28>: push eax
|
||||
0x0000041d <+29>: lea eax,[ebx-0x1a30]
|
||||
0x00000423 <+35>: push eax
|
||||
0x00000424 <+36>: push ecx
|
||||
0x0000041d <+29>: lea eax,[ebx-0x1a30] ;取 <__libc_csu_init> 地址传入 eax,然后压栈
|
||||
0x00000423 <+35>: push eax
|
||||
0x00000424 <+36>: push ecx ;ecx、esi 入栈保存
|
||||
0x00000425 <+37>: push esi
|
||||
0x00000426 <+38>: push DWORD PTR [ebx-0x8]
|
||||
0x0000042c <+44>: call 0x3e0 <__libc_start_main@plt>
|
||||
0x00000431 <+49>: hlt
|
||||
0x00000432 <+50>: mov ebx,DWORD PTR [esp]
|
||||
0x00000435 <+53>: ret
|
||||
0x00000436 <+54>: xchg ax,ax
|
||||
0x00000426 <+38>: push DWORD PTR [ebx-0x8] ;调用 main() 函数之前保存返回地址,其实就是保存 main() 函数的入口地址
|
||||
0x0000042c <+44>: call 0x3e0 <__libc_start_main@plt> ;call 指令调用 main() 函数
|
||||
0x00000431 <+49>: hlt ;hlt 指令使程序停止运行,处理器进入暂停状态,不执行任何操作,不影响标志。当 RESET 线上有复位信号、CPU 响应非屏蔽终端、CPU 响应可屏蔽终端 3 种情况之一时,CPU 脱离暂停状态,执行下一条指令
|
||||
0x00000432 <+50>: mov ebx,DWORD PTR [esp] ;esp 强制转换为双字数据后保存到 ebx
|
||||
0x00000435 <+53>: ret ;返回
|
||||
0x00000436 <+54>: xchg ax,ax ;交换 ax 和 ax 的数据,相当于 nop
|
||||
0x00000438 <+56>: xchg ax,ax
|
||||
0x0000043a <+58>: xchg ax,ax
|
||||
0x0000043c <+60>: xchg ax,ax
|
||||
@ -164,7 +164,21 @@ Dump of assembler code for function _start:
|
||||
End of assembler dump.
|
||||
```
|
||||
|
||||
#### 调用约定
|
||||
#### 函数调用约定
|
||||
函数调用约定是对函数调用时如何传递参数的一种约定。调用函数前要先把参数压入栈然后再传递给函数。
|
||||
|
||||
一个调用约定大概有如下的内容:
|
||||
- 函数参数的传递顺序和方式
|
||||
- 栈的维护方式
|
||||
- 名字修饰的策略
|
||||
|
||||
主要的函数调用约定如下,其中 cdecl 是 C 语言默认的调用约定:
|
||||
|
||||
调用约定 | 出栈方 | 参数传递 | 名字修饰
|
||||
--- | --- | --- | ---
|
||||
cdecl | 函数调用方 | 从右到左的顺序压参数入栈 | 下划线+函数名
|
||||
stdcall | 函数本身 | 从右到左的顺序压参数入栈 | 下划线+函数名+@+参数的字节数
|
||||
fastcall | 函数本身 | 都两个 DWORD(4 字节)类型或者占更少字节的参数被放入寄存器,其他剩下的参数按从右到左的顺序压入栈 | @+函数名+@+参数的字节数
|
||||
|
||||
|
||||
## 堆与内存管理
|
||||
|
Loading…
Reference in New Issue
Block a user