-
-
Save llxiaoyuan/ce5fa39ad76c09cf6fc8def0fb546c80 to your computer and use it in GitHub Desktop.
Escape From Tarkov encryption defeated
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <string.h> | |
// yousif, namazso, can1357, defcon42 | |
namespace packet | |
{ | |
constexpr size_t be_xor_key = 0xd774f59d; | |
namespace key | |
{ | |
size_t derive_1( uint8_t* packet ) | |
{ | |
return *( uint32_t* )( packet + 3 ) ^ be_xor_key; | |
} | |
size_t derive_2( uint8_t* packet ) | |
{ | |
return *( uint32_t* )( packet + 3 ) >> 0x11; | |
} | |
} | |
namespace steps | |
{ | |
void decrypt_1( uint8_t* data, uint64_t length, uint32_t xor_key ) | |
{ | |
for ( uint64_t i = 7; i < length - 3; ++i ) | |
{ | |
*( uint32_t* )( &data[ i ] ) ^= xor_key; | |
if ( ( xor_key >> ( i % 32 ) ) & 1 ) | |
xor_key *= ~xor_key; | |
if ( i < ( length - ( *( ( uint8_t* )( &xor_key ) + i % 4 ) & 3 ) - 4 ) ) | |
i += *( ( uint8_t* )( &xor_key ) + i % 3 ) & 3; | |
} | |
} | |
void decrypt_2( uint8_t* in_buf, uint64_t in_len, | |
uint8_t xor_key, uint8_t* out_buf, | |
int32_t* out_buf_sz, int32_t* out_len ) | |
{ | |
if ( in_len <= 7 ) | |
return; | |
uint32_t adjusted_idx = 0; | |
uint32_t curr_idx = 0; | |
uint8_t* curr_buf = in_buf + 7; // you need to skip 7 bytes, which is the prefix for encryption | |
for ( uint32_t i = 7; i < in_len; ++i, ++curr_buf ) | |
{ | |
xor_key -= xor_key >> ( i % 8 ); | |
uint8_t raw_byte = xor_key ^ *curr_buf; | |
if ( i >= curr_idx + 8 ) | |
{ | |
out_buf[ i - curr_idx - 8 ] = raw_byte; | |
} | |
else | |
{ | |
*curr_buf = raw_byte; | |
if ( i != 7 ) | |
continue; | |
curr_idx = ( uint8_t )( ~raw_byte ); | |
adjusted_idx = in_len - curr_idx - 8; | |
*out_len = adjusted_idx; | |
if ( adjusted_idx > * out_buf_sz ) | |
{ | |
*out_len = 0; | |
return; | |
} | |
} | |
} | |
} | |
} | |
void decrypt( uint8_t* encrypted_packet, size_t encrypted_size, | |
uint8_t* decrypted_packet, size_t* decrypted_sz ) | |
{ | |
memcpy( decrypted_packet, encrypted_packet, encrypted_size ); | |
const size_t first_key = key::derive_1( decrypted_packet ); | |
steps::decrypt_1( decrypted_packet, encrypted_size, first_key ); | |
int32_t unk1 = *decrypted_sz; | |
int32_t unk2 = 0; | |
const size_t second_key = key::derive_2( decrypted_packet ); | |
steps::decrypt_2( decrypted_packet, encrypted_size, second_key, decrypted_packet, &unk1, &unk2 ); | |
*decrypted_sz = unk2; | |
} | |
} | |
int main( ) | |
{ | |
uint8_t encrypted_packet[ ] | |
{ | |
0x18, 0xe8, 0x29, 0x45, 0xe4, 0x50, 0xf8, 0x32, 0xe4, 0x9c, 0xc8, 0x64, 0x08, 0x00, 0x45, 0x00, | |
0x00, 0x6e, 0x73, 0x95, 0x00, 0x00, 0x7f, 0x11, 0x21, 0xeb, 0x0a, 0x00, 0x01, 0x8b, 0x91, 0xef, | |
0x08, 0x85, 0xc8, 0x54, 0x42, 0x6e, 0x00, 0x5a, 0x5b, 0x8e, 0x9e, 0xbb, 0xf8, 0xc2, 0x9e, 0xc9, | |
0xa0, 0xce, 0xaa, 0xc5, 0xb2, 0xc1, 0x9d, 0xce, 0xb7, 0xc4, 0xb0, 0xd5, 0xb8, 0x8b, 0xb9, 0xe5, | |
0x81, 0xf3, 0x9a, 0xec, 0x89, 0xfb, 0x88, 0xd4, 0xbf, 0xdb, 0xb5, 0xdc, 0xbf, 0x91, 0xe2, 0x9b, | |
0xe8, 0xe8, 0x38, 0x38, 0x38, 0x00, 0x7f, 0x7f, 0x7f, 0x6f, 0xff, 0xff, 0xff, 0x0a, 0xfd, 0x08, | |
0x17, 0x2f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x43, 0x2a, 0x49, 0x3b, 0x54, 0x27, 0x48, 0x2e, 0x5a, | |
0x7a, 0x2d, 0x44, 0x2a, 0x4e, 0x21, 0x56, 0x25, 0x25, 0x25, 0x25, 0x25 | |
}; | |
uint8_t* decrypted_packet = ( uint8_t* )( malloc( sizeof( encrypted_packet ) ) ); | |
size_t decrypted_packet_sz = sizeof( encrypted_packet ); | |
packet::decrypt( encrypted_packet, sizeof( encrypted_packet ), decrypted_packet, &decrypted_packet_sz ); | |
for ( auto i = 0; i < decrypted_packet_sz; i++ ) | |
printf( "0x%x, ", decrypted_packet[ i ] ); | |
free( decrypted_packet ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment