• BUUCTF Reverse/[GWCTF 2019]re3


    在这里插入图片描述

    main函数代码,这里改写了内存空间的属性,还是自解密

    void __fastcall __noreturn main(int a1, char **a2, char **a3)
    {
      int i; // [rsp+8h] [rbp-48h]
      char s[40]; // [rsp+20h] [rbp-30h] BYREF
      unsigned __int64 v5; // [rsp+48h] [rbp-8h]
    
      v5 = __readfsqword(0x28u);
      __isoc99_scanf("%39s", s);
      if ( (unsigned int)strlen(s) != 32 )
      {
        puts("Wrong!");
        exit(0);
      }
      mprotect(&dword_400000, 0xF000uLL, 7);
      for ( i = 0; i <= 223; ++i )
        *((_BYTE *)sub_402219 + i) ^= 0x99u;
      sub_40207B(&unk_603170);
      sub_402219(s);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这里一坨数字,盲猜这里就是自解密的地方

    在这里插入图片描述

    整个idc脚本,运行完后选中这段数字,按c强制转换为代码,再将所有标红的部分选中按p,就能正常f5了

    #include 
    
    static main()
    {
        auto addr = 0x0040221A;   //这里填入要解密字节串的起始地址
        auto i = 0;
        for(i=0;i<=223;i++)   //循环结束的条件为字节串的结束地址
        {
            PatchByte(addr+i,Byte(addr+i)^0x99);   //异或的数字根据情况修改
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    反汇编出的伪代码

    __int64 __fastcall sub_40221A(__int64 a1)
    {
      unsigned int v2; // [rsp+18h] [rbp-D8h]
      int i; // [rsp+1Ch] [rbp-D4h]
      char v4[200]; // [rsp+20h] [rbp-D0h] BYREF
      unsigned __int64 v5; // [rsp+E8h] [rbp-8h]
    
      v5 = __readfsqword(0x28u);
      sub_400A71(v4, &unk_603170);
      sub_40196E(v4, a1);
      sub_40196E(v4, a1 + 16);
      v2 = 1;
      for ( i = 0; i <= 31; ++i )
      {
        if ( *(_BYTE *)(i + a1) != byte_6030A0[i] )
          v2 = 0;
      }
      return v2;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    明显byte_6030A0中就是最后变换的flag,可以shift+e提取出来

    在这里插入图片描述

    看了下sub_40196E(v4, a1); 中的加密算法,有点复杂不太想看,还是直接动调吧

    __int64 __fastcall sub_401828(__int64 a1, __int64 flag)
    {
      unsigned __int8 i; // [rsp+1Fh] [rbp-1h]
    
      sub_400B0A(0LL, a1, flag);
      for ( i = 1; i <= 9u; ++i )
      {
        sub_400BAC(a1);
        sub_400C1F(a1);
        sub_400D27(a1);
        sub_400B0A(i, a1, flag);
      }
      sub_400BAC(a1);
      sub_400C1F(a1);
      return sub_400B0A(10LL, a1, flag);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    方法参考:IDA动调ELF文件IDA远程动态调试(linux & Windows)

    添加权限

    在这里插入图片描述

    看下当前路径

    在这里插入图片描述

    填写对应信息

    在这里插入图片描述

    开始dbg,下断点输入32位字符

    在这里插入图片描述

    跟进 sub_401828,这里我把变量名改了下,方便看

    在这里插入图片描述

    这里就对flag进行了一波变换

    在这里插入图片描述

    看汇编代码,edi中存的就是输入flag的值,eax中存储的就是上面代码异或的值,打个断点,依次将eax的值记录下来

    在这里插入图片描述

    查看v4的值

    在这里插入图片描述

    直接跳转

    在这里插入图片描述

    在这里插入图片描述

    因为v4 的大小最大为200,就将7FFEA43B22E000007FFEA43B238A的数据提取出来

    在这里插入图片描述

    还是得写脚本来逆。。。

    试了下把 sub_40196E() 逆出来,,

    from z3 import *
    import numpy as np
    v4 = [
      0xCB, 0x8D, 0x49, 0x35, 0x21, 0xB4, 0x7A, 0x4C, 0xC1, 0xAE, 
      0x7E, 0x62, 0x22, 0x92, 0x66, 0xCE, 0x85, 0xBE, 0xC2, 0xA6, 
      0xA4, 0x0A, 0xB8, 0xEA, 0x65, 0xA4, 0xC6, 0x88, 0x47, 0x36, 
      0xA0, 0x46, 0x82, 0x5E, 0x98, 0x06, 0x26, 0x54, 0x20, 0xEC, 
      0x43, 0xF0, 0xE6, 0x64, 0x04, 0xC6, 0x46, 0x22, 0x32, 0x04, 
      0x0B, 0xF4, 0x14, 0x50, 0x2B, 0x18, 0x57, 0xA0, 0xCD, 0x7C, 
      0x53, 0x66, 0x8B, 0x5E, 0x09, 0x39, 0x53, 0x19, 0x1D, 0x69, 
      0x78, 0x01, 0x4A, 0xC9, 0xB5, 0x7D, 0x19, 0xAF, 0x3E, 0x23, 
      0x60, 0x8B, 0x75, 0xCD, 0x7D, 0xE2, 0x0D, 0xCC, 0x37, 0x2B, 
      0xB8, 0xB1, 0x2E, 0x84, 0x86, 0x92, 0x1F, 0xCF, 0x3A, 0xFC, 
      0x62, 0x2D, 0x37, 0x30, 0x55, 0x06, 0x8F, 0x81, 0x7B, 0x82, 
      0x09, 0x13, 0x4C, 0xCE, 0x47, 0xDD, 0x2E, 0xE3, 0x70, 0xED, 
      0x7B, 0xE5, 0xFF, 0x6C, 0x00, 0x67, 0xF6, 0x7F, 0x49, 0x8C, 
      0x95, 0xBE, 0x67, 0x6F, 0xE5, 0x53, 0x1C, 0x8A, 0x1A, 0x3F, 
      0x1C, 0xED, 0xEC, 0x40, 0x07, 0x42, 0x9C, 0x22, 0x60, 0x2D, 
      0x79, 0x71, 0x7C, 0xA7, 0x63, 0x4E, 0x60, 0x4A, 0x8F, 0x0E, 
      0xE7, 0x31, 0x37, 0xF2, 0x87, 0x1C, 0x4E, 0x83, 0xFB, 0xBB, 
      0x2D, 0xCD, 0x9B, 0xF1, 0xA2, 0xC3, 0x7A, 0xC5, 0xFB, 0xAC, 
      0x91, 0x1F, 0x3B, 0x36, 0x78, 0x41, 0xF8, 0xDC, 0xEC, 0xC9, 
      0xDB, 0x46, 0x00, 0x23, 0x40
    ]
    byte_4023A0 = [
      0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 
      0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 
      0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 
      0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 
      0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 
      0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 
      0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 
      0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 
      0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 
      0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 
      0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 
      0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 
      0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 
      0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 
      0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 
      0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 
      0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 
      0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 
      0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 
      0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 
      0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 
      0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 
      0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 
      0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 
      0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 
      0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
    ]
    def sub_400B0A(a1,flag):
        for i in range(4):
            for j in range(4):
                #print(i + 4 * j,"  " , 4 * (4 * a1 + i) + j)
                flag[i * 4 + j] ^= v4[4 * (4 * a1 + i) + j] 
                flag[i * 4 + j] %= 256
    
    
    def sub_400BAC(flag):
        for i in range(4):
            for j in range(4):
                #print(flag[i + 4 * j])
                flag[i + 4 * j] = byte_4023A0[flag[i + 4 * j]]
    def sub_400BAC_reverse(flag):
         for i in range(4):
            for j in range(4):
                flag[i + 4 * j] = byte_4023A0.index(flag[i + 4 * j])
    
    def sub_400C1F(flag):
        v2 = flag[1]
        flag[1] = flag[5]
        flag[5] = flag[9]
        flag[9] = flag[13]
        flag[13] = v2
        v3 = flag[2]
        flag[2] = flag[10]
        flag[10] = v3
        v4 = flag[6]
        flag[6] = flag[14]
        flag[14] = v4
        v5 = flag[3]
        flag[3] = flag[15]
        flag[15] = flag[11]
        flag[11] = flag[7]
        flag[7] = v5
    #flag移位
    def sub_400C1F_reverse(flag):
        v5 = flag[7]
        flag[7] = flag[11]
        flag[11] = flag[15]
        flag[15] = flag[3]
        flag[3] = v5
        v4 = flag[14]
        flag[14] = flag[6]
        flag[6] = v4
        v3 = flag[10]
        flag[10] = flag[2]
        flag[2] = v3
        v2 = flag[13]
        flag[13] = flag[9]
        flag[9] = flag[5]
        flag[5] = flag[1]
        flag[1] = v2
    
    def sub_400CFA(temp):
        return (2 * temp) ^ (27 * (temp // (2**7)))
    
    def sub_400D27(flag):
        for i in range(4):
            v2 = flag[4 * i]
            v3 = (flag[4 * i + 2] ^ flag[4 * i + 1] ^ v2 ^ flag[4 * i + 3]) % 256
            flag[4 * i] = (v3 ^ sub_400CFA(v2 ^ flag[4 * i + 1]) ^ v2) %256
            flag[4 * i + 1] ^= v3 ^ sub_400CFA(flag[4 * i + 1] ^ flag[4 * i + 2])
            flag[4 * i + 1] %= 256
            flag[4 * i + 2] ^= v3 ^ sub_400CFA(flag[4 * i + 2] ^ flag[4 * i + 3]) 
            flag[4 * i + 2] %= 256
            flag[4 * i + 3] ^= v3 ^ sub_400CFA(v2 ^ flag[4 * i + 3])
            flag[4 * i + 3] %= 256
    
    # 之前试的爆破脚本。。。超级慢
    def sub_400D27_reverse(flag):
        f = []
        for i in range(0,4):
            for j0 in range(33,128):
                for j1 in range(33,128):
                    for j2 in range(33,128):
                        for j3 in range(33,128):
                            temp = [j0,j1,j2,j3]
                            print(temp)
                            v2 = temp[0]
                            v3 = (temp[ 2] ^ temp[ 1] ^ v2 ^ temp[ 3]) % 256
                            temp[0] = (v3 ^ sub_400CFA(v2 ^ temp[ 1]) ^ v2) %256
                            temp[ 1] ^= v3 ^ sub_400CFA(temp[ 1] ^ temp[ 2])
                            temp[ 1] %= 256
                            temp[ 2] ^= v3 ^ sub_400CFA(temp[  2] ^ temp[ 3]) 
                            temp[ 2] %= 256
                            temp[3] ^= v3 ^ sub_400CFA(v2 ^ temp[  3])
                            temp[ 3] %= 256
                            if temp == flag[i:i+4]:
                                f.append(j0)
                                f.append(j1)
                                f.append(j2)
                                f.append(j3)
                                break
                    else:
                        continue
                    break
                else:
                    continue
                break
        flag = f[:]
        print(flag)
    
    #这里用了z3去解,,,但是中间有些解不出来
    def sub_400D27_reverse_2(flag):
        print(flag)
        f = []
        for i in range(4):
            print("flag",flag[4 * i:4*i + 4])
            s = Solver()
            t_0,t_1,t_2,t_3 = BitVecs('t_0 t_1 t_2 t_3',8)
            #t = [BitVecs(('t%d'% i),8) for i in range(4) ]
            '''
            for j in t:
                s.add(j>0)
                s.add(j<255)
            
            s.add(flag[4 * i] == t[0] ^ t[0] ^ t[1] ^ t[2] ^ t[3] ^ ( 2 * (t[0] ^ t[1]) ^ (27 * (t[0] ^ t[1]) >> 7)) )
            s.add(flag[4 * i + 1] == t[1] ^ t[0] ^ t[1] ^ t[2] ^ t[3] ^ ( ( 2 * (t[1] ^ t[2])) ^ (27 * (t[1] ^ t[2]) >> 7)) ) 
            s.add(flag[4 * i + 2] == t[2] ^ t[0] ^ t[1] ^ t[2] ^ t[3] ^ ( ( 2 * (t[2] ^ t[3])) ^ (27 * (t[2] ^ t[3]) >> 7)))
            s.add(flag[4 * i + 3] == t[3] ^ t[0] ^ t[1] ^ t[2] ^ t[3] ^  ( ( 2 * (t[0] ^ t[3])) ^ (27 * (t[0] ^ t[3]) >> 7)))
            '''
            s.add(flag[4 * i] == (t_0 ^ t_0 ^ t_1 ^ t_2 ^ t_3 ^ (( 2 * (t_0 ^ t_1) ^ (27 * (t_0 ^ t_1) >> 7)) % 256 )) % 256)
            s.add(flag[4 * i + 1] == (t_1 ^ t_0 ^ t_1 ^ t_2 ^ t_3 ^ ( (( 2 * (t_1 ^ t_2)) ^ (27 * (t_1 ^ t_2) >> 7)) % 256 )) % 256)
            s.add(flag[4 * i + 2] == (t_2 ^ t_0 ^ t_1 ^ t_2 ^ t_3 ^ ( (( 2 * (t_2 ^ t_3)) ^ (27 * (t_2 ^ t_3) >> 7)) % 256) ) % 256)
            s.add(flag[4 * i + 3] == (t_3 ^ t_0 ^ t_1 ^ t_2 ^ t_3 ^ ( ( ( 2 * (t_0 ^ t_3)) ^ (27 * (t_0 ^ t_3) >> 7)) % 256)) % 256)
            s.check()
            m = s.model()
            print(m)
            '''
            t_0,t_1,t_2,t_3 = BitVecs('t_0 t_1 t_2 t_3',8)
            v3 = t_0 ^ t_1 ^ t_2 ^ t_3
            s.add(flag[4 * i] == t_0 ^ t_1 ^ t_2 ^ t_3 ^ (2 * (t_0 ^ t_1)) ^ t_0) 
            '''
        flag = f[:]
        print(f)
    
    def sub_401828(flag):
        print(flag)
        sub_400B0A(0,flag)
        for i in range(1,10):
            sub_400BAC(flag)
            sub_400C1F(flag)
            sub_400D27(flag)
            sub_400B0A(i,flag)
        sub_400BAC(flag)
        sub_400C1F(flag)
        sub_400B0A(0xA,flag)
        return flag
    
    def sub_401828_reverse(flag):
        print("flag1",flag)
        sub_400B0A(0xA,flag)   #异或
        print("flag2",flag)
        sub_400C1F_reverse(flag)  #交换
        print("flag3",flag)
        sub_400BAC_reverse(flag)  #取值
        print("flag4",flag)
        for i in range(9,0,-1):
            sub_400B0A(i,flag)   #异或
            sub_400D27_reverse_2(flag)  #加密
            sub_400C1F_reverse(flag)
            sub_400BAC_reverse(flag)
        sub_400B0A(0,flag)
        return flag
    
    
    
    if __name__ == "__main__":
        flag = [0xBC, 0x0A, 0xAD, 0xC0, 0x14, 0x7C, 0x5E, 0xCC, 0xE0, 0xB1, 
      0x40, 0xBC, 0x9C, 0x51, 0xD5, 0x2B, 0x46, 0xB2, 0xB9, 0x43, 
      0x4D, 0xE5, 0x32, 0x4B, 0xAD, 0x7F, 0xB4, 0xB3, 0x9C, 0xDB, 
      0x4B, 0x5B]
        f = []
        f += sub_401828_reverse(flag[0:16])
        f += sub_401828_reverse(flag[16:]) 
        
        
        print(f)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232

    但是失败了,,,,估计中间步骤哪有问题。。。。翻了下别的大佬的wp,sub_40196E()是AES加密,,,白浪费时间写脚本了,寄

    在这里插入图片描述

    下断点运行到这里可以获得unk_603170的值 :CB8D493521B47A4CC1AE7E62229266CE ,这个是作为AES的初始秘钥

    在这里插入图片描述

    byte_6030A0的值也可以提出来:BC0AADC0147C5ECCE0B140BC9C51D52B46B2B9434DE5324BAD7FB4B39CDB4B5B

    直接AES解密就行

        flag = binascii.unhexlify('BC0AADC0147C5ECCE0B140BC9C51D52B46B2B9434DE5324BAD7FB4B39CDB4B5B')
        key = binascii.unhexlify('CB8D493521B47A4CC1AE7E62229266CE')
        mode = AES.MODE_ECB
        aes = AES.new(key,mode)
        text = aes.decrypt(flag)
        print(text)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    最终flag: flag{924a9ab2163d390410d0a1f670}

  • 相关阅读:
    数据标准详细概述-2022
    Linux systemctl 详解&自定义 systemd unit
    idea 无法识别vue3语法
    oracle数据库核心知识
    msfvenom常用参数
    山东涛雒镇万亩水稻 国稻种芯·中国水稻节:日照迎来收割季
    536、RabbitMQ详细入门教程系列 -【消息与队列进阶 RabbitMQ(二)】 2022.07.29
    Android学习笔记 73. 隐式intent
    Stanford CS143 速通PA1教程
    “淘宝拍立淘图片搜索接口:轻松找到同款商品!
  • 原文地址:https://blog.csdn.net/ookami6497/article/details/128009035