我如何使其解密而不是加密?

2024-04-20

想知道如何从加密代码中获取此代码并使用相同的代码来创建解密。

我知道这意味着我必须反转一些指令并重新排序,但我无法弄清楚哪些指令需要重新排序,哪些不需要。

(编辑)这是完整的函数,可以让事情变得更清晰一些。对堆栈溢出非常陌生,因此对于任何混淆表示歉意。

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

如果这是一项家庭作业,那么它实际上是一项相当棘手的任务。 (尽管我可能忽略了一个简单的方法。)

让我们重点关注这段代码的效果memory。为简单起见,我假设您对此代码的影响不感兴趣寄存器,尽管我无法确定是否看到调用此函数的代码。

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

因此,应用了旋转和两个异或cl。 异或是一个内卷化 https://en.wikipedia.org/wiki/Involution_(mathematics),所以我们不必更改这两条指令。 的逆rol当然是ror,尽管这并不完全正确。对进位标志的影响无法反转,但在这种情况下,该影响被忽略,所以我们很好。

但是我们忽略的所有代码又如何呢?仔细检查后,您会发现它只是用来计算edx用于xor ecx,edx。 不幸的是,原始(未加密)值[eax]参与该计算。 解密时,原始值成为最终值,即结果xor ecx,edx。 我们似乎遇到了先有鸡还是先有蛋的问题。当它依赖于相同计算的结果时如何执行计算?

效果应该很明显[eax]的计算edx,是 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

Since 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

免责声明:我没有测试它,所以它很可能不起作用。我将把调试留给你。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我如何使其解密而不是加密? 的相关文章

随机推荐