Created
January 12, 2015 00:38
-
-
Save archshift/4cb754c432ba7854212a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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