print占位符重写初探
# PREFACE: BRICS 题目都太高手了,只有这个 shellcode 是也许能做的,可惜没有 ios 设备,动调不了的话并没有把握出这个题
# shellcode
main 里面只有这个,如果不调会以为它真的输出一个环境作为版本号?
实际上,其他全在 init_array 里面
随便搜搜可以找到这个:
也就是说,main 里面会触发这个:
至此,信息就比较清晰了:
main 调用 f
占位符重写的函数,在这里会先 scanf
一个任意字符串,和一个操作数
接着触发 print,可以在上面的任意字符串中构造占位符,将需要的 flag 读入,具体的读入需求可以找到;
这个 check 函数,并且它的占位符是 R:
也就是每轮的这个位置会 check 一次
即我们需要调用一个占位符重写函数把 flag 先写到 bss 段里面,翻找以后只有这个,对于的占位符是 p
那么可以猜测,我们需要对应 flag 的位数传入 %p
,再输入 flag 存到它的模拟栈上
根据这些占位符,可以大概找一下流程:
即:
大概逻辑是:
x ** 2 - y ** 3 - num1 = num2 |
然后爆破求解就行
本来或许以为到这里就快出了?
那么为啥讨厌 ios 呢,调不起来,然后仔细一看发现
这里十个占位符只有三个注册的有参函数却传入了七个值…
那既然不能动调去直接看,那先自己写个程序测测呗,反正结束了慢慢学
#include <stdio.h> | |
#include <printf.h> | |
#include <string.h> | |
int dollar_handler(FILE *stream, const struct printf_info *info, const void *const *args) { | |
char buffer[256]; | |
int len; | |
int value = *(const int *)(args[0]); | |
len = snprintf(buffer, sizeof(buffer), "$%d", value); | |
return fprintf(stream, "here is %s", buffer); | |
} | |
static int arginfo_1(const struct printf_info *info, size_t n, int *argtypes) { | |
if (n > 0) { | |
argtypes[0] = PA_INT; | |
} | |
return 1; | |
} | |
printf("%$\n", 12345, 12346); | |
# here is $12345 |
看起来后面几个参数理论上用不到,但是感觉很不合理,遂不想做了
不过这个玩意在藏东西上其实有点意思,可以来出个小题玩一下,刚好又差不多准备搞个出虚拟机的玩,那就试试