x86程序集加密到解密

问题描述 投票:0回答:1

因此,我试图通过加密例程创建解密,但是我对此确实经验很差。谁能帮帮我吗?预先谢谢!

PS。例行程序编写得不好,是为了让我们稍后更改。编辑:抱歉,这是我的整个加密例程,我所知道的是,用我的EKey(eax)完成的所有操作都应保持不变,但我需要撤消使用char(ecx)完成的操作。我真的不知道从哪里开始,再次感谢。

char EKey = 'z';      //unique key:z

#define StudentName "asdasd"
#define MAXCHARS 6    // Max user input

using namespace std;
#include <string>               // for strings
#include <fstream>              // file I/O
#include <iostream>             // for cin >> and cout <<
#include <iomanip>              // for fancy output
#include "TimeUtils.h"          // for GetTime, GetDate, etc.

#define dollarchar '$'          // string terminator

char OChars[MAXCHARS] = { 'S','O','S','I','G',' ' },     // Original character string
EChars[MAXCHARS],                                        // Encrypted character string
DChars[MAXCHARS] = "Soon!";                              // Decrypted character string

//----------------------------- C++ Functions ----------------------------------------------------------

void get_char(char& a_character)
{
    a_character = (char)_getwche();
    if (a_character == '\r' || a_character == '\n')  // allow the enter key to work as the terminating character too
        a_character = dollarchar;
}
//-------------------------------------------------------------------------------------------------------------

void get_original_chars(int& length)
{
    char next_char = ' ';
    length = 0;
    get_char(next_char);

    while ((length < MAXCHARS) && (next_char != dollarchar))
    {
        OChars[length++] = next_char;
        get_char(next_char);
    }
}

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

void encrypt_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                          //saves EKey to the memory stack w/ a value of 0
            push   ecx                          //saves Char to the memory stack w/ a value of 83
            push   edx                          //saves EKey to the memory stack w/ a value of 1

            movzx  ecx, temp_char               //moves my character value (8 bit) to ecx (32 bit) w/ 0 extension which is 'S' and continues until the last character of my string. 

            lea    eax, EKey                    //lea (loads effective address) puts the memory address of EKey to eax 
            push   ecx                          //saves Char to the memory stack w/ a value of 83
            push   eax                          //saves Char to the memory stack w/ a value of 5241440

            call   encrypt_3                    //calls a function in this case my unique encryption routine  
            add    esp, 8                       //adds a value of 8 to the stack pointer, esp= 5241176 + 8 
            mov    temp_char, dl                //copies the value of the encrypted Char to the current Char

            pop    edx                          //removes the encrypted char from the stack memory 
            pop    ecx                          //removes the char from the stack memory   
            pop    eax                          //removes the  EKey from the stack memory
        }
        EChars[i] = temp_char;                  // Store encrypted char in the Encrypted Chars array
    }
    return;

    __asm
    {
    encrypt_3:
        push ebp                                //saves ebp to the stack memory
            mov ebp, esp                        //copies the value of esp to ebp
            mov eax, [ebp + 8]                  //adds 8 to the value of ebp then copy its value to EKey
            mov ecx, [ebp + 12]                 //adds 12 to the value of ebp (recently added 8) then copy the value to the encrypted character
            push  edx                           //puts the edx to the stack memory  
            push  ecx                           //puts CHAR to the stack memory
            push  eax                           //puts EKey to the stack memory
            movzx eax, byte ptr[eax]            //Uses the EKey (z) inside eax as the eax memory address 
            rol   al, 1                         //rotate al by 1 bit to the left, 111 1010‬ (moves the 0 at the end to the beginning)
            not al                              //invert each bit of al (1111 0100‬) becomes 0000 1011
            rol   al, 1                         //rotates the inverted binary of al to the left by 1 bit 
            rol   al, 1                         //rotates al binary by 1 bit again to the left, 0001 0110‬
            mov   edx, eax                      //copies the value of Ekey to edx, edx = 44
            pop   eax                           //removes the eax register from the stack memory        
            mov   byte ptr[eax], dl             //Uses the value of edx as the byte address of eax (Ekey)
            pop   ecx                           //removes the ecx (EKey) from the stack memory
            xor ecx, edx                        //implements the XOR operation between edx and CHAR, 83 and 44 becomes 127 (111 1111)
            mov   eax, ecx                      //copy the XORed value of Char to EKey
            ror   al, 1                         //rotates al value by 1 bit to the right 127 (0111 1111‬)
            ror   al, 1                         //rotates al value by 1 bit to the right 191 (1011 1111‬)
            ror   al, 1                         //rotates al value by 1 bit to the right 223 (1101 1111‬) al value is now 239 (1110 1111‬)
            pop   edx                           //removes edx from the stack memory 
            mov   edx, eax                      //copy the value of EKey to edx 239 (1110 1111‬)
            pop  ebp                            //removes ebp from the stack memory
            ret                                 //proceeds to the line after the call instruction 
    }
}

