我正在尝试使用XOR加密/解密文件。我有以下加密/解密例程,其中每个字节都是xor'd,结果将被位于前一个位置的字节的值减去。 ASM表示如下
crypt:
mov dl, [eax+ecx] ; read byte
xor dl, 0C5h ; xor it with oxC5
sub dl, [eax+ecx-1] ; sub the previous byte
mov [eax+ecx], dl ; save the new byte
dec eax ; decrement pointer
test eax, eax
jg short crypt ;
这就是我的加密例程应该是什么样子,我正试图将这个C / C ++移植一下。我的代码如下
#include <stdio.h>
unsigned int xorkey = 0xC5;
int main(int argc, char *argv[])
{
if(argc < 3)
{
printf("usage: encoder input output\n");
return -1;
}
FILE *in = fopen(argv[1], "rb");
if(in == NULL)
{
printf("failed to open: %s", argv[2]);
return -1;
}
FILE *out = fopen(argv[2], "wb");
if(out == NULL)
{
fclose(in);
printf("failed to open '%s' for writing.",argv[2]);
return -1;
}
int count;
char buffer[1024];
while(count = fread(buffer, 1, 1024, in))
{
int i;
int end = count;
for(i = 0;i < end; ++i)
{
((unsigned int *)buffer)[i] ^= xorkey;
}
if(fwrite(buffer, 1, count, out) != count)
{
fclose(in);
fclose(out);
printf("fwrite() error\n");
return -1;
}
}
fclose(in);
fclose(out);
return 0;
}
我无法弄清楚如何在C ++中减去字节数。 XOR例程本身看起来是正确的,不是吗? 请注意,我还尝试从文件末尾开始加密文件直到开头。有什么想法吗?
谢谢!
答案 0 :(得分:2)
以下是如何在C中编写汇编语言函数。我保持变量名称与寄存器名称相同,这样您就可以看到各个部分的匹配方式。
void do_xor_crypt(char *buffer, int count) {
char *ecx = buffer;
int eax = count - 1;
if (eax > 0) {
do {
char dl = ecx[eax];
dl ^= 0xC5;
dl -= ecx[eax-1];
ecx[eax] = dl;
eax--;
} while (eax > 0);
}
}
请注意,我已检查以确保eax
大于零(意味着count
为两个或更多),以便循环可以减去。您可以将此代码集成到您的阅读循环中,如:
while (count = fread(buffer, 1, 1024, in))
{
do_xor_crypt(buffer, count);
if (fwrite(buffer, 1, count, out) != count)
{
// ...
}
}
答案 1 :(得分:1)
您的C代码存在一些问题。
asm代码从缓冲区的末尾开始,向下运行并在eax == 0时停止。 asm代码一次操作一个字节,xor'ing并从前一个字节中减去。
asm代码似乎不会触及缓冲区的第一个字节。
您的C代码移动索引,并将该字节索引指向的四个字节与0xC5进行异或。该代码读取的字节数太多,只影响XOR的最低字节。
另外,你的for-loop从前面开始,一直到最后 - 与你的asm例程相反。
假设字符是字节大小的,那么为了模仿asm例程,你的减法步骤将是:
buffer[i] = buffer[i] - buffer[i-1];
可以改写为:
buffer[i] -= buffer[i-1];
...假设您修复了for-loop从数组的end-1到索引1。
答案 2 :(得分:0)
您需要更改buffer
以键入unsigned char
,并将for
循环更改为:
for (i = count - 1; i > 0; i--)
{
buffer[i] ^= xorkey;
buffer[i] -= buffer[i - 1];
}
请注意,此代码从一开始就以1024字节的块的形式处理文件,然后以相反的方式处理每个块。如果你想反过来处理整个文件,你需要从它的末尾开始阅读,并对每个块中的第一个字符进行特殊处理。