Need help understanding XOR cipher
Clash Royale CLAN TAG#URR8PPP
up vote
3
down vote
favorite
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 arraya2
- the length of the arraya3
-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
ADDS R6, R0, R1
LDR R0, [SP,#0x18+arg_0]
MOV R7, R2
MOV R8, R3
SUBS R5, R0, R4
loc_301E54
CMP R4, R6
BEQ locret_301E6C
ADDS R0, R5, R4
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
ADD R2, PC ; dword_8749EF
BL sub_301E44
ADD SP, SP, #0xC
c++ arm
New contributor
add a comment |Â
up vote
3
down vote
favorite
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 arraya2
- the length of the arraya3
-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
ADDS R6, R0, R1
LDR R0, [SP,#0x18+arg_0]
MOV R7, R2
MOV R8, R3
SUBS R5, R0, R4
loc_301E54
CMP R4, R6
BEQ locret_301E6C
ADDS R0, R5, R4
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
ADD R2, PC ; dword_8749EF
BL sub_301E44
ADD SP, SP, #0xC
c++ arm
New contributor
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
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 arraya2
- the length of the arraya3
-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
ADDS R6, R0, R1
LDR R0, [SP,#0x18+arg_0]
MOV R7, R2
MOV R8, R3
SUBS R5, R0, R4
loc_301E54
CMP R4, R6
BEQ locret_301E6C
ADDS R0, R5, R4
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
ADD R2, PC ; dword_8749EF
BL sub_301E44
ADD SP, SP, #0xC
c++ arm
New contributor
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 arraya2
- the length of the arraya3
-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
ADDS R6, R0, R1
LDR R0, [SP,#0x18+arg_0]
MOV R7, R2
MOV R8, R3
SUBS R5, R0, R4
loc_301E54
CMP R4, R6
BEQ locret_301E6C
ADDS R0, R5, R4
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
ADD R2, PC ; dword_8749EF
BL sub_301E44
ADD SP, SP, #0xC
c++ arm
c++ arm
New contributor
New contributor
edited Oct 4 at 0:04
New contributor
asked Oct 3 at 19:32
Chet
1185
1185
New contributor
New contributor
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
3
down vote
accepted
(_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 thatkey
was a pointer to an array (rather than just an integer) and thatv8
was being used to determine how far into the buffer we were. I attached the disassembly for completeness.
â Chet
Oct 4 at 0:06
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
(_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 thatkey
was a pointer to an array (rather than just an integer) and thatv8
was being used to determine how far into the buffer we were. I attached the disassembly for completeness.
â Chet
Oct 4 at 0:06
add a comment |Â
up vote
3
down vote
accepted
(_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 thatkey
was a pointer to an array (rather than just an integer) and thatv8
was being used to determine how far into the buffer we were. I attached the disassembly for completeness.
â Chet
Oct 4 at 0:06
add a comment |Â
up vote
3
down vote
accepted
up vote
3
down vote
accepted
(_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.
(_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.
answered Oct 3 at 20:14
user2347953
1213
1213
Thanks so much, that works. I would never have realized thatkey
was a pointer to an array (rather than just an integer) and thatv8
was being used to determine how far into the buffer we were. I attached the disassembly for completeness.
â Chet
Oct 4 at 0:06
add a comment |Â
Thanks so much, that works. I would never have realized thatkey
was a pointer to an array (rather than just an integer) and thatv8
was being used to determine how far into the buffer we were. I attached the disassembly for completeness.
â Chet
Oct 4 at 0:06
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 at 0:06
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 at 0:06
add a comment |Â
Chet is a new contributor. Be nice, and check out our Code of Conduct.
Chet is a new contributor. Be nice, and check out our Code of Conduct.
Chet is a new contributor. Be nice, and check out our Code of Conduct.
Chet is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2freverseengineering.stackexchange.com%2fquestions%2f19524%2fneed-help-understanding-xor-cipher%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password