2024年网鼎杯青龙组逆向2题wp

把附件拖入ida

shift+F12查看可疑字符串 这里很明显看到了AES加密,还有一个base64编码表。猜测解密方式和AES加密,base64编码有关

进入主函数查看 F5反编译查看伪c代码

这里我们一点一点搓代码

1.除二解密

  1. 提示用户输入标志。
  2. 检查用户输入的长度是否为 40,以及是否以 "wdflag{" 开头且第 32 个字符为 '}'。
  3. v20 的前 32 个字符复制到 dest
  4. dest 中的前 8 个元素乘以 2 并存储到 s1 中。

这里的加密过程很简单,将s2数组的前八位数字都乘以2。逆向解密过程只要将s2数组的前八位都除2就得到了flag的前八位了。

解密脚本

python 复制代码
# 定义给定的十进制数列表
decimal_numbers = [96, 98, 110, 96, 196, 102, 114, 198]

# 除以2并将结果转换为对应的字符
characters = [chr(num // 2) for num in decimal_numbers]

# 打印结果
print(characters)

并且得到前八位

2.异或加密

  • 定义了一个字符串 v22,赋值为 "XorrLord"。
  • v11 数组的索引位置 2 到 5 分别赋值为 22, 64, 120, 12。
  • 通过循环,计算 dest 数组中索引从 8 到 15 的元素与 v22 字符串对应位置的元素的异或结果,保存到数组 v13 中。

这里有个点,数组的值给的不全,是ida编译时可能出了点问题,这里我们只需要按tab键进入流程窗口,查看数组的值即可

加密的过程就是将V11数组的值与XorrLord进行异或,解密的过程就是逆向一下就好啦。

解密脚本

python 复制代码
# 给定的十进制数列表
nums1 = [109, 10, 22, 64, 120, 12, 68, 87]
# 另一个十进制数列表
nums2 = [88, 111, 114, 114, 76, 111, 114, 100]

# 进行逐个异或运算
result = [num1 ^ num2 for num1, num2 in zip(nums1, nums2)]

# 将异或结果转换为字符
char_result = [chr(num) for num in result]

print("异或结果(字符):", ''.join(char_result))

得到flag的第八位到第十五位

3.变种的base64解密

进入base64_encode函数

python 复制代码
_BYTE *__fastcall base64_encode(__int64 a1, unsigned __int64 a2, __int64 a3)
{
  int v3; // eax
  int v4; // eax
  int v5; // eax
  int v6; // eax
  int v7; // eax
  int v8; // eax
  _BYTE *result; // rax
  unsigned __int64 v10; // [rsp+8h] [rbp-30h]
  unsigned int v11; // [rsp+20h] [rbp-18h]
  int v12; // [rsp+28h] [rbp-10h]
  int v13; // [rsp+2Ch] [rbp-Ch]
  int v14; // [rsp+30h] [rbp-8h]
  int v15; // [rsp+34h] [rbp-4h]

  v10 = a2;
  v15 = 0;
  v14 = 0;
  while ( v15 < a2 )
  {
    v3 = v15++;
    v13 = *(unsigned __int8 *)(v3 + a1);
    if ( v15 >= a2 )
    {
      v5 = 0;
    }
    else
    {
      v4 = v15++;
      v5 = *(unsigned __int8 *)(v4 + a1);
    }
    v12 = v5;
    if ( v15 >= a2 )
    {
      v7 = 0;
    }
    else
    {
      v6 = v15++;
      v7 = *(unsigned __int8 *)(v6 + a1);
    }
    v11 = (v12 << 8) + (v13 << 16) + v7;
    *(_BYTE *)(a3 + v14) = base64_table[(v11 >> 18) & 0x3F];
    *(_BYTE *)(a3 + v14 + 1) = base64_table[(v11 >> 12) & 0x3F];
    *(_BYTE *)(a3 + v14 + 2) = base64_table[(v11 >> 6) & 0x3F];
    v8 = v14 + 3;
    v14 += 4;
    *(_BYTE *)(a3 + v8) = base64_table[v11 & 0x3F];
  }
  while ( v10 % 3 )
  {
    *(_BYTE *)(--v14 + a3) = 61;
    ++v10;
  }
  result = (_BYTE *)(v14 + a3);
  *result = 0;
  return result;
}

解密过程就是对字符串BYOzAjWyAVA进行变种的base64解密,新的base64编码表是DEFGHIJKLMNOPQRSTUVWXYZABabcdefghijklmnopqrstuvwxyz0123456789+/

但是这里有个小坑,新的base64编码表少了个C。我们手动给它加上去就好了,所以真正的编码表是CDEFGHIJKLMNOPQRSTUVWXYZABabcdefghijklmnopqrstuvwxyz0123456789+/

解密脚本

python 复制代码
import base64

# 自定义Base64编码表
base64_chars = 'CDEFGHIJKLMNOPQRSTUVWXYZABabcdefghijklmnopqrstuvwxyz0123456789+/'

# 待解码的Base64编码字符串
encoded_str = 'BYOzAjWyAVA'

# 添加正确的填充字符 "=",使长度变为4的倍数
while len(encoded_str) % 4 != 0:
    encoded_str += '='

# 使用自定义编码表解码
decoded_bytes = base64.b64decode(encoded_str.translate(str.maketrans(base64_chars, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')))

# 解码成字符串
decoded_text = decoded_bytes.decode('utf-8')

print("Decoded string:", decoded_text)

flag的第三个八位也得到了

4.AES加密

简单介绍一下AES算法

AES(Advanced Encryption Standard)是一种对称加密算法,广泛用于加密和解密数据。AES算法有三种密钥长度:128位、192位和256位。它将明文(plaintext)转换为密文(ciphertext),并将密文转换回明文。

AES的基本步骤包括:

  1. SubBytes(字节替代):将每个字节替换为S盒中对应的值。
  2. ShiftRows(行移位):对每一行进行循环移位操作。
  3. MixColumns(列混淆):对每一列进行固定的矩阵乘法。
  4. AddRoundKey(轮密钥加):将轮密钥与状态矩阵进行按位异或操作。

这些步骤在加密和解密过程中稍有不同,但遵循类似的原理。

AES加密流程:

  1. 密钥扩展:生成轮密钥。
  2. 初始轮密钥加:将明文与初始轮密钥进行异或操作。
  3. 多轮加密:重复固定数量的轮次,每轮包括SubBytes、ShiftRows、MixColumns和AddRoundKey操作。
  4. 最终轮:省略MixColumns,仅执行SubBytes、ShiftRows和AddRoundKey操作。
  5. 输出密文:最后一轮操作后得到的密文即为加密结果。

AES解密流程:

  1. 密钥扩展:生成轮密钥。
  2. 初始轮密钥加:将密文与最后一轮轮密钥进行异或操作。
  3. 多轮解密:逆序执行每轮的逆操作。
  4. 最终轮:省略MixColumns,仅执行逆SubBytes、逆ShiftRows和AddRoundKey操作。
  5. 输出明文:最后一轮操作后得到的明文即为解密结果。

这里的AES加密的密钥是AesMasterAesMast,明文是V4数组。

解密过程是将字符串密钥 "AesMasterAesMast" 编码为字节序列,作为AES解密所需的密钥。然后使用 ECB 模式初始化了一个AES解密器。最后使用 Cryptodome.Util.Padding 模块中的 unpad 函数去除填充,将解密后的数据恢复到原始状态。

解密脚本

python 复制代码
from Cryptodome.Cipher import AES
from Cryptodome.Util.Padding import unpad

# 提供的数据 v4
v4 = bytes([0xF6, 0xAB, 0x47, 0xBE, 0x71, 0xE4, 0x01, 0xDC, 0x03, 0x30, 0x9F, 0xF1, 0x43, 0xF1, 0xD3, 0x66])

# 使用"AesMasterAesMast"作为密钥
key = "AesMasterAesMast".encode()

# 初始化AES解密器
cipher = AES.new(key, AES.MODE_ECB)

# 解密数据
decrypted_data = cipher.decrypt(v4)

# 去除填充
unpadded_data = unpad(decrypted_data, AES.block_size)

# 输出解密后的数据
print("Decrypted data:", unpadded_data)

得到flag的最后部分

5.总结

将上面的四个部分拼接一下就得到flag了

wdflag{0170b39c5ed24c63ec3b52a6724ba7d5}

由于我写脚本能力的不熟练,所以只能将代码拆开一部分一部分的解密。但凡加密过程复杂点,我写脚本能耗好久。这次比赛的逆向题更是深有体会,只能努力提升自己写脚本的能力。

相关推荐
蜡笔小新星5 分钟前
针对初学者的PyTorch项目推荐
开发语言·人工智能·pytorch·经验分享·python·深度学习·学习
denghai邓海15 分钟前
基于势能的平面运动模拟
python·平面·状态模式
为啥不能修改昵称啊15 分钟前
静态数据区,堆,栈
java·jvm·算法
zx_zx_12322 分钟前
stack和queue --->容器适配器
开发语言·c++·算法
小周不摆烂23 分钟前
【学术论文投稿】Python网络爬虫全攻略:从零到一,打造你的数据收集利器
python
编程修仙27 分钟前
Java继承练习
java·开发语言·python
Pocker_Spades_A28 分钟前
Python学习的自我理解和想法(27)
python·学习·pycharm
laocooon52385788636 分钟前
代码之玫瑰。C++
前端·算法
hai4058737 分钟前
基于python主观题自动阅卷系统毕业设计项目
spring boot·python·jmeter·django·make与makefile
colman wang1 小时前
数据结构和算法入门
数据结构·算法