summaryrefslogtreecommitdiffstats
path: root/package_finalize/package_finalize.c
blob: 78cc725a5fbc4b94c8b02c65ea11aaf9fda9a48b (plain)
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
// package_finalize by geohot
// part of geohot's awesome tools for the PS3
//  released under GPLv3, see http://gplv3.fsf.org/

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

#include "../include/ps3_common.h"
#include "../include/oddkeys.h"
#include <openssl/sha.h>
#include <openssl/aes.h>

typedef struct {
  u32 magic;
  u32 debugFlag;
  u32 infoOffset;
  u32 unknown1;
  u32 headSize;
  u32 itemCount;
  u64 packageSize;
  u64 dataOffset;
  u64 dataSize;
} pkg_header;

int main(int argc, char* argv[]) {
  u8* data;
  u8 sha_key[0x40];
  
  if(argc < 2) {
    printf("usage: %s my.pkg\n", argv[0]);
    return -1;
  }

  int i;
  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);

  pkg_header *header = (pkg_header *)data;
  int data_offset = get_u64(&(header->dataOffset));
  int data_size = get_u64(&(header->dataSize));

// decrypt debug
  u8 sha_crap[0x40];
  memset(sha_crap, 0, 0x40);
  memcpy(sha_crap, &data[0x60], 8);
  memcpy(sha_crap+0x8, &data[0x60], 8);
  memcpy(sha_crap+0x10, &data[0x68], 8);
  memcpy(sha_crap+0x18, &data[0x68], 8);

  int dptr;
  for(dptr = data_offset; dptr < (data_offset+data_size); dptr+=0x10) {
    u8 hash[0x14];
    SHA1(sha_crap, 0x40, hash);
    for(i=0;i<0x10;i++) data[dptr+i] ^= hash[i];
    set_u64(sha_crap+0x38, get_u64(sha_crap+0x38)+1);
  }

// recrypt retail
  u8 pkg_key[0x10];
  memcpy(pkg_key, &data[0x70], 0x10);

  AES_KEY aes_key;
  AES_set_encrypt_key(retail_pkg_aes_key, 128, &aes_key);

  int num=0; u8 ecount_buf[0x10]; memset(ecount_buf, 0, 0x10);
  AES_ctr128_encrypt(&data[data_offset], &data[data_offset], data_size, &aes_key, pkg_key, ecount_buf, &num);

// write back
  FILE *g = fopen(argv[1], "wb");
  data[4] = 0x80;   // set finalize flag
  memset(&data[(data_offset+data_size)], 0, 0x60);

  // add hash
  SHA1(data, nlen-0x20, &data[nlen-0x20]);
  fwrite(data, 1, nlen, g);
  fclose(g);
}