周赛博客篇

本文描述了一次逆向工程分析过程,涉及使用ida64对64位程序进行查壳和反编译。文章详细讲解了如何分析三个加密函数,包括SHA1哈希、简单的异或操作以及Base64解码,并给出了相应的解密脚本。最后,利用z3求解器解密了一组方程组,得到了最终的解密结果。
摘要由CSDN通过智能技术生成

easy-re

下载完后进行查壳,如下图,发现无壳且为64位程序用ida64打开
在这里插入图片描述
进去查看字符串发现了几组字符串看着挺可疑但是嘶好像光看这没啥用
在这里插入图片描述
然后接下来看反编译分析了一波是有三个加密的fun函数
在这里插入图片描述
接着就从fun1开始分析到fun3结束,接下来先看fun1加密函数,fun1我们可以看出他是哈希算法的sha1加密,而在主函数中,这里加密后的字符串为f7fae20f2f0b7facff1281fdd1e8fdf6d14cd4c1

int __fastcall fun1(unsigned __int8 *a1, __int64 a2, char *a3)
{
  __int64 v3; // rdx
  int result; // eax
  unsigned int v5[8]; // [rsp+20h] [rbp-70h] BYREF
  unsigned __int8 v6[68]; // [rsp+40h] [rbp-50h] BYREF
  unsigned int v7; // [rsp+84h] [rbp-Ch]
  unsigned int Size; // [rsp+88h] [rbp-8h]
  unsigned int Size_4; // [rsp+8Ch] [rbp-4h]

  v5[0] = 1732584193;
  v5[1] = -271733879;
  v5[2] = -1732584194;
  v5[3] = 271733878;
  v5[4] = -1009589776;
  for ( Size = a2; Size > 0x3F; Size -= 64 )
  {
    v3 = a2 - Size;
    *(_QWORD *)v6 = *(_QWORD *)&a1[v3];
    *(_QWORD *)&v6[8] = *(_QWORD *)&a1[v3 + 8];
    *(_QWORD *)&v6[16] = *(_QWORD *)&a1[v3 + 16];
    *(_QWORD *)&v6[24] = *(_QWORD *)&a1[v3 + 24];
    *(_QWORD *)&v6[32] = *(_QWORD *)&a1[v3 + 32];
    *(_QWORD *)&v6[40] = *(_QWORD *)&a1[v3 + 40];
    *(_QWORD *)&v6[48] = *(_QWORD *)&a1[v3 + 48];
    *(_QWORD *)&v6[56] = *(_QWORD *)&a1[v3 + 56];
    round(v6, v5);
  }
  if ( Size <= 0x37 )
  {
    memset(v6, 0, 0x40ui64);
    memcpy(v6, &a1[a2 - Size], Size);
    v6[Size] = 0x80;
    for ( Size_4 = 56; Size_4 <= 0x3F; ++Size_4 )
      v6[Size_4] = (8 * a2) >> (8 * (63 - (unsigned __int8)Size_4));
  }
  else
  {
    memset(v6, 0, 0x40ui64);
    memcpy(v6, &a1[a2 - Size], Size);
    v6[Size] = 0x80;
    round(v6, v5);
    memset(v6, 0, 0x40ui64);
    for ( Size_4 = 56; Size_4 <= 0x3F; ++Size_4 )
      v6[Size_4] = (8 * a2) >> (8 * (63 - (unsigned __int8)Size_4));
  }
  result = round(v6, v5);
  for ( Size_4 = 0; Size_4 <= 0x13; ++Size_4 )
  {
    v7 = (unsigned __int8)(v5[Size_4 >> 2] >> (8 * (~(_BYTE)Size_4 & 3)));
    result = sprintf(&a3[2 * Size_4], "%02x", v7);
  }
  return result;
}

