【CTF】BUUCTF RE 刷(抄wp)题记录
浏览 1338 | 评论 0 | 字数 37981
Xunflash
2021年04月01日
  • 本篇可能会持续更新

    PART1

    RE11:Java逆向解密

    这个是为数不多自己做的题

    下载来是个.class文件,用jadx打开来是这个样子

    看到26有一堆奇奇怪怪的,看着就像ascii的东西,有个加密函数

    那么就写个解密脚本

    key=[180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65]
    flag=''
    for i in key:
        s=(i^32)-ord('@')
        flag+=chr(s)
    print flag
    

    运行结果:

    flag:flag{This_is_the_flag_!}

    RE12:刮开有奖

    不会,还没写呢

    RE13:[GXYCTF2019]luck_guy

    21.5.1

    又被小端序这个东西坑了:在CTF中的小端序与大端序

    下载文件出来

    ida64拖进去打开

    整个反编译出来逻辑还是比较清楚的,就是switch按照一定顺序执行,就会给flag

    看了一下感觉有用的就1,4,5 想了一下可能会是451,4551,45551这几种,然后试了一下试不出来,后面才发现又被小端序这个东西坑到了,然后调整了一下s的顺序

    直接把整个关键代码修改一下放进vscode去试一下

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include"defs.h"
    
    int main(){
      unsigned int v0;
      char v1;
      signed int i;
      signed int j;
      __int64 s;
      char v6;
      unsigned __int64 v7;
      char f1[]={71, 88, 89, 123, 100, 111, 95, 110, 111, 116, 95,0};
      char f2[9];
      int a;
    
        for ( i = 0; i <= 4; ++i )
        {
            scanf("%d",&a);
            switch ( a  )
            {
              case 1:
                puts("OK, it's flag:");
                memset(&s, 0, 0x28uLL);
    
                printf("%s %s", f1,f2);
                break;
              case 2:
                printf("Solar not like you");
                break;
              case 3:
                printf("Solar want a girlfriend");
                break;
              case 4:
                v6 = 0;
                f2[7]=127;
                f2[6]=102;
                f2[5]=111;
                f2[4]=96;
                f2[3]=103;
                f2[2]=117;
                f2[1]=99;
                f2[0]=105;
                break;
              case 5:
                for ( j = 0; j <= 7; ++j )
                {
                  if ( j % 2 == 1 )
                    v1 = f2[j] - 2;
                  else
                    v1 = f2[j] - 1;
                  f2[j] = v1;
                }
                break;
              default:
                puts("emmm,you can't find flag 23333");
                break;
            }
        }
    }
    

    输入451就出来了flag

    flag:GXY{do_not_hate_me}

    RE14:findit

    21.5.1

    下载下来发现是个apk,直接jadx打开,源码直接出来了

    代码都不用写,直接挑出关键代码稍作修改放到vscode里面运行一下就可以了

    #include<stdio.h>
    
    int main(){
        char a[] = {'T', 'h', 'i', 's', 'I', 's', 'T', 'h', 'e', 'F', 'l', 'a', 'g', 'H', 'o', 'm', 'e'};
        char b[] = {'p','v','k','q','{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'};
        char x[17];
        char y[38];
    
        for (int i = 0; i < 17; i++) {
            if ((a[i] < 'I' && a[i] >= 'A') || (a[i] < 'i' && a[i] >= 'a')) {
                x[i] = (char) (a[i] + 18);
            } else if ((a[i] < 'A' || a[i] > 'Z') && (a[i] < 'a' || a[i] > 'z')) {
                x[i] = a[i];
            } else {
                x[i] = (char) (a[i] - '\b');
            }
        }
    


    ​ for (int i2 = 0; i2 < 38; i2++) {
    ​ if ((b[i2] < 'A' || b[i2] > 'Z') && (b[i2] < 'a' || b[i2] > 'z')) {
    ​ y[i2] = b[i2];
    ​ } else {
    ​ y[i2] = (char) (b[i2] + 16);
    ​ if ((y[i2] > 'Z' && y[i2] < 'a') || y[i2] >= 'z') {
    ​ y[i2] = (char) (y[i2] - 26);
    ​ }
    ​ }
    ​ }
    ​ for(int i =0;i<17;i++){
    ​ printf("%c",x[i]);

        }
        printf("\n");
        for(int j=0;j<38;j++){
            printf("%c",y[j]);
        }
    }
    

    但是我输出y会乱码,我也不知道为啥

    于是就交给手机,把x输进去框框里面,得到flag

    flag:flag{c164675262033b4c49bdf7f9cda28a75}

    RE15:简单注册器

    21.5.8

    下载文件,发现是个apk,拖进jadx打开

    找到关键代码拖进vscode,稍微做一点修改

    #include<stdio.h>
    
        int main(){
            char x[33] = "dd2940c04462b4dd7c450528835cca15";
                x[2] = (char) ((x[2] + x[3]) - 50);
                x[4] = (char) ((x[2] + x[5]) - 48);
                x[30] = (char) ((x[31] + x[9]) - 48);
                x[14] = (char) ((x[27] + x[28]) - 97);
                for (int i = 0; i < 16; i++) {
                    char a = x[31 - i];
                    x[31 - i] = x[i];
                    x[i] = a;
                }
            printf("flag{%s}",x);
        }
    

    运行得到flag

    flag:flag{59acc538825054c7de4b26440c0999dd}

    RE16:[GWCTF 2019]pyre

    21.5.8

    下载文件,是一个pyc文件,找某度有个pyc在线反编译

    得到源码

    #!/usr/bin/env python
    # visit http://tool.lu/pyc/ for more information
    print 'Welcome to Re World!'
    print 'Your input1 is your flag~'
    l = len(input1)
    for i in range(l):
        num = ((input1[i] + i) % 128 + 128) % 128
        code += num
    
    for i in range(l - 1):
        code[i] = code[i] ^ code[i + 1]
    
    print code
    code = [
        '\x1f',
        '\x12',
        '\x1d',
        '(',
        '0',
        '4',
        '\x01',
        '\x06',
        '\x14',
        '4',
        ',',
        '\x1b',
        'U',
        '?',
        'o',
        '6',
        '*',
        ':',
        '\x01',
        'D',
        ';',
        '%',
        '\x13']
    

    然后根据源码写出解密脚本

    code = [
        '\x1f',
        '\x12',
        '\x1d',
        '(',
        '0',
        '4',
        '\x01',
        '\x06',
        '\x14',
        '4',
        ',',
        '\x1b',
        'U',
        '?',
        'o',
        '6',
        '*',
        ':',
        '\x01',
        'D',
        ';',
        '%',
        '\x13']
    
    flag=''
    
    for i in reversed(range(22)):
        code[i]=chr(ord(code[i+1])^ord(code[i]))
    
    for j in range(23):
        flag+=chr(((ord(code[j])-128)%128-j)%128)
    
    print flag
    

    其中有一个地方有点难,就是取余的逆运算(对于当代痴呆大学生:指我自己
    具体可以参考这个:求余逆运算+负数求余

    RE17:[BJDCTF2020]JustRE

    21.5.9

    下载文件,点开看了一下

    有个getflag的选项,点一下

    弹出一个窗口,点下面click it

    会计数,感觉是要动态调试,可惜我不会,于是打开ida,看了一下关键代码

    盲猜要点19999下,于是打开ce

    直接改成19998,最后点一下click it

    真不戳

    flag:flag{1999902069a45792d233ac}

    RE18:rsa

    21.5.9

    rsa不会,直接抄的BUUCTF RSA

    RE21:[2019红帽杯]easyRE

    21.5.18

    代码好乱,不会,看了一下wp

    打开文件,一堆函数,然后shift+f12打开

    找到一些东西

    看起来就是base64

    点进函数

    写半天,把这个base64解密了,上面那一串异或了就一个提示

    看别人的wp才知道还有个函数在另外一个地方

    然后来个脚本

    '''a='Iodl>Qnb(ocy'+chr(127)+'y.i'+chr(127)+'d`3w}wek9{iy=~yL@EC'
    b=''
    for i,j in zip(a,range(len(a))):
        b+=chr(ord(i)^j)
    print b'''
    
    v1='flag'
    v2=[64,  53,  32,  86,  93,  24,  34,  69,  23,  47, 
       36, 110,  98,  60,  39,  84,  72, 108,  36, 110, 
      114,  60,  50,  69,  91]
    key=''
    flag=''
    
    for i in range(4):
        key+=chr(v2[i]^ord(v1[i]))
    
    for i in range(len(v2)):
        flag+=chr(v2[i]^ord(key[i%4]))
    
    print flag
    

    flag:flag{Act1ve_Defen5e_Test}

    RE22:[ACTF新生赛2020]rome

    21.5.18

    脚本没写出来

    s='Qsw3sj_lz4_Ujw@l'
    flag=''
    for i in s:
        if ord(i)>64 and ord(i)<=90:
            flag+=chr((ord(i)-14))
        elif ord(i)>96 and ord(i)<=122:
            flag+=chr((ord(i)-18))
        else:
            flag+=i
    print flag
    

    有点问题,不知道为啥,后来就直接抄了cnblog[ BUUCTF--[ACTF新生赛2020]rome][5]

    flag:flag{Cae3ar_th4_Gre@t}

    RE23:[FlareOn4]login

    21.5.26

    简单的题

    算法都没看,直接试一下alert(rotFlag);

    然后随便输入一些字母,发现就是简单的移位

    写个脚本

    s='PyvragFvqrYbtvafNerRnfl@syner-ba.pbz'
    flag=''
    
    for i in s:
        if (i>='a' and i<='m') or (i>='A' and i<='M'):
            flag+=chr(ord(i)+13)
        elif (i>='n' and i<='z') or (i>='N' and i<='Z'):
            flag+=chr(ord(i)-13)
        else:
            flag+=i
    
    print flag
    

    flag:flag{ClientSideLoginsAreEasy@flare-on.com}

    RE25:[GUET-CTF2019]re

    21.5.26

    一堆奇葩东西

    手工处理数据之后上脚本

    a=[1629056,
    6771600,
    3682944,
    10431000,
    3977328,
    5138336,
    7532250,
    5551632,
    3409728,
    13013670,
    6088797,
    7884663,
    8944053,
    5198490,
    4544518,
    3645600,
    10115280,
    9667504,
    5364450,
    13464540,
    5488432,
    14479500,
    6451830,
    6252576,
    7763364,
    7327320,
    8741520,
    8871876,
    4086720,
    9374400,
    5759124]
    
    b=[166163712,
    731332800,
    357245568,
    1074393000,
    489211344,
    518971936,
    406741500,
    294236496,
    177305856,
    650683500,
    298351053,
    386348487,
    438258597,
    249527520,
    445362764,
    174988800,
    981182160,
    493042704,
    257493600,
    767478780,
    312840624,
    1404511500,
    316139670,
    619005024,
    372641472,
    373693320,
    498266640,
    452465676,
    208422720,
    515592000,
    719890500]
    


    ​ flag=''

    for i,j in zip(a,b):
        flag+=chr(j/i)
    print flag
    
    #坑壁题目缺第七位,看都看不到。。。
    

    坑壁题目缺第七位,看都看不到。。。害我看wp

    好像要爆破第七位..是1

    flag:flag{e165421110ba03099a1c039337}

    RE27:相册

    21.7.27

    时隔多月我又做了一题(主要原因是放假了在玩

    首先下载,发现是个apk,那么我们打开jadx看看

    这么怪的名字肯定在里面

    随便点开几个康康

    然后去c2看看

    ok,这波属于是写明了是base64了,接下来我们去so文件里面找一下base64的字符

    解压得到libcore.so

    ida打开,shift+f12

    得到几个base64

    选中的这个就是flag需要的邮箱了

    包上flag提交即可。

    flag:flag{18218465125@163.com}

    RE29:level1

    21.8.3

    ida64打开

    逻辑很清晰

    奇数进行位运算右移,偶数乘以下标

    python写个脚本就行了

    a=[198,232,816,200,1536,300,6144,984,51200,570,92160,1200,565248,756,1474560,800,6291456,1782,65536000]
    flag=''
    for i in range(1,20):
        if (i&1)!=0:
            a[i-1]=a[i-1]>>i
        else:
            a[i-1]=a[i-1]/i
    for j in a:
        flag+=chr(j)
    print flag
    

    flag:ctf2020{d9-dE6-20c}

    RE30:[MRCTF2020]Transform

    21.8.5

    无壳,打开ida64看一下main

    主要的加密还是在这两句

    这是数据

    具体就是根据索引dword_40F040打乱顺序然后再异或,然后我们只需要反过来即可,也就是倒着循环reversed(range(33))然后先异或再flag[dword_40F040[i]]=byte_40F0E0[i]即可

    写出python脚本:

    dword_40F040=[0x09,0x0A,0x0F,0x17,0x07,0x18,0x0C,0x06,0x01,0x10,0x03,0x11,0x20,0x1D,0x0B,0x1E,0x1B,0x16,0x04,0x0D,0x13,0x14,0x15,0x02,0x19,0x05,0x1F,0x08,0x12,0x1A,0x1C,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
    byte_40F0E0=[0x67,0x79,0x7B,0x7F,0x75,0x2B,0x3C,0x52,0x53,0x79,0x57,0x5E,0x5D,0x42,0x7B,0x2D,0x2A,0x66,0x42,0x7E,0x4C,0x57,0x79,0x41,0x6B,0x7E,0x65,0x3C,0x5C,0x45,0x6F,0x62,0x4D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
    flag=[0]*33
    
    for i in reversed(range(0,33)):
        byte_40F0E0[i]^=(dword_40F040[i])
        flag[dword_40F040[i]]=byte_40F0E0[i]
        
    print ''.join([chr(x) for x in flag])
    

    flag:flag{Tr4nsp0sltiON_Clph3r_1s_3z}

    RE31:[WUSTCTF2020]level2

    21.8.5


    ???
    放到kali里面upx -d,shift+f12就出来了

    flag:flag{Just_upx_-d}

    RE34:[MRCTF2020]Xor

    21.10.12

    反编译失败,调用函数参数有问题,这里删掉三个点这个东西就行了。

    超级简单的异或,直接脚本

    a='MSAWB~FXZ:J:`tQJ"N@ bpdd}8g'
    flag=''
    for i in range(27):
        flag+=chr(i^ord(a[i]))
    print flag
    

    flag:MRCTF{@_R3@1ly_E2_R3verse!}

    RE35:[FlareOn4]IgniteMe

    21.10.14

    今天线下打金华市和美杯 来早了,做了个re

    ida打开

    只有五个函数,

    这两个是关键函数,打开看看

    这个函数看起来就是对数组初始化,没啥用

    这个就比较有用了,可以看到一个简单的异或操作,但是v4初值不知道,点进sub_401000():

    查了下这个函数,也没查出什么,动调看看

    断点断在那个for循环上面

    然后双击v4,可以看到

    他的初值是4。

    于是写个脚本

    a=[   13,  38,  73,  69,  42,  23, 120,  68,  43, 108, 
       93,  94,  69,  18,  47,  23,  43,  68, 111, 110, 
       86,   9,  95,  69,  71, 115,  38,  10,  13,  19, 
       23,  72,  66,   1,  64,  77,  12,   2, 105]
    flag=''
    b=0
    v4=4
    for i in reversed(a):
       b=v4^i
       v4=b
       flag+=chr(b)
    print flag[::-1]
    

    flag:flag{R_y0u_H0t_3n0ugH_t0_1gn1t3@flare-on.com}

    RE36:[MRCTF2020]hello_world_go

    21.10.14

    go语言 逆向出来是真的复杂啊
    完全看不懂

    主函数就有flag

    flag:flag{hello_world_gogogo}

    RE37:[WUSTCTF2020]level3

    21.10.19

    main函数给了个base64

    有个奇怪的换表函数,好像在start的时候被调用了(main之前)

    直接动调一下看看被改成啥样了(脚本写了但是好像不太对?

    真不戳

    然后随便找个换表脚本就出来了

    flag:wctf2020{Base64_is_the_start_of_reverse}

    RE38:[WUSTCTF2020]Cr0ssfun

    21.10.19

    手动操作复制出来输出,没什么好说的

    flag:wctf2020{cpp_@nd_r3verse_@re_fun}

    RE39:[WUSTCTF2020]Cr0ssfun

    21.10.19
    不太会

    参考这个https://blog.csdn.net/weixin_47158947/article/details/107818896

    不过md5那个地方X2是变大写,所以这篇文章交不上去,实际flag内需要大写

    flag:flag{B8C37E33DEFDE51CF91E}

    RE40:[FlareOn6]Overlong

    21.10.28

    动调改一下就好了1C改成7F

    因为字符串很长,而for循环只循环前面28位,改长一点就行了。然后断在start函数的return 0,再点进text复制栈上内容就行了。

    flag:flag{I_a_M_t_h_e_e_n_C_o_D_i_n_g@flare-on.com}

    RE41:[ACTF新生赛2020]Oruga

    21.10.28

    打开先验证格式actf{}
    然后进到一个函数,看到+16-16+1-1这个,再看到一个奇怪的256字符的数组,直接猜测是迷宫,实际上也确实是的。

    这个题比较迷惑,是左上角开始走的,我被迷惑到了,弄成了0是起点,!是终点

    而且移动也不是一个一个走,是滑动,题目名字翻译过来也是履带,估计就是想暗示吧。

    迷宫走完就行了

    象征性的贴个输出迷宫的脚本

    map=[0,   0,   0,   0,  35,   0,   0,   0,   0,   0, 
        0,   0,  35,  35,  35,  35,   0,   0,   0,  35, 
       35,   0,   0,   0,  79,  79,   0,   0,   0,   0, 
        0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
       79,  79,   0,  80,  80,   0,   0,   0,   0,   0, 
        0,  76,   0,  79,  79,   0,  79,  79,   0,  80, 
       80,   0,   0,   0,   0,   0,   0,  76,   0,  79, 
       79,   0,  79,  79,   0,  80,   0,   0,   0,   0, 
        0,   0,  76,  76,   0,  79,  79,   0,   0,   0, 
        0,  80,   0,   0,   0,   0,   0,   0,   0,   0, 
        0,  79,  79,   0,   0,   0,   0,  80,   0,   0, 
        0,   0,  35,   0,   0,   0,   0,   0,   0,   0, 
        0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
        0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
       35,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
       77,  77,  77,   0,   0,   0,  35,   0,   0,   0, 
        0,   0,   0,   0,   0,   0,   0,  77,  77,  77, 
        0,   0,   0,   0,  69,  69,   0,   0,   0,  48, 
        0,  77,   0,  77,   0,  77,   0,   0,   0,   0, 
       69,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
        0,   0,   0,   0,   0,   0,  69,  69,  84,  84, 
       84,  73,   0,  77,   0,  77,   0,  77,   0,   0, 
        0,   0,  69,   0,   0,  84,   0,  73,   0,  77, 
        0,  77,   0,  77,   0,   0,   0,   0,  69,   0, 
        0,  84,   0,  73,   0,  77,   0,  77,   0,  77, 
       33,   0,   0,   0,  69,  69]
    map1=''
    for i in range(256):
        if i%16==0:
            map1+='\n'
        if map[i]==0:
            map1+='.'
        map1+=chr(map[i])
    print map1
    

    flag:flag{MEWEMEWJMEWJM}

    RE42:[FlareOn3]Challenge1

    21.10.29

    动调复制被初始化的base64表然后拿换标脚本解密就行了。之前写过类似的题

    import base64
    import string
    
    str1 = "x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q"
    '''
    a=[0x5A, 0x59, 0x58, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x7A, 0x79, 0x78, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F]
    string3=''
    for i in a:
        string3+=chr(i)
    print(string3)
    '''
    string1 = "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
    string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    
    print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))
    

    flag:flag{sh00ting_phish_in_a_barrel@flare-on.com}

    RE43:[UTCTF2020]basic-re

    22.1.10

    都不想放上来...以后这种太简单的题就不放出来了
    直接string或者shift+f12就有的

    flag:flag{str1ngs_1s_y0ur_fr13nd}

    RE44:[Zer0pts2020]easy strcmp

    22.1.10

    说实话,这个题挺折腾人的,不过也是因为自己python掌握的不好,类型转换老是搞不明白

    不过动调能解决的话就很不错了

    拿到题目,上来直接一个strcmp,真的很怪

    image-20220111002227465

    flag也不是这个东西。边上还有几个奇怪的函数,于是找到了这两个

    image-20220111002311582

    这个把strcmp的地址改了,为了方便,我重新命名了一下

    image-20220111002356328

    (忽略那个+=,我改过,原来是-=的)

    这个“假的”strcmp就是这么个逻辑,把一坨东西和输入进去的相减,最后得到zer0pts{********CENSORED********}这个东西

    那就加回来就行了

    python脚本不会类型转换,c语言写也报错,离谱了,于是我直接动调,算是一种新思路吧

    image-20220111003039159

    这个地方原本是sub的,改成add,然后动调,参数直接写成这样

    image-20220111003122202

    然后断点在图上那个地方,按几次f4,然后点进去看flag就行了

    image-20220111003304328

    整个就是属于是一个脑洞题...

    flag:flag{l3ts_m4k3_4_DETOUR_t0d4y}

    RE45:[ACTF新生赛2020]Universe_final_answer

    22.1.11

    直接用z3就行了

    存个学z3的教程https://firmianay.gitbooks.io/ctf-all-in-one/content/doc/5.8.1_z3.html

    image-20220111162001926

    打开之后,在这里进入目标函数

    image-20220111162211348

    一堆公式,丢到python里面用z3求解一下

    from z3 import *
    solver = Solver()
    a1=[BitVec("a1[%d]" % i,16) for i in range(10)]
    solver.add(-85 * a1[8] + 58 * a1[7] + 97 * a1[6] + a1[5] + -45 * a1[4] + 84 * a1[3] + 95 * a1[0] - 20 * a1[1] + 12 * a1[2] == 12613)
    solver.add(30 * a1[9] + -70 * a1[8] + -122 * a1[6] + -81 * a1[5] + -66 * a1[4] + -115 * a1[3] + -41 * a1[2] + -86 * a1[1] - 15 * a1[0] - 30 * a1[7] == -54400)
    solver.add(-103 * a1[9] + 120 * a1[7] + 108 * a1[5] + 48 * a1[3] + -89 * a1[2] + 78 * a1[1] - 41 * a1[0] + 31 * a1[4] - (a1[6] << 6) - 120 * a1[8] == -10283)
    solver.add(71 * a1[6] + (a1[5] << 7) + 99 * a1[4] + -111 * a1[2] + 85 * a1[1] + 79 * a1[0] - 30 * a1[3] - 119 * a1[7] + 48 * a1[8] - 16 * a1[9] == 22855)
    solver.add(5 * a1[9] + 23 * a1[8] + 122 * a1[7] + -19 * a1[6] + 99 * a1[5] + -117 * a1[4] + -69 * a1[2] + 22 * a1[1] - 98 * a1[0] + 10 * a1[3] == -2944)
    solver.add(-54 * a1[9] + -23 * a1[7] + -82 * a1[2] + -85 * a1[0] + 124 * a1[1] - 11 * a1[3] - 8 * a1[4] - 60 * a1[5] + 95 * a1[6] + 100 * a1[8] == -2222)
    solver.add(-83 * a1[9] + -111 * a1[5] + -57 * a1[0] + 41 * a1[1] + 73 * a1[2] - 18 * a1[3] + 26 * a1[4] + 16 * a1[6] + 77 * a1[7] - 63 * a1[8] == -13258)
    solver.add(81 * a1[9] + -48 * a1[8] + 66 * a1[7] + -104 * a1[6] + -121 * a1[5] + 95 * a1[4] + 85 * a1[3] + 60 * a1[2] + -85 * a1[0] + 80 * a1[1] == -1559)
    solver.add(101 * a1[9] + -85 * a1[8] + 7 * a1[6] + 117 * a1[5] + -83 * a1[4] + -101 * a1[3] + 90 * a1[2] + -28 * a1[1] + 18 * a1[0] - a1[7] == 6308)
    solver.add(99 * a1[9] + -28 * a1[8] + 5 * a1[7] + 93 * a1[6] + -18 * a1[5] + -127 * a1[4] + 6 * a1[3] + -9 * a1[2] + -93 * a1[1] + 58 * a1[0] == -1697)
    if solver.check() == sat:
        m = solver.model()
    flag1=''
    for i in [str(m.eval(a1[i])) for i in range(10)]:
        if int(i)>32768:
            i=int(i)-32768
        flag1+=chr(int(i))
    print flag1

    然后解出来的东西再放到题目里面运行一下就可以出来flag

    flag:flag{F0uRTy_7w@_42}

    PART 2

    接下来可能不会继续做一分题了(除非找信心)

    [MRCTF2020]Shit

    题目给出了源码,甚至给了decode函数。不确定的就是key,在启动后会修改。于是使用ollydbg动调出key

    源码:

    #include<Windows.h>
    #include<iostream>
    #include<ctime>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    int map[100],c=2;
    int key[7]={'b','k','d','c','e','w'};
    unsigned int ks[6]={0x8c2c133a,0xf74cb3f6,0xfedfa6f2,0xab293e3b,0x26cf8a2a,0x88a1f279};//{0x8c2cecc5,0xf74cb3f6,0xfedf590d,0xab293e3b,0x26cf75d5,0x88a1f279};
    FARPROC proc=NULL;
    int initHook()
    {
        HMODULE hModule=LoadLibraryA("Kernel32.dll");
        if(hModule)
        {
            proc=GetProcAddress(hModule,"IsDebuggerPresent");
            if(proc==NULL)
                return -1;
        }
        return 0;
    }
    PDWORD update()
    {
        if(initHook()!=0)
            exit(-1);
        HANDLE hProcess=GetModuleHandle(NULL);
        PIMAGE_DOS_HEADER dos_header=(PIMAGE_DOS_HEADER)hProcess;
        PIMAGE_NT_HEADERS nt_header=(PIMAGE_NT_HEADERS)(dos_header->e_lfanew+(DWORD)hProcess);
        IMAGE_OPTIONAL_HEADER* opt_header=&(nt_header->OptionalHeader);
        PIMAGE_IMPORT_DESCRIPTOR iat=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hProcess+opt_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
        while(iat->FirstThunk)
        {
            PIMAGE_THUNK_DATA data=(PIMAGE_THUNK_DATA)(iat->FirstThunk+(DWORD)hProcess);
            while(data->u1.Function)
            {
                if(IMAGE_SNAP_BY_ORDINAL(data->u1.AddressOfData))
                {
                    data++;
                    continue;
                }
                if((DWORD)proc==data->u1.Function)
                    return &data->u1.Function;
                data++;
            }
            iat++;
        }
        return NULL;
    }
    PDWORD table_addr=NULL;
    int writeAddr(DWORD addr)
    {
        if(table_addr==NULL)
            table_addr=update();
        DWORD dwOldProtect;
        MEMORY_BASIC_INFORMATION mbi_thunk;
        VirtualQuery(table_addr,&mbi_thunk,sizeof(MEMORY_BASIC_INFORMATION));
        VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,PAGE_READWRITE,&mbi_thunk.Protect);
        *table_addr=(DWORD)addr;
        VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,mbi_thunk.Protect,&dwOldProtect);
        return 0;
    }
    bool WINAPI CallBackProc()
    {
        writeAddr((DWORD)proc);
        map[0]=2;c--;
        key[0]='a';
        key[1]='k';
        key[2]='e';
        key[3]='y';
        key[4]='e';
        key[5]='z';
        if(IsDebuggerPresent())
        {
            MessageBoxW(NULL,L"U R Using Debugger!",L"U Suck!",MB_OK);
            return true;
        }
        return false;
    }
    void sleep()
    {
        sleep();
    }
    int checkDebug()
    {
        if(*((unsigned char *)(*(DWORD*)(__readfsdword(0x18)+0x30))+0x2))
            sleep();
        return 0;
    }
    int doit=writeAddr((DWORD)CallBackProc),dd=checkDebug();
    bool encode(char* ur_flag)
    {
        unsigned int k=0,bk=0;   
        for(int i=0;i<strlen(ur_flag);i+=4)
        {
            k=(((int)ur_flag[i])<<24)|(((int)ur_flag[i+1])<<16)|(((int)ur_flag[i+2])<<8)|((int)ur_flag[i+3]);
            k=(k>>key[i/4]) | (k<<(32-key[i/4]));
            _asm
            {
                call sub2
                _emit 0xEB
                jmp label2
            sub2:
                add dword ptr[esp],1
                retn
            label2:
            }
            k=((~(k>>16))&0x0000ffff) | (k<<16);
            k=(1<<key[i/4])^k;
            _asm
            {
                call sub7
                _emit 0xE8
                jmp label7
            sub7:
                add dword ptr[esp],1
                retn
            label7:
            }
            if(i>0)
                k^=bk;
            bk=k;
            if(k!=ks[i/4])
                return false;
        }
        return true;
    }
    void genKey()
    {
        int len=20,keylen=6,maxium=0;
        int before;
        _asm
        {
            call sub1
            _emit 0xE8
            jmp label1
        sub1:
            add dword ptr[esp],1
            retn
        label1:
        }
        srand(time(NULL));
        for(int i=1;i<=len;i++)
        {
            map[i]=map[i-1]+rand()%5;
            _asm
            {
                call sub3
                _emit 0xE8
                jmp label3
            sub3:
                add dword ptr[esp],1
                retn
            label3:
            }
            maxium=maxium>map[i]?maxium:map[i];
        }
        _asm
        {
            call sub4
            _emit 0xE8
            jmp label4
        sub4:
            add dword ptr[esp],1
            retn
        label4:
        }
        before=time(NULL);
        _asm
        {
            call sub5
            _emit 0xE8
            jmp label5
        sub5:
            add dword ptr[esp],1
            retn
        label5:
        }
        for(int i=0;i<keylen;i++)
        {
            int step=0;
            long long t=time(NULL);
            int delta=t-before;
            _asm
            {
                call sub6
                _emit 0xE8
                jmp label6
            sub6:
                add dword ptr[esp],1
                retn
            label6:
            }
            if(delta>maxium)
                return;
        
            for(int j=0;j<=len;j++)
                if(delta<=map[j])
                {
                    step=map[j];
                    _asm
                    {
                        call sub8
                        _emit 0xE8
                        jmp label8
                    sub8:
                        add dword ptr[esp],1
                        retn
                    label8:
                    }
                    break;
                }
            _asm
            {
                call sub9
                _emit 0xE8
                jmp label9
            sub9:
                add dword ptr[esp],1
                retn
            label9:
            }
            key[i]=(key[i]*c+step+i*3)%32;
            _asm
            {
                call sub10
                _emit 0xE8
                jmp label10
            sub10:
                add dword ptr[esp],1
                retn
            label10:
            }
            before=t;
        }
    }
    
    void decode()
    {
        unsigned int k=0,bk=0;
        for(int i=5;i>=0;i--)
            if(i>0)
                ks[i]^=ks[i-1];
        for(int i=0;i<24;i+=4)
        {
            k=ks[i/4];
            k=(1<<key[i/4])^k;
            k=((k>>16)) | ((~(k<<16))&0xffff0000);
            k=((k<<key[i/4])) | (k>>(32-key[i/4]));
            printf("%X\n",k);
        }
    }
    int main()
    {
        char ur_flag[50];
        cout<<"please input your flag:"<<endl;
        cin>>ur_flag;
        if(IsDebuggerPresent())
        {
            cout<<"U suck! 233333"<<endl;
            Sleep(2000);
            exit(0);
        }
        if(strlen(ur_flag)!=24)
        {
            cout<<"Wrong!"<<endl;
            Sleep(2000);
            exit(0);
        }
        genKey();
        bool flag=encode(ur_flag);
        decode();
        if(flag)
        {
            cout<<"U did it!"<<endl<<"GJ!"<<endl;
            system("pause");
            exit(0);
        }
        cout<<"Wrong!"<<endl;
        Sleep(2000);
        return 0;
    }
    

    里面还有一些新的花指令,学到了

    前面还有时间差反调试,学到许多,直接把time函数nop掉然后把0移进去就好了,其实按f9按得快一点也可以出

    image-20220208184500437

    在ida nop掉花指令之后(或者直接od nop掉也可以,但是ida有插件快一点)我们用od断在这里,先随便输24位数字,然后看ecx一个一个提取出来就可以了

    image-20220208162025593

    注意od好像不会自动识别代码,需要按ctrl+a重新识别再动调。

    最后取出来keykey[7] = { 0x03,0x10,0x0D,0x04,0x13,0x0B }

    直接拿源代码改一下就可以了

    #include<Windows.h>
    #include<iostream>
    #include<ctime>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    int map[100], c = 2;
    //int key[7] = { 'a','k','e','y','e','z' };
    int key[7] = { 0x03,0x10,0x0D,0x04,0x13,0x0B };
    unsigned int ks[6] = { 0x8c2c133a,0xf74cb3f6,0xfedfa6f2,0xab293e3b,0x26cf8a2a,0x88a1f279 };//{0x8c2cecc5,0xf74cb3f6,0xfedf590d,0xab293e3b,0x26cf75d5,0x88a1f279};
    FARPROC proc = NULL;
    void decode()
    {
        unsigned int k = 0, bk = 0;
        for (int i = 5; i >= 0; i--)
            if (i > 0)
                ks[i] ^= ks[i - 1];
        for (int i = 0; i < 24; i += 4)
        {
            k = ks[i / 4];
            k = (1 << key[i / 4]) ^ k;
            k = ((k >> 16)) | ((~(k << 16)) & 0xffff0000);
            k = ((k << key[i / 4])) | (k >> (32 - key[i / 4]));
            //printf("%X\n", k);
            for (int j = 0; j < 4; j++) {
                printf("%c", *((char*)&k + 3 - j));
            }
        }
    }
    int main()
    {
        char ur_flag[50];
        cout << "please input your flag:" << endl;
        //genKey();
        //bool flag=encode(ur_flag);
        decode();
        /*if(flag)
        {
            cout<<"U did it!"<<endl<<"GJ!"<<endl;
            system("pause");
            exit(0);
        }
        cout<<"Wrong!"<<endl;
        Sleep(2000);*/
        system("pause");
        return 0;
    }

    flag:flag{a_3a2y_re_for_test}

    [watevrCTF 2019]Repyc

    题目给了一个pyc文件,在线反编译一下,原本有很多佤 = 0 侰 = ~佤 * ~佤 俴 = 侰 + 侰 def 䯂(䵦):这种东西,用vscode自带的匹配所有,改一下全部改成人看的字符。本来改完就有点想放弃了,直接搜了下wp,发现是一个vm,第一次接触这种题目。还挺有意思的。自己整理了一下做了一遍

    #!/usr/bin/env python
    # visit https://tool.lu/pyc/ for more information
    a = 0
    b = ~a * ~a  #1
    c = b + b  #2
    
    
    def func(x):
        f1 = 0
        f3 = [a] * 16
        f4 = [a] * 100
        f5 = []
        while x[f1][a] != "exit":
            k1 = x[f1][a].lower()
            k2 = x[f1][b:]
            if k1 == "add":
                f3[k2[a]] = f3[k2[b]] + f3[k2[c]]
            elif k1 == "xor":
                f3[k2[a]] = f3[k2[b]] ^ f3[k2[c]]
            elif k1 == "sub":
                f3[k2[a]] = f3[k2[b]] - f3[k2[c]]
            elif k1 == "x":
                f3[k2[a]] = f3[k2[b]] * f3[k2[c]]
            elif k1 == "/":
                f3[k2[a]] = f3[k2[b]] / f3[k2[c]]
            elif k1 == "&":
                f3[k2[a]] = f3[k2[b]] & f3[k2[c]]
            elif k1 == "|":
                f3[k2[a]] = f3[k2[b]] | f3[k2[c]]
            elif k1 == "nop":
                f3[k2[a]] = f3[k2[a]]
            elif k1 == "mov":
                f3[k2[a]] = f3[k2[b]]
            elif k1 == "mov1":
                f3[k2[a]] = k2[b]
            elif k1 == "mov2":
                f4[k2[a]] = f3[k2[b]]
            elif k1 == "mov3":
                f3[k2[a]] = f4[k2[b]]
            elif k1 == "to0":
                f3[k2[a]] = a
            elif k1 == "to_0":
                f4[k2[a]] = a
            elif k1 == "input":
                f3[k2[a]] = input(f3[k2[b]])
            elif k1 == "input1":
                f4[k2[a]] = input(f3[k2[b]])
            elif k1 == "print":
                print(f3[k2[a]])
            elif k1 == "print1":
                print(f4[k2[a]])
            elif k1 == "\xeb\xad\xbf":
                f1 = f3[k2[a]]
            elif k1 == "\xeb\xae\x93":
                f1 = f4[k2[a]]
            elif k1 == "\xeb\xae\xb3":
                f1 = f5.pop()
            elif k1 == "\xeb\xaf\x83" or f3[k2[b]] > f3[k2[c]]:
                f1 = k2[a]
                f5.append(f1)
                continue
            elif k1 == "for_comp?":
                f3[7] = a
                for i in range(len(f3[k2[a]])):
                    if f3[k2[a]] != f3[k2[b]]:
                        f3[7] = b
                        f1 = f3[k2[c]]
                        f5.append(f1)
            elif k1 == "for_xor":
                m = ""
                for i in range(len(f3[k2[a]])):
                    m += chr(ord(f3[k2[a]][i]) ^ f3[k2[b]])
                f3[k2[a]] = m
            elif k1 == "for_-":
                m = ""
                for i in range(len(f3[k2[a]])):
                    m += chr(ord(f3[k2[a]][i]) - f3[k2[b]])
                f3[k2[a]] = m
            elif k1 == "\xeb\x96\x87" or f3[k2[b]] > f3[k2[c]]:
                f1 = f3[k2[a]]
                f5.append(f1)
                continue
            elif k1 == "\xeb\x97\x8b" or f3[k2[b]] > f3[k2[c]]:
                f1 = f4[k2[a]]
                f5.append(f1)
                continue
            elif k1 == "\xeb\x98\xb7" or f3[k2[b]] == f3[k2[c]]:
                f1 = k2[a]
                f5.append(f1)
                continue
            elif k1 == "\xeb\x9a\xab" or f3[k2[b]] == f3[k2[c]]:
                f1 = f3[k2[a]]
                f5.append(f1)
                continue
            elif k1 == "\xeb\x9d\x87" and f3[k2[b]] == f3[k2[c]]:
                f1 = f4[k2[a]]
                f5.append(f1)
                continue
            f1 += b
    
    
    func(
        [
            ["mov1", 0, "Authentication token: "],
            ["input1", 0, 0],
            [
                "mov1",
                6,
                "\xc3\xa1\xc3\x97\xc3\xa4\xc3\x93\xc3\xa2\xc3\xa6\xc3\xad\xc3\xa4\xc3\xa0\xc3\x9f\xc3\xa5\xc3\x89\xc3\x9b\xc3\xa3\xc3\xa5\xc3\xa4\xc3\x89\xc3\x96\xc3\x93\xc3\x89\xc3\xa4\xc3\xa0\xc3\x93\xc3\x89\xc3\x96\xc3\x93\xc3\xa5\xc3\xa4\xc3\x89\xc3\x93\xc3\x9a\xc3\x95\xc3\xa6\xc3\xaf\xc3\xa8\xc3\xa4\xc3\x9f\xc3\x99\xc3\x9a\xc3\x89\xc3\x9b\xc3\x93\xc3\xa4\xc3\xa0\xc3\x99\xc3\x94\xc3\x89\xc3\x93\xc3\xa2\xc3\xa6\xc3\x89\xc3\xa0\xc3\x93\xc3\x9a\xc3\x95\xc3\x93\xc3\x92\xc3\x99\xc3\xa6\xc3\xa4\xc3\xa0\xc3\x89\xc3\xa4\xc3\xa0\xc3\x9f\xc3\xa5\xc3\x89\xc3\x9f\xc3\xa5\xc3\x89\xc3\xa4\xc3\xa0\xc3\x93\xc3\x89\xc3\x9a\xc3\x93\xc3\xa1\xc3\x89\xc2\xb7\xc3\x94\xc3\xa2\xc3\x97\xc3\x9a\xc3\x95\xc3\x93\xc3\x94\xc3\x89\xc2\xb3\xc3\x9a\xc3\x95\xc3\xa6\xc3\xaf\xc3\xa8\xc3\xa4\xc3\x9f\xc3\x99\xc3\x9a\xc3\x89\xc3\x85\xc3\xa4\xc3\x97\xc3\x9a\xc3\x94\xc3\x97\xc3\xa6\xc3\x94\xc3\x89\xc3\x97\xc3\x9a\xc3\xaf\xc3\xa1\xc3\x97\xc3\xaf\xc3\xa5\xc3\x89\xc3\x9f\xc3\x89\xc3\x94\xc3\x99\xc3\x9a\xc3\xa4\xc3\x89\xc3\xa6\xc3\x93\xc3\x97\xc3\x9c\xc3\x9c\xc3\xaf\xc3\x89\xc3\xa0\xc3\x97\xc3\xa2\xc3\x93\xc3\x89\xc3\x97\xc3\x89\xc3\x91\xc3\x99\xc3\x99\xc3\x94\xc3\x89\xc3\xa2\xc3\x9f\xc3\x94\xc3\x89\xc3\x96\xc3\xa3\xc3\xa4\xc3\x89\xc3\x9f\xc3\x89\xc3\xa6\xc3\x93\xc3\x97\xc3\x9c\xc3\x9c\xc3\xaf\xc3\x89\xc3\x93\xc3\x9a\xc3\x9e\xc3\x99\xc3\xaf\xc3\x89\xc3\xa4\xc3\xa0\xc3\x9f\xc3\xa5\xc3\x89\xc3\xa5\xc3\x99\xc3\x9a\xc3\x91\xc3\x89\xc3\x9f\xc3\x89\xc3\xa0\xc3\x99\xc3\xa8\xc3\x93\xc3\x89\xc3\xaf\xc3\x99\xc3\xa3\xc3\x89\xc3\xa1\xc3\x9f\xc3\x9c\xc3\x9c\xc3\x89\xc3\x93\xc3\x9a\xc3\x9e\xc3\x99\xc3\xaf\xc3\x89\xc3\x9f\xc3\xa4\xc3\x89\xc3\x97\xc3\xa5\xc3\xa1\xc3\x93\xc3\x9c\xc3\x9c\xc2\x97\xc3\x89\xc3\xaf\xc3\x99\xc3\xa3\xc3\xa4\xc3\xa3\xc3\x96\xc3\x93\xc2\x9a\xc3\x95\xc3\x99\xc3\x9b\xc2\x99\xc3\xa1\xc3\x97\xc3\xa4\xc3\x95\xc3\xa0\xc2\xa9\xc3\xa2\xc2\xab\xc2\xb3\xc2\xa3\xc3\xaf\xc2\xb2\xc3\x95\xc3\x94\xc3\x88\xc2\xb7\xc2\xb1\xc3\xa2\xc2\xa8\xc3\xab",
            ],
            ["mov1", 2, 120],
            ["mov1", 4, 15],
            ["mov1", 3, 1],
            ["x", 2, 2, 3],
            ["add", 2, 2, 4],
            ["nop", 0, 2],
            ["to0", 3],
            ["for_xor", 6, 3],
            ["mov1", 0, "Thanks."],
            ["mov1", 1, "Authorizing access..."],
            ["print", 0],
            ["mov3", 0, 0],
            ["for_xor", 0, 2],
            ["for_-", 0, 4],
            ["mov1", 5, 19],
            ["for_comp?", 0, 6, 5],
            ["print", 1],
            ["exit"],
            ["mov1", 1, "Access denied!"],
            ["print", 1],
            ["exit"],
        ]
    )
    

    有两个寄存器f3和f4,只要一个一个把注释搞出来就挺清楚的了。先读进去一个input放在f4的0位上面,然后把key读进去放在f3的6上面,先让key和0异或(迷惑行为),再让input和135异或,再减15。

    key="á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë"
    flag=''
    for i in range(len(key)):
        flag+=chr((ord(key[i])+15)^135)
    print(flag)

    脚本有坑,编码的问题,弄成之前/x的格式出不来,而且必须python3解,不清楚为什么。

    flag长得离谱,还有个404网站链接

    flag:flag{this_must_be_the_best_encryption_method_evr_henceforth_this_is_the_new_Advanced_Encryption_Standard_anyways_i_dont_really_have_a_good_vid_but_i_really_enjoy_this_song_i_hope_you_will_enjoy_it_aswell!_youtube.com/watch?v=E5yFcdPAGv0}

    [CFI-CTF 2018]powerPacked

    拿到手看了下,发现里面有packed by upx的字样,直接upx脱壳

    然后ida反编译不能f5

    掏出ghrida,确实还是挺好使的

    image-20220409145548539

    一个巨简单的加减

    a=[0x45,0x48,0x4b,0x7d,0x6b,0x61,0x6e,0x71,0x78,0x67,0x61,0x72,0x71,0x79,0x67,0x74,0x72,0x65]
    flag=""
    for i in a:
        flag+=chr(i-2)
    print flag

    image-20220409145755018

    flag:flag{i_love_powerpc}

    本文作者:Xunflash
    本文链接:https://xunflash.top/index.php/archives/BUUCTFRE.html
    最后修改时间:2022-04-09 15:01:51
    本站未注明转载的文章均为原创,并采用 CC BY-NC-SA 4.0 授权协议,转载请注明来源,谢谢!
    评论
    114514
    textsms
    支持 Markdown 语法
    email
    link
    评论列表
    暂无评论