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

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

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

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

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

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

*i的值先返回OD查看CC1325的返回值
通过记录得到2,3,5,7,11,…猜测是质数
然后回到IDA,查看CC1325函数没发现东西,看参数v9来自函数CC16E0
进入CC16E0函数
re学习笔记(65)BUUCTF - re - [GKCTF2020]Chellys identity_第24张图片
小于a2也就是小于128,然后进CC1672函数发现了质数的代码
re学习笔记(65)BUUCTF - re - [GKCTF2020]Chellys identity_第25张图片
re学习笔记(65)BUUCTF - re - [GKCTF2020]Chellys identity_第26张图片
所以加密函数内的逻辑就差不多为,
将比输入字符ASCII码小的质数加起来,然后与输入字符进行异或,得到一个int类型数组
re学习笔记(65)BUUCTF - re - [GKCTF2020]Chellys identity_第27张图片
然后去看判断是否成功的函数
re学习笔记(65)BUUCTF - re - [GKCTF2020]Chellys identity_第28张图片
这些函数都可以通过OD调试得到返回值,根据返回值可以判断是啥,,,
然后CC1325经过调试,每次的返回值就是v9数组

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

写脚本得到flag
re学习笔记(65)BUUCTF - re - [GKCTF2020]Chellys identity_第29张图片
re学习笔记(65)BUUCTF - re - [GKCTF2020]Chellys identity_第30张图片

#include 

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}
re学习笔记(65)BUUCTF - re - [GKCTF2020]Chellys identity_第31张图片

你可能感兴趣的:(ctf小白成长ing,#,reverse)