mirror of
git://f0xx.org/android_cast
synced 2026-07-29 06:18:42 +03:00
216 lines
4.4 KiB
C
216 lines
4.4 KiB
C
#include "obfuscate_file.h"
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
static uint32_t dummy_u32(uint64_t seed, uint32_t salt)
|
|
{
|
|
uint64_t x = seed ^ ((uint64_t)salt * 0x9E3779B97F4A7C15ULL);
|
|
|
|
x ^= x >> 33;
|
|
x *= 0xFF51AFD7ED558CCDULL;
|
|
x ^= x >> 33;
|
|
return (uint32_t)(x ^ (x >> 32));
|
|
}
|
|
|
|
static void put_u32_le(uint8_t *dst, uint32_t v)
|
|
{
|
|
dst[0] = (uint8_t)(v);
|
|
dst[1] = (uint8_t)(v >> 8);
|
|
dst[2] = (uint8_t)(v >> 16);
|
|
dst[3] = (uint8_t)(v >> 24);
|
|
}
|
|
|
|
static void put_u64_le(uint8_t *dst, uint64_t v)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < 8u; i++)
|
|
dst[i] = (uint8_t)(v >> (8u * i));
|
|
}
|
|
|
|
static uint32_t get_u32_le(const uint8_t *src)
|
|
{
|
|
return (uint32_t)src[0] | ((uint32_t)src[1] << 8) | ((uint32_t)src[2] << 16) |
|
|
((uint32_t)src[3] << 24);
|
|
}
|
|
|
|
static uint64_t get_u64_le(const uint8_t *src)
|
|
{
|
|
uint64_t v = 0;
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < 8u; i++)
|
|
v |= (uint64_t)src[i] << (8u * i);
|
|
return v;
|
|
}
|
|
|
|
int32_t obf_file_payload_count(long file_size, size_t *count_out)
|
|
{
|
|
long payload_bytes;
|
|
|
|
if (file_size < 0)
|
|
return OBF_ERR_IO;
|
|
if ((unsigned long)file_size < OBF_FILE_OVERHEAD + sizeof(uint64_t))
|
|
return OBF_ERR_FORMAT;
|
|
|
|
payload_bytes = file_size - (long)OBF_FILE_OVERHEAD;
|
|
if (payload_bytes % (long)sizeof(uint64_t) != 0)
|
|
return OBF_ERR_FORMAT;
|
|
|
|
*count_out = (size_t)payload_bytes / sizeof(uint64_t);
|
|
return OBF_OK;
|
|
}
|
|
|
|
static int32_t write_encoded_file(const char *path, const uint64_t *encoded, size_t count,
|
|
uint64_t seed)
|
|
{
|
|
FILE *fp;
|
|
uint8_t hdr[OBF_FILE_HDR_SIZE];
|
|
uint8_t tail[OBF_FILE_TAIL_SIZE];
|
|
uint8_t block[sizeof(uint64_t)];
|
|
size_t i;
|
|
|
|
if (path == NULL || encoded == NULL || count == 0)
|
|
return OBF_ERR_NULL;
|
|
|
|
fp = fopen(path, "wb");
|
|
if (fp == NULL)
|
|
return OBF_ERR_IO;
|
|
|
|
put_u32_le(hdr, dummy_u32(seed, 0xA11CEu));
|
|
if (fwrite(hdr, 1, sizeof(hdr), fp) != sizeof(hdr)) {
|
|
fclose(fp);
|
|
return OBF_ERR_IO;
|
|
}
|
|
|
|
for (i = 0; i < count; i++) {
|
|
put_u64_le(block, encoded[i]);
|
|
if (fwrite(block, 1, sizeof(block), fp) != sizeof(block)) {
|
|
fclose(fp);
|
|
return OBF_ERR_IO;
|
|
}
|
|
}
|
|
|
|
put_u32_le(tail, dummy_u32(seed, 0x7A1Lu));
|
|
if (fwrite(tail, 1, sizeof(tail), fp) != sizeof(tail)) {
|
|
fclose(fp);
|
|
return OBF_ERR_IO;
|
|
}
|
|
|
|
if (fclose(fp) != 0)
|
|
return OBF_ERR_IO;
|
|
return OBF_OK;
|
|
}
|
|
|
|
int32_t write_many_to(const char *path, const uint64_t *vals, size_t count, uint64_t seed)
|
|
{
|
|
uint64_t *encoded;
|
|
size_t i;
|
|
int32_t rv;
|
|
|
|
if (path == NULL || vals == NULL || count == 0)
|
|
return OBF_ERR_NULL;
|
|
|
|
encoded = (uint64_t *)malloc(count * sizeof(uint64_t));
|
|
if (encoded == NULL)
|
|
return OBF_ERR_IO;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
rv = encode(vals[i], seed, &encoded[i]);
|
|
if (rv != OBF_OK) {
|
|
free(encoded);
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
rv = write_encoded_file(path, encoded, count, seed);
|
|
free(encoded);
|
|
return rv;
|
|
}
|
|
|
|
int32_t write_to(const char *path, uint64_t val, uint64_t seed)
|
|
{
|
|
return write_many_to(path, &val, 1, seed);
|
|
}
|
|
|
|
int32_t read_many_from(const char *path, uint64_t seed, uint64_t *out_vals, size_t out_cap,
|
|
size_t *out_count)
|
|
{
|
|
FILE *fp;
|
|
long file_size;
|
|
size_t count;
|
|
size_t i;
|
|
uint8_t hdr[OBF_FILE_HDR_SIZE];
|
|
uint8_t tail[OBF_FILE_TAIL_SIZE];
|
|
uint8_t block[sizeof(uint64_t)];
|
|
uint64_t encoded;
|
|
uint64_t decoded;
|
|
int32_t rv;
|
|
|
|
if (path == NULL || out_vals == NULL || out_count == NULL)
|
|
return OBF_ERR_NULL;
|
|
|
|
fp = fopen(path, "rb");
|
|
if (fp == NULL)
|
|
return OBF_ERR_IO;
|
|
|
|
if (fseek(fp, 0, SEEK_END) != 0) {
|
|
fclose(fp);
|
|
return OBF_ERR_IO;
|
|
}
|
|
file_size = ftell(fp);
|
|
if (file_size < 0 || fseek(fp, 0, SEEK_SET) != 0) {
|
|
fclose(fp);
|
|
return OBF_ERR_IO;
|
|
}
|
|
|
|
rv = obf_file_payload_count(file_size, &count);
|
|
if (rv != OBF_OK) {
|
|
fclose(fp);
|
|
return rv;
|
|
}
|
|
if (count > out_cap) {
|
|
fclose(fp);
|
|
return OBF_ERR_OVERFLOW;
|
|
}
|
|
|
|
if (fread(hdr, 1, sizeof(hdr), fp) != sizeof(hdr)) {
|
|
fclose(fp);
|
|
return OBF_ERR_IO;
|
|
}
|
|
(void)get_u32_le(hdr);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (fread(block, 1, sizeof(block), fp) != sizeof(block)) {
|
|
fclose(fp);
|
|
return OBF_ERR_IO;
|
|
}
|
|
encoded = get_u64_le(block);
|
|
rv = decode(encoded, seed, &decoded);
|
|
if (rv != OBF_OK) {
|
|
fclose(fp);
|
|
return rv;
|
|
}
|
|
out_vals[i] = decoded;
|
|
}
|
|
|
|
if (fread(tail, 1, sizeof(tail), fp) != sizeof(tail)) {
|
|
fclose(fp);
|
|
return OBF_ERR_IO;
|
|
}
|
|
(void)get_u32_le(tail);
|
|
|
|
fclose(fp);
|
|
*out_count = count;
|
|
return OBF_OK;
|
|
}
|
|
|
|
int32_t read_from(const char *path, uint64_t seed, uint64_t *out)
|
|
{
|
|
size_t count = 0;
|
|
|
|
return read_many_from(path, seed, out, 1, &count);
|
|
}
|