374 lines
9.8 KiB
C++
374 lines
9.8 KiB
C++
|
|
#include "an6000_decode.h"
|
|
#if (RM_MODEL == RM_MODEL_TYPE_AN6000)
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
typedef struct {
|
|
volatile unsigned long size;
|
|
volatile char type[4];
|
|
} BoxHeader_t;
|
|
|
|
typedef struct _BoxAddress_t {
|
|
fpos_t addr;
|
|
unsigned long size;
|
|
} BoxAddress_t;
|
|
|
|
/**
|
|
* @brief Convert the Byte-order(32bit) <for little-endian environment>
|
|
*
|
|
* @param[in] val target value
|
|
*
|
|
* @return convert value
|
|
*/
|
|
unsigned long convertEndian_32(unsigned long val)
|
|
{
|
|
unsigned long result = 0;
|
|
unsigned char *p1 = (unsigned char *)&val;
|
|
unsigned char *p2 = (unsigned char *)&result;
|
|
p2[0] = p1[3];
|
|
p2[1] = p1[2];
|
|
p2[2] = p1[1];
|
|
p2[3] = p1[0];
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief [DEBUG] Box data analysis
|
|
*
|
|
* @param[in] fp target file pointer
|
|
* @param[in] level analysis depth
|
|
* @param[in] parentSize parent box size
|
|
*/
|
|
void BoxAnalysis(FILE *fp, int level, size_t parentSize)
|
|
{
|
|
BoxHeader_t boxHead, childBoxHead;
|
|
char typeDesc[8] = {0};
|
|
size_t readSize;
|
|
int i;
|
|
int isNotAscii;
|
|
char *pbuf = NULL;
|
|
fpos_t pos;
|
|
|
|
while (1) {
|
|
// read box header
|
|
readSize = fread(&boxHead, 1, sizeof(BoxHeader_t), fp);
|
|
if ((feof(fp) != 0) || (readSize == 0)) {
|
|
break;
|
|
}
|
|
boxHead.size = convertEndian_32(boxHead.size);
|
|
strncpy(typeDesc, (const char *)&boxHead.type[0], 4);
|
|
if (boxHead.size == 0) {
|
|
break;
|
|
}
|
|
fgetpos(fp, &pos);
|
|
printf("[%08X] ", (unsigned long)(pos - sizeof(BoxHeader_t)));
|
|
for (i = 0; i < level; i++) {
|
|
printf(" ");
|
|
}
|
|
printf("%s[%d]\n", typeDesc, boxHead.size);
|
|
if (parentSize != (size_t)-1) {
|
|
parentSize -= boxHead.size;
|
|
}
|
|
|
|
// check child box exist
|
|
readSize = fread(&childBoxHead, 1, sizeof(BoxHeader_t), fp);
|
|
childBoxHead.size = convertEndian_32(childBoxHead.size);
|
|
isNotAscii = 0;
|
|
for (i = 0; i < 4; i++) {
|
|
if ((childBoxHead.type[i] < 'a') || (childBoxHead.type[i] > 'z')) {
|
|
++isNotAscii;
|
|
break;
|
|
}
|
|
}
|
|
fseek(fp, -(long)sizeof(BoxHeader_t), SEEK_CUR);
|
|
|
|
if ((boxHead.size > childBoxHead.size) && (isNotAscii == 0)) {
|
|
// child box exist
|
|
BoxAnalysis(fp, level + 1, boxHead.size - sizeof(BoxHeader_t));
|
|
}
|
|
else {
|
|
// child box not exist
|
|
pbuf = (char *)malloc(boxHead.size - sizeof(BoxHeader_t));
|
|
fread(pbuf, 1, boxHead.size - sizeof(BoxHeader_t), fp);
|
|
free(pbuf);
|
|
}
|
|
|
|
// check of continue the child box loop
|
|
if (parentSize == 0) {
|
|
break;
|
|
}
|
|
|
|
// terminal box
|
|
if (strncmp((const char *)boxHead.type, "FWVR", 4) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
if (parentSize == (size_t)-1) {
|
|
fseek(fp, 0, SEEK_SET);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Get the crypt target box information
|
|
*
|
|
* @param[in] fp target file pointer
|
|
* @param[out] buf target box information
|
|
* @param[in] bufSize number of \a buf buffer
|
|
* @param[in] level analysis depth
|
|
* @param[in] parentSize parent box size
|
|
*
|
|
* @return number of available target box information
|
|
*/
|
|
static bool gFound_stsz = false;
|
|
static bool gFount_udat = false;
|
|
|
|
size_t GetCryptTarget(FILE *fp, BoxAddress_t *buf, size_t bufSize, int level, size_t parentSize)
|
|
{
|
|
size_t buf_num = 0;
|
|
BoxHeader_t boxHead = {0,};
|
|
BoxHeader_t childBoxHead = {0,};
|
|
size_t readSize = 0;
|
|
int isNotAscii = 0;
|
|
int i = 0;
|
|
//char *pbuf = NULL;
|
|
fpos_t pos = 0;
|
|
|
|
if (bufSize == 0) {
|
|
return 0;
|
|
}
|
|
|
|
while (1) {
|
|
// read box header
|
|
readSize = fread(&boxHead, 1, sizeof(BoxHeader_t), fp);
|
|
if (readSize == 0) {
|
|
break;
|
|
}
|
|
boxHead.size = convertEndian_32(boxHead.size);
|
|
if (boxHead.size == 0) {
|
|
break;
|
|
}
|
|
if (parentSize != (size_t)-1) {
|
|
parentSize -= boxHead.size;
|
|
}
|
|
|
|
// check crypt target box
|
|
|
|
if (((strncmp((const char *)boxHead.type, "stsz", 4) == 0) && (gFound_stsz == false) )
|
|
|| (strncmp((const char *)boxHead.type, "udat", 4) == 0) && (gFount_udat == false)){
|
|
fgetpos(fp, &pos);
|
|
buf[buf_num].addr = pos - sizeof(BoxHeader_t);
|
|
buf[buf_num].size = boxHead.size;
|
|
fseek(fp, boxHead.size - sizeof(BoxHeader_t), SEEK_CUR);
|
|
|
|
if(strncmp((const char *)boxHead.type, "stsz", 4) == 0)
|
|
{
|
|
gFound_stsz = true;
|
|
}
|
|
else if(strncmp((const char *)boxHead.type, "udat", 4) == 0)
|
|
{
|
|
gFount_udat = true;
|
|
}
|
|
|
|
if (++buf_num == bufSize) {
|
|
return buf_num;
|
|
}
|
|
}
|
|
else {
|
|
// Existence check of child box
|
|
readSize = fread(&childBoxHead, 1, sizeof(BoxHeader_t), fp);
|
|
fseek(fp, -(long)sizeof(BoxHeader_t), SEEK_CUR);
|
|
childBoxHead.size = convertEndian_32(childBoxHead.size);
|
|
isNotAscii = 0;
|
|
for (i = 0; i < 4; i++) {
|
|
if ((childBoxHead.type[i] < 'a') || (childBoxHead.type[i] > 'z')) {
|
|
++isNotAscii;
|
|
break;
|
|
}
|
|
}
|
|
if ((boxHead.size > childBoxHead.size) && (isNotAscii == 0)) {
|
|
// child box is exist
|
|
buf_num += GetCryptTarget(fp, &buf[buf_num], bufSize - buf_num, level + 1, boxHead.size - sizeof(BoxHeader_t));
|
|
if (buf_num == bufSize) {
|
|
return buf_num;
|
|
}
|
|
}
|
|
else {
|
|
// child box is not exist
|
|
fseek(fp, boxHead.size - sizeof(BoxHeader_t), SEEK_CUR);
|
|
}
|
|
}
|
|
|
|
// check of continue the child box loop
|
|
if (parentSize == 0) {
|
|
break;
|
|
}
|
|
|
|
// terminal box
|
|
if (strncmp((const char *)boxHead.type, "FWVR", 4) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
return buf_num;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Encrypt MP4 File
|
|
*
|
|
* @param[in] filename target file name
|
|
*
|
|
* @retval 0 successful
|
|
* @retval non-zero failed
|
|
*/
|
|
int encrypt_an6000(const wchar_t *filename)
|
|
{
|
|
FILE *fp = NULL;
|
|
BoxAddress_t tgtInfo[8];
|
|
size_t infoSize, i, x;
|
|
char *pbuf;
|
|
char key = 0x19;
|
|
char preData, enc;
|
|
|
|
memset(tgtInfo, 0, sizeof(tgtInfo));
|
|
infoSize = sizeof(tgtInfo) / sizeof(BoxAddress_t);
|
|
|
|
fp = _wfopen(filename,L"r+b");
|
|
//fp = fopen(filename, "r+b");
|
|
if (fp == NULL) {
|
|
return -1;
|
|
}
|
|
fseek(fp, 0, SEEK_SET);
|
|
|
|
// Analysis box information
|
|
//BoxAnalysis(fp, 0, (size_t)-1);
|
|
infoSize = GetCryptTarget(fp, tgtInfo, infoSize, 0, -1);
|
|
|
|
for (i = 0; i < infoSize; i++) {
|
|
pbuf = (char*)malloc(tgtInfo[i].size);
|
|
|
|
// read the target data
|
|
fsetpos(fp, &tgtInfo[i].addr);
|
|
fread(pbuf, 1, tgtInfo[i].size, fp);
|
|
|
|
// data encrypt
|
|
preData = 0;
|
|
for (x = 8; x < tgtInfo[i].size; x++) {
|
|
enc = ((~pbuf[x]) ^ preData) ^ key;
|
|
preData = pbuf[x];
|
|
pbuf[x] = enc;
|
|
}
|
|
|
|
// over-write the target data
|
|
fsetpos(fp, &tgtInfo[i].addr);
|
|
fwrite(pbuf, 1, tgtInfo[i].size, fp);
|
|
|
|
free(pbuf);
|
|
}
|
|
|
|
fclose(fp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Decrypt MP4 File
|
|
*
|
|
* @param[in] filename target file name
|
|
*
|
|
* @retval 0 successful
|
|
* @retval non-zero failed
|
|
*/
|
|
int decrypt_an6000(const wchar_t *filename)
|
|
{
|
|
gFound_stsz = false;
|
|
gFount_udat = false;
|
|
|
|
FILE *fp = NULL;
|
|
BoxAddress_t tgtInfo[8] = {0,};
|
|
size_t infoSize, i, x;
|
|
char *pbuf = NULL;
|
|
char key = 0x19;
|
|
char preData = 0;
|
|
|
|
memset(tgtInfo, 0, sizeof(_BoxAddress_t) * 8);
|
|
infoSize = sizeof(tgtInfo) / sizeof(_BoxAddress_t);
|
|
|
|
// filePathCH2.toStdWString().c_str()
|
|
fp = _wfopen(filename,L"r+b");
|
|
//fp = fopen(filename, "r+b");
|
|
if (fp == NULL) {
|
|
return -1;
|
|
}
|
|
fseek(fp, 0, SEEK_SET);
|
|
|
|
// Analysis box information
|
|
infoSize = GetCryptTarget(fp, tgtInfo, infoSize, 0, -1);
|
|
|
|
for (i = 0; i < infoSize; i++) {
|
|
pbuf = (char*)malloc(tgtInfo[i].size);
|
|
|
|
// read the target data
|
|
fsetpos(fp, &tgtInfo[i].addr);
|
|
fread(pbuf, 1, tgtInfo[i].size, fp);
|
|
|
|
// data decrypt
|
|
preData = 0;
|
|
for (x = 8; x < tgtInfo[i].size; x++) {
|
|
pbuf[x] = ~((pbuf[x] ^ key) ^ preData);
|
|
preData = pbuf[x];
|
|
}
|
|
|
|
// over-write the target data
|
|
fsetpos(fp, &tgtInfo[i].addr);
|
|
fwrite(pbuf, 1, tgtInfo[i].size, fp);
|
|
|
|
free(pbuf);
|
|
}
|
|
|
|
fclose(fp);
|
|
return 0;
|
|
}
|
|
bool is_encrypted_an6000(const wchar_t *filename)
|
|
{
|
|
gFound_stsz = false;
|
|
gFount_udat = false;
|
|
|
|
FILE *fp = NULL;
|
|
BoxAddress_t tgtInfo[8] = {0,};
|
|
size_t infoSize, i, x;
|
|
|
|
memset(tgtInfo, 0, sizeof(_BoxAddress_t) * 8);
|
|
infoSize = sizeof(tgtInfo) / sizeof(_BoxAddress_t);
|
|
|
|
fp = _wfopen(filename,L"r+b");
|
|
if (fp == NULL) {
|
|
return false;
|
|
}
|
|
fseek(fp, 0, SEEK_SET);
|
|
|
|
infoSize = GetCryptTarget(fp, tgtInfo, infoSize, 0, -1);
|
|
|
|
char buffer[16] = {0,};
|
|
for (i = 0; i < infoSize; i++) {
|
|
// read the target data
|
|
tgtInfo[i].addr += 4;
|
|
fsetpos(fp, &tgtInfo[i].addr);
|
|
fread(buffer, 1, 16, fp);
|
|
if(buffer[0] == 's' && buffer[1] =='t' && buffer[2] =='s' && buffer[3] =='z') {
|
|
|
|
bool enc = (buffer[4] != 0 || buffer[5] != 0 || buffer[6] != 0 || buffer[7] != 0);
|
|
fclose(fp);
|
|
return enc;//(buffer[4] != 0 || buffer[5] != 0 || buffer[6] != 0 || buffer[7] != 0);
|
|
}
|
|
//printf("%c:%c:%c:%c\n",buffer[0],buffer[1],buffer[2],buffer[3]);
|
|
//printf("%02X:%02X:%02X:%02X %02X:%02X:%02X:%02X\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7]);
|
|
}
|
|
fclose(fp);
|
|
return true;
|
|
}
|
|
#endif // #if (RM_MODEL == RM_MODEL_TYPE_AN6000)
|