re学习笔记(65)BUUCTF - re - [GKCTF2020]Chellys identity

新手一枚,如有错误(不足)请指正,谢谢!!

题目链接:[GKCTF2020]Chelly’s identity

最近忙着看书,刷题断了好久了,,,

IDA载入,shift+F12搜索字符串
在这里插入图片描述
双击跟到函数去,来到关键函数
在这里插入图片描述
我这里的IDA修改了一下基址,因为我配合OD动态调试做的,为了让函数地址与OD地址一致。
与我函数名不一样的,需要改IDA基址
先查看OD基址
在这里插入图片描述
然后修改IDA的
在这里插入图片描述
修改成OD基址0xCB0000,然后点击【OK】
在这里插入图片描述
从OD中找到主函数的地址部分(搜索IDA显示的地址或者搜索字符串
在这里插入图片描述
cin是C++的输入
在这里插入图片描述
在这里插入图片描述
然后F8单步一下,程序恢复运行,随便输入点字符串
在这里插入图片描述
可以看到内存窗口已经有了输入
在这里插入图片描述
下一个内存访问断点,看看什么时候访问输入,然后F9运行等断点断下
在这里插入图片描述
程序被断下,选中的部分就是循环
在这里插入图片描述
回IDA找地址,发现是这里的循环
在这里插入图片描述
此时的代码,把eax,也就是输入字符串的,第一个byte位,也就是第一个字符的地址给了ecx。
在这里插入图片描述
之后ecx又给了栈上的一个内存,也就是前面IDA for循环图的v16
之后把这个值v16压入栈(push edx)然后进入了1502函数
在这里插入图片描述
执行完一个循环,发现1771函数是获取输入的长度(多次调试变换输入发现

而11D6函数是获取复制后字符串的长度
在这里插入图片描述
复制的字符串存在哪呢,去看IDA
在这里插入图片描述
由于函数点进去再出来它的变量名就变了,,注释部分没有改,v32就是原来的v16
复制后的字符串应该存到了v34,去看v34的定义在ebp+0x48处,去OD找这个地址(不知道为啥计算出来是D98,是上一个,,但也差不了多少啦)
可以看到他把输入的字符的ASCII码按int类型存储到新的一块内存地址,也就是上图IDA中的v34
在这里插入图片描述
然后这个for循环就分析完毕了
CC1771函数获取输入的长度赋值给v13
然后CC1D6获取该复制的内存地址的长度,比较这两个长度,当相等的时候也就复制完毕了
然后CC1528获取每一个字符的地址,给v32
CC15D2函数将v32复制给v34指向的内存地址
在这里插入图片描述
然后就是下面的CC11BD函数,他将v34传了进去
在这里插入图片描述
双击进去,可以猜到是判断长度是否等于16(猜不到可以用OD多调试几遍,查看一下sub_CC11D6的返回值(emmm,写到这才发现这个函数上面也出现过,做题的时候真没发现)
在这里插入图片描述
知道CC11BD函数判断长度后,看一下sub_CC1721函数
在这里插入图片描述
IDA双击进去,用OD调试一下,获取一下CC1456的返回值也就是v8的值是新复制内存的地址,而CC1375的返回值V7是新复制内存结尾的地址。
然后while循环用首地址V8进行运算,每次给首地址V8+1,直到他等于尾地址V7 。程序知道数组循环完了就退出了。
在这里插入图片描述
具体的运算就是*v8异或了v6,而v6是由for循环累加得到的。
for循环的条件就是*i小于*v8,也就是让*i小于输入字符的ASCII码值

*i的值先返回OD查看CC1325的返回值
通过记录得到2,3,5,7,11,…猜测是质数
然后回到IDA,查看CC1325函数没发现东西,看参数v9来自函数CC16E0
进入CC16E0函数
在这里插入图片描述
小于a2也就是小于128,然后进CC1672函数发现了质数的代码
在这里插入图片描述
在这里插入图片描述
所以加密函数内的逻辑就差不多为,
将比输入字符ASCII码小的质数加起来,然后与输入字符进行异或,得到一个int类型数组
在这里插入图片描述
然后去看判断是否成功的函数
在这里插入图片描述
这些函数都可以通过OD调试得到返回值,根据返回值可以判断是啥,,,
然后CC1325经过调试,每次的返回值就是v9数组

可以得到判断函数就是判断,加密后的数组是否等于v9数组

写脚本得到flag
在这里插入图片描述
在这里插入图片描述

#include <iostream>

using namespace std;

int zhishu(int num)
{
    for (int i = 2; i < num; i++)
    {
        if (!(num % i))
            return 0;
    }
    return 1;
}
int jm(int num)
{
    int sum = 0;
    for (int i = 2; i < num; i++)
        if (zhishu(i))
            sum += i;
    return sum ^ num;
}

int main()
{
    const int data[16] = { 438,1176,1089,377,377,1600,924,377,1610,924,637,639,376,566,836,830 };
    string flag = "";
    for (int i = 0; i < 16; i++)
    {
        for (int j = 0; j < 128; j++)
            if (jm(j) == data[i])
                flag += (char)j;
    }
    cout << "flag{" << flag << "}" << endl;
}

得到最终flag为flag{Che11y_1s_EG0IST}
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Forgo7ten

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值