查看字符串,找到wrong,交叉引用找到关键函数
可知:flag长度为64,分4个块分别进行加密(即每次加密16个字节)。加密结束后与byte_292C80
进行比对
查看主要加密函数
可知:每次加密会进行16次循环,加密细节又分为4个部分。
分别查看这4个部分。
sub_218D5C
:
该函数的作用的就是将块中的每一个字节进行反转,例如:使 11010010
转变为 01001011
sub_218DF8
:
这个看起来比较复杂,但实际的功能就是对加密的一个块(16个字节)中的字节进行交换,打乱顺序。
其中两个for
语句实现的功能类似于:
void swap(int result[]) {
int temp[16];
for (int i = 0; i <= 15; ++i ){
temp[i + v4[i]] = result[i];
}
for (int j = 0; j <= 15; ++j ){
result[i] = temp[i];
}
}
就是通过一个存放在v4
中的索引来进行交换。而v4[4]
的仅仅只是起一个暂存的作用。
sub_218EF4
:该函数的作用的就是将块中的每一个字节的高3位与低5位的位置进行互换。
sub_218F54
:
简单异或
那么现在就可以编写逆向脚本了
#include <iostream>
using namespace std;
void dec_4(unsigned char block[],unsigned char num)
{
for (int i = 0; i < 16; ++ i )
block[i] ^= 120 * num;
}
void dec_3(unsigned char block[])
{
for (int i = 0; i < 16; ++i )
block[i] = block[i] << 5 | block[i] >> 3;
}
void dec_2(unsigned char block[])
{
unsigned int v4[16] = {
0x0000000D, 0x00000004, 0x00000000, 0x00000005, 0x00000002, 0x0000000C, 0x0000000B, 0x00000008,
0x0000000A, 0x00000006, 0x00000001, 0x00000009, 0x00000003, 0x0000000F, 0x00000007, 0x0000000E,
};
unsigned char temp[16];
for (int i = 0; i < 16; ++i )
temp[i] = block[i];
for (int i = 0; i < 16; ++ i )
block[i] = temp[v4[i]];
}
void dec_1(unsigned char block[])
{
char v1;
for (int i = 0; i < 16; ++ i )
{
v1 = 0;
for (int j = 0; j < 8; ++ j )
v1 |= ((block[i] >> j) & 1) << (7-j);
block[i] = v1;
}
}
int main()
{
unsigned char enc[65] = {
0x3D, 0x45, 0x38, 0x7E, 0x78, 0x4B, 0x6A, 0x5C, 0x5B, 0x52, 0x4C, 0x73, 0x4E, 0x39, 0x49, 0x5F,
0x49, 0x40, 0x38, 0x5E, 0x74, 0x40, 0x66, 0x44, 0x46, 0x7A, 0x39, 0x3B, 0x67, 0x39, 0x70, 0x6C,
0x71, 0x5E, 0x6D, 0x4D, 0x5A, 0x4C, 0x7F, 0x3B, 0x4D, 0x63, 0x5E, 0x4E, 0x44, 0x5A, 0x7B, 0x51,
0x38, 0x61, 0x29, 0x63, 0x75, 0x5B, 0x67, 0x46, 0x4E, 0x5D, 0x79, 0x29, 0x4D, 0x29, 0x6D, 0x71,
};
unsigned char block[4][16];
for (int i = 0; i < 4; ++ i )
for (int j = 0; j < 16; ++ j )
block[i][j] = enc[i*16+j];
for (int i = 0; i < 4; ++ i )
{
for (char j = 0x10-1; j >= 0; j --)
{
dec_4(block[i], j);
dec_3(block[i]);
dec_2(block[i]);
dec_1(block[i]);
}
}
for (int i = 0; i < 4; ++ i )
for (int j = 0; j < 16; ++ j )
printf("%c", block[i][j]);
return 0;
}
# DASCTF{51bWZvM0p1xNHLo3A1ndrVH0|VsED3LFyRwYkEVeRqeFSNE!0!oyUki!}
得到flag