//----------------- DECRYPTION ROUTINES -----------------//

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

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

        __asm
        {
            push   eax                          //saves EKey to the memory stack w/ a value of 0
            push   ecx                          //saves Char to the memory stack w/ a value of 83

            movzx  ecx, temp_char               //moves my character value (8 bit) to ecx (32 bit) w/ 0 extension which is 'S' and continues until the last character of my string. 

            lea    eax, EKey                    //lea (loads effective address) puts the memory address of EKey to eax 
            push   ecx                          //saves Char to the memory stack w/ a value of 83
            push   eax                          //saves Char to the memory stack w/ a value of 5241440

            call   decrypt_3                    //calls a function in this case my unique encryption routine  
            add    esp, 8                       //adds a value of 8 to the stack pointer, esp= 5241176 + 8 
            mov    temp_char, dl                //copies the value of the encrypted Char to the current Char

            pop    ecx                          //removes the char from the stack memory   
            pop    eax                          //removes the  EKey from the stack memory
        }
        DChars[i] = temp_char;                  // Store decrypted char in the decrypted Chars array
    }
    return;
    __asm
    {
    decrypt_3:
        push ebp                                //saves ebp to the stack memory
            mov   ebp, esp                      //copies the value of esp to ebp
            mov   eax, [ebp + 8]                //adds 8 to the value of ebp then copy its value to EKey
            mov   ecx, [ebp + 12]               //adds 12 to the value of ebp (recently added 8) then copy the value to the encrypted character

            push  edx                           //puts the edx to the stack memory  
            push  ecx                           //puts CHAR to the stack memory
            push  eax                           //puts EKey to the stack memory

            movzx eax, byte ptr[eax]            //Uses the EKey (z) inside eax as the eax memory address 
            rol   al, 1                         //rotate al by 1 bit to the left, 111 1010‬ (moves the 0 at the end to the beginning)
            not al                              //invert each bit of al (1111 0100‬) becomes 0000 1011
            rol   al, 1                         //rotates the inverted binary of al to the left by 1 bit 
            rol   al, 1                         //rotates al binary by 1 bit again to the left, 0001 0110‬
            mov   edx, eax                      //copies the value of Ekey to edx, edx = 44
            pop   eax                           //removes the eax register from the stack memory        
            mov   byte ptr[eax], dl             //Uses the value of edx as the byte address of eax (Ekey)
            pop   ecx                           //removes the ecx (EKey) from the stack memory
            xor ecx, edx                        //implements the XOR operation between edx and CHAR, 83 and 44 becomes 127 (111 1111)
            mov   eax, ecx                      //copy the XORed value of Char to EKey
            ror   al, 1                         //rotates al value by 1 bit to the right 127 (0111 1111‬)
            ror   al, 1                         //rotates al value by 1 bit to the right 191 (1011 1111‬)
            ror   al, 1                         //rotates al value by 1 bit to the right 223 (1101 1111‬) al value is now 239 (1110 1111‬)
            pop   edx                           //removes edx from the stack memory 
            mov   edx, eax                      //copy the value of EKey to edx 239 (1110 1111‬)
            pop   ebp                           //removes ebp from the stack memory
            ret                                 //proceeds to the line after the call instruction 
    }
}

//----------------- end of decrypt_chars function-----------------//




//************ MAIN PROGRAM *************************************************************************************

