Skip to content

Instantly share code, notes, and snippets.

@llxiaoyuan
Forked from haram/decrypt.cpp
Created February 28, 2023 05:47
Show Gist options
  • Save llxiaoyuan/ce5fa39ad76c09cf6fc8def0fb546c80 to your computer and use it in GitHub Desktop.
Save llxiaoyuan/ce5fa39ad76c09cf6fc8def0fb546c80 to your computer and use it in GitHub Desktop.
Escape From Tarkov encryption defeated
#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