[2018看雪] - 第七题 - 有限域数学变换(2)

既然是个逆向题,就一定有逆向的做法

学习链接:https://bbs.pediy.com/thread-229327.htm

把题目中的运算理解成代数运算中的双射:

正向时:已知(a,b,c)可求d,那么逆向是已知d的,a,b,c三个数可以“知二求一”

也即,a、b、c、d四个数知三求一

于是,构造CM的逆运算成为了可能,倒过来算20步可以把Input运算出来(再正向检验)

逆向思路:

我们要从数列的第Xn项,逆向算到数列的第1项,本质上是一个重复的不断爆破密钥a,b,c的过程

由于a,b,c满足题意中的某种数学关系,导致暴力枚举成为了可能(64 * 64 *64,且满足出现频率的关系)

深度固定的while循环爆破

所以,如果全部爆破,每个数有64种选择,总共要爆破出来16个数,达到了64 ^ 16的计算量,还得计算20次,这样做是不现实的,于是,可以提前把表格打好进行预先处理

result[0]: 0 1 2
result[1]: 3 4 0
result[2]: 5 6 0
result[3]: 5 7 1
result[4]: 4 6 1
result[5]: 8 2 3
result[6]: 9 2 4
result[7]: 7 10 3
result[8]: 8 12 5
result[9]: 11 13 6
result[10]: 12 13 7
result[11]: 11 14 9
result[12]: 14 8 10
result[13]: 15 9 10
result[14]: 15 11 12
result[15]: 15 13 14

假设,我们已知的值是result[16]这个数组,要求的是前一轮的result,不妨把这16个值设为x0,x1,……,x15

我们对x0,x1进行枚举之后,可以发现:x2不需要枚举,可以通过x0、x1、result[0]求出来,继续这么来的话:

枚举x3之后,x4可以通过x0,x3,result[1]求出

枚举x5之后,x6可以通过x0,x5,result[2]求出(同时需要检验:x1、x4、x6与result[4]的关系)

x7可以通过x1,x5,result[3]求出

x8可以通过x2,x3,result[5]求出

得到如下的爆破代码:

#include <iostream>
#include <stdio.h>
using namespace std;

typedef unsigned char u8;
u8 cube[64][64][64];
u8 GetNumber1[64][64][64];
u8 GetNumber2[64][64][64];
u8 GetNumber3[64][64][64];
u8 result[16] = {0x14,0x22,0x1E,0x10,0x38,0x30,0x18,0x10,4,0x1A,0x24,8,2,0x26,0x38,0x2A};

void Print(int x){
	printf("<%d>: ",x);
	for(int i = 0; i < 16; i++)
		printf("%02X ",result[i]);
	char *sz = "abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    for(int i = 0; i < 16; i++)
        printf("%c",sz[result[i]]);
    puts("");
}

void test(){
    u8 x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15;
    for(x0 = 0; x0 < 64; x0++)
        for(x1 = 0; x1 < 64; x1++){
            x2 = GetNumber3[x0][x1][result[0]];
            for(x3 = 0; x3 < 64; x3++){
                x4 = GetNumber2[x3][result[1]][x0];
                for(x5 = 0; x5 < 64; x5++){
                    x6 = GetNumber2[x5][result[2]][x0];
                    if (x6 == GetNumber2[x4][result[4]][x1]){
                        x7 = GetNumber2[x5][result[3]][x1];
                        x8 = GetNumber1[result[5]][x2][x3];
                        x9 = GetNumber1[result[6]][x2][x4];
                        x10 = GetNumber2[x7][result[7]][x3];
                        x12 = GetNumber2[x8][result[8]][x5];
                        x15 = GetNumber1[result[13]][x9][x10];
                        x11 = GetNumber2[x15][result[14]][x12];
                        x14 = GetNumber2[x11][result[11]][x9];
                        x13 = GetNumber2[x11][result[9]][x6];
                        if (GetNumber1[result[10]][x13][x7] == x12 &&
                            GetNumber1[result[12]][x8][x10] == x14 &&
                            GetNumber1[result[15]][x13][x14] == x15){
                                result[0] = x0;
                                result[1] = x1;
                                result[2] = x2;
                                result[3] = x3;
                                result[4] = x4;
                                result[5] = x5;
                                result[6] = x6;
                                result[7] = x7;
                                result[8] = x8;
                                result[9] = x9;
                                result[10] = x10;
                                result[11] = x11;
                                result[12] = x12;
                                result[13] = x13;
                                result[14] = x14;
                                result[15] = x15;
                                return;
                            }
                    }
                }
            }
        }
}

int main(){
    FILE *f = fopen("Escape.exe","rb");
    fseek(f,0xe4f0,0);
    fread(cube,64*64*64,1,f);
    fclose(f);
    for(int i = 0; i < 64; i++)
    	for(int j = 0; j < 64; j++)
    		for(int k = 0; k < 64; k++){
    			GetNumber1[cube[i][j][k]][j][k] = i;
    			GetNumber2[i][cube[i][j][k]][k] = j;
    			GetNumber3[i][j][cube[i][j][k]] = k;
    		}
    Print(0);
    for(int i = 1; i <= 0x500; i++){
        test();
        Print(i);
    }
    return 0;
}
全部评论

相关推荐

ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务