int main(void)
{
    int char_count(5);  // The number of actual characters entered (upto MAXCHARS limit).

    //cout << "\nPlease enter upto " << MAXCHARS << " alphanumeric characters:  ";
    //get_original_chars (char_count);  // Input the original character string to be encrypted 

    //*****************************************************

    // Open a file to store results (you can view and edit this file in Visual Studio)

    ofstream EDump;
    EDump.open("EncryptDump.txt", ios::app);
    EDump << "\n\nFoCA Encryption program results (" << StudentName << ") Encryption key = '" << EKey << "'";
    EDump << "\nDate: " << GetDate() << "  Time: " << GetTime();

    //*****************************************************
    // Display and save to the EDump file the string just input

    cout << "\n\nOriginal string =  " << OChars << "\tHex = ";
    EDump << "\n\nOriginal string =  " << OChars << "\tHex = ";

    for (int i = 0; i < char_count; i++)
    {
        cout << hex << setw(2) << setfill('0') << ((int(OChars[i])) & 0xFF) << "  ";
        EDump << hex << setw(2) << setfill('0') << ((int(OChars[i])) & 0xFF) << "  ";
    };

    //*****************************************************
    // Encrypt the string and display/save the result

    encrypt_chars(char_count, EKey);

    cout << "\n\nEncrypted string = " << EChars << "\tHex = ";
    EDump << "\n\nEncrypted string = " << EChars << "\tHex = ";
    for (int i = 0; i < char_count; i++)
    {
        cout << ((int(EChars[i])) & 0xFF) << "  ";
        EDump << ((int(EChars[i])) & 0xFF) << "  ";
    }

    //*****************************************************
    // Decrypt the encrypted string and display/save the result

    decrypt_chars(char_count, EKey);    //**** YOU NEED TO WRITE THE BODY OF THIS FUNCTION ***

    cout << "\n\nDecrypted string = " << DChars << "\tHex = ";
    EDump << "\n\nDecrypted string = " << DChars << "\tHex = ";
    for (int i = 0; i < char_count; i++)
    {
        cout << ((int(DChars[i])) & 0xFF) << "  ";
        EDump << ((int(DChars[i])) & 0xFF) << "  ";
    }
    //*****************************************************

    cout << "\n\n\n";
    EDump << "\n\n-------------------------------------------------------------";
    EDump.close();

    system("PAUSE");
    return (0);
} // end of whole encryption/decryption program --------------------------------------------------------------------
assembly x86 reverse-engineering
1个回答
1
投票

我将您的内联汇编移植到了NASM 32位源,并在同一汇编语言源中也重新实现了外循环(encrypt_chars)。我上传了a repo with the updates和一个简短的C语言测试程序,可以在Linux上使用gcc -m32进行编译。为此,您需要NASM,gcc和my macro collection。这是汇编源:


; CC-BY-SA, source:
; https://stackoverflow.com/questions/60787907/x86-assembly-encryption-to-decryption

%include "lmacros3.mac"

%ifidni __OUTPUT_FORMAT__, bin
    bits 32
%elifidni __OUTPUT_FORMAT__, elf
    global testfunc_encode
%endif

testfunc_encode:
    lframe near
    lpar dword, EKey
    lpar dword, length
    lpar dword, EChars
    lpar dword, OChars
    lpar_return
    lenter
    pushad

    mov esi, dword [ebp + ?OChars]
    mov ebx, dword [ebp + ?EChars]
    mov edi, dword [ebp + ?length]
    test edi, edi
    jz .end

.loop:
    movzx ecx, byte [esi]
    lea eax, [ebp + ?EKey]

    push ecx
    push eax
    call encrypt_3
    add esp, 8
    mov byte [ebx], dl

    inc esi
    inc ebx
    dec edi
    jnz .loop

.end:
    popad
    lleave
    lret


encrypt_3:
    lframe near
    lpar dword, data
    lpar dword, points_to_key
    lpar_return
    lenter
;            push ebp                            ; saves ebp to the stack memory
;            mov ebp, esp                        ; copies the value of esp to ebp
;            mov eax, [ebp + 8]                  ; adds 8 to the value of ebp then copy its value to EKey
;            mov ecx, [ebp + 12]                 ; adds 12 to the value of ebp (recently added 8) then copy the value to the encrypted character
    mov eax, dword [ebp + ?points_to_key]
    mov ecx, dword [ebp + ?data]
            push  edx                           ; puts the edx to the stack memory
            push  ecx                           ; puts CHAR to the stack memory
            push  eax                           ; puts EKey to the stack memory
            movzx eax, byte [eax]               ; Uses the EKey (z) inside eax as the eax memory address
            rol   al, 1                         ; rotate al by 1 bit to the left, 111 1010‬ (moves the 0 at the end to the beginning)
            not al                              ; invert each bit of al (1111 0100‬) becomes 0000 1011
            rol   al, 1                         ; rotates the inverted binary of al to the left by 1 bit
            rol   al, 1                         ; rotates al binary by 1 bit again to the left, 0001 0110‬
            mov   edx, eax                      ; copies the value of Ekey to edx, edx = 44
            pop   eax                           ; removes the eax register from the stack memory
            mov   byte [eax], dl                ; Uses the value of edx as the byte address of eax (Ekey)
            pop   ecx                           ; removes the ecx (EKey) from the stack memory
            xor ecx, edx                        ; implements the XOR operation between edx and CHAR, 83 and 44 becomes 127 (111 1111)
            mov   eax, ecx                      ; copy the XORed value of Char to EKey
            ror   al, 1                         ; rotates al value by 1 bit to the right 127 (0111 1111‬)
            ror   al, 1                         ; rotates al value by 1 bit to the right 191 (1011 1111‬)
            ror   al, 1                         ; rotates al value by 1 bit to the right 223 (1101 1111‬) al value is now 239 (1110 1111‬)
            pop   edx                           ; removes edx from the stack memory
            mov   edx, eax                      ; copy the value of EKey to edx 239 (1110 1111‬)
