Besides using bitwise operations, basic mathematical operations can also be used. If addition has a subtraction counterpart, we can encrypt a file using addition and decrypt it with subtraction, and vice-versa. The following code shows decryption using addition:
mov ecx, 0x10
mov esi, 0x00402000
loc_00401000:
mov al, [esi]
add al, 0x10
mov [esi], al
inc esi
dec ecx
jnz loc_00401000
The beauty of byte values is that they can be processed as signed numbers, if, for example, given this set of encryption information:
data = 0x00, 0x01, 0x02, 0x0a, 0x10, 0x1A, 0xFE, 0xFF
key = 0x11
encrypt algorithm = byte subtraction
decrypt algorithm = byte addition
After each byte gets subtracted with 0x11, the encrypted data would be the following:
encrypted data = 0xEF, 0xF0, 0xF1, 0xF9, 0xFF, 0x09, 0xED, 0xEE
To restore it, we'll have to add the same value, 0x11, that was subtracted before:
decrypted data = 0x00, 0x01, 0x02, 0x0a, 0x10, 0x1A, 0xFE, 0xFF
If we look at the equivalent decimal values of the preceding bytes in unsigned and signed form, the data would look like the following:
data (unsigned) = 0, 1, 2, 10, 16, 26, 254, 255
data (signed) = 0, 1, 2, 10, 16, 26, -2, -1
Here's the encrypted data shown in decimal values:
encrypted data (unsigned) = 239, 240, 241, 249, 255, 9, 237, 238
encrypted data (signed) = -17, -16, -15, -7, -1, 9, -19, -18
To sum it up, if we were to use basic arithmetical operations, we should look at it in the value's signed form.