确实恶心。
本题的整体逻辑是通过输入的字符串变换that_girl文件,再把变换的数据写入out文件。属于已知密文求明文。
整体逻辑是通过对that_girl文本文件进行词频分析。
- 将输入的字符串转换为对应词频数组v1。
- 对v1进行类似与a=b,b=c,c=a 的元素顺序交换,记为v2。
- 将整个v2视为一整个二进制流循环左移3位,记为v3。
- 将v3写入out文件
解密脚本如下:
#include <stdio.h>
#include<stdlib.h>
#include <windows.h>
#include<map>
using namespace std;
unsigned int sub_400936(char a1)
{
unsigned int result; // rax
result = (unsigned int)(a1 - 10);
switch ( a1 )
{
case 10:
result = (unsigned int)(a1 + 35);
break;
case 32:
case 33:
case 34:
result = (unsigned int)(a1 + 10);
break;
case 39:
result = (unsigned int)(a1 + 2);
break;
case 44:
result = (unsigned int)(a1 - 4);
break;
case 46:
result = (unsigned int)(a1 - 7);
break;
case 58:
case 59:
result = (unsigned int)(a1 - 21);
break;
case 63:
result = (unsigned int)(a1 - 27);
break;
case 95:
result = (unsigned int)(a1 - 49);
break;
default:
if ( a1 <= 0x2F || a1 > 0x30 )
{
if ( a1 <= '@' || a1 > 'Z' )
{
if ( a1 > '`' && a1 <= 'z' ) // a-z
result = (unsigned int)(a1 - 87);
}
else
{
result = (unsigned int)(a1 - 55); // A-Z
}
}
else
{
result = (unsigned int)(a1 - 48); // 0
}
break;
}
return result;
}
char find_ch(int p , int* f)
{
char ch = 'a';
while(ch != 'z'+1)
{
if(f[sub_400936(ch)] == p)
return ch;
ch++;
}
if(f[sub_400936('_')] == p)
return '_';
if(f[sub_400936('\'')] == p)
return '\'';
return 0;
} //经观察发现文本文件只有这几个字符
unsigned char ida_chars[] =
{
0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x12, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x04, 0x00,
0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x14, 0x00,
0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x24, 0x00,
0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
0x1D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x1F, 0x00,
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00,
0x00, 0x00
}; //38
int main(int argc, char const *argv[])
{
unsigned char p[] ={0xec,0x29,0xe3,0x41,0xe1,0xf7,0xaa,0x1d,0x29,0xed,0x29,0x99,0x39,0xf3,0xb7,0xa9,0xe7,0xac,0x2b,0xb7,0xab,0x40,0x9f,0xa9,0x31,0x35,0x2c,0x29,0xef,0xa8,0x3d,0x4b,0xb0,0xe9,0xe1,0x68,0x7b,0x41};
unsigned char s[38] = {0};
int temp=p[37]&0x7;
for(int i=0;i<38;i++)
{
s[i]=(temp<<5)|(p[i]>>3);
temp=p[i]&0x7;
} //整体循环位移
////////////////////////////////////////////////
int* dword_6020A0 = (int*)ida_chars;
map<int,int>find_index;
int i;
for(i = 0 ; i < 38 ; i++)
{
find_index[dword_6020A0[i]] = i;
}
temp = s[1];
i = 1;
int j;
for(j = 0 ; j < 37 ; j++)
{
s[i] = s[find_index[i]];
i = find_index[i];
}
s[i] = temp;
//////////////////////////////////////////////////
int* rate = (int*)malloc(1000*sizeof(int)); //词频数组
memset(rate , 0 , 1000* sizeof(int));
FILE* fd = fopen("that_girl" , "r");
char ch;
while((ch = fgetc(fd)) != EOF)
{
rate[sub_400936(ch)]++;
}
/////////////////////////////////////////////////// a->10 z->35 _->46 '->41
for( i = 0 ; i < 38 ; i++)
{
printf("%c",find_ch(s[i] , rate));
}
return 0;
}