因此,我试图通过加密例程创建解密,但是我对此确实经验很差。谁能帮帮我吗?预先谢谢!
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 --------------------------------------------------------------------
我将您的内联汇编移植到了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.sh
和lmacros1.mac
和lmacros2.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传输到整个程序中,这并不大。