# Need help understanding XOR cipher

I am trying to modify a save file for a game. I think it is using an XOR cipher to encrypt it. Looking though the disassembly I think I found the function that decrypts it. I ran the assembly through a decompiler to get a better grip on what is going on.

I am a C# programmer with some knowledge of C/C++. I generally understand what is accomplished by this code, but there are some details I don't understand.

``````int __fastcall DecryptBuffer(unsigned __int8 *a1, int a2, int a3, unsigned int a4, int a5)
{
unsigned __int8 *v5;
unsigned __int8 *v6;
int result;
int v8;

v5 = a1;
v6 = &a1[a2];
result = a5;
v8 = a5 - (_DWORD)v5;
while ( v5 != v6 )
{
result = *v5 ^ *(unsigned __int8 *)(a3 + (unsigned int)&v5[v8] % a4);
*v5++ = result;
}
return result;
}
``````

It accepts as parameters:

• `a1` - a byte array
• `a2` - the length of the array
• `a3` - `0xB19D425B`
• `a4` - `0x107`
• `a5` - `0x00`

First, I can't figure out the value of `v8`. I don't know what `(_DWORD)v5` means, or why it is subtracted from zero.

Second, I don't know what `(unsigned int)&v5[v8]` is actually doing. I take it to mean it is looking up a byte somewhere in the array, but is it retrieving a single byte and casting to an uint, or four bytes?

Here is the disassembly:

``````sub_301E44
PUSH.W          {R4-R8,LR}
MOV             R4, R0
LDR             R0, [SP,#0x18+arg_0]
MOV             R7, R2
MOV             R8, R3
SUBS            R5, R0, R4
loc_301E54
CMP             R4, R6
BEQ             locret_301E6C
MOV             R1, R8
BL.W            __aeabi_uidivmod
LDRB            R0, [R4]
LDRB            R3, [R7,R1]
EORS            R0, R3
STRB.W          R0, [R4],#1
B               loc_301E54
locret_301E6C
POP.W           {R4-R8,PC}
``````

This is the function that calls the above:

``````PUSH            {R0-R2,LR}
MOVS            R3, #0
LDR             R2, =(dword_8749EF - 0x301E80)
STR             R3, [SP,#0x10+var_10]
MOVW            R3, #0x107
BL              sub_301E44
``````

`(_DWORD)v5` is simply casting the `__int8*` pointer to `_DWORD`. Decompilations tend to be quite messy if you don't fix variable types, so let's ignore types for a moment.

To understand the value of v8, substitute it into the expression bellow: `&v5[a5 - v5_old]`. We can also understand this as `v5 + a5 - v5_old`. `v5` is being incremented with each iteration of the loop, so the above expression is basically the current index plus `a5`.

The current index plus `a5` modulo `a4` (presumably the length of the buffer pointed to by `a3`) is then added to `a3` and the corresponding byte is XOR'd to the byte currently pointed to by `v5`.

Here's my take on the algorithm:

``````void DecryptBuffer ( char *buffer, int buffer_len, char *key, int key_len, int key_start )
{
int i;
for ( i = 0; i < buffer_len; i++ )
buffer [ i ] ^= key [ ( key_start + i ) % key_len ];
}
``````

Or in other words, XOR with the key repeating over and over.

This is quite standard, so it's probably right, but it could be wrong—as I said, the decompilation is quite messy. If you want a sure answer, either clean it up by fixing variable types or post the disassembly as well.

• Thanks so much, that works. I would never have realized that `key` was a pointer to an array (rather than just an integer) and that `v8` was being used to determine how far into the buffer we were. I attached the disassembly for completeness. – Chet Oct 4 '18 at 0:06