write codez
This commit is contained in:
parent
ead7745626
commit
6bd010e50f
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>CHOVY</RootNamespace>
|
||||
<AssemblyName>CHOVY-SIGN</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
|
@ -47,6 +47,9 @@
|
|||
<Reference Include="DiscUtils.Common, Version=0.11.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Discutils.0.11.0.2\lib\net40\DiscUtils.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DotNetZip, Version=1.13.4.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DotNetZip.1.13.4\lib\net40\DotNetZip.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
|
@ -82,6 +85,7 @@
|
|||
<Compile Include="PSVIMGStream.cs" />
|
||||
<Compile Include="PSVIMGStructs.cs" />
|
||||
<Compile Include="psvimgtools.cs" />
|
||||
<Compile Include="PSVMDBuilder.cs" />
|
||||
<EmbeddedResource Include="CHOVY.resx">
|
||||
<DependentUpon>CHOVY.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
|
102
CHOVY/CHOVY.cs
102
CHOVY/CHOVY.cs
|
@ -9,6 +9,7 @@ using System.Drawing;
|
|||
using System.IO;
|
||||
using System.Media;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CHOVY
|
||||
|
@ -222,11 +223,11 @@ namespace CHOVY
|
|||
|
||||
}
|
||||
|
||||
File.WriteAllText(GamePathFile, "ux0:pspemu/temp/game/PSP/GAME/" + TitleID + "\x00");
|
||||
// File.WriteAllText(GamePathFile, "ux0:pspemu/temp/game/PSP/GAME/" + TitleID + "\x00");
|
||||
|
||||
TotalProgress.Style = ProgressBarStyle.Marquee;
|
||||
Status.Text = "Signing the Declaration of Independance";
|
||||
UInt64 IntAid = Convert.ToUInt64(Aid,16);
|
||||
//TotalProgress.Style = ProgressBarStyle.Marquee;
|
||||
Status.Text = "Signing the Declaration of Independance 0%";
|
||||
UInt64 IntAid = BitConverter.ToUInt64(RifAid,0x00);
|
||||
int ChovyGenRes = pbp.gen__sce_ebootpbp(EbootFile, IntAid, EbootSignature);
|
||||
if (!File.Exists(EbootSignature) || ChovyGenRes != 0)
|
||||
{
|
||||
|
@ -242,10 +243,68 @@ namespace CHOVY
|
|||
// Pacakge GAME
|
||||
|
||||
|
||||
string BackupGameDir = Path.Combine(BackupWorkDir, "game");
|
||||
Directory.CreateDirectory(BackupGameDir);
|
||||
Process psvimg_create = psvimgtools.PSVIMG_CREATE(Aid, "game" ,TmpDir, Path.Combine(BackupWorkDir,"game"));
|
||||
while(!psvimg_create.HasExited)
|
||||
//string BackupGameDir = Path.Combine(BackupWorkDir, "game");
|
||||
|
||||
string[] entrys = Directory.GetFileSystemEntries(GameWorkDir, "*", SearchOption.AllDirectories);
|
||||
long noEntrys = entrys.LongLength;
|
||||
string parentPath = "ux0:pspemu/temp/game/PSP/GAME/" + TitleID;
|
||||
int noBlocks = 0;
|
||||
foreach (string fileName in Directory.GetFiles(GameWorkDir,"*",SearchOption.AllDirectories))
|
||||
{
|
||||
noBlocks += Convert.ToInt32(new FileInfo(fileName).Length / PSVIMGConstants.PSVIMG_BLOCK_SIZE);
|
||||
}
|
||||
TotalProgress.Maximum = noBlocks;
|
||||
|
||||
byte[] CmaKey = CmaKeys.GenerateKey(RifAid);
|
||||
|
||||
string BackupDir = Path.Combine(BackupWorkDir, "game");
|
||||
Directory.CreateDirectory(BackupDir);
|
||||
FileStream psvimg = File.OpenWrite(Path.Combine(BackupDir, "game.psvimg"));
|
||||
psvimg.SetLength(0);
|
||||
|
||||
PSVIMGBuilder builder = new PSVIMGBuilder(psvimg, CmaKey);
|
||||
|
||||
|
||||
|
||||
foreach (string entry in entrys)
|
||||
{
|
||||
string relativePath = entry.Remove(0, GameWorkDir.Length);
|
||||
bool isDir = File.GetAttributes(entry).HasFlag(FileAttributes.Directory);
|
||||
|
||||
if (isDir)
|
||||
{
|
||||
builder.AddDir(entry, parentPath, relativePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddFileAsync(entry, parentPath, relativePath);
|
||||
while(!builder.HasFinished)
|
||||
{
|
||||
try
|
||||
{
|
||||
int tBlocks = builder.BlocksWritten;
|
||||
TotalProgress.Value = tBlocks;
|
||||
decimal progress = Math.Floor(((decimal)tBlocks / (decimal)noBlocks) * 100);
|
||||
Status.Text = "Signing the Declaration of Independance " + progress.ToString() + "%";
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
Application.DoEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long ContentSize = builder.Finish();
|
||||
|
||||
psvimg = File.OpenRead(Path.Combine(BackupDir, "game.psvimg"));
|
||||
FileStream psvmd = File.OpenWrite(Path.Combine(BackupDir, "game.psvmd"));
|
||||
PSVMDBuilder.CreatePsvmd(psvmd, psvimg, ContentSize, "game", CmaKey);
|
||||
psvmd.Close();
|
||||
|
||||
// Directory.CreateDirectory(BackupGameDir);
|
||||
|
||||
//Process psvimg_create = psvimgtools.PSVIMG_CREATE(Aid, "game" ,TmpDir, Path.Combine(BackupWorkDir,"game"));
|
||||
/* while(!psvimg_create.HasExited)
|
||||
{
|
||||
Application.DoEvents();
|
||||
}
|
||||
|
@ -255,7 +314,7 @@ namespace CHOVY
|
|||
enable();
|
||||
return;
|
||||
}
|
||||
|
||||
*/
|
||||
// Package LICENSE
|
||||
try
|
||||
{
|
||||
|
@ -266,8 +325,8 @@ namespace CHOVY
|
|||
Directory.CreateDirectory(LicenseWorkDir);
|
||||
File.Copy(RifPath.Text, Path.Combine(LicenseWorkDir, ContentID + ".rif"), true);
|
||||
File.WriteAllText(LicensePathFile, "ux0:pspemu/temp/game/PSP/LICENSE\x00");
|
||||
Directory.CreateDirectory(BackupGameDir);
|
||||
psvimg_create = psvimgtools.PSVIMG_CREATE(Aid, "license", TmpDir, Path.Combine(BackupWorkDir, "license"));
|
||||
/*Directory.CreateDirectory(BackupGameDir);
|
||||
Process psvimg_create = psvimgtools.PSVIMG_CREATE(Aid, "license", TmpDir, Path.Combine(BackupWorkDir, "license"));
|
||||
while (!psvimg_create.HasExited)
|
||||
{
|
||||
Application.DoEvents();
|
||||
|
@ -277,7 +336,7 @@ namespace CHOVY
|
|||
MessageBox.Show("PSVIMG-CREATE.EXE FAILED!\nArguments:\n" + psvimg_create.StartInfo.Arguments + "\nStdOut:\n" + psvimg_create.StandardOutput.ReadToEnd() + "\nStdErr:\n" + psvimg_create.StandardError.ReadToEnd());
|
||||
enable();
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -367,10 +426,7 @@ namespace CHOVY
|
|||
string CmaDir = ccs.GetCmaDir();
|
||||
string CmaAid = ccs.GetCmaAid();
|
||||
string Backup = ccs.GetSelectedBackup();
|
||||
|
||||
ccs.Hide();
|
||||
this.Show();
|
||||
this.Focus();
|
||||
|
||||
WriteSetting("CmaDir", CmaDir);
|
||||
|
||||
if (Backup == "")
|
||||
|
@ -381,6 +437,10 @@ namespace CHOVY
|
|||
string BackupPath = Path.Combine(CmaDir, "PGAME", CmaAid, Backup, "game", "game.psvimg");
|
||||
if(!File.Exists(BackupPath))
|
||||
{
|
||||
MessageBox.Show("Could not find \n" + BackupPath + "\n Perhaps backup failed?", "License Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
ccs.Hide();
|
||||
this.Show();
|
||||
this.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -393,6 +453,10 @@ namespace CHOVY
|
|||
BackupPath = Path.Combine(CmaDir, "PGAME", CmaAid, Backup, "license", "license.psvimg");
|
||||
if (!File.Exists(BackupPath))
|
||||
{
|
||||
MessageBox.Show("Could not find \n"+BackupPath+"\n Perhaps backup failed?","License Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
|
||||
ccs.Hide();
|
||||
this.Show();
|
||||
this.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -419,8 +483,10 @@ namespace CHOVY
|
|||
Versionkey.Text = VerKey;
|
||||
RifPath.Text = Rif;
|
||||
|
||||
Status.Text = "Progress %";
|
||||
TotalProgress.Style = ProgressBarStyle.Continuous;
|
||||
ccs.Hide();
|
||||
this.Show();
|
||||
this.Focus();
|
||||
|
||||
MessageBox.Show("KEYS HAVE BEEN EXTRACTED FROM CMA, YOU MAY NOW LIBERATE YOURSELF", "SUCCESS", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ using System;
|
|||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using static PSVIMGTOOLS.SceIoStat;
|
||||
|
||||
namespace PSVIMGTOOLS
|
||||
|
@ -14,13 +15,42 @@ namespace PSVIMGTOOLS
|
|||
private Random rnd = new Random();
|
||||
private Stream mainStream;
|
||||
private Sha256Digest shaCtx;
|
||||
byte[] blockData;
|
||||
MemoryStream blockStream;
|
||||
private byte[] blockData;
|
||||
private MemoryStream blockStream;
|
||||
private long contentSize = 0;
|
||||
|
||||
|
||||
//async
|
||||
private int blocksWritten = 0;
|
||||
private bool finished = false;
|
||||
|
||||
public Int64 ContentSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return contentSize;
|
||||
}
|
||||
}
|
||||
public Int32 BlocksWritten
|
||||
{
|
||||
get
|
||||
{
|
||||
return blocksWritten;
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean HasFinished
|
||||
{
|
||||
get
|
||||
{
|
||||
return finished;
|
||||
}
|
||||
}
|
||||
|
||||
//Footer
|
||||
private long totalBytes = 0;
|
||||
|
||||
private byte[] aes_ecb_encrypt(byte[] plainText, byte[] IV, byte[] KEY, int size=-1)
|
||||
private byte[] aes_cbc_encrypt(byte[] plainText, byte[] IV, byte[] KEY, int size=-1)
|
||||
{
|
||||
if (size < 0)
|
||||
{
|
||||
|
@ -256,7 +286,7 @@ namespace PSVIMGTOOLS
|
|||
len += PSVIMGConstants.SHA256_BLOCK_SIZE;
|
||||
|
||||
//Get next IV
|
||||
byte[] encryptedBlock = aes_ecb_encrypt(blockData, IV, KEY, len);
|
||||
byte[] encryptedBlock = aes_cbc_encrypt(blockData, IV, KEY, len);
|
||||
for (int i = 0; i < IV.Length; i++)
|
||||
{
|
||||
int encBlockOffset = (encryptedBlock.Length - IV.Length)+i;
|
||||
|
@ -272,7 +302,7 @@ namespace PSVIMGTOOLS
|
|||
return Convert.ToInt32((PSVIMGConstants.PSVIMG_BLOCK_SIZE - blockStream.Position));
|
||||
}
|
||||
|
||||
private void writeBlock(byte[] data)
|
||||
private void writeBlock(byte[] data, bool update=false)
|
||||
{
|
||||
long dLen = data.Length;
|
||||
while (dLen > 0)
|
||||
|
@ -285,7 +315,10 @@ namespace PSVIMGTOOLS
|
|||
dLen -= remaining;
|
||||
finishBlock();
|
||||
startNewBlock();
|
||||
|
||||
if(update)
|
||||
{
|
||||
blocksWritten += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -342,6 +375,28 @@ namespace PSVIMGTOOLS
|
|||
}
|
||||
}
|
||||
|
||||
private void writeStreamAsync(Stream dst)
|
||||
{
|
||||
long numberOfBlocks = dst.Length / PSVIMGConstants.PSVIMG_BLOCK_SIZE;
|
||||
|
||||
while (dst.Position < dst.Length)
|
||||
{
|
||||
byte[] work_buf;
|
||||
Int64 bytes_remain = (dst.Length - dst.Position);
|
||||
if (bytes_remain > 0x10485760)
|
||||
{
|
||||
work_buf = new byte[0x10485760];
|
||||
}
|
||||
else
|
||||
{
|
||||
work_buf = new byte[bytes_remain];
|
||||
}
|
||||
dst.Read(work_buf, 0x00, work_buf.Length);
|
||||
writeBlock(work_buf, true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getFooter()
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
|
@ -355,11 +410,26 @@ namespace PSVIMGTOOLS
|
|||
writeUInt32(ms, 0x00);
|
||||
writeInt64(ms, totalBytes);
|
||||
ms.Seek(0x00, SeekOrigin.Begin);
|
||||
return aes_ecb_encrypt(ms.ToArray(), IV, KEY);
|
||||
return aes_cbc_encrypt(ms.ToArray(), IV, KEY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void AddFileAsync(string FilePath, string ParentPath, string PathRel)
|
||||
{
|
||||
finished = false;
|
||||
new Thread(() =>
|
||||
{
|
||||
long sz = Convert.ToInt64(sceIoStat(FilePath).Size);
|
||||
writeBlock(getHeader(FilePath, ParentPath, PathRel));
|
||||
writeStreamAsync(File.OpenRead(FilePath));
|
||||
writeBlock(getPadding(sz));
|
||||
writeBlock(getTailer());
|
||||
contentSize += sz;
|
||||
finished = true;
|
||||
}).Start();
|
||||
|
||||
}
|
||||
public void AddFile(string FilePath, string ParentPath, string PathRel)
|
||||
{
|
||||
long sz = Convert.ToInt64(sceIoStat(FilePath).Size);
|
||||
|
@ -367,6 +437,7 @@ namespace PSVIMGTOOLS
|
|||
writeStream(File.OpenRead(FilePath));
|
||||
writeBlock(getPadding(sz));
|
||||
writeBlock(getTailer());
|
||||
contentSize += sz;
|
||||
}
|
||||
|
||||
public void AddDir(string DirPath, string ParentPath, string PathRel)
|
||||
|
@ -375,7 +446,7 @@ namespace PSVIMGTOOLS
|
|||
writeBlock(getPadding(0));
|
||||
writeBlock(getTailer());
|
||||
}
|
||||
public void Finish()
|
||||
public long Finish()
|
||||
{
|
||||
finishBlock(true);
|
||||
byte[] footer = getFooter();
|
||||
|
@ -383,11 +454,13 @@ namespace PSVIMGTOOLS
|
|||
|
||||
blockStream.Close();
|
||||
mainStream.Close();
|
||||
return contentSize;
|
||||
}
|
||||
|
||||
public PSVIMGBuilder(Stream dst, byte[] Key)
|
||||
{
|
||||
totalBytes = 0;
|
||||
contentSize = 0;
|
||||
shaCtx = new Sha256Digest();
|
||||
mainStream = dst;
|
||||
KEY = Key;
|
||||
|
|
|
@ -7,10 +7,8 @@ namespace PSVIMGTOOLS
|
|||
{
|
||||
class PSVIMGStream : Stream
|
||||
{
|
||||
|
||||
private Stream baseStream;
|
||||
private MemoryStream blockStream;
|
||||
private long _position = 0;
|
||||
private byte[] key;
|
||||
public Stream BaseStream
|
||||
{
|
||||
|
@ -20,29 +18,6 @@ namespace PSVIMGTOOLS
|
|||
}
|
||||
}
|
||||
|
||||
private long position
|
||||
{
|
||||
get
|
||||
{
|
||||
return _position;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > this.Length)
|
||||
{
|
||||
_position = this.Length;
|
||||
}
|
||||
else if(value < 0)
|
||||
{
|
||||
_position = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_position = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Byte[] Key
|
||||
{
|
||||
get
|
||||
|
@ -122,7 +97,7 @@ namespace PSVIMGTOOLS
|
|||
{
|
||||
get
|
||||
{
|
||||
return position;
|
||||
return baseStream.Position - PSVIMGConstants.AES_BLOCK_SIZE;
|
||||
}
|
||||
set
|
||||
{
|
||||
|
@ -131,94 +106,65 @@ namespace PSVIMGTOOLS
|
|||
|
||||
}
|
||||
|
||||
private bool verifyFooter()
|
||||
{
|
||||
byte[] Footer = new byte[0x10];
|
||||
byte[] IV = new byte[PSVIMGConstants.AES_BLOCK_SIZE];
|
||||
|
||||
baseStream.Seek(baseStream.Length - (Footer.Length + IV.Length), SeekOrigin.Begin);
|
||||
baseStream.Read(IV, 0x00, PSVIMGConstants.AES_BLOCK_SIZE);
|
||||
baseStream.Read(Footer, 0x00, 0x10);
|
||||
|
||||
byte[] FooterDec = aes_ecb_decrypt(Footer, IV);
|
||||
UInt64 FooterLen;
|
||||
using (MemoryStream ms = new MemoryStream(FooterDec))
|
||||
{
|
||||
ms.Seek(0x4, SeekOrigin.Current);
|
||||
ms.Seek(0x4, SeekOrigin.Current);
|
||||
byte[] LenInt = new byte[0x8];
|
||||
ms.Read(LenInt, 0x00, 0x8);
|
||||
FooterLen = BitConverter.ToUInt64(LenInt, 0x00);
|
||||
}
|
||||
if(Convert.ToUInt64(baseStream.Length) == FooterLen)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public PSVIMGStream(Stream file, byte[] KEY)
|
||||
{
|
||||
baseStream = file;
|
||||
key = KEY;
|
||||
if(!verifyFooter())
|
||||
if (!verifyFooter())
|
||||
{
|
||||
throw new Exception("Invalid KEY!");
|
||||
}
|
||||
blockStream = new MemoryStream();
|
||||
this.Seek(0x00, SeekOrigin.Begin);
|
||||
baseStream.Seek(PSVIMGConstants.AES_BLOCK_SIZE, SeekOrigin.Begin);
|
||||
update();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
long totalRead = 0;
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
int remaining = (int)getRemainingBlock();
|
||||
int read = 0;
|
||||
|
||||
if (count < remaining)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
||||
if (this.Position >= this.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
long rem = getRemainingBlock();
|
||||
long totalLeft = (count - totalRead);
|
||||
if (rem < totalLeft)
|
||||
{
|
||||
byte[] remB = new byte[rem];
|
||||
long read = blockStream.Read(remB, 0x00, remB.Length);
|
||||
totalRead += read;
|
||||
ms.Write(remB, 0x00, remB.Length);
|
||||
|
||||
long indx = getBlockIndex() + 1;
|
||||
seekToBlock(indx);
|
||||
update();
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] remB = new byte[totalLeft];
|
||||
long read = blockStream.Read(remB, 0x00, remB.Length);
|
||||
totalRead += read;
|
||||
ms.Write(remB, 0x00, remB.Length);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
ms.Seek(0x00, SeekOrigin.Begin);
|
||||
totalRead = ms.Read(buffer, offset, count);
|
||||
position += totalRead;
|
||||
read += blockStream.Read(buffer, offset, count);
|
||||
baseStream.Seek(count, SeekOrigin.Current);
|
||||
}
|
||||
|
||||
return Convert.ToInt32(totalRead);
|
||||
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();
|
||||
}
|
||||
|
@ -228,24 +174,33 @@ namespace PSVIMGTOOLS
|
|||
long ret = 0;
|
||||
if (origin == SeekOrigin.Begin)
|
||||
{
|
||||
long blockNo = getBlockIndex(offset);
|
||||
seekToBlock(blockNo);
|
||||
update();
|
||||
|
||||
long onwards = offset % blockStream.Length;
|
||||
ret = blockStream.Seek(onwards, SeekOrigin.Begin);
|
||||
position = (baseStream.Position - PSVIMGConstants.AES_BLOCK_SIZE) + BlockPosition;
|
||||
ret = baseStream.Seek(offset + PSVIMGConstants.AES_BLOCK_SIZE, SeekOrigin.Begin);
|
||||
}
|
||||
else if (origin == SeekOrigin.Current)
|
||||
{
|
||||
long currentPos = this.Position;
|
||||
this.Seek(currentPos + offset, SeekOrigin.Begin);
|
||||
long pos = baseStream.Position;
|
||||
if ((pos + offset) >= PSVIMGConstants.AES_BLOCK_SIZE)
|
||||
{
|
||||
ret = baseStream.Seek(offset, SeekOrigin.Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = baseStream.Seek(offset + PSVIMGConstants.AES_BLOCK_SIZE, SeekOrigin.Current);
|
||||
}
|
||||
}
|
||||
else if (origin == SeekOrigin.End)
|
||||
{
|
||||
long len = this.Length;
|
||||
this.Seek(Length + offset, SeekOrigin.Begin);
|
||||
long pos = baseStream.Length;
|
||||
if ((pos + offset) >= PSVIMGConstants.AES_BLOCK_SIZE)
|
||||
{
|
||||
ret = baseStream.Seek(offset, SeekOrigin.End);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = baseStream.Seek(offset + PSVIMGConstants.AES_BLOCK_SIZE, SeekOrigin.End);
|
||||
}
|
||||
}
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -268,44 +223,52 @@ namespace PSVIMGTOOLS
|
|||
baseStream.Dispose();
|
||||
this.Dispose();
|
||||
}
|
||||
|
||||
private void update()
|
||||
{
|
||||
long offset = (this.Position % PSVIMGConstants.FULL_PSVIMG_SIZE);
|
||||
long blockIndex = getBlockIndex();
|
||||
byte[] decryptedBlock = getBlock(blockIndex);
|
||||
|
||||
blockStream.Dispose();
|
||||
blockStream = new MemoryStream(decryptedBlock, 0x00, decryptedBlock.Length);
|
||||
blockStream.Write(decryptedBlock, 0x00, decryptedBlock.Length);
|
||||
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 pos = -1)
|
||||
private long getBlockIndex()
|
||||
{
|
||||
long blockOffset = 0;
|
||||
long blockEnd = blockOffset + PSVIMGConstants.FULL_PSVIMG_SIZE;
|
||||
long blockIndex = 0;
|
||||
if (pos < 0)
|
||||
{
|
||||
pos = this.Position;
|
||||
}
|
||||
while (blockOffset < this.Length)
|
||||
{
|
||||
blockOffset = (blockIndex * PSVIMGConstants.FULL_PSVIMG_SIZE);
|
||||
blockEnd = blockOffset + PSVIMGConstants.FULL_PSVIMG_SIZE;
|
||||
long i = 0;
|
||||
long curPos = baseStream.Position;
|
||||
long fullBlock;
|
||||
long blockOffset;
|
||||
|
||||
|
||||
if (pos >= blockOffset && pos < blockEnd)
|
||||
while (true)
|
||||
{
|
||||
blockOffset = (i * PSVIMGConstants.FULL_PSVIMG_SIZE) + PSVIMGConstants.AES_BLOCK_SIZE;
|
||||
long remaining = getRemainingBase();
|
||||
if (remaining < PSVIMGConstants.FULL_PSVIMG_SIZE)
|
||||
{
|
||||
return blockIndex;
|
||||
fullBlock = blockOffset + remaining;
|
||||
}
|
||||
blockIndex++;
|
||||
else
|
||||
{
|
||||
fullBlock = blockOffset + PSVIMGConstants.FULL_PSVIMG_SIZE;
|
||||
}
|
||||
if ((curPos >= blockOffset) && (curPos < fullBlock))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (blockOffset > baseStream.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
throw new Exception("Not found somehow..");
|
||||
}
|
||||
return i;
|
||||
|
||||
|
||||
}
|
||||
private long getRemainingBase()
|
||||
{
|
||||
return baseStream.Length - baseStream.Position;
|
||||
|
@ -322,7 +285,7 @@ namespace PSVIMGTOOLS
|
|||
baseStream.Read(iv, 0x00, iv.Length);
|
||||
return iv;
|
||||
}
|
||||
private byte[] aes_ecb_decrypt(byte[] cipherData, byte[] IV)
|
||||
private byte[] aes_cbc_decrypt(byte[] cipherData, byte[] IV)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
Aes alg = Aes.Create();
|
||||
|
@ -341,14 +304,47 @@ namespace PSVIMGTOOLS
|
|||
|
||||
private void seekToBlock(long blockIndex)
|
||||
{
|
||||
long blockOffset = (blockIndex * PSVIMGConstants.FULL_PSVIMG_SIZE) + PSVIMGConstants.AES_BLOCK_SIZE;
|
||||
long blockOffset;
|
||||
blockOffset = (blockIndex * PSVIMGConstants.FULL_PSVIMG_SIZE) + PSVIMGConstants.AES_BLOCK_SIZE;
|
||||
|
||||
if (blockOffset > baseStream.Length)
|
||||
{
|
||||
blockOffset = baseStream.Length;
|
||||
}
|
||||
|
||||
|
||||
baseStream.Seek(blockOffset, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
private bool verifyFooter()
|
||||
{
|
||||
byte[] Footer = new byte[0x10];
|
||||
byte[] IV = new byte[PSVIMGConstants.AES_BLOCK_SIZE];
|
||||
|
||||
baseStream.Seek(baseStream.Length - (Footer.Length + IV.Length), SeekOrigin.Begin);
|
||||
baseStream.Read(IV, 0x00, PSVIMGConstants.AES_BLOCK_SIZE);
|
||||
baseStream.Read(Footer, 0x00, 0x10);
|
||||
|
||||
byte[] FooterDec = aes_cbc_decrypt(Footer, IV);
|
||||
UInt64 FooterLen;
|
||||
using (MemoryStream ms = new MemoryStream(FooterDec))
|
||||
{
|
||||
ms.Seek(0x4, SeekOrigin.Current);
|
||||
ms.Seek(0x4, SeekOrigin.Current);
|
||||
byte[] LenInt = new byte[0x8];
|
||||
ms.Read(LenInt, 0x00, 0x8);
|
||||
FooterLen = BitConverter.ToUInt64(LenInt, 0x00);
|
||||
}
|
||||
if (Convert.ToUInt64(baseStream.Length) == FooterLen)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getBlock(long blockIndex)
|
||||
{
|
||||
byte[] iv = getIV(blockIndex);
|
||||
|
@ -362,9 +358,11 @@ namespace PSVIMGTOOLS
|
|||
{
|
||||
encryptedBlock = new byte[remaining];
|
||||
}
|
||||
baseStream.Read(encryptedBlock, 0x00, encryptedBlock.Length);
|
||||
byte[] decryptedBlock = aes_ecb_decrypt(encryptedBlock, iv);
|
||||
|
||||
|
||||
baseStream.Read(encryptedBlock, 0x00, encryptedBlock.Length);
|
||||
byte[] decryptedBlock = aes_cbc_decrypt(encryptedBlock, iv);
|
||||
return decryptedBlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
using Ionic.Zlib;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
namespace PSVIMGTOOLS
|
||||
{
|
||||
class PSVMDBuilder
|
||||
{
|
||||
private static void memset(byte[] buf, byte content, long length)
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
buf[i] = content;
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeUInt64(Stream dst, UInt64 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x8);
|
||||
}
|
||||
private static void writeInt64(Stream dst, Int64 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x8);
|
||||
}
|
||||
private static void writeUInt16(Stream dst, UInt16 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x2);
|
||||
}
|
||||
private static void writeInt16(Stream dst, Int16 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x2);
|
||||
}
|
||||
|
||||
private static void writeInt32(Stream dst, Int32 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x4);
|
||||
}
|
||||
private static void writeUInt32(Stream dst, UInt32 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x4);
|
||||
}
|
||||
|
||||
|
||||
private static void writeString(Stream dst, string str, int len = -1)
|
||||
{
|
||||
if (len < 0)
|
||||
{
|
||||
len = str.Length;
|
||||
}
|
||||
|
||||
byte[] StrBytes = Encoding.UTF8.GetBytes(str);
|
||||
dst.Write(StrBytes, 0x00, len);
|
||||
}
|
||||
|
||||
private static void writePadding(Stream dst, byte paddingByte, long paddingLen)
|
||||
{
|
||||
byte[] paddingData = new byte[paddingLen];
|
||||
memset(paddingData, paddingByte, paddingLen);
|
||||
dst.Write(paddingData, 0x00, paddingData.Length);
|
||||
}
|
||||
private static void writeStringWithPadding(Stream dst, string str, int padSize, byte padByte = 0x78)
|
||||
{
|
||||
int StrLen = str.Length;
|
||||
if (StrLen > padSize)
|
||||
{
|
||||
StrLen = padSize;
|
||||
}
|
||||
|
||||
int PaddingLen = (padSize - StrLen) - 1;
|
||||
writeString(dst, str, StrLen);
|
||||
dst.WriteByte(0x00);
|
||||
writePadding(dst, padByte, PaddingLen);
|
||||
}
|
||||
|
||||
private static byte[] aes_cbc_decrypt(byte[] cipherData, byte[] IV, byte[] Key)
|
||||
{
|
||||
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 static byte[] aes_cbc_encrypt(byte[] plainText, byte[] IV, byte[] KEY, int size = -1)
|
||||
{
|
||||
if (size < 0)
|
||||
{
|
||||
size = plainText.Length;
|
||||
}
|
||||
|
||||
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.CreateEncryptor(), CryptoStreamMode.Write);
|
||||
cs.Write(plainText, 0, size);
|
||||
cs.Close();
|
||||
byte[] cipherText = ms.ToArray();
|
||||
return cipherText;
|
||||
}
|
||||
|
||||
|
||||
public static void CreatePsvmd(Stream OutputStream, Stream EncryptedPsvimg, long ContentSize, string BackupType,byte[] Key)
|
||||
{
|
||||
byte[] IV = new byte[PSVIMGConstants.AES_BLOCK_SIZE];
|
||||
EncryptedPsvimg.Seek(0x00, SeekOrigin.Begin);
|
||||
EncryptedPsvimg.Read(IV, 0x00, IV.Length);
|
||||
MemoryStream ms = new MemoryStream();
|
||||
|
||||
writeUInt32(ms, 0xFEE1900D); // magic
|
||||
writeUInt32(ms, 0x2); // type
|
||||
writeUInt64(ms, 0x03000000); // fw ver
|
||||
ms.Write(new byte[0x10], 0x00, 0x10); // PSID
|
||||
writeStringWithPadding(ms, BackupType, 0x40, 0x00); //backup type
|
||||
writeInt64(ms, EncryptedPsvimg.Length); // total size
|
||||
writeUInt32(ms, 0x2); //version
|
||||
writeInt64(ms, ContentSize); // content size
|
||||
ms.Write(IV, 0x00, IV.Length); // IV
|
||||
writeInt64(ms, 0x00); //ux0 info
|
||||
writeInt64(ms, 0x00); //ur0 info
|
||||
writeInt64(ms, 0x00); //unused 98
|
||||
writeInt64(ms, 0x00); //unused A0
|
||||
writeUInt32(ms, 0x1); //add data
|
||||
|
||||
ms.Seek(0x00, SeekOrigin.Begin);
|
||||
byte[] psvMd = ms.ToArray();
|
||||
|
||||
ms.Close();
|
||||
|
||||
ms = new MemoryStream();
|
||||
byte[] psvMdCompressed = ZlibStream.CompressBuffer(psvMd);
|
||||
psvMdCompressed[0x1] = 0x9C;
|
||||
ms.Write(psvMdCompressed, 0x00, psvMdCompressed.Length);
|
||||
|
||||
SHA256 sha = SHA256.Create();
|
||||
byte[] shadata = sha.ComputeHash(psvMdCompressed);
|
||||
ms.Write(shadata, 0x00, shadata.Length);
|
||||
|
||||
writeInt32(ms, 0x00);
|
||||
writeUInt32(ms, 0x00);
|
||||
writeInt64(ms, ms.Length+0x8);
|
||||
ms.Seek(0x00, SeekOrigin.Begin);
|
||||
byte[] toEncrypt = ms.ToArray();
|
||||
ms.Close();
|
||||
|
||||
byte[] EncryptedData = aes_cbc_encrypt(toEncrypt, IV, Key);
|
||||
OutputStream.Write(IV, 0x00, IV.Length);
|
||||
OutputStream.Write(EncryptedData, 0x00, toEncrypt.Length);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
public static byte[] DecryptPsvmd(Stream PsvMdFile, byte[] Key)
|
||||
{
|
||||
byte[] IV = new byte[PSVIMGConstants.AES_BLOCK_SIZE];
|
||||
PsvMdFile.Read(IV, 0x00, IV.Length);
|
||||
byte[] remaining = new byte[PsvMdFile.Length - IV.Length];
|
||||
PsvMdFile.Read(remaining, 0x00, remaining.Length);
|
||||
byte[] zlibCompressed = aes_cbc_decrypt(remaining, IV, Key);
|
||||
return zlibCompressed;
|
||||
// return ZlibStream.UncompressBuffer(zlibCompressed);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,28 +13,8 @@ namespace CHOVY
|
|||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
/*
|
||||
|
||||
FileStream fs = File.OpenWrite(@"C:\Users\earsy\Documents\Visual Studio 2017\Projects\CSharpImgTools\CSharpImgTools\bin\Debug\test.psvimg");
|
||||
PSVIMGBuilder psvBuild = new PSVIMGBuilder(fs, CmaKeys.GenerateKey(new byte[] { 0xcf, 0x61, 0x85, 0xd5, 0xa7, 0x87, 0x0c, 0x4a }));
|
||||
psvBuild.AddFile(@"C:\Users\earsy\Documents\Visual Studio 2017\Projects\CSharpImgTools\CSharpImgTools\bin\Debug\EBOOT.PBP", @"ux0:temp/game/PCSG90096/app/PCSG90096", @"/EBOOT.PBP");
|
||||
psvBuild.AddDir(@"C:\Users\earsy\Documents\Visual Studio 2017\Projects\CSharpImgTools\CSharpImgTools\bin\Debug", @"ux0:temp/game/PCSG90096/app/PCSG90096", @"/sce_sys");
|
||||
psvBuild.AddFile(@"C:\Users\earsy\Documents\Visual Studio 2017\Projects\CSharpImgTools\CSharpImgTools\bin\Debug\param.sfo", @"ux0:temp/game/PCSG90096/app/PCSG90096", @"/sce_sys/param.sfo");
|
||||
psvBuild.Finish();
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
FileStream fs2 = File.OpenRead(@"C:\Users\earsy\Documents\Visual Studio 2017\Projects\CSharpImgTools\CSharpImgTools\bin\Debug\test.psvimg");
|
||||
fs2.CopyTo(ms);
|
||||
fs2.Close();
|
||||
ms.Seek(0x00, SeekOrigin.Begin);
|
||||
FileStream fs3 = File.OpenWrite(@"C:\Users\earsy\Documents\Visual Studio 2017\Projects\CSharpImgTools\CSharpImgTools\bin\Debug\test.psvimgd");
|
||||
PSVIMGStream psv = new PSVIMGStream(ms, CmaKeys.GenerateKey(new byte[] { 0xcf, 0x61, 0x85, 0xd5, 0xa7, 0x87, 0x0c, 0x4a }));
|
||||
psv.CopyTo(fs3);
|
||||
fs3.Close();
|
||||
psv.Close();
|
||||
*/
|
||||
|
||||
|
||||
FileStream psvmd = File.OpenRead(@"C:\Users\earsy\Documents\PS Vita\PGAME\cf6185d5a7870c4a\UCES00304\game\game.psvmd");
|
||||
//File.WriteAllBytes(@"C:\Users\earsy\Documents\PS Vita\PGAME\cf6185d5a7870c4a\UCES00304\game\game.psvmdi", PSVMDBuilder.DecryptPsvmd(psvmd, CmaKeys.GenerateKey(new byte[] { 0xcf, 0x61, 0x85, 0xd5, 0xa7, 0x87, 0x0c, 0x4a })));
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new CHOVY());
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
<packages>
|
||||
<package id="BouncyCastle" version="1.8.5" targetFramework="net45" />
|
||||
<package id="Discutils" version="0.11.0.2" targetFramework="net452" />
|
||||
<package id="DotNetZip" version="1.13.4" targetFramework="net46" />
|
||||
</packages>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue