目录
Reverse6 I_am_the_Mathematician
Reverse1 迷失之门
该用哪吧钥匙开门呢?
1.用Exeinfo PE打开附件中的ez.exe文件,该文件是64位可执行文件,没有加壳
2.用IDA Pro(64-bit)打开,直接反编译附件里的主函数main() ,即F5 查看伪代码,在此进行分析:
(1)使用 gets_s 获取用户输入并存储在 Buffer 中
(2)Buffer的长度 <= 0x1B,v7设为1。遍历 Buffer 的第 5 到第 25 个字符,检查是否都是小写字母或者下划线,如果有任何一个字符不是小写字母且不等于下划线,则将 v7 设为 0。后面再将Buffer传给check()函数进行检查
(3)Buffer的长度 > 0x1B,暂停程序
4.将我们输入的值做了一系列的计算,最后又把输入的值通过return check_2(a1) 传给了check_2() 函数里面
继续跟进分析 check() 函数(N对符号重命名)
(1)预先设置好一些字符数组,包含大写字母、小写字母和符号。
(2)遍历输入字符串的每个字符 a1[i] ,如果字符不是 ASCII 127 且大于 ASCII 32 ,进行进一步处理
(3)计算其与预定义字符数组对应字符的差值,根据计算的差值,将输入字符串的字符替换为预定义字符数组中的字符。如果某个字符的差值不符合条件,输出错误信息
(4)将经过处理的字符串传递给 check_2() 函数进行进一步处理
5.在check_2() 函数中发现flag,继续跟进分析 check_2() 函数(R将ASCII码转字符)
(1)逐字符验证输入字符串 a1 是否与预定义的字符串 "FSBBhKHKKdyXkDSJQPTJbpxgbH6" 完全匹配
(2)如果字符匹配,则继续比较下一个字符
(3)如果任何一个字符不匹配,则返回当前字符的 ASCII 值,函数结束
6.实现解密过程,利用字符集和 key 生成加密过程中使用的映射,根据映射和 key 还原原始字符串。写出并执行解密脚本拿到flag
def find_character_index(character, reference_string, base_offset):
return reference_string.find(character) + base_offset if character in reference_string else -1
def decode_sequence(encoded_sequence, cipher_key):
mapping = []
# Add additional mapping characters as needed.
alpha_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
alpha_lower = "abcdefghijklmnopqrstuvwxyz"
special_char_mapping = "0123456789+/-=!#&*()?;:*^%"
for character in encoded_sequence:
char_idx = find_character_index(character, alpha_upper, 0)
if char_idx == -1:
char_idx = find_character_index(character, alpha_lower, 26) # 4*6+2
if char_idx == -1:
char_idx = find_character_index(character, special_char_mapping, 52) # 4*13
if char_idx != -1:
mapping.append(char_idx)
else:
print("Invalid character, stopping.")
break
return ''.join(chr(cipher_key[i] + offset) for i, offset in enumerate(mapping))
encoded_message = "FSBBhKHHKdyXkDSJQPTJbpxgbH6"
cipher_key = [word for word in b"DABBZXQESVFRWNGTHYJUMKIOLPC"]
decoded_output = decode_sequence(encoded_message, cipher_key)
print(decoded_output)
Reverse2 CrypticConundrum
Do not get lost!
1.用Exeinfo PE打开附件中的Cryptic.exe文件,该文件是64位可执行文件,加了UPX壳
2.使用upx工具脱壳:Releases · upx/upx · GitHub
-
打开cmd命令行,cd+路径到达upx.exe所在目录
-
输入upx.exe或拖入upx.exe可以打开看指令
-
输入upx -d然后拖入待脱壳文件回车
3.去壳成功,用IDA Pro(64-bit)打开,直接反编译附件里的主函数main(),即F5 查看伪代码,在此进行分析:
(1)在处理输入后,验证其是否与预定义的值匹配
(2)mix() 和 Encryption() 函数对输入进行转换
4.继续跟进分析 mix() 函数
(1)mix() 函数经过一系列复杂的操作混淆输入字符串 input
(2)操作包括字符的加减法、字符串反转、根据辅助字符串 Str 的奇偶性调整字符等,最终将原始输入字符串的副本返回
(3)mix() 并非关键函数
5.继续跟进分析 Encryption() 函数,Encryption() 函数对输入字符串 input 进行复杂的多步骤加密处理。具体步骤如下:
(1)调用 NewEncryption() 函数对字符串进行初步加密
(2)反转字符串
(3)每隔一个字符进行异或操作
(4)所有字符与 key[2] 进行异或操作
(5)从倒数第二个字符开始,每个字符减去下一个字符的值
(6)将每个字符加上10
通过这些步骤,输入字符串 input 经过一系列复杂的变换,使得原始字符串变得更加混淆和加密
6.继续跟进分析 NewEncryption() 函数,NewEncryption() 函数对输入字符串 input 进行简单的加密处理,具体步骤如下:
(1)每个字符依次减去密钥字符串 key 中的字符值,密钥字符串 key 循环使用前四个字符
(2)反转输入字符串的前半部分和后半部分的字符位置
7.由以上分析可知,Encryption()函数为关键函数,通过动态调试寻找密文和key
动态调试中找到 v7 即 key:ISCC
动态调试中找到密文:0xA4 ,0x7A ,0xDD ,0x37 ,0x20 ,0x2C ,0x7D ,0xCB ,0xAD ,0x5E ,0x50 ,0xCA ,0xE7 ,0x35 ,0x79 ,0xA4 ,0x2F ,0xC5 ,0x9F ,0x6D ,0x20 ,0x22 ,0x99 ,0x87 ,0xE0 ,0x34
8.根据加密过程写出并执行解密脚本拿到flag
#include <stdio.h>
#include <string.h>
void Decrypt(char *enc, char *key, int len) {
// 所有字符减去10
for (int i = 0; i < len; ++i) {
enc[i] -= 10;
}
// 依次加上下一个字符的值
for (int i = 0; i < len - 1; ++i) {
enc[i] += enc[i + 1];
}
// 所有字符与 key[2] 进行异或操作
for (int i = 0; i < len - 1; ++i) {
enc[i] ^= key[2];
}
// 每隔一个字符进行异或操作
for (int i = 0; i < len; i += 2) {
enc[i] ^= key[i % 4];
}
// 反转字符串
for (int i = 0; i < len / 2; ++i) {
char temp = enc[i];
enc[i] = enc[len - i - 1];
enc[len - i - 1] = temp;
}
for (int i = 0; i < len / 2; ++i) {
char temp = enc[i];
enc[i] = enc[len - i - 1];
enc[len - i - 1] = temp;
}
// 每个字符加上 key 的相应字符值
for (int i = 0; i < len; ++i) {
enc[i] += key[i % 4];
}
}
int main() {
char enc[] = {0xA4 ,0x7A ,0xDD ,0x37 ,0x20 ,0x2C ,0x7D ,0xCB ,0xAD ,0x5E ,0x50 ,0xCA ,0xE7 ,0x35 ,0x79 ,0xA4 ,0x2F ,0xC5 ,0x9F ,0x6D ,0x20 ,0x22 ,0x99 ,0x87 ,0xE0 ,0x34 };
char key[] = "ISCC";
int len = strlen(enc);
// 解密
Decrypt(enc, key, len);
// 打印解密后的结果
printf("Decrypted data: %s\n", enc);
return 0;
}
Reverse3 Badcode
好学的小明又开始学习c++了,他猛猛写了一堆代码,并且很高兴实现了功能,但是我们发现,他的代码写的真的很差,这次他又将自己的秘密藏在里面,你能揭穿他的秘密吗?
1.用Exeinfo PE打开附件中的Badcode.exe文件,该文件是32位可执行文件,没有加壳
2.用IDA Pro(32-bit)打开,直接反编译附件里的主函数main() ,即F5 查看伪代码,在此分析关键代码
3.sub_401B60() 这个函数是接受两个参数的,IDA只识别出来一个参数,重新定义该函数并反编译它
用U将函数名称设为无定义,选中下面所有数据内容,按C转换为代码,再用F5反编译
4.从unknown_libname_3(input) ==24和跟进分析unknown_libname_3() 函数可以得知unknown_libname_3() 函数用于获取字符串的长度
跟进分析sub_401B60() 函数、sub_401B40() 函数和下方Buf1的赋值可知sub_401B40() 和sub_401B60(k)函数用于获取内存地址
5.跟进分析sub_201620
使用固定的种子值 0x18u 初始化随机数生成器,生成 0 到 9 之间的固定随机数,并转换为 ASCII 字符 '0' 到 '9'。
6.此处:
(1)判断输入字符串是否长度为24
(2)循环遍历input中的每个字符
(3)对每个字符进行变换。如果索引 j 是偶数,字符的ASCII值加2;如果是奇数,字符的ASCII值减3
7.此处:
(1)遍历 input 中的每个字符
(2)将v16中字符的ASCII值减去 48 转换成对应的整数值,然后与input中的字符进行异或运算
(3)将异或结果存储回 input的相应位置中
8.继续跟进分析 sub_4014C0() 函数
通过观察我们可以发现这是标准的XXTEA加密,密钥为 &unk_407018:0x12345678, 0x9ABCDEF0, 0xFEDCBA98, 0x76543210(小端序)
参考对比XXTEA的算法实现:TEA XTEA XXTEA-CSDN博客
密文:0x211D94C1 ,0xA4EBE805 ,0xAD8C722D ,0XC643DAD4 ,0XC5B19919 ,0X54B0B6B2
9.根据加密过程写出并执行解密脚本拿到flag
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
void btea(uint32_t* v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--)
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}
int main(){
uint32_t Buf2[6]= {0x211D94C1 ,0xA4EBE805 ,0xAD8C722D ,0xC643DAD4 ,0xC5B19919 ,0x54B0B6B2};
uint32_t key[] = { 0x12345678,0x9ABCDEF0,0x0FEDCBA98,0x76543210 };
btea(Buf2, -6, key);
unsigned char* p = (unsigned char*)Buf2;
for (int i = 0; i < 24; i++)
{
printf("%u,", p[i]); //将输出的p填充到下方a中
}
unsigned char a[] = { 64,82,68,69,113,78,56,125,45,122,109,61,73,92,78,122,104,80,82,113,80,65,99,120 };
char encbuf[] = "674094872038771148666737";
for (int i = 0; i < 24; i++)
{
a[i]=(encbuf[i] - '0') ^ a[i];
}
for (int i = 0; i < 24; i++)
{
if (i % 2)
{
a[i] -= 2;
}
else {
a[i] += 3;
}
}
for(int i = 0; i < 24; i++)
{
printf("%c",a[i]);
}
}
Reverse4 DLLCode
把鸡蛋放在同一个篮子里是一个错误的决定
解压附件拿到得到一个exe文件和一个dll文件
1.用Exeinfo PE打开附件中的BEIXUAN-6.exe文件,该文件是32位可执行文件,没有加壳
2.用IDA Pro(32-bit)打开,直接反编译附件里的主函数main() ,即F5 查看伪代码,在此分析关键代码:
(1)程序调用了Encode函数对明文进行操作,进到Encode()函数中,发现此处调用了外部的DLL动态库文件
3.IDA Pro(32-bit)打开附件里面的动态库文件BH_Dll.dll,反编译里面的Encode()函数,进行分析:
(1)检查a2[4]是否为 12,如果满足条件,对 a2的数据进行编码并存储在 a1中
(2)如果不满足条件,则直接在 a1中存储错误信息
(3)key为”ISCC“
4.回到main()函数中,经分析sub_4014D0() 进行了加密,在这个函数中:
(1)重新排序
(2)索引修改后为密文的后半部分
5.获取密文v8:[0 ,16 ,56 ,44 ,10 ,61 ,118 ,43 ,27 ,0 ,20 ,3 ,67 ,99 ,83 ,89 ,70 ,84 ,64 ,103 ,116 ,125 ,117 ,64 ]
8.根据加密过程写出并执行解密脚本拿到flag
data = [0,16,56,21,10,61,113,43,11,0,20,3,67,89,83,89,70,84,64,103,116,125,117,98]
first_part, second_part = data[:12], data[12:]
reordering = [2, 0, 3, 1, 6, 4, 7, 5, 10, 8, 11, 9]
s = [0] * 12
key = "ISCC"
for i in range(len(s)):
s[i] = second_part[reordering[i]]
for i in range(len(first_part)):
first_part[i] ^= ord(key[i % len(key)])
result = ""
for i in range(len(first_part)):
result += chr(first_part[i]) + chr(s[i])
print(result)
Reverse5 Find_All
当你走出这片森林,未来的光明将是你的收获,路途的脚印亦是你的宝藏
1.用Exeinfo PE打开附件中的ez.exe文件,该文件是32位可执行文件,没有加壳
2.用IDA Pro(32-bit)打开,直接反编译附件里的主函数main() ,即F5 查看伪代码
进行简单分析可知,该题为迷宫问题,密文数据在sub_4015F0() 函数里面
3.转到调用sub_4015F0() 函数的sub_401410() 函数,可以找到加密逻辑
4.提取出密文,构造解密的脚本,用ida自带的python环境跑,如下所示即可拿到flag
v4 = [get_wide_byte(0x00401625+i*7) for i in range(24)]
for i in range(0,len(v4) - 1,4):
v4[i + 2] ^= v4[i + 3]
v4[i + 1] ^= v4[i + 2]
v4[i] ^= v4[i + 1]
print(bytes(v4).decode())
Reverse6 I_am_the_Mathematician
The mathematician has a codebook.
Who is the mathematician and where is the true code?
1.用Exeinfo PE打开附件中的main.exe文件,该文件是32位可执行文件,没有加壳
2.用IDA Pro(32-bit)打开,直接反编译附件里的主函数main() ,即F5 查看伪代码
看到关键词:Fibonacci,题目似乎涉及斐波那契数列
3.分析代码发现代码进行简单的逐个字符累计减少前面的数值,写出并执行脚本code_book_21.txt密文进行解密
def fib(n):
a, b = 0, 1
lis = []
for _ in range(n):
lis.append(a)
a, b = b, a + b
return lis
with open(r"./code_book_21.txt", "r") as file:
data = file.read()
file.close()
target = fib(20)
assert target[-1] > len(data)
print(f"ISCC{{{''.join(data[i - 1] if i < len(data) else '' for i in target)}}}")
Reverse7 AI
小明刚刚学会深度学习,于是他信心满满制作了自己第一个人工智能模型,但是貌似训练出了一点问题。于是他很羞涩地将模型和按顺序读取的样本藏了起来。他认为你们永远发现不了,于是悄悄地又放了一个秘密在里面……(无需包裹ISCC{})
1.pyc文件是py文件编译后生成的字节码文件
使用pyc在线编译工具对附件中的pyc文件进行反编译得到源码 在线Python pyc文件编译与反编译
得到一个用于加密的Python脚本,将用户输入的长度为24的字符串 user_input 逐字符加密,然后与预期的 Base64 字符串进行比较。
简单阐述加密过程:
(1)遍历 user_input 的每个字符及其索引 i,根据索引 i 的奇偶性,调整当前字符的 ASCII 值ascii_val 如果 i 是偶数,则新 ASCII 值为 ascii_val + offset 如果 i 是奇数,则新 ASCII 值为 ascii_val - offset
(2)使用异或操作 (^) 对新的 ASCII 值进行加密,得到加密后的字符 encrypted_char。
(3)将加密后的字符添加到 encrypted 列表中。
2.根据加密过程写出并执行解密脚本拿到key1
import base64
def decrypt(encrypted_base64, offset_str):
encrypted_bytes = base64.b64decode(encrypted_base64)
encrypted_str = encrypted_bytes.decode('utf-8')
if len(encrypted_str) != 24:
return 'Invalid encrypted string length'
decrypted = []
for i, char in enumerate(encrypted_str):
offset = int(offset_str[i])
new_ascii = ord(char) ^ offset
if i % 2 == 0:
original_ascii = new_ascii - offset
else:
original_ascii = new_ascii + offset
decrypted_char = chr(original_ascii)
decrypted.append(decrypted_char)
return ''.join(decrypted)
offset_str = '123456789012345678901234'
encrypted_base64 = 'TWF/c1sse19GMW5gYVRoWWFrZ3lhd0B9'
decrypted_str = decrypt(encrypted_base64, offset_str)
print('Decrypted string: {}'.format(decrypted_str))
3.解压压缩包需要密码,输入key1,输入Key{Y0u_F1nd_The_key_w@}进行解压
4.查看model_net.png,该图片展现了使用 PyTorch 定义并加载神经网络模型的代码,由获取的图片和名称可以得知该模型用于数字识别和分类
(1)定义了包含三层全连接层的网络结构 Net
(2)从confused_digit_recognition_model.pt加载预训练的模型权重
(3)定义了一系列图像预处理步骤:将图像转换为灰度图像,调整图像大小为 28x28,将图像转换为 PyTorch 张量,归一化图像数据,使其均值为 0.5,标准差为 0.5
5.补全代码,识别图片得到key2
import torch
import os
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(28*28, 128)
self.fc2 = nn.Linear(128, 64)
self.fc3 = nn.Linear(64, 10)
def forward(self, x):
x = x.view(-1, 28*28)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
model = torch.load('confused_digit_recognition_model.pt')
model.eval()
transform = transforms.Compose([
transforms.Grayscale(num_output_channels=1),
transforms.Resize((28, 28)),
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
def process_image(image_path):
try:
image = Image.open(image_path) # 打开图像文件
image = transform(image) # 应用预处理管道
image = image.unsqueeze(0) # 增加一个批次维度,因为模型期望输入是 [batch_size, channels, height, width]
return image
except Exception as e:
print(f"Error processing image {image_path}: {e}")
return None
def predict(image, model):
output = model(image)
_, predicted = torch.max(output, 1)
return predicted.item()
def predict_images_in_folder(folder_path, model):
results = {}
for i in range(1, 25):
image_path = os.path.join(folder_path, f"{i}.png")
image = process_image(image_path)
if image is not None:
predicted_class = predict(image, model)
results[image_path] = predicted_class
else:
results[image_path] = 'Error processing image'
return results
folder_path = r'D:\\A________________iscc\\myISCC\\题目\\reverse\\AI\\AI\\PNG'
predictions = predict_images_in_folder(folder_path, model)
for image_name, prediction in predictions.items():
print(prediction,end='')
6.用密码key2解压压缩包对照表.7z,拿到对照表
7.依据对照表写出并执行脚本拿到flag
str='538863262298483714602759'
arry={'0':'@nd','1':'a!','2':'_', '3':'F', '4':'SSS','5':'W@','6':'K','7':'1','8':'C','9':'d'}
for i in str:
print(arry[i],end='')