(已弃坑,请看i春秋月刊 Linux pwn入门,地址见文章)鬼哥手把手带你入门栈溢出(0):了解基本原理

由于本人水平较有限,并且发现了一个很好的教程,故弃坑。

i春秋月刊的Linux pwn 入门 -》  https://bbs.ichunqiu.com/thread-47090-1-1.html

目录

基础知识准备

汇编基础

C语言

gdb-peda调试

-------------------------正文从这里开始-------------------------

了解函数的栈帧布局、调用及返回过程

编码

调试(可跳过看总结,建议自行调试加深理解)

总结

栈溢出原理


基础知识准备

 

汇编基础

首先要对汇编有一定基础,下面的,尤其加粗部分必须懂(其他的遇到了,现学也行)

常用指令:mov  lea  push  pop 

add  sub  inc  dec   and  or  not  xor 

call   ret  jmp  cmp  jz ... 

寄存器(eax  ebx  ecx  edx  esp  ebp  eip  eflags  cs  ds  ... )

C语言

不说了,遇到不懂的函数现查就行 

gdb-peda调试

最简单的调试要会

break(b)

run(r) 

continue(c) 

next(n) 

ni :下一句汇编

step(s) :单步步入

si:汇编单步步入(可以看到函数中push ebp mov ebp,esp  add esp xxh)

stack:看栈用,比如 stack 20

x/<n/f/u> <addr> :按照格式查看指定的内存地址

 

-------------------------正文从这里开始-------------------------

 

了解函数的栈帧布局、调用及返回过程

环境:ubuntu16.04(64位)

调试工具:gdb-peda

编码

写一个测试程序(stack_frame.c),代码如下:

#include <stdio.h>

int add(int a,int b){
    int result = 0;
    result = a+b;
    return result;
}

int main(int argc,char *argv[])
{
    int a = 0x41;
    int b = 0x42;
    int tmp = 0;
    
    tmp = add(a,b);
    printf("result = %d\n",tmp);
    
    return 0;
}

编译:

gcc -g -o stack_frame stack_frame.c #带有调试信息

调试(可跳过看总结,建议自行调试加深理解)

gdb stack_frame

b main

r

main函数局部变量初始化

 

三条指令很明显是在给main函数局部变量初始化,注意观察变量在栈中的位置(与ebp和esp相对位置)

查看更多指令:

x/16i $eip 

继续调试,观察参数压入栈中的顺序和位置

步入call add,并查看保存原ebp,调整ebp和esp的过程:

si
ni

继续执行直到leave,可以看到

此时,add函数栈的结构如下:

执行leave指令后(相当于mov esp,ebp    pop ebp 这两条),栈顶为返回地址,ebp恢复为main栈帧的ebp

再执行ret指令(相当于pop eip),返回到main的下一条执行。

 

总结

int add(int a,int b)的函数调用和返回流程(对于采用cdecl调用方式的函数而言) 

1.在main函数中

(1)从右往左压入参数:

 push b     

push a

(2)将返回地址入栈并转向add:

call add

此时栈帧如下

2.在add函数中

(1)保存main栈帧的ebp:

push ebp

(2)在main栈帧的上面建立add的栈帧:

mov ebp,esp

sub esp,0x10 ; 开辟一段空间,大于等于局部变量占用的内存,具体大小由编译器决定

(3)执行函数语句

此时栈帧如下

(4)销毁栈帧:

leave (mov esp,ebp   pop ebp)

(5)返回:

ret (相当于pop eip,这一步会将返回地址从栈里取出)

3.回到main函数中

(1)进行堆栈平衡(恢复main栈帧中 原esp值):

add esp,0x10

(2)继续执行

 

栈溢出原理

如果局部变量中有字符数组,输入时不检查越界,那么写入足够数量的字符便可修改函数返回地址

在当前函数执行ret指令的时候,便能控制eip的指向,控制程序执行的流程

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值