x86 程序集加密到解密 [英] x86 assembly encryption to decryption

查看:73
本文介绍了x86 程序集加密到解密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我试图从加密例程中创建解密,但我对它的体验真的很差.谁能帮帮我吗?提前致谢!

附注.例程写得不好,故意让我们以后改变.抱歉,这是我的整个 encry[ption 例程,我所知道的是,用我的 EKey (eax) 完成的所有事情都应该保持不变,但我需要反转对 char (ecx) 所做的一切.我真的不知道从哪里开始,再次提前致谢.

char EKey = 'z';//唯一键:z#define StudentName "asdasd"#define MAXCHARS 6//最大用户输入使用命名空间标准;#include <字符串>//对于字符串#include <fstream>//文件输入输出#include //对于 cin >>和 cout<<#include //用于花哨的输出#include "TimeUtils.h"//用于 GetTime、GetDate 等.#define Dollarchar '$'//字符串终止符char OChars[MAXCHARS] = { 'S','O','S','I','G',' ' },//原始字符串EChars[MAXCHARS],//加密后的字符串DChars[MAXCHARS] = "很快!";//解密后的字符串//------------------------- C++ 函数 ----------------------------------------------------------void get_char(char& a_character){a_character = (char)_getwche();if (a_character == '\r' || a_character == '\n')//也允许输入键作为终止字符a_character = 美元字符;}//-------------------------------------------------------------------------------------------------------------void get_original_chars(int& 长度){字符 next_char = ' ';长度 = 0;get_char(next_char);while ((length < MAXCHARS) && (next_char != Dollarchar)){OChars[length++] = next_char;get_char(next_char);}}//----------------- 加密例程-----------------//void encrypt_chars(int 长度,char EKey){字符 temp_char;//字符临时存储for (int i = 0; i < length; i++)//一次加密一个字符{temp_char = OChars[i];//从原始字符数组中获取下一个字符__asm{push eax//将 EKey 保存到内存堆栈中,值为 0push ecx//将 Char 保存到内存堆栈中,值为 83push edx//将 EKey 保存到内存堆栈中,值为 1movzx ecx, temp_char//将我的字符值(8 位)移动到带有 0 扩展名的 ecx(32 位),即 'S' 并一直持续到我的字符串的最后一个字符.lea eax, EKey//lea(加载有效地址)把EKey的内存地址放到eaxpush ecx//将 Char 保存到内存堆栈中,值为 83push eax//将 Char 保存到内存堆栈中,值为 5241440call encrypt_3//在这种情况下调用一个函数我独特的加密例程add esp, 8//向堆栈指针添加值8,esp= 5241176 + 8mov temp_char, dl//将加密后的Char值复制到当前Charpop edx//从堆栈内存中删除加密的字符pop ecx//从堆栈内存中移除字符pop eax//从栈内存中取出EKey}EChars[i] = temp_char;//将加密字符存储在加密字符数组中}返回;__asm{加密_3:push ebp//将ebp存入栈内存mov ebp, esp//复制esp的值到ebpmov eax, [ebp + 8]//将 ebp 的值加 8,然后将其值复制到 EKeymov ecx, [ebp + 12]//将ebp的值加12(最近加了8)然后把值复制到加密字符push edx//将edx放入堆栈内存push ecx//将CHAR放入堆栈内存push eax//将EKey放入栈内存movzx eax, byte ptr[eax]//使用eax内部的EKey(z)作为eax内存地址rol al, 1//al 向左旋转 1 位,111 1010(将末尾的 0 移到开头)not al//反转 al (1111 0100) 的每一位变为 0000 1011rol al, 1//将al的反转二进制向左旋转1位rol al, 1//将 al 二进制再次向左旋转 1 位,0001 0110mov edx, eax//将Ekey的值复制到edx, edx = 44pop eax//从栈内存中移除eax寄存器mov byte ptr[eax], dl//使用edx的值作为eax(Ekey)的字节地址pop ecx//从栈内存中取出ecx(EKey)xor ecx, edx//实现edx和CHAR之间的异或运算,83和44变成127(111 1111)mov eax, ecx//将Char的异或值复制到EKeyror al, 1//将 al 值向右旋转 1 位 127 (0111 1111)ror al, 1//将 al 值向右旋转 1 位 191 (1011 1111)ror al, 1//将 al 值向右旋转 1 位 223 (1101 1111) al 值现在是 239 (1110 1111)pop edx//从堆栈内存中移除edxmov edx, eax//将EKey的值复制到edx 239 (1110 1111)pop ebp//从栈内存中移除ebpret//转到调用指令后的行}}//----------------- 解密程序-----------------//无效解密字符(整数长度,字符EKey){字符 temp_char;//字符临时存储for (int i = 0; i < length; i++)//一次解密一个字符{temp_char = EChars[i];//从加密字符数组中获取下一个字符__asm{push eax//将 EKey 保存到内存堆栈中,值为 0push ecx//将 Char 保存到内存堆栈中,值为 83movzx ecx, temp_char//将我的字符值(8 位)移动到带有 0 扩展名的 ecx(32 位),即 'S' 并一直持续到我的字符串的最后一个字符.lea eax, EKey//lea(加载有效地址)把EKey的内存地址放到eaxpush ecx//将 Char 保存到内存堆栈中,值为 83push eax//将 Char 保存到内存堆栈中,值为 5241440调用decrypt_3//在这种情况下调用一个函数我独特的加密例程add esp, 8//向堆栈指针添加值8,esp= 5241176 + 8mov temp_char, dl//将加密后的Char值复制到当前Charpop ecx//从堆栈内存中移除字符pop eax//从栈内存中取出EKey}DChars[i] = temp_char;//将解密后的字符存储在解密后的字符数组中}返回;__asm{解密_3:push ebp//将ebp存入栈内存mov ebp, esp//复制esp的值到ebpmov eax, [ebp + 8]//将 ebp 的值加 8,然后将其值复制到 EKeymov ecx, [ebp + 12]//将ebp的值加12(最近加了8)然后把值复制到加密字符push edx//将edx放入堆栈内存push ecx//将CHAR放入堆栈内存push eax//将EKey放入栈内存movzx eax, byte ptr[eax]//使用eax内部的EKey(z)作为eax内存地址rol al, 1//al 向左旋转 1 位,111 1010(将末尾的 0 移到开头)not al//反转 al (1111 0100) 的每一位变为 0000 1011rol al, 1//将al的反转二进制向左旋转1位rol al, 1//将 al 二进制再次向左旋转 1 位,0001 0110mov edx, eax//将Ekey的值复制到edx, edx = 44pop eax//从栈内存中移除eax寄存器mov byte ptr[eax], dl//使用edx的值作为eax(Ekey)的字节地址pop ecx//从栈内存中取出ecx(EKey)xor ecx, edx//实现edx和CHAR之间的异或运算,83和44变成127(111 1111)mov eax, ecx//将Char的异或值复制到EKeyror al, 1//将 al 值向右旋转 1 位 127 (0111 1111)ror al, 1//将 al 值向右旋转 1 位 191 (1011 1111)ror al, 1//将 al 值向右旋转 1 位 223 (1101 1111) al 值现在是 239 (1110 1111)pop edx//从堆栈内存中移除edxmov edx, eax//将EKey的值复制到edx 239 (1110 1111)pop ebp//从栈内存中移除ebpret//转到调用指令后的行}}//----------------- 解密字符函数结束-----------------////************ 主程序 *******************************************************************************************int main(void){int char_count(5);//输入的实际字符数(最多 MAXCHARS 限制).//cout<<"\n请输入最多" <<最大字符<<"字母数字字符:  ";//get_original_chars(char_count);//输入要加密的原始字符串//*********************************************************//打开一个文件来存储结果(你可以在 Visual Studio 中查看和编辑这个文件)ofstream EDump;EDump.open("EncryptDump.txt", ios::app);EDump<<"\n\nFoCA 加密程序结果 (" << StudentName << ") Encryption key = '" <<EKey<<"'";EDump<<"\n日期:" <<获取日期()<<" 时间:" <<获取时间();//*********************************************************//显示刚刚输入的字符串并保存到EDump文件cout<<"\n\n原始字符串 = " <<OChars<<"\tHex = ";EDump<<"\n\n原始字符串 = " <<OChars<<"\tHex = ";for (int i = 0; i < char_count; i++){cout<<十六进制<

解决方案

我将您的内联程序集移植到 NASM 32 位源代码,并以相同的程序集语言重新实现了外循环 (encrypt_chars)来源也是.我上传了 一个带有更新的 repo 和一个可以在 Linux 上编译的 C 语言的简短测试程序使用 gcc -m32.要构建它,您需要 NASM、gcc 和 我的宏集合.汇编源代码如下:

<预><代码>;CC-BY-SA,来源:;https://stackoverflow.com/questions/60787907/x86-assembly-encryption-to-decryption%include "lmacros3.mac"%ifidni __OUTPUT_FORMAT__, bin位 32%elifidni __OUTPUT_FORMAT__, 小精灵全局 testfunc_encode%万一testfunc_encode:lframe附近lpar 双字,EKeylpar 双字,长度lpar 双字,ECharslpar dword, OCharslpar_return出借人推杆mov esi, dword [ebp + ?OChars]mov ebx, dword [ebp + ?EChars]mov edi, dword [ebp + ?length]测试edi,edijz.end.环形:movzx ecx, 字节 [esi]lea eax, [ebp + ?EKey]推ECX推eax调用 encrypt_3添加 esp, 8mov 字节 [ebx], dl公司公司十月循环.结尾:弹出框离开输入加密_3:lframe附近lpar 双字,数据lpar 双字,points_to_keylpar_return出借人;推送 ebp ;将 ebp 保存到堆栈内存;移动 ebp, esp ;将 esp 的值复制到 ebp;mov eax, [ebp + 8] ;将 ebp 的值加 8,然后将其值复制到 EKey;mov ecx, [ebp + 12] ;将 ebp 的值加 12(最近加了 8)然后将该值复制到加密字符mov eax, dword [ebp + ?points_to_key]mov ecx, dword [ebp + ?data]推 edx ;将 edx 放入堆栈内存推 ecx ;将 CHAR 放入堆栈内存推 eax ;将 EKey 放入堆栈内存movzx eax, 字节 [eax] ;使用 eax 内部的 EKey (z) 作为 eax 内存地址卷, 1 ;将 al 向左旋转 1 位,111 1010(将末尾的 0 移到开头)不是 ;将 al (1111 0100) 的每一位反转为 0000 1011卷, 1 ;将 al 的反转二进制向左旋转 1 位卷, 1 ;将 al 二进制再次向左旋转 1 位,0001 0110移动 edx, eax ;将 Ekey 的值复制到 edx,edx = 44流行音乐;从堆栈内存中删除 eax 寄存器mov 字节 [eax], dl ;使用edx的值作为eax(Ekey)的字节地址流行 ecx ;从堆栈内存中移除 ecx (EKey)异或 ecx, edx ;实现edx和CHAR之间的异或运算,83和44变成127(111 1111)移动 eax, ecx ;将 Char 的异或值复制到 EKeyr al, 1 ;将 al 值向右旋转 1 位 127 (0111 1111)r al, 1 ;将 al 值向右旋转 1 位 191 (1011 1111)r al, 1 ;将 al 值向右旋转 1 位 223 (1101 1111) al 值现在是 239 (1110 1111)流行edx;从堆栈内存中删除 edx移动 edx, eax ;将 EKey 的值复制到 edx 239 (1110 1111);流行 ebp ;从堆栈内存中删除 ebp;退;转到调用指令后的行离开,优化恢复输入%ifidni __OUTPUT_FORMAT__, 小精灵全局 testfunc_decode%万一testfunc_decode:lframe附近lpar 双字,EKeylpar 双字,长度lpar 双字,ECharslpar dword, OCharslpar_return出借人推杆mov esi, dword [ebp + ?OChars]mov ebx, dword [ebp + ?EChars]mov edi, dword [ebp + ?length]测试edi,edijz.end.环形:movzx ecx, 字节 [esi]lea eax, [ebp + ?EKey]推ECX推eax调用解密_3添加 esp, 8mov 字节 [ebx], dl公司公司十月循环.结尾:弹出框离开输入解密_3:lframe附近lpar 双字,数据lpar 双字,points_to_keylpar_return出借人mov eax, dword [ebp + ?points_to_key]mov ecx, dword [ebp + ?data]推 edx ;将 edx 放入堆栈内存推 ecx ;将 CHAR 放入堆栈内存推 eax ;将 EKey 放入堆栈内存movzx eax, 字节 [eax] ;使用 eax 内部的 EKey (z) 作为 eax 内存地址卷, 1 ;将 al 向左旋转 1 位,111 1010(将末尾的 0 移到开头)不是 ;将 al (1111 0100) 的每一位反转为 0000 1011卷, 1 ;将 al 的反转二进制向左旋转 1 位卷, 1 ;将 al 二进制再次向左旋转 1 位,0001 0110移动 edx, eax ;将 Ekey 的值复制到 edx,edx = 44流行音乐;从堆栈内存中删除 eax 寄存器mov 字节 [eax], dl ;使用edx的值作为eax(Ekey)的字节地址流行 ecx ;从堆栈内存中移除 ecx (EKey)%如果 0;xor cl, KEYBYTE;错误 CL, 3异或 ecx, edx ;实现edx和CHAR之间的异或运算,83和44变成127(111 1111)移动 eax, ecx ;将 Char 的异或值复制到 EKeyr al, 1 ;将 al 值向右旋转 1 位 127 (0111 1111)r al, 1 ;将 al 值向右旋转 1 位 191 (1011 1111)r al, 1 ;将 al 值向右旋转 1 位 223 (1101 1111) al 值现在是 239 (1110 1111)%别的;滚动 cl, 3;xor cl, KEYBYTE滚动 cl, 3异或 cl, dl移动%万一流行edx;从堆栈内存中删除 edx移动 edx, eax ;将 EKey 的值复制到 edx 239 (1110 1111)离开,优化恢复输入

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

<预><代码>//CC-BY-SA,来源://https://stackoverflow.com/questions/60787907/x86-assembly-encryption-to-decryption#include #include #include void testfunc_encode(uint8_t* OChars, uint8_t* EChars, uint32_t 长度, uint8_t EKey);void testfunc_decode(uint8_t* OChars, uint8_t* EChars, uint32_t 长度, uint8_t EKey);uint32_t 下一个(uint32_t 之前){uint32_t 移位 = 先前 >>1;返回 ( (之前 & 1) ? 移位 ^ 0x80200003 : 移位);}int test1() {const uint32_t bufsize = 1024/4;uint32_t 原始 [bufsize];uint32_t 编码 [bufsize];uint32_t 解码 [bufsize];uint32_t ii;uint32_t ll = 1;int rc = 0;对于 (ii = 0; ii

我用 bash 编写了一个测试脚本.它默认使用 ../lmacros/ 作为宏集合的来源.如果您将宏文件(lmacros1.maclmacros2.maclmacros3.mac) 其他地方.您还可以通过这种方式为 NASM 或 C 编译器指定不同的标志.这是脚本:

#!/bin/bash设置 -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./主要的

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

$ NASM=oldnasm ./test.sh使用相同的密钥测试 1 成功!使用不同密钥的测试 2 没有成功.使用相同的密钥测试 3 成功!使用不同密钥的测试 4 没有成功.$

为了创建 decrypt_3,我只需要从 encrypt_3 函数中更改一个特定部分.密钥计算保持完全相同.我们只需要更改如何使用该键字节值将输入字节转换为输出字节.我在这里引用特定部分:

%if 0;xor cl, KEYBYTE;错误 CL, 3异或 ecx, edx ;实现edx和CHAR之间的异或运算,83和44变成127(111 1111)移动 eax, ecx ;将 Char 的异或值复制到 EKeyr al, 1 ;将 al 值向右旋转 1 位 127 (0111 1111)r al, 1 ;将 al 值向右旋转 1 位 191 (1011 1111)r al, 1 ;将 al 值向右旋转 1 位 223 (1101 1111) al 值现在是 239 (1110 1111)%别的;滚动 cl, 3;xor cl, KEYBYTE滚动 cl, 3异或 cl, dl移动%万一

我没有优化程序,也没有更新你在汇编源代码中的注释.你大概可以把解码的具体解转入你的整个程序,它不大.

So I am trying to create decryption from an encryption routine but I really have a poor experience with it. Can anyone please help me? Thank you in advance!

PS. the routine is poorly written intentionally for us to change later on. edited: sorry, here is my whole encry[ption routine, all I know is that everything done with my EKey (eax) should remain the same but I need to reverse whats done with the char (ecx). I dont really know where to start, Thanks in advance again.

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

解决方案

I ported your inline assembly to NASM 32-bit source and re-implemented the outer loop (encrypt_chars) in the same assembly language source too. I uploaded a repo with the updates and a short test program in C which can be compiled on Linux with gcc -m32. For building this you need NASM, gcc, and my macro collection. Here's the assembly source:


; 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

I made a C test program which fills a 1 KiB buffer with a 32-bit LFSR, then tries encoding and decoding the data a few times with various keys. It will display "Error:" if an unexpected result happens. Here's the source:


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

I made a test script in bash. It defaults to use ../lmacros/ as the source of the macro collection. You can change that (eg by running NASMINCLUDE=path/to/macros/ ./test.sh) if you put the macro files (lmacros1.mac and lmacros2.mac and lmacros3.mac) somewhere else. You can also specify different flags to NASM or the C compiler in this way. This is the script:

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

This is what it looks like to run it, if it succeeds:

$ 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.
$ 

There was only one specific part that I had to change from the encrypt_3 function to create decrypt_3. The key calculation remains exactly the same. We only need to change how that key byte value is used to transform the input byte, into what becomes the output byte. I'm quoting the specific part here:

%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

I did not optimise the program, nor update your comments in the assembly source. You can probably transfer the specific solution of the decoding into your whole program, it isn't large.

这篇关于x86 程序集加密到解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