print占位符重写初探

# PREFACE: BRICS 题目都太高手了,只有这个 shellcode 是也许能做的,可惜没有 ios 设备,动调不了的话并没有把握出这个题

# shellcode

main 里面只有这个,如果不调会以为它真的输出一个环境作为版本号?

image-20230927081520710

实际上,其他全在 init_array 里面

image-20230927081242134

随便搜搜可以找到这个:

image-20230927081346303

也就是说,main 里面会触发这个:

image-20230927081803593

image-20230927081816418

至此,信息就比较清晰了:

main 调用 f 占位符重写的函数,在这里会先 scanf 一个任意字符串,和一个操作数

接着触发 print,可以在上面的任意字符串中构造占位符,将需要的 flag 读入,具体的读入需求可以找到;

image-20230927082133233

这个 check 函数,并且它的占位符是 R:

image-20230927082216693

也就是每轮的这个位置会 check 一次

即我们需要调用一个占位符重写函数把 flag 先写到 bss 段里面,翻找以后只有这个,对于的占位符是 p

image-20230927082259489

image-20230927082322860

那么可以猜测,我们需要对应 flag 的位数传入 %p ,再输入 flag 存到它的模拟栈上

根据这些占位符,可以大概找一下流程:

image-20230927082606541

即:

image-20230927082617079

大概逻辑是:

n
x ** 2 - y ** 3 - num1 = num2

然后爆破求解就行

本来或许以为到这里就快出了?

那么为啥讨厌 ios 呢,调不起来,然后仔细一看发现

image-20230927082853386

这里十个占位符只有三个注册的有参函数却传入了七个值…

那既然不能动调去直接看,那先自己写个程序测测呗,反正结束了慢慢学

p
#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

看起来后面几个参数理论上用不到,但是感觉很不合理,遂不想做了

不过这个玩意在藏东西上其实有点意思,可以来出个小题玩一下,刚好又差不多准备搞个出虚拟机的玩,那就试试

# 9-29: 不对,想了想应该还是 ida 抽风,估计看看汇编调用的话这些参数问题不大
# 不过出题已经放在 list 上了,先把题出了看看,再看有没有时间把这个题给做了,最近确实会比较忙