How would i make this a decryption instead of an encryption?

好久不见. 提交于 2019-12-03 01:19:39

问题


Wanna know how to get this from being a encryption code and using the same code to create a decryption.

I know it means that I have to reverse some of the instruction and re-order it but I can't figure out which ones need to be reordered and which ones don't.

(edit) Heres the full function to make things a bit clearer. Very new to stack overflow so apologies for any confusions.

//---------------------------------------------------------------------------------------------------------------
//----------------- 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:


If this is a homework assignment, then it's actually quite a tricky one. (Though I may have overlooked a simple approach.)

Let's focus on the effect this code has on memory. For simplicity I will assume you are not interested in the effect this code has on registers, though I cannot be sure within seeing the code calling this function.

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

So in goes an address (eax). The byte at this address is put into cl, and after some transformations, cl is put back at the same address. We need to figure out what those transformations are, and invert those.

    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

So a rotate and two xors are applied to cl. Xor is an involution, so we do not have to change those two instructions. The inverse of rol is of course ror, though that is not entirely true. The effect on the carry flag cannot be inverted, but in this case that effect is ignored, so we are good.

But what about all the code we ignored? On close inspection, you'll notice it is only there to calculate the value of edx that is used in xor ecx,edx. Unfortunately, the original (unencrypted) value of [eax] is involved in that calculation. When decrypting, the original value becomes the final value, i.e. the result of xor ecx,edx. We seem to have a chicken-and-egg problem. How to perform the calculation when it depends on the result of that same calculation?

It should be clear that the effect of [eax] on the calculation of edx, is either 1 out of only 8 possible cases, due to this statement:

    and   cl, 0x7

That means we can use a loop to try all different possibilities, until we found one where the result of the calculation matches the value we found in [eax]. That loop will be very similar to this loop found in the encryptor:

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

However, the exit condition of the loop will be different.

    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

Since xor is commutative and associative, we can rewrite this code. Instead of incrementing bl until it matches cl, we will decrement cl until its (partially) transformed value is zero (modulo 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

As for the rest of the code, that can stay as it is. It is mainly the initial part of the calculation of edx, before [eax] becomes involved.

Here is the complete solution:

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

Disclaimer: I did not test it, so it's quite likely it will not work. I will leave the debugging up to you.



来源:https://stackoverflow.com/questions/56684346/how-would-i-make-this-a-decryption-instead-of-an-encryption

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!