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)
21 #define MKDIR(x,y) mkdir(x)
23 #define MKDIR(x,y) mkdir(x,y)
27 static u8
*pkg
= NULL
;
32 static void decrypt_retail_pkg(void)
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)
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)
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
);
101 else if (flags
== 1 || flags
== 3)
102 memcpy_to_file(fname
, pkg
+ file_offset
, size
);
104 fail("unknown flags: %08x", flags
);
108 int main(int argc
, char *argv
[])
112 if (argc
!= 2 && argc
!= 3)
113 fail("usage: ungpkg filename.pkg [target]");
115 pkg
= mmap_file(argv
[1]);
119 memset(dir
, 0, 0x31);
120 memset(dir
, 0, 0x30);
121 memcpy(dir
, pkg
+ 0x30, 0x30);
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();