# What's the inverse function of this decryption function? [closed]

size_t decrypt(unsigned char *buffer, size_t buflen)
{
size_t i = 0, j = 0;
signed int seed = 7, temp = 0;
for( ; (temp = (signed int) buffer[i]) && i < buflen; ++i)
{
if (temp == 0x5C) continue;
if (temp >= 0x20)
{
temp -= seed;
if (temp < 0x20)
temp += 0x5F;
}
buffer[j++] = temp;
seed = (seed + temp) % 8 + 1;
}
return j;       // Return the size of decrypted buffer .
}


seed = (seed+temp) % 8 + 1;, temp is obviously a character of plaintext. It uses a decrypted char to generate the key, which is used for next round.

But I don't know how to handle if (temp == 0x5C) continue;, Because the inverse operation of temp -= seed is temp += seed, which can generate a value "0x5C"，and that will be skipped by the decryption function ...

Update:

Here is the encrypted data, you guys can test it ..

unsigned char data[87] = { 0x0A, 0x0A, 0x0A, 0x0A, 0x73, 0x76, 0x76, 0x6A, 0x23, 0x79, 0x6B, 0x77, 0x4C, 0x6E, 0x68, 0x6D, 0x75, 0x6D, 0x5A, 0x68, 0x79, 0x76, 0x35, 0x4F, 0x76, 0x70, 0x75, 0x47, 0x7A, 0x75, 0x34, 0x6F, 0x69, 0x61, 0x77, 0x7C, 0x6B, 0x3C, 0x25, 0x22, 0x20, 0x28, 0x7C, 0x0A, 0x28, 0x21, 0x22, 0x23, 0x70, 0x62, 0x73, 0x74, 0x6A, 0x71, 0x66, 0x27, 0x7C, 0x66, 0x69, 0x6E, 0x6C, 0x25, 0x22, 0x20, 0x0A, 0x0A, 0x26, 0x27, 0x28, 0x21, 0x74, 0x6A, 0x77, 0x5C, 0x7D, 0x78, 0x6F, 0x28, 0x25, 0x7A, 0x64, 0x67, 0x74, 0x6A, 0x0A, 0x24, 0x0A };

• What makes you think that there exists an inverse? – poncho Jun 4 '15 at 17:18
• I quickly changed the formatting of the code, so the background is a nice rectangle instead of "per-line-length". – SEJPM Jun 5 '15 at 12:41
• For the very reason outlined in the question, it is not possible to make en encryption function accepting any arbitrary input (in particular with bytes in the 0x54 to 0x5B range, that is TUVWXYZ[ in ASCII) and such that the supplied decryption function will output the original plaintext. – fgrieu Jun 5 '15 at 13:41
• I'm guessing the choice to ignore 0x5C bytes is a cheap mechanism for being able to pepper the ciphertext with dummy bytes to mislead people. Whether it was a calculated choice by the authors in that the bytes fgrieu mentions are never used as input (so that reliable encryption is possible) or just an "obfuscation gone wrong" horror story, no-one can say. – Thomas Jun 5 '15 at 14:42
• Note that 0x5C is the backslash character, often used to escape things. However, escapes usually aren't just fixed. – Maarten Bodewes Jun 13 '15 at 23:57

First, let's try to undestand how decrypt works. Here I present you a slightly modified, more readable version of the same code, with no functional change:

size_t decrypt(unsigned char *buffer, size_t buflen) {
size_t opos = 0;
int seed = 7;

for (size_t ipos = 0; ipos < buflen; ++ipos)  {
int temp = buffer[ipos];


This first condition is used to terminate the decryption process if the string is shorter than bufsize. For instance, this might happen if the string is loaded in the buffer using a strcpy:

        if (temp == '\0') break;


If a literal \ is found the ciphertext, it's skipped. I suppose \ is the escape character, and this hypothesis seems to be confirmed by looking at the ciphertext you supply, where combinations like \} are present. This could have been put in place so that the encrypted program can be embedded in a string in another program. But that's just a wild guess.

        if (temp == '\\') continue;


0x20 (ASCII space) marks the beginning of the printable area of the ASCII table. Control characters (like line feeds and tabs) are copied as-is to ciphertext:

        if (temp >= ' ') {
temp -= seed;


The following statement is used to keep the ciphertext in the ASCII printable range by wrapping it around. Those bytes that map in the (non-printable) interval 0-0x20 are traslated to the 0x5f-0x7f interval, which is the higher part of the 7-bit ascii table.

            if(temp < ' ') temp += 0x5F;
}

buffer[opos++] = temp;


seed is updated using a simple linear-congruential RNG seeded with 7 and updated with temp, which at this point of the execution holds a byte of plaintext. So, the corresponding encryption function will have seed + buffer[ipos] or the like:

        seed = (seed + temp) % 8 + 1;
}

return opos;
}


This is a basic obfuscation mechanism that only supports 7bit ASCII and produces an output in the printable range, allowing safer trasmission and storage as text file.

That said, this is the encryption function I reconstructed following a trial and error process:

size_t encrypt(unsigned char *buffer, size_t buflen) {
size_t opos = 0;
int seed = 7;

for (size_t ipos = 0; ipos < buflen; ++ipos) {
int temp = buffer[ipos];

if (temp == '\0') break;

if (temp >= ' ') {
temp = ' ' + (temp + seed - ' ') % 0x80;
}

seed = (buffer[ipos] + seed) % 8 + 1;
buffer[opos++] = temp;
}

return opos;
}

• @GerronJo with a few more trials, I got a correct version. See the edit. – Stefano Sanfilippo Jun 15 '15 at 11:29