C printf原型解析

printf 函数原型解析

c 复制代码
int __cdecl printf(const char *format, ...);
  1. 返回值:int,代表成功输出的字符个数
  2. 调用约定 (x86):__cdecl,调用者负责堆栈平衡;x64 下 Windows 统一 ABI,__cdecl关键字失效
  3. 参数结构
    ○ 固定参数:const char *format 格式化字符串
    ○ 可变参数:...,必须放在末尾
  4. 工作原理 遍历 format 字符串,读到%时,读取后面的格式符(%d/%f/%s),依靠格式符来告诉 va_arg 该取什么类型的数据
    ⚠️重点:C 语言本身不会自动检测可变参数的数量与类型,完全靠格式化字符串,类型不匹配直接触发未定义行为

va_list 系列宏使用流程

c 复制代码
va_list args;           // 定义可变参数迭代指针
va_start(args, format); // 绑定到最后一个固定参数,args指向第一个可变参数
va_arg(args, type);     // 取出当前参数,指针自动向后偏移
va_end(args);           // 清理

内存布局区分

● x86(cdecl):参数从右向左全部压栈,所有可变参数都在栈上连续存放,va_arg本质就是指针 + 类型宽度偏移

● x64 Windows ABI:前 4 个参数优先放在rcx,rdx,r8,r9寄存器,剩余参数入栈;va_start 会处理寄存器里存放的参数,不再单纯只操作栈

坑:x64 下可变参数不是全部在栈上,逆向调试的时候容易踩坑

格式符对应 va_arg 取值

格式符 va_arg 取类型 说明
%d int 整型
%f double 注意:float 传可变参数会自动提升为 double,不能写 float
%s char* 字符串指针

两种可变参数设计方案对比

  1. 显式计数法
c 复制代码
int Sum(int count, ...);

第一个参数 count,直接写明后面一共有多少个参数;适合参数类型全部相同场景

示例:Sum(3,10,20,30),count=3 代表 3 个可变参数

  1. 特征匹配法(printf 采用) 靠格式化字符串format里面的%占位符,统计参数数量、识别参数类型;适合参数类型混杂场景

核心注意事项

  1. 类型严格匹配 格式符和真实参数类型不一致,会读取错误内存,程序崩溃或者乱输出
    比如%d读取 double,直接取 4 字节,解析结果完全错误
  2. 读取顺序 可变参数读取顺序和传入顺序一致;x86 虽然参数从右往左压栈,但是栈增长向下,遍历的时候依然从左到右取参数
  3. 缺参问题 格式化字符串写了 3 个%,但是只传 2 个实参 → va_arg 继续向后读取栈上随机内存,属于未定义行为(格式化字符串漏洞原理基础)
  4. 整型提升规则 可变参数中char、short会自动提升为int;float自动提升为double,va_arg不能用char/short/float

底层逆向视角

● x86:va_start就是获取栈上固定参数的地址,计算偏移找到第一个可变参数

va_arg = 指针 + sizeof (类型)

● x64:va_list不再是单纯指针,是一个结构体,内部保存寄存器中存放参数的备份地址 + 栈参数地址,所以 x64 的 va 系列宏实现比 x86 复杂很多

格式化字符串漏洞关联拓展(拓展)

printf 第一个参数可控,用户可以自己写入%p %x %n,就能读取栈上内存甚至写入内存,就是经典的格式化字符串漏洞,根源就是 printf 靠字符串解析参数,没有边界校验

相关推荐
Severus_black1 小时前
【C++初阶】list使用及相关实现,思路顺滑流畅!
c语言·数据结构·c++·stl·list
噢,我明白了2 小时前
JAVA中的一些基础应用知识点
java·开发语言
东姬AI3 小时前
挖出948个内核漏洞、自动写补丁:GPT-6 Cyber把AI推进“实战岗“,内容行业还卡在哪一关?
人工智能·网络安全·openai·gpt-6
时间的拾荒人3 小时前
Redis 入门详解:核心特性、重要文件与全局命令实战
开发语言·redis·面试
敲上瘾3 小时前
Qt Widgets入门:项目模板解析与Hello World
开发语言·数据库·c++·qt·ui·qt6.3
码途行者4 小时前
网站的SQL 注入:从攻击原理到防御措施
开发语言·sql·php
旖旎夜光4 小时前
【C++ 基础入门】C++ 多态(中):虚函数表、多态原理与动静绑定
开发语言·c++·笔记·学习
你看我名字5 小时前
产品参数昨天还对,今天已过期:数眼智能与大模型应用如何做资料版本校验
开发语言·架构
希和20275 小时前
C语言程序设计题|有序数组插入数字冒泡排序
c语言·数据结构·算法
老秦包你会5 小时前
计算机网络第二课 ----Socket(套接字)编程预备
开发语言·计算机网络·php