Reputation:
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 --------------------------------------------------------------------
Upvotes: 0
Views: 1172
Reputation: 2763
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.
Upvotes: 1