[suctf_2018] Enigma

0x00 背景

这次比赛因为撞上了运动会, 加上周日还有一些别的事情, 所以其实也就打了半天, 就做出来了这个题目(虽然可能打两天也只能做出来这一个题目QAQ), 算是xctf中第一个独立做出来的题目, 竟然又是逆向......pwn是真的太难了..........多看师傅们的wp吧.... 因为刚好选了门课, 讲的就是图灵奖得主的生平, 当然首先要讲的就是图灵了, 讲图灵自然就绕不过他二战期间帮助英国军方破解德国的密码机--Enigma 的故事了.....这也是我没有做pwn, 而是选择先做这个题的原因.
贴上官方wp

0x01 程序分析

看到这个题目我首先想到两种解法: 爆破或者逆算法. 因为enigma是每个字母单独加密的, 所以完全可以每个字母单独爆破. 并不会很慢. 应该要比逆算法快不少(对于一名逆向新手而言)
所以我就决定先自己用c重新实现一下程序中的算法, 然后爆破之. 这个过程就是体力活.......没有太多技术含量..........(可能有骚操作但是我不会吧......), 个人感觉了解enigma加密原理对理解程序有很大的帮助. 总之最后自己用c复现出来代码如下(对比官方wp中的官方实现, 我意识到了巨大的差距...........):

#include <stdio.h>
#include <stdlib.h>

char target[36] = {'\xa8', '\x1c', '\xaf', '\xd9', '\x00', '\x6c', '\xac', '\x02',
                   '\x9b', '\x05', '\xe3', '\x68', '\x2f', '\xc7', '\x78', '\x3a',
                   '\x02', '\xbc', '\xbf', '\xb9', '\x4d', '\x1c', '\x7d', '\x6e',
                   '\x31', '\x1b', '\x9b', '\x84', '\xd4', '\x84', '\x00', '\x76',
                   '\x5a', '\x4d', '\x06', '\x75'};

char key0[4] = {'\x31', '\x62', '\x93', '\xc4'};
char key1[4] = {'\x21', '\x42', '\x63', '\x84'};
char key2[4] = {'\x3d', '\x7a', '\xb7', '\xf4'};

int key0_idx = 0;
int key1_idx = 0;
int key2_idx = 0;

char v17=0;
char v18=0;

int encode3[9] = {0x2f9bacef, 0x97CDD677, 0x4BE6EB3B, 0x0A5F3759D,
                  0x0D2F9BACE, 0x697CDD67, 0x0B4BE6EB3, 0x5A5F3759, 0x2D2F9BAC};
char input[36] = {'c'};
char input2[36];
char encoded[36];

int g_val = 0x5f3759df;

char encode00(char key,  int idx){
    void * v1[2];
    char input_i = input[idx];
    for(int i=0; i<8; ++i){
        char v3 = v17;
        int v4 = ((key & (1 << (i&0x3f))) != 0);
        int v5 = ((input_i & (1 << (i&0x3f))) != 0);
        v18 = v3 ^ v4 ^ v5;
        v17 = v4 & v5 | v3 & (v4 | v5);
        if(v18 == 0){
            input[idx] = input[idx] & ~(1 << (i&0x3f));
        }else{
            input[idx] = input[idx] | (1 << (i&0x3f));
        }
    }
    return input[idx];
}

int keyset[3] = {0, 0, 0};

char encode0(int idx){
    v17 = 0;
    v18 = 0;
    char key = key0[key0_idx];
    char ret = encode00(key, idx);

    key = key1[key1_idx];
    ret = encode00(key, idx);

    key = key2[key2_idx];
    ret = encode00(key, idx);

    encoded[idx] = ret;
    if ( ++key0_idx == 4 )
    {
      key0_idx = 0;
      ++key1_idx;
    }
    if ( key1_idx == 4 )
    {
      key1_idx = 0;
      ++key2_idx;
    }
    if ( key2_idx == 4 )
      key2_idx = 0;
    return ret;
}

int func(int a1, int a2){
    return (((a1&0xff) & (1 << (a2 & 0x3f))) != 0);
}

char encode11(int idx, int j){
    char encoded_i = encoded[idx];
    int v0 = func(encoded_i, j);
    int v1 = (v0 != func(encoded_i, 7-j));
    if(v1){
        encoded_i |= (1 << (j & 0x3f));
    }else{
        encoded_i &= ~(1 << (j & 0x3f));
    }
    encoded[idx] = encoded_i;
    return encoded_i;
}

