一、题目来源介绍
题目来源于看雪论坛CTF题库->题目要求为:
本题Flag值为123456用户的序列号。
二、解题过程
万事不要慌,先把软件运行起来康康:
哟呵!这是需要破解的节奏呀!!!由于是exe文件,首先使用exeinfope检查是否存在壳的现象:
查壳工具表明,软件不存在加壳操作。从题目查找序列号可以了解到,解题方法相当于破解该软件,那就上道具,开启OD整起来,一路F8干就完事了。遇到弹窗不要慌(因为题目要求123456用户序列号,所以Username就是123456),下断点并重新运行再F9直到:
CompareStringA()这个函数,传入值为我们自己的序列号以及通过用户名(123456)生成的序列号,做对比相同就注册成功,反之失败。进入函数后就会发现我们想要的答案了:
结果一目了然,明显的是用户123456的序列号为894904543,当然这也是本题的Flag。
三、算法原理解释
算法是这样的:
先把用户名的第一位去掉,再在用户名最后加一个ASCII码为0的字符组成新的字符串s1然后再进入下面的四步运算.
第一步,ASCII码AA,89,C4,FE,46加到新字符串s1头部组成字符串s2,S1与S2各位异或得s3
第二步,S3尾部加E7,03,D0,F0,78组成S4,S4与S3各位异或得S5
第三步,F7,FD,F4,E7,B9加到S5头部得S6,S6与S5各位异或得S7
第四步,S7尾部加B5,1B,C9,50,73组成S8,S8与S7各位异或得S9
做完这四步后,最后得到S9,再把S9的第一,五,九...位相加放到第一位,第二,六,十...位相加放到第二位,第三,七,十一...位相加放到第三位,第四,八,十二...位相加放到第四位,这样最后得到长度为四的字符串S10,再把S10的ASCII码看成是一个32位的无符号整数,转化为10进制数就得到注册码了.
四、注册机代码
#include <stdio.h>
#include <string.h>
int main()
{
unsigned char a[40] = {0xAA,
0x89, 0xC4, 0xFE, 0x46, 0x78, 0xF0, 0xD0, 0x03, 0xE7, 0xF7, 0xFD, 0xF4, 0xE7, 0xB9, 0xB5, 0x1B,
0xC9, 0x50, 0x73, 0x00, 0x48, 0x90, 0x25, 0x00, 0xDC, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
char temp[10] = "qwer";
unsigned char user[10];
int userLen = strlen(temp);
int index = 0;
unsigned int res;
unsigned char ch;
for(int i=0; i<userLen; i++)
user[i] = (unsigned char) temp[i];
user[userLen] = '\0';
index = 0;
for(int i=1; i<=userLen; i++)
{
ch = user[i];
user[i] ^= a[index];
a[index] = ch;
index++;
if(index>=5)
index -= 5;
}
index = 5;
for(int i=userLen; i>0; i--)
{
ch = user[i];
user[i] ^= a[index];
a[index] = ch;
index++;
if(index>=10)
index -= 5;
}
index = 10;
for(int i=1; i<=userLen; i++)
{
ch = user[i];
user[i] ^= a[index];
a[index] = ch;
index++;
if(index>=15)
index -= 5;
}
index = 15;
for(int i=userLen; i>0; i--)
{
ch = user[i];
user[i] ^= a[index];
a[index] = ch;
index++;
if(index>=20)
index -= 5;
}
for(int i=1; i<=4; i++)
{
for(int j=i+4; j<=userLen; j+=4)
user[i] += user[j];
}
res = (user[4]<<24) + (user[3]<<16) + (user[2]<<8) + user[1];
printf("%u\n", res);
return 0;
}
OVER!!!!!!!