RE学习日记(二)-- 按小组做好

题目名称:按小组做好

一、题目描述

二、解题过程

题目中说找到序列号为5B134977135E7D13的名字,然后下载文件,用PEiD查看文件是win 32位应用

idea打开文件,按F5查看反编译代码

分析主函数

函数一开始声明了很多变量,其中特别的是

char v8; // [sp+Ch] [bp-130h]@1
char v9; // [sp+Dh] [bp-12Fh]@1
char v10; // [sp+Eh] [bp-12Eh]@1

sp是栈顶指针,可以看出这三个变量的地址sp+Chsp+Dhsp+Eh是连续的。

然后程序由scanf(aS, &v11);接受一个输入并赋值给v11

v3 = 0;
for ( i = 0; v3 < (signed int)strlen(&v11); ++i )
{
if ( i >= 3 )
i = 0;
sprintf(&v15, aS02x, &v15, *(&v11 + v3++) ^ *(&v8 + i));
}

v3 作为索引,循环遍历 v11 中的每个字符。

其中sprintf()函数是一个关键,它用于将格式化的数据输出到一个字符串中。用在需要将多种数据类型格式化为字符串或者将多个字符串拼接在一起的场合。其中aS02x是将字符串格式化为两个一组的16进制数。

*(&v11 + v3++):取 v11 的当前字符,v3++ 是后置递增操作,表示以v3作为v11的下标依次取v11中的值。

*(&v8 + i):从v8的地址开始往后取三个值(i>=3),从上面声明变量处已经发现v8v9v10是三个地址连续的值,所以这里就是取 v8, v9, v10 中的值。

*(&v11 + v3++) ^ *(&v8 + i):用v11中取的值与v8v9v10进行异或运算,将结果存储在 v15 中。

最后根据aS02x的格式进行字符串格式化储存在v15中。

memset(&v11, 0, 0x64u);
sub_4011B9((int)aInputSerial, v7);
scanf(aS, &v11);
if ( !strcmp(&v11, &v15) )
{
sub_4011B9((int)aCorrect, *(int *)&v8);
result = 0;
}
else
{
sub_4011B9((int)aWrong, *(int *)&v8);
result = 0;
}

使用 scanf 读取另一个字符串(Serial)到 v11

字符串比较使用strcmp比较v11v15。如果相同,显示正确信息。如果不同,显示错误信息。

我们结合程序运行的逻辑可以发现整个程序就是对Name的值进行异或操作然后格式化为两个一组的16进制数,然后与Serial进行比较。

按照这个逻辑我们对Serial进行反向操作就可以得到Name的值,由于Name最后是被格式化为两个一组的16进制数存储的。

所以我们也要将Serial分为两个一组的16进制格式,然后与v8v9v10的值进行异或运算。

得到Name后运行程序验证一下

Correct!说明我们得到的Name是正确的。

三、解题脚本

Serial = [0x5B, 0x13, 0x49, 0x77, 0x13, 0x5E, 0x7D, 0x13]
Name = ''
v8 = [16, 32, 48]

for i in range(len(Serial)):
Name += chr(Serial[i] ^ v8[i % 3])

print(Name)

四、提交结果

五、flag

flag{K3yg3nm3}