Thank you to anyone who has already donated - your generous donations helped make three months of treatment possible.

My brother Nate continues to fight stage IV Hodgkin's lymphoma. He's just 31, with a wife and baby girl. They have no active income (since he's been unable to return to work), no insurance, and cannot afford the treatment he needs. Nate and his family need your help. Please consider a donation, every dollar helps. Thanks.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// depkg by geohot
// needs openssl and zlib
// 100 lines for your pkg file needs

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/aes.h>
#include "zlib.h"

#define u64 unsigned long long
#define u32 unsigned int
#define u16 unsigned short int
#define u8 unsigned char

u64 get_u64(void* vd) {
  u8 *d = (u8*)vd;
  return ((u64)d[0]<<56) | ((u64)d[1]<<48) | ((u64)d[2]<<40) | ((u64)d[3]<<32) | (d[4]<<24) | (d[5]<<16) | (d[6]<<8) | d[7];
}

u32 get_u32(void* vd) {
  u8 *d = (u8*)vd;
  return (d[0]<<24) | (d[1]<<16) | (d[2]<<8) | d[3];
}

u8 pkg_riv[] = {0x4A,0xCE,0xF0,0x12,0x24,0xFB,0xEE,0xDF,0x82,0x45,0xF8,0xFF,0x10,0x21,0x1E,0x6E};
u8 pkg_erk[] = {0xA9,0x78,0x18,0xBD,0x19,0x3A,0x67,0xA1,0x6F,0xE8,0x3A,0x85,0x5E,0x1B,0xE9,0xFB,0x56,0x40,0x93,0x8D,0x4D,0xBC,0xB2,0xCB,0x52,0xC5,0xA2,0xF8,0xB0,0x2B,0x10,0x31};

AES_KEY aes_key;
u8* data;

#define INFLATION_BUFFER_SIZE 0x1000000
u8 inf_buffer[INFLATION_BUFFER_SIZE];

int inf(u8 *source, int source_size, u8 *dest, int* dest_size) {
  int ret;
  unsigned have;
  z_stream strm;

  strm.zalloc = Z_NULL;
  strm.zfree = Z_NULL;
  strm.opaque = Z_NULL;
  strm.avail_in = source_size;
  strm.next_in = source;
  strm.avail_out = *dest_size;
  strm.next_out = dest;
  ret = inflateInit(&strm);
  if(ret != Z_OK)
    return ret;

  ret = inflate(&strm, Z_NO_FLUSH);
  (*dest_size) -= strm.avail_out;

  (void)inflateEnd(&strm);
  return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}

int main(int argc, char *argv[]) {
  u8 iv[0x10], ecount_buf[0x10];
  int num;
  FILE *f=fopen(argv[1], "rb");
  fseek(f, 0, SEEK_END);
  int nlen = ftell(f);
  fseek(f, 0, SEEK_SET);
  data = (u8*)malloc(nlen);
  fread(data, 1, nlen, f);
  fclose(f);
  printf("read 0x%X bytes of pkg\n", nlen);

  int metadata_offset = 0x20+get_u32(data+0xC);
  int file_offset = get_u64(data+0x10);

  AES_set_decrypt_key(pkg_erk, 256, &aes_key);
  AES_cbc_encrypt(&data[metadata_offset], &data[metadata_offset], 0x40, &aes_key, pkg_riv, AES_DECRYPT);

  memset(ecount_buf, 0, 16); num=0;
  AES_set_encrypt_key(&data[metadata_offset], 128, &aes_key);
  AES_ctr128_encrypt(&data[metadata_offset+0x40], &data[metadata_offset+0x40], file_offset-0x40-metadata_offset, &aes_key, &data[metadata_offset+0x20], ecount_buf, &num);

  u64 pkg_start = get_u64(data+0xE0);
  u64 pkg_size = get_u64(data+0xE8);

  printf("pkg data @ %llx with size %llx\n", pkg_start, pkg_size);

  memset(ecount_buf, 0, 16); num=0;
  AES_set_encrypt_key(&data[0x230], 128, &aes_key);
  AES_ctr128_encrypt(&data[pkg_start], &data[pkg_start], pkg_size, &aes_key, &data[0x240], ecount_buf, &num);

  int real_size = INFLATION_BUFFER_SIZE;
  printf("inflated: %d\n", inf(&data[pkg_start], pkg_size, inf_buffer, &real_size));

  printf("writing %X\n", real_size);

  FILE *fout = fopen(argv[2], "wb");
  fwrite(inf_buffer, 1, real_size, fout);
  fclose(fout);
exit:
  free(data);
}