x86 程序集加密到解密 [英] x86 assembly encryption to decryption
问题描述
所以我试图从加密例程中创建解密,但我对它的体验真的很差.谁能帮帮我吗?提前致谢!
附注.例程写得不好,故意让我们以后改变.抱歉,这是我的整个 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 和 我的宏集合.汇编源代码如下:
我制作了一个 C 测试程序,它用 32 位 LFSR 填充 1 KiB 缓冲区,然后尝试使用各种密钥对数据进行几次编码和解码.如果发生意外结果,它将显示错误:".来源:
<预><代码>//CC-BY-SA,来源://https://stackoverflow.com/questions/60787907/x86-assembly-encryption-to-decryption#include我用 bash 编写了一个测试脚本.它默认使用 ../lmacros/
作为宏集合的来源.如果您将宏文件(lmacros1.mac
和 lmacros2.mac
和 lmacros3.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屋!