;            pop  ebp                            ; removes ebp from the stack memory
;            ret                                 ; proceeds to the line after the call instruction
    lleave , optimiserestoresp
    lret


%ifidni __OUTPUT_FORMAT__, elf
    global testfunc_decode
%endif

testfunc_decode:
    lframe near
    lpar dword, EKey
    lpar dword, length
    lpar dword, EChars
    lpar dword, OChars
    lpar_return
    lenter
    pushad

    mov esi, dword [ebp + ?OChars]
    mov ebx, dword [ebp + ?EChars]
    mov edi, dword [ebp + ?length]
    test edi, edi
    jz .end

.loop:
    movzx ecx, byte [esi]
    lea eax, [ebp + ?EKey]

    push ecx
    push eax
    call decrypt_3
    add esp, 8
    mov byte [ebx], dl

    inc esi
    inc ebx
    dec edi
    jnz .loop

.end:
    popad
    lleave
    lret


decrypt_3:
    lframe near
    lpar dword, data
    lpar dword, points_to_key
    lpar_return
    lenter
    mov eax, dword [ebp + ?points_to_key]
    mov ecx, dword [ebp + ?data]
            push  edx                           ; puts the edx to the stack memory
            push  ecx                           ; puts CHAR to the stack memory
            push  eax                           ; puts EKey to the stack memory
            movzx eax, byte [eax]               ; Uses the EKey (z) inside eax as the eax memory address
            rol   al, 1                         ; rotate al by 1 bit to the left, 111 1010‬ (moves the 0 at the end to the beginning)
            not al                              ; invert each bit of al (1111 0100‬) becomes 0000 1011
            rol   al, 1                         ; rotates the inverted binary of al to the left by 1 bit
            rol   al, 1                         ; rotates al binary by 1 bit again to the left, 0001 0110‬
            mov   edx, eax                      ; copies the value of Ekey to edx, edx = 44
            pop   eax                           ; removes the eax register from the stack memory
            mov   byte [eax], dl                ; Uses the value of edx as the byte address of eax (Ekey)
            pop   ecx                           ; removes the ecx (EKey) from the stack memory

%if 0
; xor cl, KEYBYTE
; ror cl, 3
            xor ecx, edx                        ; implements the XOR operation between edx and CHAR, 83 and 44 becomes 127 (111 1111)
            mov   eax, ecx                      ; copy the XORed value of Char to EKey
            ror   al, 1                         ; rotates al value by 1 bit to the right 127 (0111 1111‬)
            ror   al, 1                         ; rotates al value by 1 bit to the right 191 (1011 1111‬)
            ror   al, 1                         ; rotates al value by 1 bit to the right 223 (1101 1111‬) al value is now 239 (1110 1111‬)
%else
; rol cl, 3
; xor cl, KEYBYTE
    rol cl, 3
    xor cl, dl
    mov al, cl
%endif
            pop   edx                           ; removes edx from the stack memory
            mov   edx, eax                      ; copy the value of EKey to edx 239 (1110 1111‬)
    lleave , optimiserestoresp
    lret

我制作了一个C测试程序,该程序用32位LFSR填充1 KiB缓冲区,然后尝试使用各种密钥对数据进行几次编码和解码。如果发生意外结果,它将显示“错误:”。来源:


// CC-BY-SA, source:
// https://stackoverflow.com/questions/60787907/x86-assembly-encryption-to-decryption

#include <stdint.h>
#include <stdio.h>
#include <string.h>

void testfunc_encode(uint8_t* OChars, uint8_t* EChars, uint32_t length, uint8_t EKey);
void testfunc_decode(uint8_t* OChars, uint8_t* EChars, uint32_t length, uint8_t EKey);

