首页
社区
课程
招聘
[原创]CTF 2019 第一题 流浪者
发表于: 2019-3-10 18:25 2146

[原创]CTF 2019 第一题 流浪者

2019-3-10 18:25
2146
用x64dbg打开程序,查找字符串:

可以找到错误提示和正确提示字符串。
双击“错了”字符串,可以找到弹出错误提示的函数:

搜索命令:“call 0x004017B0”,找到调用的地方:

往上翻看,可以看到关键代码:

可见程序调用了一个函数来验证注册码。
分析算法可知,程序中有一个字符串常量s = "abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ",程序首先对输入的注册码进行处理,计算出一个相同长度的数组a,对i从0到len(a) - 1,所有s[a[i]]构成了一个新字符串,最后判断新字符串是否等于“KanXueCTF2019JustForhappy”。如果相等的话就弹出正确提示,否则就弹出错误提示。以上过程可用c语言描述:

但是此时还不清楚数组a是怎么来的,于是查找命令"call 0x004017F0",来到验证函数的调用处:

往上看,可以看到数组a的生成过程。

分析算法可知,程序先检测输入的字符是否是小写字母、大写字母或数字,如果不是则直接提示错误。对用户输入的每一个字符input[i],
     (1)若 input[i] 为小写字母,则a[i] = input[i] - 0x57;
     (2)若 input[i] 为大写字母, 则a[i] = input[i] - 0x1d;
     (3)若 input[i] 为数字,则a[i] = input[i] - 0x30.


知道了以上算法,我们便可从最终的" KanXueCTF2019JustForhappy "逆推出数组a的内容,然后进一步逆推出注册码。
计算注册码的c语言程序如下所示:
#include <stdio.h>
#include <string.h>

int main()
{
    char mask[] = "abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ";
    char dest[] = "KanXueCTF2019JustForhappy";

    for (int i = 0; i < 25; ++i)
    {
            for (int j = 0; j < strlen(mask); ++j)
            {
                if (mask[j] == dest[i])
                {
                    if (j <= 9)
                    {
                        printf("%c", j + '0');
                    }
                    else if (j >= 10 && j <= 35)
                    {
                        printf("%c", j + 0x57);
                    }
                    else
                    {
                        printf("%c", j + 0x1d);
                    }
                }
            }
        }
        printf("\n");

        return 0;
}
最终算出的注册码为:j0rXI4bTeustBiIGHeCF70DDM.

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//