作者:笨笨雄
工具:VC
首先看看XOR的运算规则:
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0
1 XOR 1 = 0
注意到下面的规律:
p XOR k = c,c XOR k = p,p XOR c = k
把P看成明文,通过XOR运算后得到密文C,那么K值便是密钥。因此XOR常用于加密。由于简单,而且速度很快,常用于简单的字符加密,以对抗字符参考。本文仅讨论使用8位key,只作一次xor运算的情况。尽管安全性很差(p xor c = k),但是大家都喜欢用简单的方法
先从最简单的ASCII编码开始。它包括26个英文字母和10个数字以及一些符号。单字节的编码,而且最高位一般情况下为0。由于每个字节都由固定的KEY进行XOR加密,因此检查每一个字节的最高位是否相同,便能知道处理的字符是否为ASCII编码。
我们知道,英文使用空格(0x20)来分隔每一单词。这样便为我们提供了另外一个攻击XOR加密字符的途径。我猜想“congratulation!”大概是注册文本信息中可能出现的最长的一个单词。它的长度是15,也就是说我们可以从第16个字节开始,将密文XOR 0x20,得出KEY。现在需要穷举的KEY数量就只有15(我假设第一个字符不会为空格,最短的单词大概就只有i和a了。)
现在我们需要做的只是为注册信息中可能出现的单词建立一个字典,测试每一个KEY。下面是实现的C代码片段:
/*-----------------------------------------------------------------------代码:numread = fread (buffer,sizeof(char),150,srcfile);
for(a=16; a != 0; a--)
{
ckey = buffer[a] ^ 0x20; //从16字节开始xor 0x20
for (i=0; i != a; i++)
decode[i] = buffer[i] ^ ckey; //尝试用该key解密
if (bingo = KeyCheck(decode)) //keycheck测试key是否正确
break;
}
无key还原简单XOR字符示例
Code by 笨笨雄/www.pediy.com
下面是判断KEY是否正确的函数
------------------------------------------------------------------------*/
代码:char *map[10]= //字典
{
"key",
"valid",
"congratulation",
"is",
"thanks",
"the",
"register",
"to",
"please",
"full"
};
附件中的XOR.exe用于对文本文件进行XOR加密。具体格式为xor srcfile outfile。按提示输入加密的KEY便可以生成演示所需要的加密文件。Ascii.exe为解密示例程序。代码:bool KeyCheck(char *pDecode)
{
int Counter,Slength;
/*---------------------------------------------------------------------
此处假设得到的密文是整段字符的起始位置,只比较第
一个单词是否匹配。为了应付更复杂的情况,应在整个
解密缓冲区中搜索字典中的单词。恩,我有点懒
---------------------------------------------------------------------*/
for (Counter = 0; Counter != 10; Counter++)
{
Slength = strlen(map[Counter]);
if((_strnicmp(map[Counter],pDecode,Slength))==0)
return true;
}
return false;
}
按照上述思路扩展,也可以解密一些被加密的链接信息。可以假定www或者http之类的信息。然而对于中文却无能为力。或许你会想到用逗号或者句号,天知道一句话里面多少个字之后才会有逗号?你甚至可能连句号都看不到,还有问号感叹号什么的。因此,我们需要另一种思路。
注意到KEY只有8位的假设,以及p xor c = k。也就是说,比较可能出现的明文和密文XOR得出的KEY,如果相等,我们便找到真正的KEY了。这种方法更加灵活,由于字符始终要被解密出来的,通过人工输入软件中出现的字符,便能解密出其他字符,记录成功解密的字符,完善自动解密的字典。下面是简单的示例代码片段:
附件中的DecodeXor.exe便是示例程序,gbk.txt和ascii.txt为示例文本。你可以在附件中的src文件夹中找到相应的源代码。代码:char *map[10]= //中文字典
{
"失败",
"恭喜",
"成功",
"授权",
"支持",
"用户",
"注册",
"限制",
"功能",
"联系"
};
/*-----------------------------------------------------------------------
无key还原简单XOR字符示例
Code by 笨笨雄/www.pediy.com
------------------------------------------------------------------------*/
numread = fread (buffer,sizeof(char),150,srcfile);
bingo=false;
for (j = 0; j != numread; j++)
{
for (a = 0; a != 10; a++)
{
Slength = strlen(map[a]);
t_Byte = (*map[a]); //从字典中取字符
tKey = buffer[j] ^ t_Byte; //获得第一个KEY
counter = 1;
for (i = 1; i != Slength ; i++)
{
p_Byte = map[a] + i;
t_Byte = (*p_Byte);
ckey = buffer[j+i] ^ t_Byte;
if (ckey == tKey) //测试其他的KEY是否相同
counter++;
}
if (counter == Slength)
{
bingo=true; //相同的次数等于字符长度
break; //则认为找到KEY
}
}
if (bingo)
break;
}