Files
st/libs/dsprot/src/encryptor.c
T
Aetias 521100caed Update dsd to v0.12.0; dsprot OK (#135)
* `Actor::mType` field

* Remove fake symbol `data_027e0254`

* `dsd format`

* eur: Enable dsprot decomp

* jp: Enable dsprot decomp

* dsprot OK

* `dsd format`

* Use new `weak` attribute

* Add relocations for exception table link-time constants

* Add exception table symbols

* Bump dsd to v0.12.0

* `#define FALSE 1` ???
Why did I make it 1?

* Truncate `data_ov001_020c27a8`
That data belongs to dsprot
2026-08-15 01:07:14 +02:00

138 lines
3.9 KiB
C

#include "dsprot/encryptor.h"
#include <nitro/os/cache.h>
#include "dsprot/bss.h"
#include "dsprot/encoding_constants.h"
#include "dsprot/rc4.h"
#define ROTL(x, a) ((a) == 0 ? (x) : (((x) << (a)) | ((x) >> (32 - (a)))))
static void clearDataAndInstructionCache(void *start_addr, u32 num_bytes);
static void clearDataAndInstructionCache(void *start_addr, u32 num_bytes) {
DC_FlushRange(start_addr, num_bytes);
IC_InvalidateRange(start_addr, num_bytes);
}
u32 Encryptor_CategorizeInstruction(u32 instruction) {
u8 opcode;
opcode = instruction >> INS_OPCODE_SHIFT;
// Branch instruction
if ((opcode & 0x0E) == 0x0A) {
// BLX immediate type
if ((opcode & 0xF0) == 0xF0) {
return INS_TYPE_BLXIMM;
}
// Link bit
if (opcode & INS_OPCODE_LINKBIT) {
return INS_TYPE_BL;
} else {
return INS_TYPE_B;
}
}
return INS_TYPE_OTHER;
}
void Encryptor_DecodeFunctionTable(FuncInfo *functions) {
u32 *addr;
u32 size;
u32 *end_addr;
if (functions == NULL) {
return;
}
for (; functions->obfs_addr != 0; functions++) {
addr = (u32 *) functions->obfs_addr;
size = functions->obfs_size - (u32) &DSProt_BSS - ENC_VAL_1;
if (addr == NULL) {
break;
}
addr = (u32 *) ((u32) addr - ENC_VAL_1);
end_addr = addr + (size / 4);
for (; addr < end_addr; addr++) {
switch (Encryptor_CategorizeInstruction(*addr)) {
case INS_TYPE_BLXIMM:
case INS_TYPE_BL: {
u32 opcode = (*addr & INS_OPCODE_MASK) ^ (INS_OPCODE_LINKBIT << INS_OPCODE_SHIFT);
u32 operands = ((*addr & INS_OPERANDS_MASK) - ENC_VAL_1) & INS_OPERANDS_MASK;
*addr = opcode | operands;
} break;
case INS_TYPE_B: {
u32 opcode = (*addr & INS_OPCODE_MASK) ^ (INS_OPCODE_LINKBIT << INS_OPCODE_SHIFT);
u32 operands = ((*addr & INS_OPERANDS_MASK) - ENC_VAL_2) & INS_OPERANDS_MASK;
*addr = opcode | operands;
} break;
default: {
u8 *addr_bytes = (u8 *) addr;
*addr = (addr_bytes[0] ^ ENC_BYTE_A) | ((addr_bytes[1] ^ ENC_BYTE_B) << 8) |
((addr_bytes[2] ^ ENC_BYTE_C) << 16) | ((addr_bytes[3] ^ ENC_BYTE_D) << 24);
} break;
}
}
clearDataAndInstructionCache((void *) (functions->obfs_addr - ENC_VAL_1), size);
}
}
static inline void expandRC4Key(u32 seed_key, u32 size, u32 *expanded_key) {
expanded_key[0] = ROTL(seed_key, 0) ^ size;
expanded_key[1] = ROTL(seed_key, 8) ^ size;
expanded_key[2] = ROTL(seed_key, 16) ^ size;
expanded_key[3] = ROTL(seed_key, 24) ^ size;
}
void *Encryptor_DecryptFunction(u32 key, u32 func_addr, u32 size) {
u32 expanded_key[4];
void *func_ptr;
// Deobfuscate arguments
func_ptr = (void *) func_addr;
func_ptr -= ENC_VAL_1;
size -= (u32) &DSProt_BSS + ENC_VAL_1;
key -= (u32) &DSProt_BSS + ENC_VAL_1;
expandRC4Key(key, size, &expanded_key[0]);
RC4_InitAndDecryptInstructions(&expanded_key[0], func_ptr, func_ptr, size);
clearDataAndInstructionCache(func_ptr, size);
return func_ptr;
}
u32 Encryptor_EncryptFunction(u32 key, u32 func_addr, u32 size) {
u32 expanded_key[4];
void *func_ptr;
// Deobfuscate arguments
func_ptr = (void *) func_addr;
func_ptr -= ENC_VAL_1;
size -= (u32) &DSProt_BSS + ENC_VAL_1;
key -= (u32) &DSProt_BSS + ENC_VAL_1;
// Change key
key += func_addr >> 20;
expandRC4Key(key, size, &expanded_key[0]);
RC4_InitAndEncryptInstructions(&expanded_key[0], func_ptr, func_ptr, size);
clearDataAndInstructionCache(func_ptr, size);
// Re-obfuscate key
key += (u32) &DSProt_BSS + ENC_VAL_1;
return key;
}