Add COPYING file
[ps3tools.git] / ungpkg.c
blob1f644ae71ca1eb59c44c229e3353b0729f82035b
1 // Copyright 2010-2011 Sven Peter <svenpeter@gmail.com>
2 // Licensed under the terms of the GNU GPL, version 2
3 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
5 // Thanks to Mathieulh for his C# retail unpacker
6 // (http://twitter.com/#!/Mathieulh/status/23070344881381376)
7 // Thanks to Matt_P for his python debug unpacker
8 // (https://github.com/HACKERCHANNEL/PS3Py/blob/master/pkg.py)
10 #include "tools.h"
11 #include "types.h"
13 #include <stdio.h>
14 #include <string.h>
15 #include <assert.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <sys/stat.h>
20 #ifdef WIN32
21 #define MKDIR(x,y) mkdir(x)
22 #else
23 #define MKDIR(x,y) mkdir(x,y)
24 #endif
27 static u8 *pkg = NULL;
28 static u64 size;
29 static u64 offset;
32 static void decrypt_retail_pkg(void)
34 u8 key[0x10];
35 u8 iv[0x10];
37 if (be16(pkg + 0x06) != 1)
38 fail("invalid pkg type: %x", be16(pkg + 0x06));
40 if (key_get_simple("gpkg-key", key, 0x10) < 0)
41 fail("failed to load the package key.");
43 memcpy(iv, pkg + 0x70, 0x10);
44 aes128ctr(key, iv, pkg + offset, size, pkg + offset);
47 static void decrypt_debug_pkg(void)
49 u8 key[0x40];
50 u8 bfr[0x1c];
51 u64 i;
53 memset(key, 0, sizeof key);
54 memcpy(key, pkg + 0x60, 8);
55 memcpy(key + 0x08, pkg + 0x60, 8);
56 memcpy(key + 0x10, pkg + 0x60 + 0x08, 8);
57 memcpy(key + 0x18, pkg + 0x60 + 0x08, 8);
59 sha1(key, sizeof key, bfr);
61 for (i = 0; i < size; i++) {
62 if (i != 0 && (i % 16) == 0) {
63 wbe64(key + 0x38, be64(key + 0x38) + 1);
64 sha1(key, sizeof key, bfr);
66 pkg[offset + i] ^= bfr[i & 0xf];
70 static void unpack_pkg(void)
72 u64 i;
73 u64 n_files;
74 u32 fname_len;
75 u32 fname_off;
76 u64 file_offset;
77 u32 flags;
78 char fname[256];
79 u8 *tmp;
81 n_files = be32(pkg + 0x14);
83 for (i = 0; i < n_files; i++) {
84 tmp = pkg + offset + i*0x20;
86 fname_off = be32(tmp) + offset;
87 fname_len = be32(tmp + 0x04);
88 file_offset = be64(tmp + 0x08) + offset;
89 size = be64(tmp + 0x10);
90 flags = be32(tmp + 0x18);
92 if (fname_len >= sizeof fname)
93 fail("filename too long: %s", pkg + fname_off);
95 memset(fname, 0, sizeof fname);
96 strncpy(fname, (char *)(pkg + fname_off), fname_len);
98 flags &= 0xff;
99 if (flags == 4)
100 MKDIR(fname, 0777);
101 else if (flags == 1 || flags == 3)
102 memcpy_to_file(fname, pkg + file_offset, size);
103 else
104 fail("unknown flags: %08x", flags);
108 int main(int argc, char *argv[])
110 char *dir;
112 if (argc != 2 && argc != 3)
113 fail("usage: ungpkg filename.pkg [target]");
115 pkg = mmap_file(argv[1]);
117 if (argc == 2) {
118 dir = malloc(0x31);
119 memset(dir, 0, 0x31);
120 memset(dir, 0, 0x30);
121 memcpy(dir, pkg + 0x30, 0x30);
122 } else {
123 dir = argv[2];
126 MKDIR(dir, 0777);
128 if (chdir(dir) != 0)
129 fail("chdir(%s)", dir);
131 offset = be64(pkg + 0x20);
132 size = be64(pkg + 0x28);
134 if (be16(pkg + 0x04) & 0x8000)
135 decrypt_retail_pkg();
136 else
137 decrypt_debug_pkg();
139 unpack_pkg();
141 return 0;