Как бы я сделал это дешифрование вместо шифрования? - PullRequest
0 голосов
/ 20 июня 2019

Хочу знать, как получить это из кода шифрования и использования того же кода для создания расшифровки.

Я знаю, это означает, что я должен отменить некоторые инструкции и переупорядочить их, но яне могу понять, какие из них нужно переупорядочить, а какие нет.

(правка) Вот полная функция, чтобы сделать вещи немного понятнее.Очень новый способ переполнения стека, поэтому извиняюсь за любые недоразумения.

//---------------------------------------------------------------------------------------------------------------
//----------------- ENCRYPTION ROUTINES -------------------------------------------------------------------------

void decrypt_chars (int length, char EKey)
{
  char temp_char;                       // Character temporary store

  for (int i = 0; i < length; i++)      // Encrypt characters one at a time
  {                                     
    temp_char = OChars[i];              // Get the next char from Original Chars array

    __asm                               
    {                                   
      push   eax                        // stores the "eax" register out onto the stack
      push   ecx                        // stores the "ecx" register out onto the stack
      push   edx                        // stores the "edx" register out onto the stack
                                        //
      movzx  ecx, temp_char             // zeroise "ecx" register and move values in "temp_char" varaible to "ecx" register
      lea    eax, EKey                  // copies address of values contained within the EKey varaible and moves it into "eax"register
                                        //
      push eax                          //
      push ecx                          //
                                        //
      call   decryptX                   // runs the function called "decryptX"
      mov    temp_char, dl              // move values in "dl" register into "temp_char" variable
                                        //
      add esp, 8                        // 
      pop    edx                        // removes the "edx" register from the stack
      pop    ecx                        // removes the "ecx" register from the stack
      pop    eax                        // removes the "eax" register from the stack
    }                                   //
    EChars[i] = temp_char;              // store encrypted char in the Encrypted Chars array
  }
  return;

  __asm
  {

  decryptX:
        push  ebp            // stores the pointer onto the stack

            mov   ebp, esp       // move values in "esp" register into "ebp" register
            mov   eax, [ebp + 12]// take value from the stack that is 8 bits above
                                 // from the pointer a putting it in the "eax" register
            mov   ecx, [ebp + 8] // take value from the stack that is 8 bits above 
                                 // from the pointer a putting it on ecx


            push  eax            // stores the Ekey address onto the stack
            xchg  eax, ecx       // puts temp_char's value into the EKey address register and Ekey address into temp_char register

            ror al, 1
            ror al, 1
            dec eax
            neg al


            mov   ebx, eax       // move temp_char value into "ebx" register
            pop   eax            // removes temp_char from the stack
            push  ebx            // stores temp_char value onto the stack
            pop   edx            // removes "edx" register value from the stack
            movzx ecx, [eax]     // zeroise "ecx" register and move the address stored in "eax" register to "ecx" register
            ror   cl, 1          // rotate "cl" register value in bytes to the right by 1
            xor cl, 0x96         // Exclusive OR (or XOR) the byte values within "cl" register with hex value 0x96 in binary
            push  ecx            // stores the Ekey address onto the stack
            and   cl, 0x7        // AND the byte values within "cl" register with hex value 0x7 in binary

            X:                       // Position X:

        add dl, 2            // add 2 to value within dl
            sub cl, 1            // subtract 1 from value within cl
            jg X                   // jump to "X" position
            pop   ecx            // removes "ecx" register value from the stack
            xor   ecx, edx       // exclusive OR (or XOR) the byte values within "ecx" register with the byte values within "edx" register
            mov[eax], cl         // move "cl" register value into the address stored in "eax" register.
            pop   ebp            // returning ebp back to the orginal value
            ret                  // return, end of encryptX function
  }

  //--- End of Assembly code
}
//*** end of encrypt_chars function
//--------------------------------------------------------------------------------------------------------------

1 Ответ

2 голосов
/ 21 июня 2019

Если это домашнее задание, то оно довольно сложное. (Хотя, возможно, я упустил простой подход.)

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