char encode12(int idx, int j){
    char encoded_i = encoded[idx];
    int v0 = func(encoded_i, 7-j);
    int v1 = (v0 != func(encoded_i, j));
    if(v1){
        encoded_i |= (1 << ((7-j)&0x3f));
    }else{
        encoded_i &= ~(1 << ((7-j)&0x3f));
    }
    encoded[idx] = encoded_i;
    return encoded_i;
}

int encode1(int i){
    for(int j=0; j<=2; ++j){
        encode11(i, j);
        encode12(i, j);
        encode11(i, j);
    }
}


int encode22(){
    int v0 = func(g_val, 31);
    int v1 = (func(g_val, 7) ^ v0);
    int v2 = (func(g_val, 5) ^ v1);
    int v3 = (func(g_val, 3) ^ v2);
    int v4 = (func(g_val, 2) ^ v3);
    int v16 = (v4 ^ func(g_val, 0));
    g_val = g_val>>1;

    int v6 = (v16!=0);

    if(v6){
        g_val |= (1 << (31 & 0x3f));
    }else{
        g_val &= ~(1 << (31 & 0x3f));
    }
    return g_val;
}

char encode2(int i){
    char *e3_ptr = (char *) encode3;
    char ret = encoded[i] ^ e3_ptr[i];
    encoded[i] = ret;
    return ret;
}

void show(){
    printf("output:\n" );
    for(int i=0; i<36; ++i){
        printf("%d, %2x, %c\n", i, encoded[i], encoded[i]);
    }
    printf("input:\n" );
    for(int i=0; i<36; ++i){
        printf("%d: %2x, %c\n", i, input2[i], input2[i]);
    }
    for(int i=0; i<36; ++i){
        printf("%c", input2[i]);
    }
}

void idx2key(int idx){
    key0_idx = idx % 4;
    key1_idx = (idx >> 2) % 4;
    key2_idx = (idx >> 4) % 4;
}

int decode(){
    char *e3_ptr = (char *)encode3;
    for(int i=0; i<36; ++i){
        for(char possible = 0; ; ++possible){
            idx2key(i);
            input[i] = possible;
            input2[i] = possible;
            encode0(i);
            encode1(i);
            char ret = encode2(i);
            if(ret == target[i]){
                int a = i;
                break;
            }
        }
    }
    show();
    return 0;
}


int test(){
    for(int i=0; i<36; ++i){
        input[i] = 'a';
        encode0(i);
        encode1(i);
        encode2(i);
    }
    show();
}

int main(){
    decode();
    // test();
    // printf("hello" );
    return 0;
}

然后其实也就没啥了, 爆破的算法很无脑.......不过期间遇到了一个坑, 就是enigma是有种东西叫转子, 每加密一个字母转子就会转一个单位, 不同状态的转子对应的加密映射是不同的. 所以爆破的时候一定需要将每一位对应的转子的状态设置好, 否则就会出现奇怪的东西. 还卡在一个地方是因为我把用来存贮输入的flag的数组input在爆破的过程中修改了.......进而导致最后输出input的时候得到的是一串包含一堆不可见字符的怎么看都不像flag的乱码........所以我们要牢记软件构造的教导!养成良好的编程习惯!不要修改参数!!!

0x04 exp

参考上面代码的decode()函数

0x05 收获

逆向真好玩.
pwn是不可能pwn的, 这辈子都不可能pwn的, 漏洞又找不到, 找到了漏洞又不会利用, 只有靠看wp勉强明白题目什么意思这样子


图片发自简书App
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容

  • 今天是过年返家的第二天,打开电视接着看了一部上次看了一半没看完的电影,叫做模仿游戏,图灵大家都知道,但是不知道他竟...
    Johnny_Chang阅读 930评论 0 1
  • 昨天突发奇想,于是今天就直接不去上班了。 反正去不去没差啦。 我打算去杭州,然后西湖环山徒步走一圈~~ 据说一圈是...
    LostAbaddon阅读 440评论 20 1
  • 导读:很多的作品里都可以看到莫斯球的踪影。莫斯比较好繁殖,长出来很美观,随便丢一点在水里就能长出来。 水草缸雨林缸...
    养草的大灰狼阅读 1,980评论 1 2
  • 今天是正月初一,我觉得从2017年开始就应该多做点什么了,前一段时间看一篇文章,说“年初综合症”:新年伊始,很多人...
    jiangxinq阅读 239评论 0 1