Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@archshift
Created January 12, 2015 00:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save archshift/4cb754c432ba7854212a to your computer and use it in GitHub Desktop.
Save archshift/4cb754c432ba7854212a to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
void tea_decrypt (uint32_t *v, uint32_t *k) {
uint32_t v0=0, v1=0, sum=0;
uint32_t delta=0x61C88647;
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
do {
sum -= delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
} while (sum != 0x78DDE6E4);
v[0] ^= v0;
v[1] ^= v1;
}
int main (int argc, char **argv) {
if (argc != 3) {
printf("usage: %s gateway.dg decrypted.dg\n", argv[0]);
return 0;
}
uint32_t base[2];
uint32_t tea_key[4] = { 0x6E6629A0, 0x6F6AC2A1, 0x12B1908A, 0x1A31FDB};
FILE *gateway = fopen(argv[1], "rb");
FILE *decrypted = fopen(argv[2], "wb");
while (fread(base, 8, 1, gateway)) {
tea_decrypt(base, tea_key);
tea_key[0] += 8;
fwrite(base, 8, 1, decrypted);
}
// done
fclose(gateway);
fclose(decrypted);
return EXIT_SUCCESS;
}
#include <string>
#include <cinttypes>
#include <cstring>
#include <cstdlib>
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
enum : size_t {
NCCH_OFFSET_MAGIC = 0x100,
NCCH_OFFSET_SIZE = 0x104,
NCCH_OFFSET_NAME = 0x150,
};
size_t FindSequenceInBuffer(const u8* buffer, const size_t buf_len, const size_t start_pos, const u8* seq, const size_t seq_len)
{
for (size_t i = start_pos; i < buf_len; ++i)
{
if (memcmp(buffer + i, seq, seq_len) == 0)
return i;
}
return -1;
}
void StripNullBytes(std::string* str)
{
size_t end_pos = str->find_last_not_of('\0');
if (end_pos != std::string::npos)
*str = str->substr(0, end_pos + 1);
}
size_t WriteBufferToFile(const std::string& filename, const u8* buffer, const size_t size)
{
FILE* file = fopen(filename.c_str(), "wb");
size_t size_written = fwrite(buffer, 1, size, file);
fclose(file);
return size_written;
}
std::unique_ptr<u8> ReadDGFile(const std::string& filename, size_t* out_size)
{
FILE* dg_file = fopen(filename.c_str(), "rb");
fseek(dg_file, 0, SEEK_END);
*out_size = ftell(dg_file);
fseek(dg_file, 0, SEEK_SET);
std::unique_ptr<u8> file_buf(new u8[*out_size]);
fread(file_buf.get(), 1, *out_size, dg_file);
fclose(dg_file);
return file_buf;
}
int main(int argc, char** argv)
{
if (argc != 2) return -1;
size_t dg_size;
auto file_buf = ReadDGFile(argv[1], &dg_size);
const static u8* magic = reinterpret_cast<const u8*>("NCCH");
size_t magic_pos = 0;
while (true)
{
magic_pos = FindSequenceInBuffer(file_buf.get(), dg_size, magic_pos, magic, 4);
if (magic_pos == (size_t)-1) break;
u8* ncch_start = (file_buf.get() + magic_pos) - NCCH_OFFSET_MAGIC;
size_t ncch_size = *reinterpret_cast<u32*>(ncch_start + NCCH_OFFSET_SIZE) * 0x200;
std::string ncch_name((char*)(ncch_start + NCCH_OFFSET_NAME), 16);
StripNullBytes(&ncch_name);
if (ncch_name.substr(0, 4) != "CTR-") {
magic_pos++;
continue;
}
WriteBufferToFile(ncch_name + ".cxi", ncch_start, ncch_size);
magic_pos++;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment