一道Crypto题

【题源】北京理工大学计算机学院创新创业基地2018年2017级暑假集训选拔赛

【问题背景】
CTF比赛中文一般译作夺旗赛,在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式。其大致流程是,参赛团队之间通过进行攻防对抗、程序分析等形式,率先从主办方给出的比赛环境中得到一串具有一定格式的字符串或其他内容,并将其提交给主办方,从而夺得分数。为了方便称呼,我们把这样的内容称之为“Flag”。

【问题描述】
Crypto是CTF比赛中常见的一种题型,其问题大多与加密有关。这一天Alice就遇到了一道简单的Crypto题目,题目给出了对字符串的一个加密算法和密文,要求你破解这个加密算法,并解密出Flag。该加密算法是这样的:首先读入明文字符串,随后使用下方代码中的unpack函数把明文字符串编码为长度为w的数字序列datas,随后使用encode函数对datas数组进行了加密。encode函数的参数n为数字序列的长度,iv是将给定的参数。

int unpack(char * str, unsigned int * datas) {
    int len = strlen(str), w = len / 4;
    if (len % 4 != 0) w++;
    for (int i = 0; i < w; i++) {
        datas[i] = 0;
        for (int j = 0; j < 4; j++) {
            datas[i] <<= 8;
            datas[i] += (i * 4 + j < len) ? str[i * 4 + j] : 0;
        }
    }
    return w;
}

unsigned int crypto(unsigned int x) {
    return x ^ (x >> 16);
}

void encode(unsigned int * datas, unsigned int iv, int n) {
    datas[0] = crypto(datas[0] ^ iv);
    for (int i = 1; i < n; i++)
        datas[i] = crypto(datas[i] ^ datas[i - 1]);
}

现在给出加密后的密文数字序列,请编写解密算法解密出明文字符串。保证加密前的明文字符串仅包含数字、大小写英文字母、下划线和左右花括号(“{”和“}”)。

【输入描述】
本题有多组测试用例,用例之间用空行隔开,处理到文件末为止。
对每组用例,第一行两个整数为n(n<=10^5)和iv(0<iv<2^32-1),iv代表数字序列的长度和加密参数;第二行为n个整数,代表密文数字序列。保证数字序列中每一个数字均在32位无符号整数范围内。保证输入文件中所有数字串长度之和不超过6^10。
【输出描述】
对每组测试用例输出一行一个字符串,为解密后的明文字符串。

【示例输入】
4 666666
1667575340 186401886 1816346995 172182320
5 1120170000
76035551 2146073409 1251569323 536091756 1837724133

【示例输出】
coachyang_inf
FLAG{b1t5s_sUmm3r}

【解题思路】

首先分析题目给定的三个函数。

unpack()是将字符串转化成unsign int矩阵,实际上保存的是ASCII码。

encode()和crypto()则是利用异或运算进行加密计算。

不难注意到异或运算和crypto()的可逆性,即加密和解密可通过相同的运算来实现。再注意一下矩阵每一行解密的顺序,即可完成这道题。

具体细节以后再补充。

【代码】

在题目给定三个函数的基础上编程

unsigned int * uncode(unsigned int *datas, int n, int iv) {
    unsigned int *solve = new unsigned int[n];
    for (int i = n - 1; i > 0; i--) {
        solve[i] = crypto(datas[i]);
        solve[i] ^= datas[i - 1];
    }
    solve[0] = crypto(datas[0]);
    solve[0] ^= iv;
    return solve;
}

char* pack(unsigned int *codeArr, int n) {
    char *flag = new char[4 * n];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 4; j++) {
            flag[i * 4 + j] = (codeArr[i] >> (8 * (3 - j))) & 127;
        }
    }
    return flag;
}

int main() {
    int n;
    int iv;
    unsigned int *cryptograph;
    while (cin >> n) {
        cin >> iv;
        cryptograph = new unsigned int[n];
        for (int i = 0; i < n; i++) {
            cin >> cryptograph[i];
        }
        unsigned int *code = uncode(cryptograph, n, iv);
        char *flag = pack(code, n);
        cout << flag << endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/null-0/p/9277839.html

时间: 2024-08-30 18:31:29

一道Crypto题的相关文章

每天一道Java题[11]

题目 synchronized怎么实现线程同步?请修改<每天一道Java题[10]>中的MyRunnableThread类以解决三个线程都获取到10的问题. 解答 方法一: 采用synchronized关键字包裹需要保证线程安全的代码块,来实现线程同步.语法格式为: Synchronized(expression){ //需同步的代码 } <每天一道Java题[10]>中的MyRunnableThread类修改为: package me.huangzijian; public cl

每天一道Java题[3]

问题 为什么在重写equals()方法的同时,必须重写hashCode()方法? 解答 在<每天一道Java题[2]>中,已经对hashCode()能否判断两个对象是否相等做出了解释.equals()方法与hashCode()方法的关系如下: 如果两个对象的hashCode()返回值不一样,则equals()返回的结果必为false. 如果两个对象的hashCode()返回值一样的时候,equals()返回的结果未知. 如果两个对象的equals()返回的结果为true,则两个对象的hashC

一天一道算法题---6.26---二分查找

感谢微信平台---一天一道算法题----每天多一点进步-- 好累啊  现在在用win7自带的输入法 打起来真麻烦 快点把这2天的搞完就重装了 还是直接来源于----〉 待字闺中 分析 给定一个数组A,其中有一个位置被称为Magic Index,含义是:如果i是Magic Index,则A[i] = i.假设A中的元素递增有序.且不重复,请给出方法,找到这个Magic Index.更进一步,当A中允许有重复的元素,该怎么办呢? 没有重复元素的情况 一些同学在遇到这个题目的时候,往往会觉得比较简单.

一天一道算法题--6.25--无定义

感谢微信平台---一天一道算法题--每天多一点进步---- 其实今天我接下去补上的几题都来自---待字闺中 所以我就原封不动的将它的题目与分析搬过来了 原题 给定一个数组,我们可以找到两个不相交的.并且是连续的子数组A和B,A中的数字和为sum(A), B中的元素和为sum(B).找到这样的A和B,满足sum(A) - sum(B)的绝对值是最大的. 例如:[2, -1 -2, 1, -4, 2, 8]划分为A=[-1, -2, 1, -4], B=[2, 8], 最大的值为16 分析 如果没有

一天一道算法题---6.27---二分图

感谢微信平台---一天一道算法题---每天多一点进步--- Ah... last... 也很晚了 快2点半了 C罗也告别这届世界杯了  主要还是输给德国太多球了 美国也没赢 唉 还是来源于----> 待字闺中 原题 大家都知道facebook用户都是双向的好友,a是b的好友,那么b一定是a的好友,现在给定一个用户列表,其中有些用户是好友,有些不是,请判断,这些用户是否可以划分为两组,并且每组内的用户,互相都不是好友.如果能,请给出这个划分. 例子1: 用户:{1, 2, 3} 好友关系:1-2,

前端面试的一道算法题

(使用canvas解答) 下面说一个跟前端有点相关并且有点趣的一道算法题. 题目: 平面上有若干个不特定的形状,如下图所示.请写程序求出物体的个数,以及每个不同物体的面积. 分析 想要知道有多少个图形,想到的就是先获取图片中的每一个像素点然后判获取像素点的背景颜色(RGBA).想要获得图片中的每一个像素点,那就可以联想到使用h5的canvas.如下: 菜鸟教程中canvas的getimagedata方法http://www.runoob.com/tags/canvas-getimagedata.

一天一道算法题--6.19--二分搜索

感谢微信平台---一天一道算法题---每天多一点进步 这是昨天的 只贴下题目 == 再把今天的也是一样处理了   这2天 不想写 可能晚上会有改变吧.. problem: 给定一个最多包含40亿个随机排列的32位 二进制的无符号整数 找出不在文件中的数.显然 由于 2^32=4294967196大于4亿 所以缺少的数不止一个 现限制只能使用几个外部的临时文件和仅几百个字节的内存. ****************************** 过了明天 就没事了 =-= 一天一道算法题--6.19

一道推理题

题目:http://115.28.76.232/problem?pid=1115 题意:初始给定两个完美数1和3,如果都是完美数,那么也是完美数.现在给定一个数,判断 它是否是完美数. 分析:嗯,这道题Mayuyu有两种方法,第一种方法是按照题意有,那么我们进行递归直接判 断.这样做的时间复杂度很高,通过打表对一些数的观察发现,只需要看这个数是否只由3和5组成. 打表代码: #include <iostream> #include <string.h> #include <s

一天一道算法题--6.13---计算几何

感谢微信平台---一天一道算法题---每天多一点进步 本来 想在世界杯之前 可以 开开心心地A了今天的算法题  .... 竟然是计算几何 我高数 那么渣....... 这题 先放着吧..... 哎.... 链接 还是一样先放出来 . touch me 平常这个点 再过会 就应该要碎觉了 今天 = 个揭幕战 累死我的节奏,,, 现在去做点什么呢........... 一天一道算法题--6.13---计算几何,布布扣,bubuko.com