1.x86和amd64传递参数的不同方式
x86
* 使用栈来传递参数 *使用eax存放返回值 *参数倒数压入栈
amd64
*前六个参数依次存放于rdi、rsi、rdx、rcx、r8、r9寄存器中 *第七个以后的参数存放于栈中(于x86的存放规则相同)
2.canary保护
C语言中存在readfsqword(),对应为在栈上放置一个canary。
汇编实现对应为mov rax,fs:28H
mov [rsp+128h+var_20],rax
3.context.log_level = "debug"
功能打开脚本的调试模式;
4.堆管理器是存在与动态链接库里的一段代码,这段代码就是用来管理堆这段区域。
在用户和操作系统之间,作为动态内存管理之间的中间人。
5.申请内存的系统调用
brk(主线程),mmap(子线程或者需要内存空间过大的子线程)
6.利用mprotect函数修改权限
mprotect函数用于设置一块内存的保护权限(将从start开始、长度为len的内存的保护属性修改为prot指定的值),函数原型:
int mportect(void *addr,size_t len,int port);
addr 内存修改的开始地址;len修改的内存的长度,
port 的取值如下,可以通过值相加将这几个属性结合使用:
*可写,值为1
*可读,值为2
*可执行,值为4
*不允许访问,值为0
在一道题中大佬们使用这个函数的作用,做出了题目,记录一下这个函数。
7.open("/dev/urandom", 0); 新的产生随机数的函数
int fd = open("/dev/urandom", O_RDONLY)
产生随机数
8.sprintf 字符串格式化函数
功能:把格式化的数据写入某个字符串中
int sprintf(char *string,char *format,[argument,..])
参数列表
string --这是指向字符数组的指针,该数组存储了C字符串
format --在格式串内部使用一些以“%”开头的格式说明符(format specifications)来占据一个位置,在后边的变参列表中提供相应的变量,最终函数就会用相应位置的变量来替代那个说明符,产生一个调用者想要的字符串。
1>把整数123 打印成一个字符串保存在s 中。
sprintf(s, "%d", 123); //产生"123"
2>可以指定宽度,不足的左边补空格:
sprintf(s, "%8d%8d", 123, 4567); //产生:" 123 4567"
3>当然也可以左对齐:
sprintf(s, "%-8d%8d", 123, 4567); //产生:"123 4567"
函数解释原文链接:https://blog.csdn.net/u013485792/article/details/50475473
9.\xhh 转义字符的意思是转换成与hh的十六进制相等的ascll码值的字符
10.canary,4(fs)或8()gs字节存在于栈上
11.如何绕过canary?(格式化字符串绕过canary)
核心思想是泄露canary的值
12.在编译C语言程序时,如何开关各种保护措施
gcc编译命令中,-m32是编译32位的程序;-fno-stack-protector 指得是不生成canary;gcc -v 查看PIE的默认配置,如果是--enable-default-pie 则是默认开启,要去掉需要添加参数 -no-pie
13.格式化字符串中%p,和%s
%p 用地址的格式打印参数的值
%s 将参数的值当作地址,打印地址中的数据
14.memset函数
作用:在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快的方法。这条语句把a中所有字节换做字符"0",常用来对指针或字符串的初始化。
void *memset(void *s, int ch, size_t n);
函数解释:将s中前n个字节 (typedef unsigned int size_t)用 ch 替换并返回 s将ch设置为0