但由于是周赛所以flag的格式是一定的都是SLsec{,这样前六位就可以确定下来了,接下来就是脚本问题了,这个爆破脚本找了好多表示找不到根本找不到,所以这里就只能借鉴学长给的脚本了

import hashlib
known_prefix = "SLsec{"
known_hash = "f7fae20f2f0b7facff1281fdd1e8fdf6d14cd4c1"

# 枚举后两位字符
for i in range(256):
    for j in range(256):
        candidate = known_prefix + chr(i) + chr(j)
        candidate_hash = hashlib.sha1(candidate.encode()).hexdigest()
        if candidate_hash == known_hash:
            print("Found the original string: ", candidate)
            exit()

运行结果为SLsec{co,第一段ok接下来我们看第二个加密函数fun2

char *__fastcall fun2(char *a1, char *a2)
{
  char *result; // rax
  size_t v3; // [rsp+20h] [rbp-10h]
  size_t i; // [rsp+28h] [rbp-8h]

  v3 = strlen(a1);
  for ( i = 0i64; i < v3; ++i )
    a2[i] = (a1[i] ^ 0x66) + 66;
  result = &a2[v3];
  a2[v3] = 0;
  return result;
}

这里就是一个简单的异或,加密后的字符串为JBUWED{WK,所以这里写一个简单的异或脚本``

def decrypt(a2):
    v3 = len(a2)
    a1 = bytearray(v3)

    for i in range(v3):
        a1[i] = (a2[i] - 66) ^ 0x66

    return a1.decode('utf-8')

encrypted_str = "JBUWED{WK"
decrypt_attempt = decrypt(encrypted_str.encode('utf-8'))

print(decrypt_attempt)

运行结果为nfused_so
在这里插入图片描述
最后看fun3加密函数,加密后的字符串为WPrYVgNoQx6vTPNuU8e!,再点进去函数里面看看发现是base表换了的base64但还是base64加密,这里找一个在线网站base64自定义解码
fun3加密函数为

_BYTE *__fastcall fun3(const unsigned __int8 *a1, int a2)
{
  int v3; // eax
  int v4; // eax
  int v5; // eax
  int v6; // eax
  int v7; // eax
  char v8[72]; // [rsp+20h] [rbp-60h] BYREF
  _BYTE *v9; // [rsp+68h] [rbp-18h]
  int v10; // [rsp+74h] [rbp-Ch]
  int v11; // [rsp+78h] [rbp-8h]
  int i; // [rsp+7Ch] [rbp-4h]

  strcpy(v8, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz+/@!#$");
  v10 = 4 * ((a2 + 2) / 3);
  v9 = malloc(v10 + 1);
  if ( !v9 )
    return 0i64;
  i = 0;
  v11 = 0;
  while ( i < a2 )
  {
    v9[v11] = v8[a1[i] >> 2];
    if ( a2 <= i + 1 )
      v3 = 0;
    else
      v3 = a1[i + 1] >> 4;
    v9[v11 + 1] = v8[(16 * a1[i]) & 0x30 | v3];
    if ( a2 <= i + 1 )
    {
      v5 = 0;
    }
    else
    {
      if ( a2 <= i + 2 )
        v4 = 0;
      else
        v4 = a1[i + 2] >> 6;
      v5 = (4 * a1[i + 1]) & 0x3C | v4;
    }
    v9[v11 + 2] = v8[v5];
    if ( a2 <= i + 2 )
      v6 = 0;
    else
      v6 = a1[i + 2] & 0x3F;
    v9[v11 + 3] = v8[v6];
    i += 3;
    v11 += 4;
  }
  for ( i = a2; i % 3; ++i )
  {
    v7 = v11++;
    v9[v7] = 61;
  }
  v9[v11] = 0;
  return v9;
}

解密后为ul_run_quietly}
在这里插入图片描述
所以第三段flag为ul_run_quietly},所以将三段flag何在一起也就是SLsec{confused_soul_run_quietly}

你会解方程组不会

查壳无壳用ida打开,进入主函数的反编译
image-20230422001942638
for循环是对输入的字符出进行异或加密,然后看v1,是一个if函数,函数里面是一堆方程组,然后用z3方程组解密即可

from z3 import *

v2 = Int('a2')
v3 = Int('a3')
v4 = Int('a4')
v5 = Int('a5')
v6 = Int('a6')
v7 = Int('a7')
v8 = Int('a8')
v9 = Int('a9')
v10 = Int('a10')
v11 = Int('a11')
v12 = Int('a12')
v13 = Int('a13')
v14 = Int('a14')
v15 = Int('a15')
s = Solver()

s.add(15 * v11
     + -36 * v10
     + 13 * v9
     + 25 * v8
     + 43 * v6
     + 65 * v4
     + 88 * v2
     + 67 * v3
     - 5 * v5
     + 89 * v7
     + 11 * v12
     + 47 * v13
     - 60 * v14
     + 29 * v15 == 22748,
     -41 * v13
     + 2 * v12
     + 8 * v11
     + 7 * v3
     + 89 * v2
     + 12 * v4
     - 25 * v5
     + 41 * v6
     + 23 * v7
     + 20 * v8
     - 66 * v9
     + 31 * v10
     - 39 * v14
     + 17 * v15 == 7258,
     -34 * v14
     + 90 * v13
     + 101 * v12
     + -33 * v10
     + 15 * v9
     + 27 * v8
     + 53 * v6
     + 35 * v3
     + 28 * v2
     + 16 * v4
     - 65 * v5
     + 39 * v7
     + 13 * v11
     + 23 * v15 == 26190,
     (v9 * 128)
     + 81 * v7
     + -59 * v5
     + 35 * v4
     + 34 * v3
     + 23 * v2
     + 49 * v6
     + 25 * v8
     - 32 * v10
     + 75 * v11
     + 81 * v12
     + 47 * v13
     - 60 * v14
     + 29 * v15 == 37136,
     90 * v8
     + 79 * v7
     + 42 * v6
     + -52 * v5
     + 35 * v4
     + 97 * v3
     + 38 * v2
     + 23 * v9
     - 36 * v10
     + 57 * v11
     + 81 * v12
     + 42 * v13
     - 62 * v14
     - 11 * v15 == 27915,
     -61 * v14
     + 41 * v12
     + -26 * v10
     + 49 * v7
     + 47 * v6
     + -45 * v5
     + 35 * v4
     + 22 * v2
     + 27 * v3
     + 29 * v8
     + 18 * v9
     + 35 * v11
     + 40 * v13
     + 28 * v15 == 17298,
     43 * v13
     + 76 * v12
     + 34 * v11
     + -47 * v10
     + 85 * v9
     + 23 * v8
     + 86 * v7
     + -42 * v6
     + 45 * v3
     + 12 * v2
     + 35 * v4
     - 9 * v5
     - 44 * v14
     + 65 * v15 == 19875,
     57 * v13
     + 25 * v11
     + -30 * v10
     + 86 * v8
     + 79 * v7
     + 35 * v4
     + 62 * v3
     + 79 * v2
     - 85 * v5
     + 33 * v6
     + 14 * v9
     + 11 * v12
     - 50 * v14
     - 9 * v15 == 22784,
     47 * v13
     + 2 * v12
     + -36 * v10
     + 2 * v8
     + 29 * v7
     + (v4 * 64)
     + 8 * v2
     + 6 * v3
     - 85 * v5
     + 73 * v6
     + 23 * v9
     + 5 * v11
     - (v14 * 64)
     + 27 * v15 == 9710,
     41 * v12
     + -38 * v10
     + -51 * v5
     + 68 * v4
     + -68 * v3
     + 67 * v2
     - 43 * v6
     + 81 * v7
     + 22 * v8
     - 12 * v9
     + 75 * v11
     + 27 * v13
     - 52 * v14
     + 31 * v15 == 13376,
    -67 * v14
     + 31 * v12
     + 15 * v9
     + -51 * v5
     + 63 * v3
     + 85 * v2
     + 5 * v4
     + 44 * v6
     + 36 * v7
     + 28 * v8
     - 6 * v10
     + 45 * v11
     + 7 * v13
     + 78 * v15 == 24065,
     43 * v13
     + -35 * v10
     + 25 * v8
     + 43 * v6
     + 47 * v2
     + (v3 * 64)
     + 66 * v4
     - 5 * v5
     + 112 * v7
     + 13 * v9
     + 95 * v11
     + 21 * v12
     - 61 * v14
     + 20 * v15 == 27687,
      -61 * v14
     + 47 * v13
     + 89 * v12
     + 14 * v11
     + -92 * v10
     + 56 * v9
     + 23 * v8
     + 89 * v7
     + 49 * v6
     + -25 * v5
     + 85 * v4
     + 67 * v3
     + 89 * v2
     - 29 * v15 == 29250,
    -60 * v14
     + 51 * v12
     + 16 * v11
     + 12 * v9
     + 25 * v8
     + -43 * v6
     + 34 * v3
     + 95 * v2
     + 62 * v4
     - 9 * v5
     + 83 * v7
     - 36 * v10
     + 47 * v13
     - 24 * v15 == 15317)

if 'un' not in str(s.check()):
    print(s.model())   #输出解

这里解出了方程组的解,但是要注意有些数据换了位置所以要把数据调整后在进行for循环的异或解密,异或脚本如下

direct ={       
     13 : 74,
     3 : 24,
     4 : 119,
     10 : 108,
     12 : 88,
     7 : 43,
     14 : 88,
     9 : 91,
     6 : 104,
     5 : 7,
     8 : 28,
     15 : 33,
     2 : 10,
     11 : 52}
flag = [0 for i in range(15)]
for i in direct:
    flag[i-2] = direct[i]  

for i in range(13, -1, -1):
    flag[i] ^= flag[i + 1]   
flag_str = ''
for i in range(14):
     flag_str += chr(flag[i])
print(flag_str)

运行两端脚本后即可得出flagSLsec{U_G07_th3_k3y!}
但是这里要注意的是在运用z3模块的时候要下载z3和z3-solve两个模块,这样才能保证脚本的正常运行

总结

我是小趴菜!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值