Простая подпрограмма шифрования XOR в C / C ++ - PullRequest
1 голос
/ 16 февраля 2011

Я пытаюсь зашифровать / расшифровать файл с помощью 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 выглядит правильно, правда? Обратите внимание, что я также пытаюсь зашифровать файл, начиная с конца файла и до его начала. Есть идеи?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 16 февраля 2011

Вот как вы можете написать эту функцию на ассемблере на 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 голос
/ 16 февраля 2011

В вашем коде C есть пара ошибок.

Ассемблерный код начинается в конце буфера и работает вниз и останавливается, когда eax == 0. ASM-код работает с байтом за раз, ксорируя и вычитая из предыдущего байта.

Казалось бы, asm-код не затрагивает первый байт буфера.

Ваш код на C перемещает индекс и записывает четыре байта, указанные этим байтовым индексом, с помощью 0xC5. Этот код читает три байта слишком много и влияет только на младший байт с XOR.

Кроме того, ваш цикл for начинается спереди и проходит до конца - в противоположность вашей процедуре asm.

Если предположить, что символы имеют байтовый размер, то для имитации процедуры asm ваш шаг вычитания будет:

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

, который можно переписать как:

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

... при условии, что вы исправили цикл for для перехода от конца 1 массива к индексу 1.

0 голосов
/ 16 февраля 2011

Вам нужно изменить buffer на unsigned char и изменить for цикл на:

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

Обратите внимание, что этот код работает с файлом в 1024-байтовых чанках с самого начала, а затем работает на каждом чанке в обратном порядке. Если вы хотите работать с целым файлом в обратном порядке, вам нужно начать чтение с конца и иметь специальную обработку для первого символа в каждом блоке.

...