encryptL:
    push  eax
    ...                ; ignoring this code because its effect on eax is undone by the following pop
    pop   eax
    ...                ; code not affecting eax
    movzx ecx, [eax]
    ...                ; code not affecting eax
    mov   [eax], cl
    ret

Итак, адрес идет (eax). Байт по этому адресу помещается в cl, а после некоторых преобразований cl возвращается по тому же адресу. Нам нужно выяснить, что это за преобразования, и инвертировать их.

    ror   cl, 1
    xor   cl, 0x96
    push  ecx
    ...                ; ignoring this code because its effect on ecx is undone by the following pop
    pop   ecx
    xor   ecx, edx

Таким образом, поворот и два xors применяются к cl. Xor - это инволюция , поэтому нам не нужно менять эти две инструкции. Обратное значение rol, конечно, ror, хотя это не совсем так. Эффект на флаге переноса не может быть инвертирован, но в этом случае этот эффект игнорируется, поэтому мы хороши.

Но как насчет всего кода, который мы игнорировали? При внимательном рассмотрении вы заметите, что он рассчитывает только значение edx, которое используется в xor ecx,edx. К сожалению, исходное (незашифрованное) значение [eax] участвует в этом расчете. При дешифровании исходное значение становится окончательным, то есть результатом xor ecx,edx. Кажется, у нас проблемы с яйцом и курицей. Как выполнить расчет, когда он зависит от результата того же расчета?

Должно быть ясно, что влияние [eax] на вычисление edx, является либо 1 из 8 возможных случаев, из-за этого утверждения:

    and   cl, 0x7

Это означает, что мы можем использовать цикл, чтобы опробовать все различные возможности, пока не найдем тот, в котором результат вычисления совпадает со значением, найденным в [eax]. Этот цикл будет очень похож на этот цикл в шифраторе:

X:
    add   dl, 2
    sub   cl, 1
    jg    X

Однако условие выхода из цикла будет другим.

    mov   bl,0        ; using bl as a loop counter (similar to cl in original loop)
X:
    inc   bl
    add   dl,2        ; same as in the original loop
    mov   cl,[eax]    ; fetch encrypted byte from memory
    xor   ecx,edx     ; try transforming cl with the current value of dl
    xor   ebx,ecx     ; compare cl with the loop counter (bl)
    and   bl,7        ; only compare the 3 least significant bits
    jg    X           ; if not zero, try again with the next possible value of dl

Поскольку xor является коммутативным и ассоциативным, мы можем переписать этот код. Вместо увеличения bl до совпадения с cl мы будем уменьшать cl до тех пор, пока его (частично) преобразованное значение не станет равным нулю (по модулю 8).

    mov   cl,[eax]    ; fetch encrypted byte from memory
X:
    add   dl,2        ; same as in the original loop
    sub   cl,1        ; same as in the original loop
    push  ecx
    xor   ecx,edx     ; transform cl with the current value of dl
    and   cl,7        ; only consider the 3 least significant bits
    pop   ecx         ; restore cl (without clobbering flags)
    jg    X           ; if equal, then we found the right starting point

Что касается остальной части кода, он может оставаться как есть. В основном это начальная часть вычисления edx, прежде чем [eax] становится вовлеченным.

Вот полное решение:

encryptL:
    push  eax
    xchg  eax, ecx
    neg   al
    inc   eax
    rol   al, 1
    rol   al, 1
    mov   ebx, eax
    pop   eax
    push  ebx
    pop   edx

    movzx ecx, [eax]
    push  ecx
X:
    add   dl,2
    sub   cl,1
    push  ecx
    xor   ecx,edx
    and   cl,7
    pop   ecx
    jg    X

    pop   ecx
    xor   ecx,edx
    xor   cl,0x96
    rol   cl,1
    mov   [eax],cl
    ret

Отказ от ответственности: я не тестировал его, поэтому вполне вероятно, что он не будет работать. Я оставлю отладку до вас.

...