uint32_t next(uint32_t prior) {
    uint32_t shifted = prior >> 1;
    return ( (prior & 1) ? shifted ^ 0x80200003 : shifted);
}

int test1() {
    const uint32_t bufsize = 1024 / 4;
    uint32_t original[bufsize];
    uint32_t encoded[bufsize];
    uint32_t decoded[bufsize];
    uint32_t ii;
    uint32_t ll = 1;
    int rc = 0;

    for (ii = 0; ii < bufsize; ++ii) {
        original[ii] = ll;
        ll = next(ll);
    }

    testfunc_encode((void*)original, (void*)encoded, bufsize * 4, 0x00);

    testfunc_decode((void*)encoded, (void*)decoded, bufsize * 4, 0x00);

    if (memcmp((void*)original, (void*)decoded, bufsize * 4) == 0) {
        printf("Test 1 with same key succeeded!\n");
    } else {
        printf("Error: Test 1 with same key did not succeed.\n");
        rc = 1;
    }

    testfunc_decode((void*)encoded, (void*)decoded, bufsize * 4, 0x26);

    if (memcmp((void*)original, (void*)decoded, bufsize * 4) == 0) {
        printf("Error: Test 2 with different key succeeded!\n");
        rc = 1;
    } else {
        printf("Test 2 with different key did not succeed.\n");
    }


    testfunc_encode((void*)original, (void*)encoded, bufsize * 4, 0x26);

    testfunc_decode((void*)encoded, (void*)decoded, bufsize * 4, 0x26);

    if (memcmp((void*)original, (void*)decoded, bufsize * 4) == 0) {
        printf("Test 3 with same key succeeded!\n");
    } else {
        printf("Error: Test 3 with same key did not succeed.\n");
        rc = 1;
    }

    testfunc_decode((void*)encoded, (void*)decoded, bufsize * 4, 0xFF);

    if (memcmp((void*)original, (void*)decoded, bufsize * 4) == 0) {
        printf("Error: Test 4 with different key succeeded!\n");
        rc = 1;
    } else {
        printf("Test 4 with different key did not succeed.\n");
    }

    return rc;
}

int main() {
    int rc = 0;
    rc |= test1();
    return rc;
}

我用bash编写了一个测试脚本。默认情况下,将../lmacros/用作宏集合的源。如果将宏文件(NASMINCLUDE=path/to/macros/ ./test.shlmacros1.maclmacros2.mac)放在其他位置,则可以更改此设置(例如,通过运行lmacros3.mac)。您还可以通过这种方式为NASM或C编译器指定不同的标志。这是脚本:

#! /bin/bash

set -e

[ -z "$NASM" ] && NASM=nasm
[ -z "$NASMOPT" ] && NASMOPT="-g"
[ -z "$NASMINCLUDE" ] && NASMINCLUDE=../lmacros/
[ -z "$CC" ] && CC=gcc
[ -z "$CCOPT" ] && CCOPT="-g -O0 -m32"

"$NASM" -felf $NASMOPT test.asm -o test.o -I "$NASMINCLUDE"
"$CC" $CCOPT main.c test.o -o main
./main

如果成功,这就是运行它的样子:

$ NASM=oldnasm ./test.sh
Test 1 with same key succeeded!
Test 2 with different key did not succeed.
Test 3 with same key succeeded!
Test 4 with different key did not succeed.
$ 

我只需要从encrypt_3函数更改为创建decrypt_3的一个特定部分。密钥计算完全相同。我们只需要更改密钥字节值将输入字节转换为输出字节的方式即可。我在这里引用了特定的部分:

%if 0
; xor cl, KEYBYTE
; ror cl, 3
            xor ecx, edx                        ; implements the XOR operation between edx and CHAR, 83 and 44 becomes 127 (111 1111)
            mov   eax, ecx                      ; copy the XORed value of Char to EKey
            ror   al, 1                         ; rotates al value by 1 bit to the right 127 (0111 1111‬)
            ror   al, 1                         ; rotates al value by 1 bit to the right 191 (1011 1111‬)
            ror   al, 1                         ; rotates al value by 1 bit to the right 223 (1101 1111‬) al value is now 239 (1110 1111‬)
%else
; rol cl, 3
; xor cl, KEYBYTE
    rol cl, 3
    xor cl, dl
    mov al, cl
%endif

我没有优化程序,也没有更新程序集源中的注释。您可能可以将解码的the specific solution传输到整个程序中,这并不大。

© www.soinside.com 2019 - 2024. All rights reserved.