Sponsored Links

Sponsored Links

Page 1 of 5 123 ... LastLast
Results 1 to 10 of 44



  1. #1
    Forum Moderator PS3 News's Avatar
    Join Date
    Apr 2005
    Posts
    27,501
    Sponsored Links

    PS4 System Software Update 1.50 Details by Sony Now Available

    Sponsored Links
    Sony Social Media Manager Sid Shuman shared details today on the upcoming PS4 System Software update 1.50 below that includes browser functionality, which will coincide with the North American PlayStation 4 launch day!

    To quote: We wanted to shed some light on system software update version 1.50 for PS4, which will launch simultaneously with the system's official North American launch on November 15th, 2013. By updating to system software version 1.50, you'll be able to experience a variety of new features in addition to the basic functions of PS4.

    The system software update 1.50 is approximately 300 MB, and will include the following features:

    Remote Play

    Users will be able to access PS4 titles displayed on their living room TVs and play them on a PS Vita system over Wi-Fi networks by using PS4 Link (Depending on network environment or titles, remote play performance may vary outside of the home).

    We anticipate that most PS4 titles will be playable on the PS Vita system through Remote Play. The latest PS Vita system software version, to be released soon, will be required to use PS4 Link.

    Second Screen

    Users can use the PS4 Link application for the PS Vita system, and PlayStation App for iPhone, iPad, and Android-based smartphones and tablets, to use these devices as second screens in supported titles.

    PlayStation App has the ability to enable users to interact with games with their mobiles devices. For example on The Playroom, a title pre-installed in all PS4 systems that requires PlayStation Camera, users can draw pictures on their mobile device screens and flick them towards the TV. The images then appear as a 3D object within the game.

    Record, take screenshots, and upload gameplay effortlessly

    The PS4 system provides dedicated, "always on" video encoding systems that enables seamless uploading of gameplay.

    Users can share their epic triumphs by simply hitting the Share button on DualShock 4, take screenshots or scan through the last 15 minutes of gameplay, tag it and return to the game-the video uploads as the user plays.

    At the PS4 system's launch in North America, users will be able to share their images and videos with friends on Facebook and screenshots with followers on Twitter, though users will need to sign up for individual accounts to use Facebook and Twitter.

    Broadcast and spectate gameplay

    The PS4 system also enhances social spectating by enabling users to broadcast their gameplay in real-time to game fans around the globe, using Ustream and Twitch live internet streaming services (users will need to sign up for individual accounts to use Ustream and Twitch).

    There are two ways for users to view live broadcasts. First, the Live from PlayStation application on PS4 aggregates streams from all PlayStation users. Second, users can spectate friends' PS4 gameplay from PCs, and applications such as Ustream, Twitch, and browsers, which are installed on their mobile devices.

    These applications can be easily started up via PlayStation App, and users can also use these applications to post comments to gameplay broadcasts. Furthermore, users with PlayStation Camera can stream camera images and microphone sounds along with their live gameplay broadcast.

    Play as you download

    This feature enables users to play supported digital titles as they are being downloaded. The time it takes to begin playing will vary depending on game data size and network environments, and not all titles will support this feature When a game is purchased, users can start playing after PS4 downloads a portion of the data, while the rest of the game is downloaded in the background during actual gameplay. Games may be downloaded in stand-by mode.

    Multi log-in

    A maximum of four users can log-in to a single PS4 system simultaneously. These players can use their own save data to play games, and also earn trophies on their own Sony Entertainment Network accounts even when playing a multiplayer game together on a single PS4 system.

    Party (Voice chat)

    By using the Mono Headset bundled with the PS4 system, users will be able to chat with up to eight friends enjoying different applications or games. Furthermore, users can use Party to chat between PS4 and PS Vita systems.

    Face recognition and voice commands

    Users with PlayStation Camera will be able to register their facial image onto their PS4 system, and login to their system using facial recognition instead of DualShock 4.

    Furthermore, users can use either the microphone of the Mono Head set connected to DualShock 4, or PlayStation Camera to navigate through the PS4 home screen (PlayStation Dynamic Menu) with voice commands to start up games and shutdown the system, among other features; please refer to PS4's online manual for recognizable voice commands.

    Background music player

    Users can enjoy gameplay while listening to music in the background with Music Unlimited, a cloud-based digital music service. Users can also voice chat with friends while listening to music. Learn more about Music Unlimited [Register or Login to view links].

    Online Multiplayer

    PlayStation Plus members will be able to play PS4 titles online with other players via the network. PS Plus makes it easy for members to join available online multiplayer matches in a variety of ways, including the ability to easily join a game from a live stream broadcast or Party voice chats.

    Blu-ray Disc and DVD player

    Users can enjoy not only gaming on their PS4 system, but also Blu-ray and DVD video contents. When using for the first time, users must connect to the internet to activate this feature.

    Some features will not be available at launch, such as "suspend/resume mode" which is a feature that keeps the PS4 system in a low power state and promptly takes users back to their game.

    We will provide additional information about system software update version 1.50 and features available at the PS4 system's North America launch, and features that will be available after launch, in the near future.

    Finally, Sony's President of Worldwide Studios Shuhei Yoshida confirmed on [Register or Login to view links] that you can play your PlayStaion 4 without ever connecting to the internet. Thus, the Day One update is not required for the console to function.

    James ‏(Jimmy_Lmao): will i be able to take my PS4 home and play games offline without ever connecting to the internet and doing a day 1 update? thankyou!

    Shuhei Yoshida ‏(yosp): yes

    PS4 System Software Update 1.50 Details by Sony Now Available

    More PlayStation 4 News...

  2. #2
    Senior Member spark32's Avatar
    Join Date
    Mar 2008
    Posts
    207
    Sponsored Links
    Sponsored Links
    I wonder if you log in to an account with purchases not on a home console with a second controller if it will let you play it on your profile on the first controller by yourself.

  3. #3
    Senior Member proskopina's Avatar
    Join Date
    Jun 2009
    Posts
    186
    Sponsored Links

    PS4 trailer by Greeks

    Sponsored Links
    I made a video from the latest ps4 trailer with different colours and music.. maybe can be front page... thank you



    Last edited by proskopina; 10-29-2013 at 09:40 AM

  4. #4
    Contributor B7U3 C50SS's Avatar
    Join Date
    Oct 2013
    Posts
    13
    Sponsored Links

    The PS4 is still using the .PUP file??

    Sponsored Links
    Okay so in my studies I've come across these three links... They are direct links to download download PS4 updates (sorta) they aren't even live YET. HOPE YOU ENJOY!! And get a kick outa' it..

    US: [Register or Login to view links]
    JP: [Register or Login to view links]
    EU: [Register or Login to view links]

  5. #5
    Member PSGamer24's Avatar
    Join Date
    Jun 2010
    Posts
    56
    Firmware 1.50 is live: [Register or Login to view links]

  6. #6
    Contributor B7U3 C50SS's Avatar
    Join Date
    Oct 2013
    Posts
    13
    Yes, it is.

  7. #7
    Forum Moderator PS3 News's Avatar
    Join Date
    Apr 2005
    Posts
    27,501

    PlayStation 4 FW Update 1.5 (PS4UPDATE.PUP) & PS4 Updatelist XML Out

    Following up on the initial PS4 Firmware 1.50 Update details, today Sony PlayStation 4 hacker SKFU has made available the PS4UPDATE.PUP and Recovery file link and analysis, which comes shortly after some ps4-updatelist.xml files were made public by B7U3 C50SS as well.

    Download: [Register or Login to view links] / [Register or Login to view links] (Mirror) / [Register or Login to view links] (Mirror #2) / [Register or Login to view links] / [Register or Login to view links] (Recovery - Mirror) / [Register or Login to view links] by flat_z / PS4PUP.exe (Compiled) by PSGamer24 / [Register or Login to view links] / [Register or Login to view links] / [Register or Login to view links] / [Register or Login to view links] by xerpi / PS4PUP.exe v3 (Compiled) by PSGamer24 / [Register or Login to view links] / [Register or Login to view links] by Hykem / PS4PUP.exe v4 (Compiled) by PSGamer24 / [Register or Login to view links] (Compiled EXE) by $n!pR / [Register or Login to view links] (based on [Register or Login to view links]) / [Register or Login to view links]

    To quote: PlayStation 4 - Update File Analysis

    Hey guys,

    Here comes a short analysis of the PlayStation 4 update files. Available at:
    • PS4 Update File: [Register or Login to view links] (Size in Bytes: 322,831,872)
    • PS4 Recovery Update File: [Register or Login to view links] (Size in Bytes: 901,133,312)

    Best regards,

    - SKFU

    Update: The update files were removed from the SONY update server. Since it is unclear if this was firmware version 1.00 or 1.50, let's hope there was some mistake made by SONY here which helps us in future
    • Firmware .PUP - c64d11f839ac8628176941b99fd3670e
    • Recovery .PUP - 6f4d6afe98dd7297c70aa4d6e7e5482b

    Update #2: It appears Frumix (via neogaf.com/forum/showpost.php?p=87942869&postcount=1) also discovered the same thing, who states the following additional details:

    PS4 1.5 Update File is apparently up on update servers #1
    • Update file (308 MB)
    • Recovery file (859 MB)

    Just like on PS3, it seems it's the same file across all regions (data in the american xml seems to be erroneous somehow). Not sure what you might need it for this early, but here you go. Update if old.

    IMPORTANT: If you're unsure what to do with any of this, wait until official Sony page goes online.

    According to Sony's Shuei Yoshida confirmed that the PS4 1.50 System Update won't be included on PlayStation 4 game discs.

    When asked if the servers fail on launch day, Yoshida answered with "No" outright. He also stated that games will not insert the update, so users will have to download it from the Internet.

    From Sony PlayStation 4 hacker flat_z (via pastie.org/private/4wgojewhp2pq7declhkhw) comes a Python script to extract embedded .PUPs from the PS4 container, as follows:
    Code:
    import sys, os, struct
    
    if len(sys.argv) < 3:
    	script_file_name = os.path.split(sys.argv[0])[1]
    	print 'usage: {0} <pup container file> <output directory>'.format(script_file_name)
    	sys.exit()
    
    pup_file_path = sys.argv[1]
    if not os.path.isfile(pup_file_path):
    	print 'error: invalid file specified'
    	sys.exit()
    
    output_dir = sys.argv[2]
    if not os.path.exists(output_dir):
    	os.makedirs(output_dir)
    elif not os.path.isdir(output_dir):
    	print 'error: invalid directory specified'
    	sys.exit()
    
    header_fmt = '<4sI4xIQ8x'
    entry_fmt = '<II8x32s'
    
    block_size = 512
    
    pup_file_size = os.path.getsize(pup_file_path)
    with open(pup_file_path, 'rb') as pup_file:
    	magic, version, num_entries, num_blocks = struct.unpack(header_fmt, pup_file.read(struct.calcsize(header_fmt)))
    	if magic != 'SLB2':
    		print 'wrong file magic'
    		sys.exit()
    	if version != 1:
    		print 'unsupported file version'
    		sys.exit()
    	if num_blocks * block_size != pup_file_size:
    		print 'wrong number of blocks'
    		sys.exit()
    	entry_data = pup_file.read(num_entries * struct.calcsize(entry_fmt))
    	for i in xrange(num_entries):
    	        block_index, size, file_name = struct.unpack(entry_fmt, entry_data[i * struct.calcsize(entry_fmt):(i + 1) * struct.calcsize(entry_fmt)])
    		file_name = file_name.rstrip('\x00')
    		file_path = os.path.join(output_dir, file_name)
    		with open(file_path, 'wb') as entry_file:
    			pup_file.seek(block_index * block_size)
    			num_segments = 1 + (size - 1) / block_size if size > 0 else 0
    			for j in xrange(num_segments):
    				segment_size = block_size if j < (num_segments - 1) else size - (num_segments - 1) * block_size
    				data = pup_file.read(segment_size)
    				entry_file.write(data)
    An updated and commented UnPKG Python Script revision by flat_z (via psdevwiki.com/ps4/Talk:PKG_files) as well:
    Code:
    # UnPKG rev 0x00000007 (public edition), (c) flatz
     
    import sys, os, hashlib, hmac, struct, traceback
    from cStringIO import StringIO
     
    # parse arguments
     
    if len(sys.argv) < 3:
    	script_file_name = os.path.split(sys.argv[0])[1]
    	print 'usage: {0} <pkg file> <output dir>'.format(script_file_name)
    	sys.exit()
     
    pkg_file_path = sys.argv[1]
    if not os.path.isfile(pkg_file_path):
    	print 'error: invalid file specified'
    	sys.exit()
     
    output_dir = sys.argv[2]
    if os.path.exists(output_dir) and not os.path.isdir(output_dir):
    	print 'error: invalid directory specified'
    	sys.exit()
    elif not os.path.exists(output_dir):
    	os.makedirs(output_dir)
     
    # cryptography functions
     
    def sha256(data):
    	return hashlib.sha256(data).digest()
     
    # utility functions
     
    uint64_fmt, uint32_fmt, uint16_fmt, uint8_fmt = '>Q', '>I', '>H', '>B'
    int64_fmt, int32_fmt, int16_fmt, int8_fmt = '>q', '>i', '>h', '>b'
     
    def read_string(f, length):
    	return f.read(length)
    def read_cstring(f):
    	s = ''
    	while True:
    		c = f.read(1)
    		if not c:
    			return False
    		if ord(c) == 0:
    			break
    		s += c
    	return s
     
    def read_uint8_le(f):
    	return struct.unpack('<B', f.read(struct.calcsize('<B')))[0]
    def read_uint8_be(f):
    	return struct.unpack('>B', f.read(struct.calcsize('>B')))[0]
    def read_uint16_le(f):
    	return struct.unpack('<H', f.read(struct.calcsize('<H')))[0]
    def read_uint16_be(f):
    	return struct.unpack('>H', f.read(struct.calcsize('>H')))[0]
    def read_uint32_le(f):
    	return struct.unpack('<I', f.read(struct.calcsize('<I')))[0]
    def read_uint32_be(f):
    	return struct.unpack('>I', f.read(struct.calcsize('>I')))[0]
    def read_uint64_le(f):
    	return struct.unpack('<Q', f.read(struct.calcsize('<Q')))[0]
    def read_uint64_be(f):
    	return struct.unpack('>Q', f.read(struct.calcsize('>Q')))[0]
    def read_int8_le(f):
    	return struct.unpack('<b', f.read(struct.calcsize('<b')))[0]
    def read_int8_be(f):
    	return struct.unpack('>b', f.read(struct.calcsize('>b')))[0]
    def read_int16_le(f):
    	return struct.unpack('<h', f.read(struct.calcsize('<h')))[0]
    def read_int16_be(f):
    	return struct.unpack('>h', f.read(struct.calcsize('>h')))[0]
    def read_int32_le(f):
    	return struct.unpack('<i', f.read(struct.calcsize('<i')))[0]
    def read_int32_be(f):
    	return struct.unpack('>i', f.read(struct.calcsize('>i')))[0]
    def read_int64_le(f):
    	return struct.unpack('<q', f.read(struct.calcsize('<q')))[0]
    def read_int64_be(f):
    	return struct.unpack('>q', f.read(struct.calcsize('>q')))[0]
     
    # main code
     
    PKG_MAGIC = '\x7FCNT'
    CONTENT_ID_SIZE = 0x24
    SHA256_HASH_SIZE = 0x20
     
    FILE_TYPE_FLAGS_RETAIL = 1 << 31
     
    ENTRY_TYPE_DIGEST_TABLE = 0x0001
    ENTRY_TYPE_META_TABLE   = 0x0100
    ENTRY_TYPE_NAME_TABLE   = 0x0200
     
    ENTRY_TYPE_LICENSE = 0x04
    ENTRY_TYPE_FILE1   = 0x10
    ENTRY_TYPE_FILE2   = 0x12
     
    ENTRY_TABLE_MAP = {
    	ENTRY_TYPE_DIGEST_TABLE: '.digests',
    	ENTRY_TYPE_META_TABLE: '.meta',
    	ENTRY_TYPE_NAME_TABLE: '.names',
     
    	0x0400: 'license.dat',
    	0x0401: 'license.info',
    	0x1000: 'param.sfo',
    	0x1001: 'playgo-chunk.dat',
    	0x1002: 'playgo-chunk.sha',
    	0x1003: 'playgo-manifest.xml',
    	0x1004: 'pronunciation.xml',
    	0x1005: 'pronunciation.sig',
    	0x1006: 'pic1.png',
    	0x1008: 'app/playgo-chunk.dat',
    	0x1200: 'icon0.png',
    	0x1220: 'pic0.png',
    	0x1260: 'changeinfo/changeinfo.xml',
    }
     
    class MyError(Exception):
    	def __init__(self, message):
    		self.message = message
     
    	def __str__(self):
    		return repr(self.message)
     
    class FileTableEntry:
    	entry_fmt = '>IIIIII8x'
     
    	def __init__(self):
    		pass
     
    	def read(self, f):
    		self.type, self.unk1, self.flags1, self.flags2, self.offset, self.size = struct.unpack(self.entry_fmt, f.read(struct.calcsize(self.entry_fmt)))
    		self.key_index = (self.flags2 & 0xF000) >> 12
    		self.name = None
     
    try:
    	with open(pkg_file_path, 'rb') as pkg_file:
    		magic = read_string(pkg_file, 4)
    		if magic != PKG_MAGIC:
    			raise MyError('invalid file magic')
     
    		type = read_uint32_be(pkg_file)
    		is_retail = (type & FILE_TYPE_FLAGS_RETAIL) != 0
     
    		pkg_file.seek(0x10) # FIXME: or maybe uint16 at 0x16???
    		num_table_entries = read_uint32_be(pkg_file)
     
    		pkg_file.seek(0x18)
    		file_table_offset = read_uint32_be(pkg_file)
     
    		pkg_file.seek(0x40)
    		content_id = read_cstring(pkg_file)
    		if len(content_id) != CONTENT_ID_SIZE:
    			raise MyError('invalid content id')
     
    		pkg_file.seek(0x140)
    		digest_table_digest = pkg_file.read(SHA256_HASH_SIZE)
     
    		table_entries = []
    		pkg_file.seek(file_table_offset)
    		for i in xrange(num_table_entries):
    			entry = FileTableEntry()
    			entry.read(pkg_file)
    			table_entries.append(entry)
     
    		entry_names = None
    		entry_digests = None
    		for i in xrange(num_table_entries):
    			entry = table_entries[i]
    			if entry.type == ENTRY_TYPE_NAME_TABLE:
    				pkg_file.seek(entry.offset)
    				data = pkg_file.read(entry.size)
    				if data and len(data) > 0:
    					data = StringIO(data)
    					entry_names = []
    					c = data.read(1)
    					if ord(c) == 0:
    						while True:
    							name = read_cstring(data)
    							if not name:
    								break
    							entry_names.append(name)
    					else:
    						raise MyError('weird name table format')
    				break
    		entry_name_index = 0
    		for i in xrange(num_table_entries):
    			entry = table_entries[i]
    			type, index = (entry.type >> 8) & 0xFF, entry.type & 0xFF
    			if type == ENTRY_TYPE_FILE1 or type == ENTRY_TYPE_FILE2:
    				if entry_name_index < len(entry_names):
    					entry.name = entry_names[entry_name_index]
    					entry_name_index += 1
    				else:
    					raise MyError('entry name index out of bounds')
    			elif entry.type in ENTRY_TABLE_MAP:
    				entry.name = ENTRY_TABLE_MAP[entry.type]
    			if entry.type == ENTRY_TYPE_DIGEST_TABLE and entry_digests is None:
    				pkg_file.seek(entry.offset)
    				entry_digests = pkg_file.read(entry.size)
     
    		computed_digest_table_digest = None
    		computed_entry_digests = '\x00' * 32
    		for i in xrange(num_table_entries):
    			entry = table_entries[i]
    			name = entry.name if entry.name is not None else 'entry_{0:03}.bin'.format(i)
    			file_path = os.path.join(output_dir, name)
    			file_dir = os.path.split(file_path)[0]
    			if not os.path.exists(file_dir):
    				os.makedirs(file_dir)
    			with open(file_path, 'wb') as entry_file:
    				pkg_file.seek(entry.offset)
    				data = pkg_file.read(entry.size)
    				entry_file.write(data)
    				if entry.type != ENTRY_TYPE_DIGEST_TABLE:
    					computed_entry_digests += sha256(data)
    				else:
    					computed_digest_table_digest = sha256(data)
    		is_digests_valid = computed_entry_digests == entry_digests and computed_digest_table_digest == digest_table_digest
     
            	print 'File information:'
    		print '             Magic: 0x{0}'.format(magic.encode('hex').upper())
    		print '              Type: 0x{0:08X}'.format(type), '(retail)' if is_retail else ''
    		print '        Content ID: {0}'.format(content_id)
    		print ' Num table entries: {0}'.format(num_table_entries)
    		print 'Entry table offset: 0x{0:08X}'.format(file_table_offset)
    		print '     Digest status: {0}'.format('OK' if is_digests_valid else 'FAIL')
    		print
     
    		if num_table_entries > 0:
    			print 'Table entries:'
    			for i in xrange(num_table_entries):
    				entry = table_entries[i]
    				print '  Entry #{0:03}:'.format(i)
    				print '         Type: 0x{0:08X}'.format(entry.type)
    				print '         Unk1: 0x{0:08X}'.format(entry.unk1)
    				if entry.name is not None:
    					print '         Name: {0}'.format(entry.name)
    				print '       Offset: 0x{0:08X}'.format(entry.offset)
    				print '         Size: 0x{0:08X}'.format(entry.size)
    				print '      Flags 1: 0x{0:08X}'.format(entry.flags1)
    				print '      Flags 2: 0x{0:08X}'.format(entry.flags2)
    				print '    Key index: {0}'.format('N/A' if entry.key_index == 0 else entry.key_index)
    			print
     
    except IOError:
    	print 'error: i/o error during processing'
    except MyError as e:
    	print 'error: {0}', e.message
    except:
    	print 'error: unexpected error:', sys.exc_info()[0]
    	traceback.print_exc(file=sys.stdout)
    Table Entry Hashes (SHA-256)

    The first entry in the index table points to a block of hashes (Using Amazon Instant Video: UP2064-CUSA00130_00-AIV00000000000US.pkg for this example).
    Code:
    0x2A80  00 00 00 01 00 00 00 00 40 00 00 00 00 00 00 00  ........@....... First Entry in Index Table.
    0x2A90  00 00 2C A0 00 00 02 20 00 00 00 00 00 00 00 00  .., ... ........
    0x2AA0  00 00 00 10 00 00 00 00 60 00 00 00 00 00 00 00  ........`.......
    0x2AB0  00 00 20 00 00 00 08 00 00 00 00 00 00 00 00 00  .. .............
    0x2AC0  00 00 00 20 00 00 00 00 E0 00 00 00 00 00 30 00  ... .........0.
    0x2AD0  00 00 28 00 00 00 01 00 00 00 00 00 00 00 00 00  ..(.............
    ...
    Offset: 0x00002CA0 Length: 0x00000220
    Code:
    0x2CA0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0x2CB0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0x2CC0  B4 34 DD 9C B3 C7 91 96 EC F7 D1 F6 8F 8A 2D 18  4ݜǑ.-.
    0x2CD0  8D 07 8F 2D 33 E9 09 6B 1D 22 B5 4E 7A F2 6D 6A  ...-3.k."Nzmj
    0x2CE0  F0 F5 9E 95 F4 74 13 FE 9F 35 DB 44 57 76 DE 49  t.5DWvI
    0x2CF0  90 B1 68 20 97 8F 70 79 9D 62 95 CD 97 67 5D B0  .h .py.b͗g]
    0x2D00  1D 6E EE E7 67 3D 7E B4 2F 78 F1 26 2C EE EC 7A  .ng=~/x&,z
    0x2D10  10 40 90 BA FD 0F F9 AF BE ED F1 BC DE 84 30 55  .@..ބ0U
    0x2D20  57 65 D8 7B DD 85 5E D0 73 1B 78 4D A6 EE 00 CF  We{݅^s.xM.
    0x2D30  A1 0C 3F C4 03 E0 19 5A 0B 36 E1 64 33 7A D1 C6  .?..Z.6d3z
    0x2D40  1A 4E E9 FA 4F DD AD F4 63 FF 73 8F 9F 24 6F 0E  .NO.cs.$o.
    0x2D50  DF 22 EB 3D 43 F1 A3 7D C6 D0 BD 97 49 03 EC C2  "=C}нI.
    0x2D60  DB 04 17 61 81 6A 14 9B 0F A3 B6 D7 6D AA 48 5A  ..a.j..mHZ
    0x2D70  1F 3E 95 6B 63 BD AE B2 A2 E0 AE 44 8D D0 05 EA  .>kcD..
    0x2D80  93 BB 8F 3E 60 72 F8 0C BD BA DB 0E 4D 01 AA AA  .>`r..M.
    0x2D90  65 C0 97 E3 89 18 BB A2 17 6E 49 EE 3A 36 CA 91  e..nI:6ʑ
    0x2DA0  5B EE 4F 1B 1B 7F 52 17 04 99 DD 8C 19 3A 31 BB  [O...R..݌.:1
    0x2DB0  79 9D F4 70 38 D5 F6 DD FF AA 76 5E 10 F2 CC 8F  y.p8v^..
    0x2DC0  0A D9 DC 1C BA 98 EB B3 4A 74 02 E9 F1 0A 0A 90  ..Jt....
    0x2DD0  69 AC D0 29 9F 93 DF 45 80 35 6E FB AF D6 B1 A5  i)E5nֱ
    0x2DE0  C6 13 74 C9 51 F7 BA A5 CF 0D DE 13 E3 BB 02 0D  .tQ....
    0x2DF0  06 6E 44 64 FF 2A CA 37 B0 20 4C 03 44 CA 5E C9  .nDd*7 L.D^
    0x2E00  B4 D0 03 6B 54 4A 66 ED C7 32 CB D2 E0 34 CF 5F  .kTJf24_
    0x2E10  5B 1F 46 B5 81 72 09 D3 33 B3 3E 5E FC 01 6B 11  [.F.r.3>^.k.
    0x2E20  9A DF 99 EE A2 2B 5E E2 72 B9 32 02 6B B7 E8 D1  ߙ+^r2.k
    0x2E30  5A 9D B8 A9 97 17 47 4F 11 75 FA 41 6E 79 7A 1B  Z..GO.uAnyz.
    0x2E40  94 A5 62 30 EA E0 99 89 3D BB 34 5D 0B F5 E3 17  b0=4]..
    0x2E50  BE 2C EE 7B D5 EA 8F 05 FB 0E 07 A2 40 FF 7A 59  ,{....@zY
    0x2E60  6B FE F8 0B 1E 61 85 83 18 9A 53 3A F0 91 46 B7  k..a.S:F
    0x2E70  86 83 38 B8 C1 3E E8 74 C5 4F 4E E6 B6 28 7F 52  8>tON(.R
    0x2E80  55 FE CE EA F4 9E 98 2A BC A5 C4 21 D6 44 17 C9  U*!D.
    0x2E90  76 D9 1C 02 FD 75 BB 37 C3 96 1A C3 1C 3E 5B 5F  v..u7Ö..>[_
    0x2EA0  2B 37 CA 02 AB E2 B7 C6 FB 74 23 B9 A6 C2 C6 0B  +7.t#.
    0x2EB0  70 6F 79 CB AE 80 D9 B9 62 1A D6 69 F6 47 FB F2  poyˮٹb.iG
    First hash is blank, can't hash the table of hashes. The remaining hashes are for each of the remaining Index Table Entries.

    i.e the second entry in the Index Table should have a SHA-256 matching the following:
    Code:
    0xB434DD9CB3C79196ECF7D1F68F8A2D188D078F2D33E9096B1D22B54E7AF26D6A
    For those curious:
    • Normal firmwares have 3 PUPs inside.
    • Recovery firmwares have 4 PUPs inside.
    • Debug firmwares have 5 PUPs inside.

    Everything is encrypted after that, even the selfs, so might take a while until we see runable x86/64 code appearing from the PUPs.

    Finally, from xerpi comes a few revisions of his own PlayStation 4 PUP Extractor (linked above) with details below as follows:

    [xerpi] here's my version of a PS4 PUP extractor: pastebin.com/qdgumb8t
    [flatz] xerpi, i think SKFU is wrong with the fixed size of header
    [flatz] seems like data is aligned to the block size
    [flatz] so if you have 20 files for example, then data offset should be 0x400
    [xerpi] I've thought this, but I've read that there are a maximum of 10 files
    [flatz] i think it is just his assumption
    [xerpi] so If there's no file limit, the data would be: 32 + 48*filecount
    [xerpi] data offset*
    [xerpi] but there's still a reserved space so I don't know if this space will continue existing
    [flatz] actually you don't need to calculate data offset
    [flatz] just get it from entry table
    [flatz] data_offset = block_index * block_size
    [flatz] header always start with block_index = 0
    [xerpi] right, but as I see block_size is 512
    [xerpi] so the first PUP offset (data_offset) will be 512 bytes after the begin of the file
    [xerpi] I don't see any dynamic number telling the size of the blocks
    [flatz] it is fixed to 512
    [flatz] data_offset = align_up(header_size + entry_size * num_entries, 512) where header_size = 0x20, entry_size = 0x30
    [xerpi] yes, so I set the general offset to PS4_PUP_HEADER_SIZE + header-]pups[i].offset
    [xerpi] ok, so the only static size here is the size of the header of the header (the top part of the header)
    [flatz] yep
    [flatz] and block size
    [xerpi] yeah
    [xerpi] It makes sense now, thanks
    [flatz] np
    [flatz] seems like they use some sort of mapping/paging.. that's why they use fixed-size blocks and padding to make data size multiple of block size
    [xerpi] I see
    [xerpi] done: pastebin.com/bHXBhTyc
    [flatz] great
    [xerpi] treat it as an "experiment"
    [xerpi] I was bored when I saw this info so I decided to try to do a simple pup extractor
    [flatz] i'm too
    [xerpi] btw I got to go now, it's a bit late here hahaha
    [xerpi] cya

    ps4pupextractor v2 by xerpi
    Code:
    // Copyright (c) 2013   xerpi
    
    /*
       Fast and simple PS4 PUP extractor
       Thanks to SKFU for the PUP information analysis
       Version 1, may have lots of bugs (coded fast)
       I'm not even sure this will work on Big Endian machines...
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    
    #define PS4_PUP_MAGIC             0x32424C53 //Little endian
    #define PS4_PUP_HEADER_SIZE       512
    #define PS4_PUP_HEADER_INFO_SIZE  32 //Until PUP entries
    #define PS4_PUP_ENTRY_SIZE        48 //PUP entry size 
    
    struct ps4pup_pup_info {
    	uint32_t offset;
    	uint32_t content_size;
    	uint64_t reserved;
    	uint8_t  filename[32];
    } __attribute__((packed));
    
    struct ps4pup_header {
    	uint32_t magic;
    	uint64_t version;
    	uint32_t file_count;
    	uint32_t block_count;
    	uint8_t  reserved1[12];
    	struct ps4pup_pup_info *pups;
    	uint8_t  reserved2[288];
    } __attribute__((packed));
    
    
    int  ps4pup_read_header(FILE *fd, struct ps4pup_header *header);
    void ps4pup_free_header(struct ps4pup_header *header);
    int  ps4pup_extract(FILE *fd, struct ps4pup_header *header);
    void ps4pup_print_header(const struct ps4pup_header *header);
    
    void print_usage(void);
    
    int main (int argc, char *argv[])
    {
    	if (argc < 2) {
    		print_usage();
    		goto exit_error;
    	}
    	
    	FILE *fd;
    	if ((fd = fopen(argv[1], "rb")) == NULL ) {
    		printf ("Could not open %s\n", argv[1]);
    		goto exit_close;
    	}
    	
    	struct ps4pup_header h;
    	
    	if (!ps4pup_read_header(fd, &h)) {
    		printf("Error reading PUP file\n");
    		goto exit_close;
    	}
    	
    	ps4pup_print_header(&h);
    	
    	printf("\nExtracting PUP files...\n");
    	
    	if (!ps4pup_extract(fd, &h)) {
    		printf("Error extracting PUP files\n");
    		ps4pup_free_header(&h);
    		goto exit_close;
    	}
    	
    	printf("Done!\n");
    	
    	
    	ps4pup_free_header(&h);
    	return 1;
    	
    	
    exit_close:
    	fclose(fd);
    exit_error:	
    	return EXIT_FAILURE;
    }
    
    int ps4pup_read_header(FILE *fd, struct ps4pup_header *header)
    {
    	if (fd == NULL || header == NULL) {
    		return 0;
    	}
    	
    	fseek(fd, 0, SEEK_SET);
    	fread((void*)header, 1, PS4_PUP_HEADER_INFO_SIZE, fd);
    	
    	if (header->magic != PS4_PUP_MAGIC) {
    		printf("This is not a PUP file!\n");
    		return 0;
    	}
    	
    	header->pups = malloc (header->file_count * sizeof(struct ps4pup_pup_info));
    	
    	int i;
    	for (i = 0; i < header->file_count; ++i) {
    		fread((void*)&header->pups[i], 1, PS4_PUP_ENTRY_SIZE, fd);
    	}
    	
    	return 1;
    }
    
    
    void ps4pup_free_header(struct ps4pup_header *header)
    {	
    	if (header) {
    		if (header->pups) {
    			free(header->pups);
    		}
    	}
    }
    
    int ps4pup_extract(FILE *fd, struct ps4pup_header *header)
    {
    	if (fd == NULL || header == NULL) {
    		return 0;
    	}
    	
    	FILE *pup_out;
    	uint8_t copy_buffer[512];
    	
    	int i;
    	for (i = 0; i < header->file_count; ++i) {
    		fseek(fd, PS4_PUP_HEADER_SIZE + header->pups[i].offset, SEEK_SET);
    		pup_out = fopen(header->pups[i].filename, "wb");
    		int copy_size = header->pups[i].content_size;
    		
    		while (copy_size > 0) {
    			if (copy_size > 512) {
    				fread(copy_buffer, 1, 512, fd);
    				fwrite(copy_buffer, 1, 512, pup_out);
    				copy_size -= 512;
    			} else {
    				fread(copy_buffer, 1, copy_size, fd);
    				fwrite(copy_buffer, 1, copy_size, pup_out);
    				copy_size = 0;	
    			}
    		}
    		fflush(pup_out);
    		fclose(pup_out);
    	}	
    	
    	
    	return 1;	
    }
    
    void ps4pup_print_header(const struct ps4pup_header *header)
    {
    	char magic_string[5];
    	strncpy(magic_string, (char*)(uintptr_t)(&header->magic), 4);
    	magic_string[4] = '\0';
    	printf("Magic:      0x%X  %s\n", header->magic, magic_string);
    	printf("Version:    %lu\n", header->version);
    	printf("File count: %i\n", header->file_count);
    	
    	int i;
    	for (i = 0; i < header->file_count; ++i) {
    		printf("PUP %i:\n", i+1);
    		printf("  Offset:   0x%X\n", header->pups[i].offset);
    		printf("  Size:     %i\n", header->pups[i].content_size);
    		printf("  Filename: %s\n", header->pups[i].filename);
    		
    	}
    }
    
    void print_usage(void)
    {	
    	printf("Usage:\nps4pupextractor <PS4UPDATE.PUP>\n");
    	printf("It will extract the PUPs as: PS4UPDATEX.PUP being X the PUP number\n");
    }
    ps4pupextractor v2 by xerpi
    Code:
    // Copyright (c) 2013   xerpi
    
    /*
        Fast and simple PS4 PUP extractor
        Thanks to SKFU for the PUP information analysis
        Version 2, may have lots of bugs (coded fast)
        I'm not even sure this will work on Big Endian machines...
    
        Compiling:
            gcc -o ps4pupextractor ps4pupextractor.c
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    
    #define PS4_PUP_MAGIC        0x32424C53
    #define PS4_PUP_HEADER_SIZE  32 //Until PUP entries
    #define PS4_PUP_ENTRY_SIZE   48 //PUP entry size 
    
    struct ps4pup_pup_info {
    	uint32_t offset;
    	uint32_t content_size;
    	uint64_t reserved;
    	uint8_t  filename[32];
    } __attribute__((packed));
    
    struct ps4pup_header {
    	uint32_t magic;
    	uint64_t version;
    	uint32_t file_count;
    	uint32_t block_count;
    	uint8_t  reserved1[12];
    	struct ps4pup_pup_info *pups;
    	uint8_t  reserved2[288];
    } __attribute__((packed));
    
    
    int  ps4pup_read_header(FILE *fd, struct ps4pup_header *header);
    void ps4pup_free_header(struct ps4pup_header *header);
    int  ps4pup_extract(FILE *fd, struct ps4pup_header *header);
    void ps4pup_print_header(const struct ps4pup_header *header);
    
    void print_usage(void);
    
    int main (int argc, char *argv[])
    {
    	if (argc < 2) {
    		print_usage();
    		goto exit_error;
    	}
    	
    	FILE *fd;
    	if ((fd = fopen(argv[1], "rb")) == NULL ) {
    		printf ("Could not open %s\n", argv[1]);
    		goto exit_close;
    	}
    	
    	struct ps4pup_header h;
    	
    	if (!ps4pup_read_header(fd, &h)) {
    		printf("Error reading PUP file\n");
    		goto exit_close;
    	}
    	
    	ps4pup_print_header(&h);
    	
    	printf("\nExtracting PUP files...\n");
    	
    	if (!ps4pup_extract(fd, &h)) {
    		printf("Error extracting PUP files\n");
    		ps4pup_free_header(&h);
    		goto exit_close;
    	}
    	
    	printf("Done!\n");
    	
    	
    	ps4pup_free_header(&h);
    	return 1;
    	
    	
    exit_close:
    	fclose(fd);
    exit_error:	
    	return EXIT_FAILURE;
    }
    
    int ps4pup_read_header(FILE *fd, struct ps4pup_header *header)
    {
    	if (fd == NULL || header == NULL) {
    		return 0;
    	}
    	
    	fseek(fd, 0, SEEK_SET);
    	fread((void*)header, 1, PS4_PUP_HEADER_SIZE, fd);
    	
    	if (header->magic != PS4_PUP_MAGIC) {
    		printf("This is not a PUP file!\n");
    		return 0;
    	}
    	
    	header->pups = malloc (header->file_count * sizeof(struct ps4pup_pup_info));
    	
    	int i;
    	for (i = 0; i < header->file_count; ++i) {
    		fread((void*)&header->pups[i], 1, PS4_PUP_ENTRY_SIZE, fd);
    	}
    	
    	return 1;
    }
    
    
    void ps4pup_free_header(struct ps4pup_header *header)
    {	
    	if (header) {
    		if (header->pups) {
    			free(header->pups);
    		}
    	}
    }
    
    int ps4pup_extract(FILE *fd, struct ps4pup_header *header)
    {
    	if (fd == NULL || header == NULL) {
    		return 0;
    	}
    	
    	FILE *pup_out;
    	uint8_t copy_buffer[512];
    	int data_offset = PS4_PUP_HEADER_SIZE + PS4_PUP_ENTRY_SIZE * header->file_count;
    	data_offset = (data_offset+511) & ~511; //Align to 512 bytes
    		
    	int i;
    	for (i = 0; i < header->file_count; ++i) {
    		fseek(fd, data_offset + header->pups[i].offset, SEEK_SET);
    		pup_out = fopen(header->pups[i].filename, "wb");
    		int copy_size = header->pups[i].content_size;
    		
    		while (copy_size > 0) {
    			if (copy_size > 512) {
    				fread(copy_buffer, 1, 512, fd);
    				fwrite(copy_buffer, 1, 512, pup_out);
    				copy_size -= 512;
    			} else {
    				fread(copy_buffer, 1, copy_size, fd);
    				fwrite(copy_buffer, 1, copy_size, pup_out);
    				copy_size = 0;	
    			}
    		}
    		fflush(pup_out);
    		fclose(pup_out);
    	}	
    	
    	
    	return 1;	
    }
    
    void ps4pup_print_header(const struct ps4pup_header *header)
    {
    	char magic_string[5];
    	strncpy(magic_string, (char*)(uintptr_t)(&header->magic), 4);
    	magic_string[4] = '\0';
    	printf("Magic:       0x%X  %s\n", header->magic, magic_string);
    	printf("Version:     %lu\n", header->version);
    	printf("File count:  %i\n", header->file_count);
    	printf("Block count: %i\n", header->block_count);
    	
    	int i;
    	for (i = 0; i < header->file_count; ++i) {
    		printf("PUP %i:\n", i+1);
    		printf("  Offset:   0x%X\n", header->pups[i].offset);
    		printf("  Size:     %i\n", header->pups[i].content_size);
    		printf("  Filename: %s\n", header->pups[i].filename);
    		
    	}
    }
    
    void print_usage(void)
    {	
    	printf("Usage:\nps4pupextractor <PS4UPDATE.PUP>\n");
    	printf("It will extract the PUPs as: PS4UPDATEX.PUP being X the PUP number\n");
    }
    ps4pupextractor v3 by xerpi (via xerpi)
    Code:
    // Copyright (c) 2013   xerpi
    
    /*
        Fast and simple PS4 PUP extractor
        Thanks to SKFU for the PUP information analysis
        Version 3, may have lots of bugs (coded fast)
        I'm not even sure if this will work on Big Endian machines...
        Also thanks to flatz for answering my silly questions :P
    
        Compiling:
            gcc -o ps4pupextractor ps4pupextractor.c
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    
    #define PS4_PUP_MAGIC        0x32424C53
    #define PS4_PUP_HEADER_SIZE  32 //Until PUP entries
    #define PS4_PUP_ENTRY_SIZE   48 //PUP entry size
    #define COPY_BUFFER_SIZE     1024
    
    struct ps4pup_pup_info {
    	uint32_t offset;
    	uint32_t content_size;
    	uint64_t reserved;
    	uint8_t  filename[32];
    } __attribute__((packed));
    
    struct ps4pup_header {
    	uint32_t magic;
    	uint64_t version;
    	uint32_t file_count;
    	uint32_t block_count;
    	uint8_t  reserved1[12];
    	struct ps4pup_pup_info *pups;
    	uint8_t  reserved2[288];
    } __attribute__((packed));
    
    
    int  ps4pup_read_header(FILE *fd, struct ps4pup_header *header);
    void ps4pup_free_header(struct ps4pup_header *header);
    int  ps4pup_extract(FILE *fd, struct ps4pup_header *header);
    void ps4pup_print_header(const struct ps4pup_header *header);
    
    void print_usage(void);
    
    int main (int argc, char *argv[])
    {
    	if (argc < 2) {
    		print_usage();
    		goto exit_error;
    	}
    	
    	FILE *fd;
    	if ((fd = fopen(argv[1], "rb")) == NULL ) {
    		printf ("Could not open %s\n", argv[1]);
    		goto exit_close;
    	}
    	
    	struct ps4pup_header h;
    	memset(&h, 0, sizeof(struct ps4pup_header));
    	
    	if (!ps4pup_read_header(fd, &h)) {
    		printf("Error reading PUP file\n");
    		goto exit_close;
    	}
    	
    	ps4pup_print_header(&h);
    	
    	printf("\nExtracting PUP files...\n");
    	
    	if (!ps4pup_extract(fd, &h)) {
    		printf("Error extracting PUP files\n");
    		ps4pup_free_header(&h);
    		goto exit_close;
    	}
    	
    	printf("Done!\n");
    	
    	
    	ps4pup_free_header(&h);
    	return 1;
    	
    	
    exit_close:
    	fclose(fd);
    exit_error:	
    	return EXIT_FAILURE;
    }
    
    int ps4pup_read_header(FILE *fd, struct ps4pup_header *header)
    {
    	if (fd == NULL || header == NULL) {
    		return 0;
    	}
    	
    	fseek(fd, 0, SEEK_SET);
    	if (fread((void*)header, 1, PS4_PUP_HEADER_SIZE, fd) != PS4_PUP_HEADER_SIZE) {
    			printf("Error reading PUP header");
    			return 0;
    	}
    	
    	if (header->magic != PS4_PUP_MAGIC) {
    		printf("This is not a PUP file!\n");
    		return 0;
    	}
    	
    	header->pups = malloc (header->file_count * sizeof(struct ps4pup_pup_info));
    	
    	int i;
    	for (i = 0; i < header->file_count; ++i) {
    		if (fread((void*)&header->pups[i], 1, PS4_PUP_ENTRY_SIZE, fd) != PS4_PUP_ENTRY_SIZE) {
    			printf("Error reading PUP entry %i\n", i+1);
    			return 0;			
    		}
    	}
    	
    	return 1;
    }
    
    
    void ps4pup_free_header(struct ps4pup_header *header)
    {	
    	if (header) {
    		if (header->pups) {
    			free(header->pups);
    		}
    	}
    }
    
    int ps4pup_extract(FILE *fd, struct ps4pup_header *header)
    {
    	if (fd == NULL || header == NULL) {
    		return 0;
    	}
    	
    	FILE *pup_out;
    	uint8_t copy_buffer[COPY_BUFFER_SIZE];
    	int data_offset = PS4_PUP_HEADER_SIZE + PS4_PUP_ENTRY_SIZE * header->file_count;
    	data_offset = (data_offset+511) & ~511; //Align to 512 bytes
    		
    	int i;
    	for (i = 0; i < header->file_count; ++i) {
    		fseek(fd, data_offset + header->pups[i].offset, SEEK_SET);
    		pup_out = fopen(header->pups[i].filename, "wb");
    		int copy_size = header->pups[i].content_size;
    		
    		printf("  Extracting PUP %i...", i+1);
    		
    		while (copy_size > 0) {
    			if (copy_size > COPY_BUFFER_SIZE) {
    				if (fread(copy_buffer, 1, COPY_BUFFER_SIZE, fd) != COPY_BUFFER_SIZE) {
    					printf("Error, skipping PUP\n");
    					break;
    				}
    				fwrite(copy_buffer, 1, COPY_BUFFER_SIZE, pup_out);
    				copy_size -= COPY_BUFFER_SIZE;
    			} else {
    				if (fread(copy_buffer, 1, copy_size, fd) != copy_size) {
    					printf("Error, skipping PUP\n");
    					break;					
    				}
    				fwrite(copy_buffer, 1, copy_size, pup_out);
    				copy_size = 0;	
    			}
    		}
    		printf("Done!\n");
    		fsync(fileno(pup_out));		
    		fclose(pup_out);
    	}	
    	return 1;	
    }
    
    void ps4pup_print_header(const struct ps4pup_header *header)
    {
    	char magic_string[5];
    	strncpy(magic_string, (char*)(uintptr_t)(&header->magic), 4);
    	magic_string[4] = '\0';
    	printf("Magic:       0x%X  %s\n", header->magic, magic_string);
    	printf("Version:     %lu\n", header->version);
    	printf("File count:  %i\n", header->file_count);
    	printf("Block count: %i\n", header->block_count);
    	
    	int i;
    	for (i = 0; i < header->file_count; ++i) {
    		printf("PUP %i:\n", i+1);
    		printf("  Offset:   0x%X\n", header->pups[i].offset);
    		printf("  Size:     %i\n", header->pups[i].content_size);
    		printf("  Filename: %s\n", header->pups[i].filename);
    		
    	}
    }
    
    void print_usage(void)
    {	
    	printf("Usage:\nps4pupextractor <PS4UPDATE.PUP>\n");
    	printf("It will extract the PUPs as: PS4UPDATEX.PUP being X the PUP number\n");
    }
    From Hykem also comes a PS4 PUP Unpacker, as follows:
    Code:
    /* 
    	PS4 PUP unpacker by Hykem.
    	Processes and splits the PUP files contained in the PS4 PUP pack file (PS4UPDATE.PUP).
    */
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define PS4_PUP_PACK_MAGIC        0x32424C53 // SLB2
    #define PS4_PUP_PACK_HEADER_SIZE  0x200
    
    // Main PUP packed header (size == 0x20):
    // 0x00: 53 4C 42 32 -> SLB2 
    // 0x04: 01 00 00 00 -> Version?
    // 0x08: 00 00 00 00 -> Unknown
    // 0x0C: 02 00 00 00 -> Number of PUP files in this pack
    // 0x10: 03 9F 09 00 -> Total number of blocks (512 bytes)
    // 0x14: 00 00 00 00 -> Unknown
    // 0x18: 00 00 00 00 -> Unknown
    // 0x1C: 00 00 00 00 -> Unknown
    struct pup_pack_header {
    	uint32_t magic;
    	uint32_t version;
    	uint32_t unk1;
    	uint32_t pup_file_num;
    	uint32_t pup_total_block_num;
    	uint32_t unk2;
    	uint32_t unk3;
    	uint32_t unk4;
    	struct pup_entry *pup_entry_list;
    } __attribute__((packed));
    
    // PUP file entry (size == 0x30):
    // 0x00: 01 00 00 00 -> Offset (in blocks, so 1 is the first block of 512 bytes after the header)
    // 0x04: 00 76 AE 0D -> File size
    // 0x08: 00 00 00 00 -> Unknown
    // 0x0C: 00 00 00 00 -> Unknown
    // 0x10: 50 53 34 55 -> File name (e.g.: PS4UPDATE1.PUP) (0x20 bytes)
    // 0x14: 50 44 41 54 
    // 0x18: 45 31 2E 50 
    // 0x1C: 55 50 00 00 
    // 0x20: 00 00 00 00 
    // 0x24: 00 00 00 00 
    // 0x28: 00 00 00 00 
    // 0x2C: 00 00 00 00
    struct pup_entry {
    	uint32_t block_offset;
    	uint32_t file_size;
    	uint32_t unk1;
    	uint32_t unk2;
    	uint8_t  file_name[32];
    } __attribute__((packed));
    
    int main (int argc, char *argv[])
    {
    	if (argc < 2) {
    		printf("Usage: ps4unpacker PS4UPDATE.PUP\n");
    		return 0;
    	}
    	
    	// Open file and setup the header structs.
    	FILE *in;
    	FILE *out;
    	struct pup_pack_header header;
    	memset(&header, 0, sizeof(struct pup_pack_header));
    	
    	if ((in = fopen(argv[1], "rb")) == NULL ) {
    		printf ("File not found!\n");
    		return 0;
    	}
    	
    	// Read in the main pack header.
    	fseek(in, 0, SEEK_SET);
    	fread(&header, 1,  0x20, in);
    	
    	if (header.magic != PS4_PUP_PACK_MAGIC) {
    		printf("Invalid PS4 PUP file!\n");
    		return 0;
    	}
    	
    	printf("PS4 PUP pack header\n");
    	printf("- PUP pack magic: 0x%X\n", header.magic);
    	printf("- PUP pack version: %i\n", header.version);
    	printf("- PUP files in this pack: %i\n", header.pup_file_num);
    	printf("- Total number of blocks: %i\n", header.pup_total_block_num);
    	printf("\n");
    	
    	// Read in all the PUP entries.
    	int i;
    	header.pup_entry_list = malloc(header.pup_file_num * sizeof(struct pup_entry));
    
    	for (i = 0; i < header.pup_file_num; ++i) {
    		fread(&header.pup_entry_list[i], 1, 0x30, in);
    		printf("PUP file entry %i:\n", i);
    		printf("- Block offset: 0x%X\n", header.pup_entry_list[i].block_offset);
    		printf("- PUP file size: %i\n", header.pup_entry_list[i].file_size);
    		printf("- PUP file name: %s\n", header.pup_entry_list[i].file_name);
    		printf("\n");
    	}
    
    	// Create a large enough buffer and start copying the data.
    	int buffer_size = PS4_PUP_PACK_HEADER_SIZE * 4;
    	int pup_offset = PS4_PUP_PACK_HEADER_SIZE;
    	uint8_t buffer[buffer_size];
    	
    	int ii;
    	for (ii = 0; ii < header.pup_file_num; ++ii) {
    		fseek(in, pup_offset, SEEK_SET);
    		out = fopen(header.pup_entry_list[ii].file_name, "wb");	
    
    		printf("Dumping PUP file %s from offset 0x%X with size %i\n", header.pup_entry_list[ii].file_name, pup_offset, header.pup_entry_list[ii].file_size);
    		
    		int fsize = header.pup_entry_list[ii].file_size;
    		pup_offset += (fsize + 511) & ~511; // 512 bytes alignment.
    		
    		while (fsize > 0) {
    			if (fsize > buffer_size) {
    				fread(buffer, 1, buffer_size, in);
    				fwrite(buffer, 1, buffer_size, out);
    				fsize -= buffer_size;
    			} else {
    				fread(buffer, 1, fsize, in);
    				fwrite(buffer, 1, fsize, out);
    				fsize = 0;	
    			}
    		}
    	
    		fclose(out);
    	}	
    
    	fclose(in);
    
    	printf("Finished!\n");
    	
    	return 1;
    }
    Update #3: As the official PS4 Firmware v1.50 PUP (1.501) is now released, this leak apparently was the PlayStation 4 v1.50 PUP not the v1.501 Update for those wondering.

    Update #4: From Habib via harryoke come the PS4 - SLB2 Structure - .PUP KEYS, as follows:
    Code:
     /* file structure of SLB goes as following, if unpacking make sure you use 64 bits little endian on windows os */
     typedef unsigned char u8;
     typedef unsigned long int u32;
     typedef unsigned long long int u64;
     
     typedef struct{
     	u32 offset; //1 block is headersize (512 padded)
     	u32 cryptSize;
     	u64 reserved; //probably file alignment
     	u8 fileName[32];
     } fileEntry;
     
     typedef struct{
     	u32 magic; //SLB2
     	u64 version; //1
     	u32 fileCount;
     	u32 blockCount;
     	u8 reserved[12];
     	fileEntry files[10];
     } ps4pup;
    SLB PUP Files

    These files are contained inside of SLB2 containers. They contain data pertaining to system firmware.

    You are able to decrypt inner pup files using the follow keys:
    Code:
    erk=DB7A24EC38BDB45B98CCD7D363EA2AF0C326E65081E0630CB9AB2D215865878A
    riv=C9205F46F6021697E670F13DFA726212
    pub=A8FD6DB24532D094EFA08BD35C9A72287D905C6B27B42BE4AB925AAF4AFFF34D41EEB54DD128700D
    priv=001AD976FCDE86F5B8F63453EF3A7F94E861975BA3
    ctype=30
    0x40 bytes after the magic are encrypted with aes. (256 bits CBC Mode). The new encrypted buffer contains the new erk and riv to be used for the next decryption. The next 0x240 bytes are decrypted with aes. (128 bits CTR Mode). That 0x240 bytes contain a table of information relating to the system files. Each entry in there contains the offset for encrypted sections, sha1 hmac keys, and the erk and riv to decrypt each encrypted section. Each section is decrypted using aes. (128 bits CTR mode).

    PlayStation 4 FW Update 1.5 (PS4UPDATE.PUP) & PS4 Updatelist XML Out

    PlayStation 4 FW Update 1.5 (PS4UPDATE.PUP) & PS4 Updatelist XML Out

    PlayStation 4 FW Update 1.5 (PS4UPDATE.PUP) & PS4 Updatelist XML Out

    More PlayStation 4 News...
    Attached Images<br><br> Attached Images

    Attached Files Attached Files

  8. #8
    Registered User cracrus's Avatar
    Join Date
    Nov 2005
    Posts
    12
    file is offline now

  9. #9
    Forum Moderator PS3 News's Avatar
    Join Date
    Apr 2005
    Posts
    27,501
    Figures... I will hunt around for some mirrors in a few hours, if anyone comes across any before that feel free to share them and I'll +Rep ya.

  10. #10
    Contributor B7U3 C50SS's Avatar
    Join Date
    Oct 2013
    Posts
    13
    OKAY.. After looking it says on the pic from skfu (the one with the header) "The PUP file is really not a .pup file anymore it is actually several other .pup files. Thanks Roy for the info."

    or something in the like to that.. i may have made mistypes. lol

    Firmware .PUP - c64d11f839ac8628176941b99fd3670e
    Recovery .PUP - 6f4d6afe98dd7297c70aa4d6e7e5482b

    btw it looks as though the python scrypt appears to be made for a task on the builder - is it? pastie.org/private/4wgojewhp2pq7declhkhw
    Code:
    
    import sys, os, struct
    
    if len(sys.argv) < 3:
    	script_file_name = os.path.split(sys.argv[0])[1]
    	print 'usage: {0} <pup container file> <output directory>'.format(script_file_name)
    	sys.exit()
    
    pup_file_path = sys.argv[1]
    if not os.path.isfile(pup_file_path):
    	print 'error: invalid file specified'
    	sys.exit()
    
    output_dir = sys.argv[2]
    if not os.path.exists(output_dir):
    	os.makedirs(output_dir)
    elif not os.path.isdir(output_dir):
    	print 'error: invalid directory specified'
    	sys.exit()
    
    header_fmt = '<4sI4xIQ8x'
    entry_fmt = '<II8x32s'
    
    block_size = 512
    
    pup_file_size = os.path.getsize(pup_file_path)
    with open(pup_file_path, 'rb') as pup_file:
    	magic, version, num_entries, num_blocks = struct.unpack(header_fmt, pup_file.read(struct.calcsize(header_fmt)))
    	if magic != 'SLB2':
    		print 'wrong file magic'
    		sys.exit()
    	if version != 1:
    		print 'unsupported file version'
    		sys.exit()
    	if num_blocks * block_size != pup_file_size:
    		print 'wrong number of blocks'
    		sys.exit()
    	entry_data = pup_file.read(num_entries * struct.calcsize(entry_fmt))
    	for i in xrange(num_entries):
    	        block_index, size, file_name = struct.unpack(entry_fmt, entry_data[i * struct.calcsize(entry_fmt):(i + 1) * struct.calcsize(entry_fmt)])
    		file_name = file_name.rstrip('\x00')
    		file_path = os.path.join(output_dir, file_name)
    		with open(file_path, 'wb') as entry_file:
    			pup_file.seek(block_index * block_size)
    			num_segments = 1 + (size - 1) / block_size if size > 0 else 0
    			for j in xrange(num_segments):
    				segment_size = block_size if j < (num_segments - 1) else size - (num_segments - 1) * block_size
    				data = pup_file.read(segment_size)
    				entry_file.write(data)
    i guess i have the absolute worst timing, huh? i was.. not aware that the dl link was up at all last night and went off of basic assumptions that this should be out.. i'm really ashamed of myself..

    oh god it's just a code to export the .pup files from the full .pup... now i feel like an idiot...
    Last edited by B7U3 C50SS; 10-29-2013 at 09:04 PM Reason: Automerged Doublepost

 

Sponsored Links

Page 1 of 5 123 ... LastLast
Affiliates - Contact Us - PS3 Downloads - Privacy Statement - Site Rules - Top - © 2014 PlayStation 3 News