更多linux内核视频教程文档资料免费领取后台私信【内核】自行获取.
Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂
// stack.c
int add_func(int a, int b)
{
int c, d;
c = a;
d = b;
return c + d;
}
int mAIn(int argc, char *argv[])
{
int total;
total = add_func(1, 2);
return 0;
}
add_func:
pushl %ebp // 保存ebp寄存器到栈
movl %esp, %ebp // 把ebp进程设置为esp的值
subl $16, %esp // 为局部变量申请空间
movl 8(%ebp), %eax // 把参数a保存到eax寄存器中
movl %eax, -8(%ebp) // 把eax寄存器的值保存到局部变量c中(c = a)
movl 12(%ebp), %eax // 把参数b保存到eax寄存器中
movl %eax, -4(%ebp) // 把eax寄存器到值保存到局部变量d中(d = b)
movl -8(%ebp), %edx // 把d的值保存到edx寄存器中
movl -4(%ebp), %eax // 把c的值保存到eax寄存器中
addl %edx, %eax // 将eax寄存器与edx寄存器的值相加,保存到eax中(返回值)
leave
ret // 函数返回
...
movl %ebp, %esp
popl %ebp
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#define PTR_SIZE 8 // 指针的大小
#define EBP_SIZE 8 // ebp寄存器的大小
void inject_callback()
{
printf("inject_callback called...n");
exit(0);
}
void func_call(char *addr, int len)
{
char tmpBuf[16] = {0xff};
memcpy(tmpBuf + 16 + EBP_SIZE, addr, len);
printf("func_call called...n");
}
int main(int argc, char** argv)
{
uint64_t injectPtr = (uint64_t)&inject_callback;
func_call(&injectPtr, PTR_SIZE);
printf("main exited...n");
return 0;
}
$ gcc stack-overflow.c -fno-stack-protector -o stack-overflow
$ ./stack-overflow
func_call called...
inject_callback called...
在编译上面程序时,一定要加上 -fno-stack-protector 参数,否则将会触发栈溢出保护,导致执行失败。