PWN-C语言函数分析
printf函数分析
printf简单实现
-
第一个参数必须的,是一个”格式字符串“的作用,作用:说明后续的其他参数该怎么解析
-
格式化字符串标志的前导字符是**%,%后面的字母序列**用来说明后续参数格式
-
格式化字符串之后的参数,都是按64位8字节、32位4字节对齐。如果不对齐就没办法解析出来那个字符的类型
- 要不然printf()没办法知道主调函数(caller)怎么传参的
-
在printf内部,需要调用write()函数,还有vsnprintf()函数
v
表示可变参数,s
表示字符串,n
表示记录了最大长度的printf -
真正的实现可变参数的是以vs开头一堆函数,
v
表示可变参数,s
表示字符串 -
printf()实现的时候,调用vsnprintf()把参数序列化到一个字符缓冲区
-
调用write()系统调用,把处理之后的字符序列,打印到“标准输出stdout”
-
Linux上标准输入输出都是一个文件
1 | 例如:在32位机中,使用%c打印一个字符a,这个字符a也是占用32位的 |
1 | int scf_printf(const char*fmt,...) |
vsnprintf函数解析
- 在调用printf()函数的时候,里面会调用vsnprintf()函数
1 | int scfvsnprintf(char *buf, int size, const char* fmt,va_list* ap) |
ulong2a函数解析
1 | int scf_ulong2a(char *buf, int *pn, int size, uint64_t num) |
long2a函数解析
1 | int scf_long2a(char* buf, int* pn, int size, int64_t num) |
hex2a函数解析
1 | int scf_hex2a(char* buf, int* pn, int size, uint64_t num) |
hex2a_prefix函数解析
1 | int scf_hex2a_prefix(char* buf, int* pn, int size, uint64_t num) |
p2a函数解析
1 | int scf_p2a(cahr* buf,int* pn, int size, const char* str) |
str2a函数解析
1 | int scf_str2a(char* buf, int* pn, int size, const char* str) |
double2a函数解析
1 | int scf_double2a(char* buf, int* pn, int size, double num) |
printf在glibc的源码
-
以glibc版本2.31为例
-
printf
1 | /* Copyright (C) 1991-2020 Free Software Foundation, Inc. |
- fprintf
1 | /* Copyright (C) 1991-2020 Free Software Foundation, Inc. |
malloc函数分析
- malloc是C语言中堆内存的一个库函数
- 程序运行的进程结构如下图排序
- 低地址端是代码段和数据段
- 数据段的后面就是堆段
- 在高地址这边最顶上是进程的栈空间
- 在进程的栈空间与堆空间这边有一块空闲区域,可以使栈往下增长,也可以使堆往上增长
- 对于进程来说,进程这个数据段的末尾,在Linux系统上有一个特别的标记叫:brk。等到程序需要分配堆空间的时候,brk就会往高地址的地方移动。
- 在操作系统使用brk函数进行系统调用的时候,分配的堆内存空间只能是连续的。当使用brk函数申请的堆内存被释放后,brk就会往低地址的地方移动,相当于brk是一个指针,指向堆顶。也就是在使用brk函数申请堆内存的时候,只能线性的增长或者线性的回收。
- malloc负责的就是堆内存的管理,使用malloc来分配堆内存,然后使用free来释放堆内存
malloc简单实现
- 前提说明:这里的数据类型,例如uint8_t等都是基本数据类型的别称
1 | typedef signed char int8_t; |
1 | // 系统调用 brk()/sbrk() |
malloc在glibc的源码
__libc_malloc
__libc_malloc
只是用来简单封装_int_malloc
函数。_int_malloc
才是申请内存块的核心。- 调用该函数时,首先检查是否有钩子函数
__malloc_hook
,用于用户自定义的堆分配函数。 - 用户申请的字节一旦进入申请内存函数中就变成了无符号整数
1 | // wapper for int_malloc |
__int_malloc
sysmalloc
calloc函数分析
calloc函数简单实现
1 | uint8_t* scf__calloc(uintptr_t n, uintptr_t size) |
realloc函数分析
realloc函数简单实现
1 | uint8_t* scf__realloc(uint8_t* p,uintptr_t size) |
free函数
free函数简单实现
1 | //free()很麻烦,很容易出错,所有的“回退”都很麻烦 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 iyheart的博客!
评论