Godspeed Chovy
This commit is contained in:
parent
8387d6029c
commit
9d698dc492
|
@ -77,6 +77,8 @@
|
|||
<Compile Include="pbp.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="PSVIMGReader.cs" />
|
||||
<Compile Include="PSVIMGStream.cs" />
|
||||
<Compile Include="psvimgtools.cs" />
|
||||
<EmbeddedResource Include="CHOVY.resx">
|
||||
<DependentUpon>CHOVY.cs</DependentUpon>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using DiscUtils.Iso9660;
|
||||
using Microsoft.Win32;
|
||||
using Param_SFO;
|
||||
using PSVIMGTOOLS;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
|
@ -313,9 +314,6 @@ namespace CHOVY
|
|||
|
||||
private void FindFromCMA_Click(object sender, EventArgs e)
|
||||
{
|
||||
/* Ccs_FormClosing(null, null);
|
||||
return;*/
|
||||
|
||||
this.Hide();
|
||||
string cmaDir = "";
|
||||
string accountId = "0000000000000000";
|
||||
|
@ -386,86 +384,54 @@ namespace CHOVY
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string output = Path.Combine(Application.StartupPath, "_tmp");
|
||||
Directory.CreateDirectory(output);
|
||||
|
||||
string OutputPbp = Path.Combine(output, "ux0_pspemu_temp_game_PSP_GAME_" + Backup, "EBOOT.PBP");
|
||||
string GameFolder = Path.Combine(output, "ux0_pspemu_temp_game_PSP_GAME_" + Backup);
|
||||
string LicenseFolder = Path.Combine(output, "ux0_pspemu_temp_game_PSP_LICENSE");
|
||||
|
||||
Status.Text = "Declaring Independance from the GAME.PSVIMG";
|
||||
|
||||
string BackupPath = Path.Combine(CmaDir, "PGAME", CmaAid, Backup, "game", "game.psvimg");
|
||||
if(!File.Exists(BackupPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
TotalProgress.Style = ProgressBarStyle.Marquee;
|
||||
Process psvimg = psvimgtools.PSVIMG_EXTRACT(CmaAid, BackupPath, output);
|
||||
while (!psvimg.HasExited)
|
||||
{
|
||||
Application.DoEvents();
|
||||
}
|
||||
if(!Directory.Exists(GameFolder) || psvimg.ExitCode != 0)
|
||||
{
|
||||
MessageBox.Show("PSVIMG-EXTRACT.EXE FAILED!\nArguments:\n" + psvimg.StartInfo.Arguments + "\nStdOut:\n" + psvimg.StandardOutput.ReadToEnd() + "\nStdErr:\n" + psvimg.StandardError.ReadToEnd());
|
||||
return;
|
||||
}
|
||||
|
||||
Status.Text = "Declaring Independance from the LICENSE.PSVIMG";
|
||||
byte[] AID = BitConverter.GetBytes(Convert.ToInt64(CmaAid, 16));
|
||||
Array.Reverse(AID);
|
||||
byte[] Key = CmaKeys.GenerateKey(AID);
|
||||
|
||||
PSVIMGStream GamePsvimg = new PSVIMGStream(File.OpenRead(BackupPath), Key);
|
||||
|
||||
BackupPath = Path.Combine(CmaDir, "PGAME", CmaAid, Backup, "license", "license.psvimg");
|
||||
psvimg = psvimgtools.PSVIMG_EXTRACT(CmaAid, BackupPath, output);
|
||||
while(!psvimg.HasExited)
|
||||
if (!File.Exists(BackupPath))
|
||||
{
|
||||
Application.DoEvents();
|
||||
}
|
||||
if (!Directory.Exists(LicenseFolder) || psvimg.ExitCode != 0)
|
||||
{
|
||||
MessageBox.Show("PSVIMG-EXTRACT.EXE FAILED!\nArguments:\n" + psvimg.StartInfo.Arguments + "\nStdOut:\n" + psvimg.StandardOutput.ReadToEnd() + "\nStdErr:\n" + psvimg.StandardError.ReadToEnd());
|
||||
return;
|
||||
}
|
||||
|
||||
/* -- This was some debug stuff
|
||||
OpenFileDialog Openpbp = new OpenFileDialog();
|
||||
Openpbp.ShowDialog();
|
||||
string OutputPbp = Openpbp.FileName;
|
||||
PSVIMGStream LicensePsvimg = new PSVIMGStream(File.OpenRead(BackupPath), Key);
|
||||
|
||||
OpenFileDialog OpenRif = new OpenFileDialog();
|
||||
OpenRif.ShowDialog();
|
||||
string Rif = OpenRif.FileName;
|
||||
*/
|
||||
string Rif = Path.Combine(Application.StartupPath, "GAME.RIF");
|
||||
|
||||
byte[] VersionKey = pbp.GetVersionKey(OutputPbp);
|
||||
PSVIMGFileStream EbootPbp = new PSVIMGFileStream(GamePsvimg, "/EBOOT.PBP");
|
||||
byte[] VersionKey = pbp.GetVersionKey(EbootPbp);
|
||||
string VerKey = BitConverter.ToString(VersionKey).Replace("-", "");
|
||||
WriteSetting("VersionKey", VerKey);
|
||||
|
||||
string ContentID = pbp.GetContentId(OutputPbp);
|
||||
string Rif = Path.Combine(Application.StartupPath, "GAME.RIF");
|
||||
string LicensePath = Path.Combine(output, "ux0_pspemu_temp_game_PSP_LICENSE", ContentID + ".rif");
|
||||
if(!File.Exists(LicensePath))
|
||||
{
|
||||
MessageBox.Show("Cannot find RIF", "RIF ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
File.Copy(LicensePath, Rif, true);
|
||||
string ContentID = pbp.GetContentId(EbootPbp);
|
||||
PSVIMGFileStream LicenseRif = new PSVIMGFileStream(LicensePsvimg, "/"+ ContentID+ ".rif");
|
||||
byte[] LicenseFile = new byte[LicenseRif.Length];
|
||||
LicenseRif.Read(LicenseFile, 0x00, Convert.ToInt32(LicenseRif.Length));
|
||||
File.WriteAllBytes(Rif, LicenseFile);
|
||||
|
||||
LicenseRif.Close();
|
||||
LicensePsvimg.Close();
|
||||
EbootPbp.Close();
|
||||
GamePsvimg.Close();
|
||||
|
||||
WriteSetting("RifPath", Rif);
|
||||
WriteSetting("CmaDir", CmaDir);
|
||||
|
||||
Versionkey.Text = VerKey;
|
||||
RifPath.Text = Rif;
|
||||
|
||||
if (Directory.Exists(output))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(output, true);
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
}
|
||||
|
||||
Status.Text = "Progress %";
|
||||
TotalProgress.Style = ProgressBarStyle.Continuous;
|
||||
MessageBox.Show("KEYS HAVE BEEN EXTRACTED FROM CMA, YOU MAY NOW LIBERATE YOURSELF", "SUCCESS", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
private void BrowseButton_Click(object sender, EventArgs e)
|
||||
|
|
|
@ -0,0 +1,407 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PSVIMGTOOLS
|
||||
{
|
||||
internal class strings
|
||||
{
|
||||
internal static string readTerminator(byte[] StringBytes)
|
||||
{
|
||||
string str = "";
|
||||
foreach (byte sByte in StringBytes)
|
||||
{
|
||||
if (sByte != 0x00)
|
||||
{
|
||||
str += (char)sByte;
|
||||
}
|
||||
else
|
||||
{
|
||||
return str;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
class SceDateTime
|
||||
{
|
||||
public UInt16 Year;
|
||||
public UInt16 Month;
|
||||
public UInt16 Day;
|
||||
public UInt16 Hour;
|
||||
public UInt16 Minute;
|
||||
public UInt16 Second;
|
||||
public UInt32 Microsecond;
|
||||
|
||||
public SceDateTime()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class SceIoStat
|
||||
{
|
||||
public UInt32 Mode;
|
||||
public uint Attributes;
|
||||
/** Size of the file in bytes. */
|
||||
public UInt64 Size;
|
||||
/** Creation time. */
|
||||
public SceDateTime CreationTime;
|
||||
/** Access time. */
|
||||
public SceDateTime AccessTime;
|
||||
/** Modification time. */
|
||||
public SceDateTime ModificaionTime;
|
||||
/** Device-specific data. */
|
||||
public UInt32[] Private = new UInt32[6];
|
||||
public SceIoStat()
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class PsvImgTailer
|
||||
{
|
||||
public UInt64 Flags;
|
||||
public Byte[] Padding = new Byte[1004];
|
||||
public Byte[] bEnd = new Byte[12];
|
||||
|
||||
public String End
|
||||
{
|
||||
get
|
||||
{
|
||||
return strings.readTerminator(bEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
class PsvImgHeader
|
||||
{
|
||||
public UInt64 SysTime;
|
||||
public UInt64 Flags;
|
||||
public SceIoStat Statistics;
|
||||
public Byte[] bParentPath = new Byte[256];
|
||||
public UInt32 unk_16C; // set to 1
|
||||
public Byte[] bPath = new Byte[256];
|
||||
public Byte[] Padding = new Byte[904];
|
||||
public Byte[] bEnd = new Byte[12];
|
||||
|
||||
public String Path
|
||||
{
|
||||
get
|
||||
{
|
||||
return strings.readTerminator(bPath);
|
||||
}
|
||||
}
|
||||
|
||||
public String End
|
||||
{
|
||||
get
|
||||
{
|
||||
return strings.readTerminator(bEnd);
|
||||
}
|
||||
}
|
||||
|
||||
public String ParentPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return strings.readTerminator(bParentPath);
|
||||
}
|
||||
}
|
||||
public PsvImgHeader()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PSVIMGFileStream : Stream
|
||||
{
|
||||
|
||||
long length = 0;
|
||||
long startPos = 0;
|
||||
long endPos = 0;
|
||||
long position = 0;
|
||||
|
||||
PSVIMGStream psvStream;
|
||||
public PSVIMGFileStream(PSVIMGStream psv, string Path)
|
||||
{
|
||||
psvStream = psv;
|
||||
findFile(Path);
|
||||
}
|
||||
public override bool CanRead
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public override bool CanWrite
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return position;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.Seek(value, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
psvStream.Flush();
|
||||
}
|
||||
private int _read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
int read = 0;
|
||||
while(true)
|
||||
{
|
||||
int remainBlock = Convert.ToInt32(psvStream.BlockRemaining - psvStream.SHA256_BLOCK_SIZE);
|
||||
int remainRead = count - read;
|
||||
|
||||
if (remainRead < remainBlock)
|
||||
{
|
||||
byte[] tmp = new byte[remainRead];
|
||||
psvStream.Read(tmp, 0x00, remainRead);
|
||||
ms.Write(tmp,0x00,tmp.Length);
|
||||
read += remainRead;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] tmp = new byte[remainBlock];
|
||||
psvStream.Read(tmp, 0x00, remainBlock);
|
||||
ms.Write(tmp, 0x00, tmp.Length);
|
||||
psvStream.Seek(psvStream.SHA256_BLOCK_SIZE, SeekOrigin.Current);
|
||||
read += Convert.ToInt32(remainBlock);
|
||||
}
|
||||
}
|
||||
ms.Seek(0x00, SeekOrigin.Begin);
|
||||
return ms.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private long _seek(long amount,SeekOrigin orig)
|
||||
{
|
||||
long ToSeek = 0;
|
||||
long SeekAdd = 0;
|
||||
long remainBlock = psvStream.BlockRemaining - psvStream.SHA256_BLOCK_SIZE;
|
||||
while (true)
|
||||
{
|
||||
long remainSeek = amount - ToSeek;
|
||||
|
||||
if (remainSeek < remainBlock)
|
||||
{
|
||||
ToSeek += remainSeek;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ToSeek += remainBlock;
|
||||
SeekAdd += psvStream.SHA256_BLOCK_SIZE;
|
||||
}
|
||||
remainBlock = psvStream.PSVIMG_BLOCK_SIZE;
|
||||
}
|
||||
ToSeek += SeekAdd;
|
||||
return psvStream.Seek(ToSeek,orig);
|
||||
}
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if((startPos+count) > endPos)
|
||||
{
|
||||
count = Convert.ToInt32(endPos);
|
||||
}
|
||||
return _read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
if(origin == SeekOrigin.Begin)
|
||||
{
|
||||
if(offset <= endPos)
|
||||
{
|
||||
psvStream.Seek(startPos, SeekOrigin.Begin);
|
||||
_seek(offset, SeekOrigin.Current);
|
||||
position = offset;
|
||||
return position;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IndexOutOfRangeException("Offset is out of range of file");
|
||||
}
|
||||
|
||||
}
|
||||
else if(origin == SeekOrigin.Current)
|
||||
{
|
||||
if (offset <= endPos)
|
||||
{
|
||||
_seek(offset, SeekOrigin.Current);
|
||||
position += offset;
|
||||
return position;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IndexOutOfRangeException("Offset is out of range of file");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
long realOffset = endPos + offset;
|
||||
if (realOffset <= endPos)
|
||||
{
|
||||
_seek(realOffset, SeekOrigin.Begin);
|
||||
return this.Position;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IndexOutOfRangeException("Offset is out of range of file");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotImplementedException("PSVFileStream is Read-Only");
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotImplementedException("PSVFileStream is Read-Only");
|
||||
}
|
||||
|
||||
private ushort readUInt16()
|
||||
{
|
||||
byte[] intBuf = new byte[0x2];
|
||||
_read(intBuf, 0x00, 0x02);
|
||||
return BitConverter.ToUInt16(intBuf,0);
|
||||
}
|
||||
private uint readUInt32()
|
||||
{
|
||||
byte[] intBuf = new byte[0x4];
|
||||
_read(intBuf, 0x00, 0x04);
|
||||
return BitConverter.ToUInt32(intBuf,0);
|
||||
}
|
||||
private ulong readUInt64()
|
||||
{
|
||||
byte[] intBuf = new byte[0x8];
|
||||
_read(intBuf, 0x00, 0x08);
|
||||
return BitConverter.ToUInt64(intBuf,0);
|
||||
}
|
||||
private SceDateTime readDatetime()
|
||||
{
|
||||
SceDateTime dateTime = new SceDateTime();
|
||||
dateTime.Year = readUInt16();
|
||||
dateTime.Month = readUInt16();
|
||||
dateTime.Day = readUInt16();
|
||||
dateTime.Hour = readUInt16();
|
||||
dateTime.Minute = readUInt16();
|
||||
dateTime.Second = readUInt16();
|
||||
dateTime.Microsecond = readUInt32();
|
||||
return dateTime;
|
||||
}
|
||||
private SceIoStat readStats()
|
||||
{
|
||||
SceIoStat stat = new SceIoStat();
|
||||
stat.Mode = readUInt32();
|
||||
stat.Attributes = readUInt32();
|
||||
stat.Size = readUInt64();
|
||||
stat.CreationTime = readDatetime();
|
||||
stat.AccessTime = readDatetime();
|
||||
stat.ModificaionTime = readDatetime();
|
||||
for(int i = 0; i < stat.Private.Length; i++)
|
||||
{
|
||||
stat.Private[i] = readUInt32();
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
private PsvImgHeader readHeader()
|
||||
{
|
||||
PsvImgHeader header = new PsvImgHeader();
|
||||
header.SysTime = readUInt64();
|
||||
header.Flags = readUInt64();
|
||||
header.Statistics = readStats();
|
||||
_read(header.bParentPath, 0x00, 256);
|
||||
header.unk_16C = readUInt32();
|
||||
_read(header.bPath, 0x00, 256);
|
||||
_read(header.Padding, 0x00, 904);
|
||||
_read(header.bEnd, 0x00, 12);
|
||||
return header;
|
||||
}
|
||||
|
||||
private PsvImgTailer readTailer()
|
||||
{
|
||||
PsvImgTailer tailer = new PsvImgTailer();
|
||||
tailer.Flags = readUInt64();
|
||||
_read(tailer.Padding, 0x00, 1004);
|
||||
_read(tailer.bEnd, 0x00, 12);
|
||||
return tailer;
|
||||
}
|
||||
private void findFile(string path)
|
||||
{
|
||||
_seek(0x00, SeekOrigin.Begin);
|
||||
while (psvStream.Position < psvStream.Length)
|
||||
{
|
||||
PsvImgHeader header = readHeader();
|
||||
long size = (long)header.Statistics.Size;
|
||||
|
||||
//Read Padding (if any)
|
||||
int padding;
|
||||
if ((size & (psvStream.PSVIMG_ENTRY_ALIGN - 1))>=1)
|
||||
{
|
||||
padding = Convert.ToInt32(psvStream.PSVIMG_ENTRY_ALIGN - (size & (psvStream.PSVIMG_ENTRY_ALIGN - 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
padding = 0;
|
||||
}
|
||||
|
||||
if (header.Path == path)
|
||||
{
|
||||
length = size;
|
||||
startPos = psvStream.Position;
|
||||
endPos = startPos + length;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
_seek(size+padding, SeekOrigin.Current);
|
||||
PsvImgTailer tailer = readTailer();
|
||||
}
|
||||
|
||||
}
|
||||
throw new FileNotFoundException("Cannot find file specified");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,340 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
|
||||
namespace PSVIMGTOOLS
|
||||
{
|
||||
class PSVIMGStream : Stream
|
||||
{
|
||||
|
||||
public int AES_BLOCK_SIZE = 0x10;
|
||||
public int SHA256_BLOCK_SIZE = 0x20;
|
||||
public int PSVIMG_BLOCK_SIZE = 0x8000;
|
||||
public int FULL_PSVIMG_SIZE = 0x8020;
|
||||
public int PSVIMG_ENTRY_ALIGN = 0x400;
|
||||
private Stream baseStream;
|
||||
private MemoryStream blockStream;
|
||||
private byte[] key;
|
||||
public Stream BaseStream
|
||||
{
|
||||
get
|
||||
{
|
||||
return baseStream;
|
||||
}
|
||||
}
|
||||
|
||||
public Byte[] Key
|
||||
{
|
||||
get
|
||||
{
|
||||
return key;
|
||||
}
|
||||
set
|
||||
{
|
||||
key = value;
|
||||
}
|
||||
}
|
||||
|
||||
public long BlockNo
|
||||
{
|
||||
get
|
||||
{
|
||||
return getBlockIndex();
|
||||
}
|
||||
set
|
||||
{
|
||||
seekToBlock(value);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
public long BlockRemaining
|
||||
{
|
||||
get
|
||||
{
|
||||
return getRemainingBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public long BlockPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return blockStream.Position;
|
||||
}
|
||||
set
|
||||
{
|
||||
blockStream.Seek(value, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
public override bool CanWrite
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return baseStream.Length - AES_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return baseStream.Position - AES_BLOCK_SIZE;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.Seek(value, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public PSVIMGStream(Stream file, byte[] KEY)
|
||||
{
|
||||
baseStream = file;
|
||||
key = KEY;
|
||||
blockStream = new MemoryStream();
|
||||
baseStream.Seek(AES_BLOCK_SIZE, SeekOrigin.Begin);
|
||||
update();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int remaining = (int)getRemainingBlock();
|
||||
int read = 0;
|
||||
|
||||
if (count < remaining)
|
||||
{
|
||||
read += blockStream.Read(buffer, offset, count);
|
||||
baseStream.Seek(count, SeekOrigin.Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
update();
|
||||
remaining = (int)getRemainingBlock();
|
||||
int curPos = count - read;
|
||||
|
||||
if (curPos > remaining)
|
||||
{
|
||||
read += remaining;
|
||||
blockStream.CopyTo(ms, remaining);
|
||||
baseStream.Seek(remaining, SeekOrigin.Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
read += curPos;
|
||||
blockStream.CopyTo(ms, curPos);
|
||||
baseStream.Seek(curPos, SeekOrigin.Current);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
ms.Seek(0x00, SeekOrigin.Begin);
|
||||
ms.Read(buffer, offset, count);
|
||||
}
|
||||
}
|
||||
return read;
|
||||
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
update();
|
||||
baseStream.Flush();
|
||||
blockStream.Flush();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
long ret = 0;
|
||||
if(origin == SeekOrigin.Begin)
|
||||
{
|
||||
ret = baseStream.Seek(offset + AES_BLOCK_SIZE, SeekOrigin.Begin);
|
||||
}
|
||||
else if (origin == SeekOrigin.Current)
|
||||
{
|
||||
long pos = baseStream.Position;
|
||||
if ((pos + offset) >= AES_BLOCK_SIZE)
|
||||
{
|
||||
ret = baseStream.Seek(offset, SeekOrigin.Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = baseStream.Seek(offset+ AES_BLOCK_SIZE, SeekOrigin.Current);
|
||||
}
|
||||
}
|
||||
else if (origin == SeekOrigin.End)
|
||||
{
|
||||
long pos = baseStream.Length;
|
||||
if ((pos + offset) >= AES_BLOCK_SIZE)
|
||||
{
|
||||
ret = baseStream.Seek(offset, SeekOrigin.End);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = baseStream.Seek(offset + AES_BLOCK_SIZE, SeekOrigin.End);
|
||||
}
|
||||
}
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotImplementedException("PSVIMGStream is Read-Only");
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotImplementedException("PSVIMGStream is Read-Only");
|
||||
}
|
||||
|
||||
|
||||
public new void Close()
|
||||
{
|
||||
blockStream.Close();
|
||||
blockStream.Dispose();
|
||||
baseStream.Close();
|
||||
baseStream.Dispose();
|
||||
this.Dispose();
|
||||
}
|
||||
private void update()
|
||||
{
|
||||
long offset = (this.Position % FULL_PSVIMG_SIZE);
|
||||
long blockIndex = getBlockIndex();
|
||||
byte[] decryptedBlock = getBlock(blockIndex);
|
||||
blockStream.Seek(0x00, SeekOrigin.Begin);
|
||||
blockStream.SetLength(decryptedBlock.Length);
|
||||
blockStream.Write(decryptedBlock, 0x00, decryptedBlock.Length);
|
||||
seekToBlock(blockIndex);
|
||||
baseStream.Seek(offset, SeekOrigin.Current);
|
||||
blockStream.Seek(offset, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
private long getBlockIndex()
|
||||
{
|
||||
long i = 0;
|
||||
long curPos = baseStream.Position;
|
||||
long fullBlock;
|
||||
long blockOffset;
|
||||
|
||||
while (true)
|
||||
{
|
||||
blockOffset = (i * FULL_PSVIMG_SIZE) + AES_BLOCK_SIZE;
|
||||
long remaining = getRemainingBase();
|
||||
if (remaining < FULL_PSVIMG_SIZE)
|
||||
{
|
||||
fullBlock = blockOffset + remaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
fullBlock = blockOffset + FULL_PSVIMG_SIZE;
|
||||
}
|
||||
if ((curPos >= blockOffset) && (curPos < fullBlock))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (blockOffset > baseStream.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
|
||||
|
||||
}
|
||||
private long getRemainingBase()
|
||||
{
|
||||
return baseStream.Length - baseStream.Position;
|
||||
}
|
||||
private long getRemainingBlock()
|
||||
{
|
||||
return blockStream.Length - blockStream.Position;
|
||||
}
|
||||
private byte[] getIV(long blockindex)
|
||||
{
|
||||
byte[] iv = new byte[0x10];
|
||||
seekToBlock(blockindex);
|
||||
baseStream.Seek(baseStream.Position - AES_BLOCK_SIZE, SeekOrigin.Begin);
|
||||
baseStream.Read(iv, 0x00, iv.Length);
|
||||
return iv;
|
||||
}
|
||||
private byte[] aes_ecb_decrypt(byte[] cipherData, byte[] IV)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
Aes alg = Aes.Create();
|
||||
alg.Mode = CipherMode.CBC;
|
||||
alg.Padding = PaddingMode.None;
|
||||
alg.KeySize = 256;
|
||||
alg.BlockSize = 128;
|
||||
alg.Key = key;
|
||||
alg.IV = IV;
|
||||
CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
|
||||
cs.Write(cipherData, 0, cipherData.Length);
|
||||
cs.Close();
|
||||
byte[] decryptedData = ms.ToArray();
|
||||
return decryptedData;
|
||||
}
|
||||
|
||||
private void seekToBlock(long blockIndex)
|
||||
{
|
||||
long blockOffset;
|
||||
blockOffset = (blockIndex * FULL_PSVIMG_SIZE) + AES_BLOCK_SIZE;
|
||||
|
||||
if (blockOffset > baseStream.Length)
|
||||
{
|
||||
blockOffset = baseStream.Length;
|
||||
}
|
||||
|
||||
|
||||
baseStream.Seek(blockOffset, SeekOrigin.Begin);
|
||||
}
|
||||
private byte[] getBlock(long blockIndex)
|
||||
{
|
||||
byte[] iv = getIV(blockIndex);
|
||||
long remaining = getRemainingBase();
|
||||
byte[] encryptedBlock;
|
||||
if (FULL_PSVIMG_SIZE < remaining)
|
||||
{
|
||||
encryptedBlock = new byte[FULL_PSVIMG_SIZE];
|
||||
}
|
||||
else
|
||||
{
|
||||
encryptedBlock = new byte[remaining];
|
||||
}
|
||||
|
||||
|
||||
baseStream.Read(encryptedBlock, 0x00, encryptedBlock.Length);
|
||||
byte[] decryptedBlock = aes_ecb_decrypt(encryptedBlock, iv);
|
||||
return decryptedBlock;
|
||||
}
|
||||
}
|
||||
}
|
21
CHOVY/pbp.cs
21
CHOVY/pbp.cs
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using PSVIMGTOOLS;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
@ -58,16 +59,20 @@ namespace CHOVY
|
|||
}
|
||||
|
||||
|
||||
public unsafe static byte[] GetVersionKey(string pbpfile)
|
||||
private static UInt32 readUInt32(Stream src)
|
||||
{
|
||||
byte[] intBuf = new byte[0x4];
|
||||
src.Read(intBuf, 0x00, 0x04);
|
||||
return BitConverter.ToUInt32(intBuf, 0);
|
||||
}
|
||||
public unsafe static byte[] GetVersionKey(Stream pbp)
|
||||
{
|
||||
MAC_KEY mkey;
|
||||
|
||||
kirk_init();
|
||||
|
||||
FileStream pbp = File.OpenRead(pbpfile);
|
||||
BinaryReader binPBP = new BinaryReader(pbp);
|
||||
pbp.Seek(0x24,SeekOrigin.Begin);
|
||||
int NPUMDIMGOffest = binPBP.ReadInt32();
|
||||
Int64 NPUMDIMGOffest = Convert.ToInt64(readUInt32(pbp));
|
||||
|
||||
pbp.Seek(NPUMDIMGOffest, SeekOrigin.Begin);
|
||||
|
||||
|
@ -92,12 +97,10 @@ namespace CHOVY
|
|||
return chovy_gen(EbootFile, AID, OutSceebootpbpFile);
|
||||
}
|
||||
|
||||
public static string GetContentId(string pbpfile)
|
||||
public static string GetContentId(Stream pbp)
|
||||
{
|
||||
FileStream pbp = File.OpenRead(pbpfile);
|
||||
BinaryReader binPBP = new BinaryReader(pbp);
|
||||
pbp.Seek(0x24, SeekOrigin.Begin);
|
||||
int NPUMDIMGOffest = binPBP.ReadInt32();
|
||||
Int64 NPUMDIMGOffest = Convert.ToInt64(readUInt32(pbp));
|
||||
pbp.Seek(NPUMDIMGOffest+0x10, SeekOrigin.Begin);
|
||||
byte[] ContentId = new byte[0x24];
|
||||
pbp.Read(ContentId, 0x00, 0x24);
|
||||
|
|
Loading…
Reference in New Issue