[Zer0pts2020]easy strcmp

在这里插入图片描述

是elf格式的64位程序,无壳
在这里插入图片描述

int64指的是64位有符号整型

fastcall是一种函数调用规定

按理来说main函数的写法上是只能有2个参数的,不知道为什么这里有3个

初看main函数的逻辑是输入的第一个参数和"zer0pts{CENSORED}"一样就成功了

所以直接把"zer0pts{CENSORED}"提交,错了。
在这里插入图片描述
看一下这些函数,名字格式是sub_xxx的函数时ida没能识别的函数,后面的数字是函数的起始地址
在这里插入图片描述
在这里插入图片描述
这里可以看到,init函数在main函数之前调用了,进去看看init函数干了什么
在这里插入图片描述
signed指的是有符号数,不写的情况下默认是signed。
db指的是1个字节,dw:2, dd:4, dq:8。
offset指的是偏移量
在这里插入图片描述
按道理来讲,&off_200DF0的值应该是这个变量的地址,也就是上图中的0x200DF0
所以v4>0。
在这里插入图片描述
这里前面是把(&funcs_889 + i)解引用,解引用之后是一个函数地址,然后再把这个函数地址强制类型转化成函数,后面跟的(a1, a2, a3)是这个函数的参数。
因为这里for循环给的条件是i != v4,所以for循环里面不会调用sub_6A0,只会调用6E0和795这两个函数,6E0函数里面啥也没有,现在进到795里面去看一下。
在这里插入图片描述
可以看到,它把off_201028的值设为了sub_6EA函数的地址,我们来看看off_201028里面存的原本是什么东西。
在这里插入图片描述
可以看到off_201028是函数表中的数据,原本存的是strcmp函数的地址,这么说来,main函数中,每次调用strcmp函数的时候,实际上调用的其实是sub_6EA函数,接下来好好看看sub_6EA中的内容。
在这里插入图片描述
首先i获取了输入的flag字符串的长度,然后把字符串的每8个字节作为一个整体,减去qword_201060数组中对应的8个字节,最后再执行qword_201090函数,返回结果,qword_201090的值在795函数中被赋值成了&strcmp,所以在减完之后的字符串要与"zer0pts{CENSORED}"相等,于是可以写这样一个脚本

#include <iostream>
using namespace std;

int main()
{
    char p[] = "zer0pts{********CENSORED********}";
    uint64_t k[5] = {0, 0x410A4335494A0942, 0x0B0EF2F50BE619F0, 0x4F0A3A064A35282B, 0};
    for (int i = 0; i < 4; i++)
    {
        *(uint64_t *)&(p[i * 8]) += k[i];
    }
    cout << p;
    return 0;
}


//flag{l3ts_m4k3_4_DETOUR_t0d4y}

得到flag

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值