f x y z 经过‘00100110’按位异或后,得到 @ ^ _ \ ,而其他字母经异或后仍在字母集内,你觉得错了,其实是你的理解有问题,程序结果没有任何问题。
总体上字符串加密能分为两类, 第一类是混淆保护中的字符串加密技术。主要特征是修改代码执行路径。大部分混淆保护工具的字符串加密都是这一类。
第二类就是加密壳中的字符串加密技术。这种不用修改IL代码,直接对元数据中的字符串加密。这一类以remotesoft,maxtocode为代表。
先看第一类,加密实现大致如下。
加密前:
MessageBox.Show("Hellow World!");
加密后:
MessageBox.Show(Helper.Decode("A34579dfbbeyu346563345/=="));
简单的说就是将原来使用字符串的地方,将直接使用字符串改为间接使用字符串。在这里保护软件将字符串 "Hellow World!" 进行加密 得到结果 "A34579dfbbeyu346563345/=="。 Helper.Decode 是保护软件提供的一个解密函数,他实现将 "A34579dfbbeyu346563345/==" 还原为 "Hellow World!" 。
因为是混淆保护,所以我们能分析得到 Decode 的代码。然后直接用这个函数的代码写一个小工具将程式集中所有加密的字符串都还原。生成一个字符串对应表。以方便代码阅读和调试。
如果再深入,能实现自动将字符串还原到原程式集中。
再来看上面例子的IL代码。
加密前:
ldstr "Hellow World!"
call MessageBox.Show(string)
加密后:
ldstr "A34579dfbbeyu346563345/=="
call string Helper.Decode(string)
call MessageBox.Show(string)
怎么还原,其实非常简单,我们已知道了decode的代码,而且已能实现字符串的解密了。得到了字符串的对应表。
直接将
ldstr "A34579dfbbeyu346563345/=="
call string Helper.Decode(string)
替换为
ldstr "Hellow World"
即可。写一个小工具使用正则表达式搜索替换就能了。
第二类字符串加密保护:
实现就是直接对元数据中的String流进行加密。
这类保护有一个缺陷,程式运行后 元数据中的String流会解密后在内存中完整还原。在我前面的文章里面有介绍元数据的dump。这里就不重复罗嗦了。
对于第一类字符串加密保护,更有其他的形式,如 Helper.Decode这个函数能是个native的函数。或是和流程混淆结合。
问题不小,你表面用的是C
但是,好多地方不符合C的语法
,,比如:
for
(int
i=0;
str[i]
!=
'\0';
i++)
还有,就是你好像没有弄清楚
,你要做什么似的,有好多无用的东西,
就像你的函数里的,key
,虽然你提到key了,但是你根本没有使用key,你只是使用45来进行加密,,还有就是一个文件
的大小,是不确定的,你用一个100个字符的字符串来存,有点那个不安全了,,如果稍长一点就会出问题,产生运行时错误。其实你这个加密和解密是一个可逆过程,用一个函数,就可以了,具体你想要的也不是太明白,就给你弄了一个简单一点加密和解密程序
,输入输出不是同一个文件
,不知道是不是你想要的。
#include
#include
#include
void
Decrypt()
{
char
fname[FILENAME_MAX];
char
fname2[FILENAME_MAX];
FILE*
fp;
FILE*
fp1;
int
key;
char
c;
printf("输入要加/解密文件的路径:\n");
scanf("%s",
fname);
printf("请输入密钥:\n");
scanf("%d",key);
strcpy(fname2,fname);
strcat(fname2,".txt");
if(
(fp
=
fopen(fname,"r+"))
==
NULL)
{
printf("error");
exit(1);
}
if(
(fp1
=
fopen(fname2,"w+"))
==
NULL)
{
printf("error");
exit(1);
}
while(
(c
=
fgetc(fp))
!=
EOF)
{
c
=
c^key;
fputc(c,fp1);
}
fcloseall();
}
int
main()
{
Decrypt();
return
0;
}
如果想看一些好一点的加密算法
,我这里有一些,联系我发给你
,,
加密解密的算法都没错,错的是解密程序里的文件操作方法。
rewind(fp)没有必要。因为fp已经被close了。
一般不推荐同时对一个文件又读又写,因为这样会导致很多缓冲区同步的问题。比如:
fputc()和getc()之间,必须要调用fflush(fp);
即使这样,还是会有问题。比如回车,getc()可能会返回两个字符,\n和\a。但是用fputc()写入的时候,分别写入\n和\a会把第二行第一个字符覆盖掉。
正确的做法是:
先把解密的数据保存到字符串里,全部结束之后,一次性把解密完的字符串写到文件里去。
void main()
{
char ch,name[30];
char content[1000];
int n = 0;
FILE *fp;
printf("name:\a");
gets(name);
fp = fopen(name,"r+");
if(fp==NULL)
{
printf("No file: %s!\n\a",name);
return;
}
ch = getc(fp);
while(ch!=EOF)
{
if((isalpha(ch))!=0)
{
if((ch = 'a' ch = 'd') || (ch = 'A' ch ='D'))
ch = ch + 22;
else
ch = ch - 4;
}
content[n++] = ch;
ch = getc(fp);
//ch = getc(fp);
}
content[n] = 0;
rewind(fp);
fprintf(fp, "%s", content);
fclose(fp);
printf("%s ok\a\n",name);
printf("content: %s\n", content);
printf("\n");
}
字符S的ASCII码加280%26之后,超出可显示范围。不在代码集里。建议不要使用字符比较,改用ASCII码比较。