一道“简单”的二进制题目
Last updated:May.03, 2018 CST 19:03:10
这道题本来想当作面试题给出,但认真考虑了一下,还是算了,怕被找上门真人快打……找好的懂底层的开发真难啊。
题目
请指出下列代码是否存在问题。如有,请指明错误,并预测程序运行输出,并说明原因。
// gcc test.c -o test -g && ./test
#include <stdio.h>
int main(void){
unsigned int i = 0x12345678;
float j = 0x9abcdef0;
printf("%dt%ft", j, i);
printf("%dt%fn", i, j);
printf("%pt%xt", j, i);
printf("%pt%xn", i, j);
}
答案
这道题的来源是最近同事调试exp中遇到的小问题,主要涉及到了:
- 调用约定
printf
原理- 浮点数存储
首先说下正确的答案:
存在错误,在第三次和第四次时传入参数类型和格式化字符串不符。打印输出的第一行可能是:
305419896 2596069120.000000 305419896 2596069120.000000
第二行中第一个、第三个输出数字为0x12345678,第二个和第四个不可预测。
分析
一般来说比较容易从源代码发现的问题是:
- 第三行、第四行的格式化字符串中,参数给定错误。
- 声明的变量j由于浮点数自身问题,会丢失精度,变成
0x9abcdf00
,也就是2596069120.000000
。这里涉及到的就是浮点数存储问题,不再赘述。
但观察输出,又有了几个新问题,分别是:
- 第一次、第二次与第三次、第四次调用
printf
时,参数顺序有了变化,但为何没有体现在输出结果中 - 第三次、第四次调用
printf
时,输出为何是不可预测的
printf
的特殊之处在于,他是一个变参函数。变参函数的传参方式,在System V AMD64 ABI(Page 20)中有如下描述:
- 整数类型按照
rdi->rsi->rdx->rcx->r8->r9
的顺序 - 浮点数类型按照
xmm0->xmm1->...->xmm6->xmm7
的顺序,部分类型只占用半个寄存器的,可以将寄存器拆成两半使用 - 其他参数和复杂类型(如直接传结构体)从栈走
而在printf->vfprintf
内部的代码中,处理这些变参的方法如下:
LABEL (form_integer):
/* Signed decimal integer. */
base = 10;
if (is_longlong)
{
long long int signed_number;
if (fspec == NULL)
signed_number = va_arg (ap, long long int);
else
signed_number = args_value[fspec->data_arg].pa_long_long_int;
//...
LABEL (form_float):
{
/* Floating-point number. This is handled by printf_fp.c. */
//...
if (is_long_double)
the_arg.pa_long_double = va_arg (ap, long double);
else
the_arg.pa_double = va_arg (ap, double);
ptr = (const void *) &the_arg;
而va_arg
总是按照这个宏里指定的类型提取参数。
说到这,上面两个问题的答案都明确了:
- 前两次调用
printf
时,%d
和%f
分别从rdi
和xmm0
中取参数,使用的索引是两套体系,因此无论传入参数顺序如何变化,都不影响取值顺序。 - 后两次调用
prinf
时,需要从rdi
和rsi
中取值,rdi
为之前设定的值,但rsi
没有被特定赋值过,因此无法确定这个值。
尝试更改编译参数加入-Wall
,会发现出现了编译警告。此外,类似的问题在ARM64等其他平台下仍然存在,可以自行检索查询。
FROM :blog.iret.xyz | Author:blog.iret.xyz
/01 痕迹清除简介在渗透测试过程中,Windows日志往往会记录系统上的敏感操作,如添加用户,远程登录,执行命令等。攻击者 通常会对Windows日志进行清除和绕过。 /02 Windows痕迹清除如何查看: 事件查看器->Windows日志 Win …
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论