1

我正在尝试使用 XOR 加密/解密文件。我有以下加密/解密例程,其中每个字节都被异或,结果减去位于前一个位置的字节的值。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 例程本身看起来是正确的,不是吗?请注意,我还尝试从文件末尾到开头加密文件。有任何想法吗?

谢谢!

4

3 回答 3

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)
    {
        // ...
    }
}
于 2011-02-16T07:27:24.453 回答
1

您的 C 代码有一些问题。

asm 代码从缓冲区的末尾开始,向下运行并在 eax == 0 时停止。asm 代码一次对一个字节进行操作,对前一个字节进行异或和减法。

asm 代码似乎不会触及缓冲区的第一个字节。

您的 C 代码移动一个索引,并将该字节索引指向的四个字节与 0xC5 进行异或运算。该代码读取的三个字节太多,并且只影响 XOR 的最低字节。

另外,您的 for 循环从前面开始并一直运行到结尾 - 与您的 asm 例程相反。

假设 chars 是字节大小的,那么为了模仿 asm 例程,您的减法步骤将是:

buffer[i] = buffer[i] - buffer[i-1];

可以重写为:

buffer[i] -= buffer[i-1];

...假设您将 for 循环修复为从数组的 end-1 到索引 1。

于 2011-02-16T07:00:14.313 回答
0

您需要更改buffer为 type unsigned char,并将for循环更改为:

for (i = count - 1; i > 0; i--)
{
    buffer[i] ^= xorkey;
    buffer[i] -= buffer[i - 1];
}

请注意,此代码从一开始就以 1024 字节块的形式处理文件,然后反向处理每个块。如果要反向处理整个文件,则需要从文件末尾开始读取,并对每个块中的第一个字符进行特殊处理。

于 2011-02-16T08:49:51.170 回答