This commit is contained in:
parent
9d698dc492
commit
ead7745626
|
@ -5,7 +5,7 @@
|
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D46AA2C2-2BDC-45C7-ACA5-D7A2295564E8}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>CHOVY</RootNamespace>
|
||||
<AssemblyName>CHOVY-SIGN</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
|
@ -34,13 +34,13 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'CHOVY|AnyCPU'">
|
||||
<OutputPath>bin\CHOVY\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BouncyCastle.Crypto, Version=1.8.5.0, Culture=neutral, PublicKeyToken=0e99375e54769942">
|
||||
<HintPath>..\packages\BouncyCastle.1.8.5\lib\BouncyCastle.Crypto.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DiscUtils, Version=0.11.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Discutils.0.11.0.2\lib\net40\DiscUtils.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -77,8 +77,10 @@
|
|||
<Compile Include="pbp.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="PSVIMGReader.cs" />
|
||||
<Compile Include="PSVIMGBuilder.cs" />
|
||||
<Compile Include="PSVIMGFileStream.cs" />
|
||||
<Compile Include="PSVIMGStream.cs" />
|
||||
<Compile Include="PSVIMGStructs.cs" />
|
||||
<Compile Include="psvimgtools.cs" />
|
||||
<EmbeddedResource Include="CHOVY.resx">
|
||||
<DependentUpon>CHOVY.cs</DependentUpon>
|
||||
|
|
|
@ -13,8 +13,6 @@ using System.Windows.Forms;
|
|||
|
||||
namespace CHOVY
|
||||
{
|
||||
|
||||
|
||||
public partial class CHOVY : Form
|
||||
{
|
||||
bool MutedAudio = false;
|
||||
|
@ -78,7 +76,7 @@ namespace CHOVY
|
|||
{
|
||||
|
||||
RegistryKey key;
|
||||
key = Registry.CurrentUser.CreateSubKey(@"Software\CHOVY");
|
||||
key = Registry.CurrentUser.CreateSubKey(@"Software\CHOVYProject\Chovy-Sign");
|
||||
Value = key.GetValue(Setting).ToString();
|
||||
key.Close();
|
||||
}
|
||||
|
@ -90,9 +88,8 @@ namespace CHOVY
|
|||
{
|
||||
try
|
||||
{
|
||||
|
||||
RegistryKey key;
|
||||
key = Registry.CurrentUser.CreateSubKey(@"Software\CHOVY");
|
||||
key = Registry.CurrentUser.CreateSubKey(@"Software\CHOVYProject\Chovy-Sign");
|
||||
key.SetValue(Setting, Value);
|
||||
key.Close();
|
||||
}
|
||||
|
@ -317,49 +314,44 @@ namespace CHOVY
|
|||
this.Hide();
|
||||
string cmaDir = "";
|
||||
string accountId = "0000000000000000";
|
||||
|
||||
try
|
||||
{
|
||||
cmaDir = ReadSetting("CmaDir");
|
||||
//try qcma
|
||||
cmaDir = Registry.CurrentUser.OpenSubKey(@"Software\codestation\qcma").GetValue("appsPath").ToString();
|
||||
accountId = Registry.CurrentUser.OpenSubKey(@"Software\codestation\qcma").GetValue("lastAccountId").ToString();
|
||||
}
|
||||
catch(Exception)
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
//try qcma
|
||||
cmaDir = Registry.CurrentUser.OpenSubKey(@"Software\codestation\qcma").GetValue("appsPath").ToString();
|
||||
accountId = Registry.CurrentUser.OpenSubKey(@"Software\codestation\qcma").GetValue("lastAccountId").ToString();
|
||||
//try sony cma
|
||||
cmaDir = Registry.CurrentUser.OpenSubKey(@"Software\Sony Corporation\Content Manager Assistant\Settings").GetValue("ApplicationHomePath").ToString();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
//try sony cma
|
||||
cmaDir = Registry.CurrentUser.OpenSubKey(@"Software\Sony Corporation\Content Manager Assistant\Settings").GetValue("ApplicationHomePath").ToString();
|
||||
//try devkit cma
|
||||
cmaDir = Registry.CurrentUser.OpenSubKey(@"Software\SCE\PSP2\Services\Content Manager Assistant for PlayStation(R)Vita DevKit\Settings").GetValue("ApplicationHomePath").ToString();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
//try devkit cma
|
||||
cmaDir = Registry.CurrentUser.OpenSubKey(@"Software\SCE\PSP2\Services\Content Manager Assistant for PlayStation(R)Vita DevKit\Settings").GetValue("ApplicationHomePath").ToString();
|
||||
string DefaultDir = Path.Combine(Environment.GetEnvironmentVariable("HOMEDRIVE"), Environment.GetEnvironmentVariable("HOMEPATH"), "Documents", "PS Vita");
|
||||
if (Directory.Exists(DefaultDir))
|
||||
{
|
||||
cmaDir = DefaultDir;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
string DefaultDir = Path.Combine(Environment.GetEnvironmentVariable("HOMEDRIVE"), Environment.GetEnvironmentVariable("HOMEPATH"), "Documents", "PS Vita");
|
||||
if (Directory.Exists(DefaultDir))
|
||||
{
|
||||
cmaDir = DefaultDir;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
//Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -379,6 +371,7 @@ namespace CHOVY
|
|||
ccs.Hide();
|
||||
this.Show();
|
||||
this.Focus();
|
||||
WriteSetting("CmaDir", CmaDir);
|
||||
|
||||
if (Backup == "")
|
||||
{
|
||||
|
@ -414,9 +407,7 @@ namespace CHOVY
|
|||
|
||||
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.WriteToFile(Rif);
|
||||
|
||||
LicenseRif.Close();
|
||||
LicensePsvimg.Close();
|
||||
|
@ -424,7 +415,6 @@ namespace CHOVY
|
|||
GamePsvimg.Close();
|
||||
|
||||
WriteSetting("RifPath", Rif);
|
||||
WriteSetting("CmaDir", CmaDir);
|
||||
|
||||
Versionkey.Text = VerKey;
|
||||
RifPath.Text = Rif;
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace CHOVY
|
|||
{
|
||||
public partial class CHOVYCmaSelector : Form
|
||||
{
|
||||
public CHOVYCmaSelector(string CMA="",string AID="")
|
||||
public CHOVYCmaSelector(string CMA = "", string AID = "")
|
||||
{
|
||||
InitializeComponent();
|
||||
CMADir.Text = CMA;
|
||||
|
@ -20,7 +20,7 @@ namespace CHOVY
|
|||
{
|
||||
return BackupList.Text.Substring(0, 9);
|
||||
}
|
||||
catch(Exception)
|
||||
catch (Exception)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ namespace CHOVY
|
|||
{
|
||||
return AIDSelector.Text;
|
||||
}
|
||||
|
||||
|
||||
private void UpdateAidList()
|
||||
{
|
||||
AIDSelector.Items.Clear();
|
||||
|
@ -71,7 +71,7 @@ namespace CHOVY
|
|||
string BackupName = (Path.GetFileName(Dir) + " - " + Title);
|
||||
BackupList.Items.Add(BackupName);
|
||||
}
|
||||
catch(Exception)
|
||||
catch (Exception)
|
||||
{
|
||||
BackupList.Items.Add(Path.GetFileName(Dir));
|
||||
}
|
||||
|
@ -107,4 +107,4 @@ namespace CHOVY
|
|||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,402 @@
|
|||
using Org.BouncyCastle.Crypto.Digests;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using static PSVIMGTOOLS.SceIoStat;
|
||||
|
||||
namespace PSVIMGTOOLS
|
||||
{
|
||||
class PSVIMGBuilder
|
||||
{
|
||||
private byte[] IV = new byte[0x10];
|
||||
private byte[] KEY;
|
||||
private Random rnd = new Random();
|
||||
private Stream mainStream;
|
||||
private Sha256Digest shaCtx;
|
||||
byte[] blockData;
|
||||
MemoryStream blockStream;
|
||||
|
||||
//Footer
|
||||
private long totalBytes = 0;
|
||||
|
||||
private byte[] aes_ecb_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;
|
||||
}
|
||||
|
||||
private void writeUInt64(Stream dst,UInt64 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x8);
|
||||
}
|
||||
private void writeInt64(Stream dst,Int64 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x8);
|
||||
}
|
||||
private void writeUInt16(Stream dst, UInt16 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x2);
|
||||
}
|
||||
private void writeInt16(Stream dst, Int16 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x2);
|
||||
}
|
||||
|
||||
private void writeInt32(Stream dst, Int32 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x4);
|
||||
}
|
||||
private void writeUInt32(Stream dst, UInt32 value)
|
||||
{
|
||||
byte[] ValueBytes = BitConverter.GetBytes(value);
|
||||
dst.Write(ValueBytes, 0x00, 0x4);
|
||||
}
|
||||
|
||||
private SceDateTime dateTimeToSceDateTime(DateTime dt)
|
||||
{
|
||||
SceDateTime sdt = new SceDateTime();
|
||||
sdt.Day = Convert.ToUInt16(dt.Day);
|
||||
sdt.Month = Convert.ToUInt16(dt.Month);
|
||||
sdt.Year = Convert.ToUInt16(dt.Year);
|
||||
|
||||
|
||||
sdt.Hour = Convert.ToUInt16(dt.Hour);
|
||||
sdt.Minute = Convert.ToUInt16(dt.Minute);
|
||||
sdt.Second = Convert.ToUInt16(dt.Second);
|
||||
sdt.Microsecond = Convert.ToUInt32(dt.Millisecond * 1000);
|
||||
return sdt;
|
||||
}
|
||||
|
||||
private SceIoStat sceIoStat(string path)
|
||||
{
|
||||
SceIoStat stats = new SceIoStat();
|
||||
FileAttributes attrbutes = File.GetAttributes(path);
|
||||
|
||||
if (attrbutes.HasFlag(FileAttributes.Directory))
|
||||
{
|
||||
stats.Mode |= Modes.Directory;
|
||||
stats.Attributes |= AttributesEnum.Directory;
|
||||
stats.Size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
stats.Mode |= Modes.File;
|
||||
stats.Attributes |= AttributesEnum.File;
|
||||
stats.Size = Convert.ToUInt64(new FileInfo(path).Length);
|
||||
|
||||
}
|
||||
|
||||
if(attrbutes.HasFlag(FileAttributes.ReadOnly))
|
||||
{
|
||||
stats.Mode |= Modes.GroupRead;
|
||||
stats.Mode |= Modes.GroupExecute;
|
||||
|
||||
stats.Mode |= Modes.OthersExecute;
|
||||
stats.Mode |= Modes.OthersRead;
|
||||
|
||||
stats.Mode |= Modes.UserRead;
|
||||
stats.Mode |= Modes.UserExecute;
|
||||
|
||||
stats.Attributes |= AttributesEnum.Read;
|
||||
stats.Attributes |= AttributesEnum.Execute;
|
||||
}
|
||||
else
|
||||
{
|
||||
stats.Mode |= Modes.GroupRead;
|
||||
stats.Mode |= Modes.GroupExecute;
|
||||
stats.Mode |= Modes.GroupWrite;
|
||||
|
||||
stats.Mode |= Modes.OthersExecute;
|
||||
stats.Mode |= Modes.OthersRead;
|
||||
stats.Mode |= Modes.OthersWrite;
|
||||
|
||||
stats.Mode |= Modes.UserRead;
|
||||
stats.Mode |= Modes.UserExecute;
|
||||
stats.Mode |= Modes.UserWrite;
|
||||
|
||||
stats.Attributes |= AttributesEnum.Read;
|
||||
stats.Attributes |= AttributesEnum.Write;
|
||||
stats.Attributes |= AttributesEnum.Execute;
|
||||
}
|
||||
|
||||
stats.CreationTime = dateTimeToSceDateTime(File.GetCreationTimeUtc(path));
|
||||
stats.AccessTime = dateTimeToSceDateTime(File.GetLastAccessTimeUtc(path));
|
||||
stats.ModificaionTime = dateTimeToSceDateTime(File.GetLastWriteTimeUtc(path));
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
private void writeSceDateTime(Stream dst,SceDateTime time)
|
||||
{
|
||||
writeUInt16(dst, time.Year);
|
||||
writeUInt16(dst, time.Month);
|
||||
writeUInt16(dst, time.Day);
|
||||
|
||||
writeUInt16(dst, time.Hour);
|
||||
writeUInt16(dst, time.Minute);
|
||||
writeUInt16(dst, time.Second);
|
||||
writeUInt32(dst, time.Microsecond);
|
||||
}
|
||||
|
||||
private void writeSceIoStat(Stream dst, SceIoStat stats)
|
||||
{
|
||||
writeUInt32(dst, Convert.ToUInt32(stats.Mode));
|
||||
writeUInt32(dst, Convert.ToUInt32(stats.Attributes));
|
||||
writeUInt64(dst, stats.Size);
|
||||
writeSceDateTime(dst, stats.CreationTime);
|
||||
writeSceDateTime(dst, stats.AccessTime);
|
||||
writeSceDateTime(dst, stats.ModificaionTime);
|
||||
foreach(UInt32 i in stats.Private)
|
||||
{
|
||||
writeUInt32(dst,i);
|
||||
}
|
||||
}
|
||||
|
||||
private void memset(byte[] buf, byte content, long length)
|
||||
{
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
buf[i] = content;
|
||||
}
|
||||
}
|
||||
|
||||
private 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 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 void writePadding(Stream dst, byte paddingByte, long paddingLen)
|
||||
{
|
||||
byte[] paddingData = new byte[paddingLen];
|
||||
memset(paddingData, paddingByte, paddingLen);
|
||||
dst.Write(paddingData, 0x00, paddingData.Length);
|
||||
}
|
||||
private byte[] getHeader(string FilePath, string ParentPath, string PathRel)
|
||||
{
|
||||
using (MemoryStream Header = new MemoryStream())
|
||||
{
|
||||
writeInt64(Header, DateTime.UtcNow.Ticks); // SysTime
|
||||
writeInt64(Header, 0); // Flags
|
||||
writeSceIoStat(Header, sceIoStat(FilePath));
|
||||
writeStringWithPadding(Header, ParentPath, 256); // Parent Path
|
||||
writeUInt32(Header, 1); //unk_16C
|
||||
writeStringWithPadding(Header, PathRel, 256); //Relative Path
|
||||
writePadding(Header, 0x78, 904); //'x'
|
||||
writeString(Header, PSVIMGConstants.PSVIMG_HEADER_END); //EndOfHeader
|
||||
Header.Seek(0x00, SeekOrigin.Begin);
|
||||
return Header.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private void startNewBlock()
|
||||
{
|
||||
blockData = new byte[PSVIMGConstants.FULL_PSVIMG_SIZE];
|
||||
blockStream = new MemoryStream(blockData, 0x00, PSVIMGConstants.FULL_PSVIMG_SIZE);
|
||||
}
|
||||
|
||||
|
||||
private byte[] shaBlock(int length = PSVIMGConstants.PSVIMG_BLOCK_SIZE,bool final=false)
|
||||
{
|
||||
byte[] outbytes = new byte[PSVIMGConstants.SHA256_BLOCK_SIZE];
|
||||
shaCtx.BlockUpdate(blockData, 0x00, length);
|
||||
Sha256Digest shaTmp = (Sha256Digest)shaCtx.Copy();
|
||||
shaTmp.DoFinal(outbytes,0x00);
|
||||
return outbytes;
|
||||
}
|
||||
|
||||
private void finishBlock(bool final = false)
|
||||
{
|
||||
int len = Convert.ToInt32(blockStream.Position);
|
||||
byte[] shaBytes = shaBlock(len, final);
|
||||
blockStream.Write(shaBytes, 0x00, PSVIMGConstants.SHA256_BLOCK_SIZE);
|
||||
blockStream.Close();
|
||||
len += PSVIMGConstants.SHA256_BLOCK_SIZE;
|
||||
|
||||
//Get next IV
|
||||
byte[] encryptedBlock = aes_ecb_encrypt(blockData, IV, KEY, len);
|
||||
for (int i = 0; i < IV.Length; i++)
|
||||
{
|
||||
int encBlockOffset = (encryptedBlock.Length - IV.Length)+i;
|
||||
IV[i] = encryptedBlock[encBlockOffset];
|
||||
}
|
||||
|
||||
mainStream.Write(encryptedBlock, 0x00, encryptedBlock.Length);
|
||||
totalBytes += encryptedBlock.Length;
|
||||
}
|
||||
|
||||
private int remainingBlockSize()
|
||||
{
|
||||
return Convert.ToInt32((PSVIMGConstants.PSVIMG_BLOCK_SIZE - blockStream.Position));
|
||||
}
|
||||
|
||||
private void writeBlock(byte[] data)
|
||||
{
|
||||
long dLen = data.Length;
|
||||
while (dLen > 0)
|
||||
{
|
||||
int remaining = remainingBlockSize();
|
||||
|
||||
if (dLen > remaining)
|
||||
{
|
||||
blockStream.Write(data, 0x00, remaining);
|
||||
dLen -= remaining;
|
||||
finishBlock();
|
||||
startNewBlock();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
blockStream.Write(data, 0x00, Convert.ToInt32(dLen));
|
||||
dLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private byte[] getPadding(long size)
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
long paddingSize = PSVIMGPadding.GetPadding(size);
|
||||
if(paddingSize != 0)
|
||||
{
|
||||
writePadding(ms, 0x2B, paddingSize-PSVIMGConstants.PSVIMG_PADDING_END.Length);
|
||||
writeString(ms, PSVIMGConstants.PSVIMG_PADDING_END);
|
||||
}
|
||||
ms.Seek(0x00, SeekOrigin.Begin);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getTailer()
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
writeUInt64(ms, 0x00);
|
||||
writePadding(ms, 0x7a, 1004);
|
||||
writeString(ms, PSVIMGConstants.PSVIMG_TAILOR_END);
|
||||
|
||||
ms.Seek(0x00, SeekOrigin.Begin);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeStream(Stream dst)
|
||||
{
|
||||
while(dst.Position < dst.Length)
|
||||
{
|
||||
byte[] work_buf;
|
||||
Int64 bytes_remain = (dst.Length - dst.Position);
|
||||
if (bytes_remain > 0x8388608)
|
||||
{
|
||||
work_buf = new byte[0x8388608];
|
||||
}
|
||||
else
|
||||
{
|
||||
work_buf = new byte[bytes_remain];
|
||||
}
|
||||
dst.Read(work_buf, 0x00, work_buf.Length);
|
||||
writeBlock(work_buf);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getFooter()
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
// uint sz = Convert.ToUInt32(totalBytes & (PSVIMGConstants.AES_BLOCK_SIZE - 1));
|
||||
// int paddingInt = Convert.ToInt32(PSVIMGConstants.AES_BLOCK_SIZE - (sz & (PSVIMGConstants.AES_BLOCK_SIZE - 1)));
|
||||
|
||||
totalBytes += 0x10; //number of bytes used by this footer.
|
||||
|
||||
writeInt32(ms, 0x00); // int padding (idk wht this is)
|
||||
writeUInt32(ms, 0x00);
|
||||
writeInt64(ms, totalBytes);
|
||||
ms.Seek(0x00, SeekOrigin.Begin);
|
||||
return aes_ecb_encrypt(ms.ToArray(), IV, KEY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void AddFile(string FilePath, string ParentPath, string PathRel)
|
||||
{
|
||||
long sz = Convert.ToInt64(sceIoStat(FilePath).Size);
|
||||
writeBlock(getHeader(FilePath, ParentPath, PathRel));
|
||||
writeStream(File.OpenRead(FilePath));
|
||||
writeBlock(getPadding(sz));
|
||||
writeBlock(getTailer());
|
||||
}
|
||||
|
||||
public void AddDir(string DirPath, string ParentPath, string PathRel)
|
||||
{
|
||||
writeBlock(getHeader(DirPath, ParentPath, PathRel));
|
||||
writeBlock(getPadding(0));
|
||||
writeBlock(getTailer());
|
||||
}
|
||||
public void Finish()
|
||||
{
|
||||
finishBlock(true);
|
||||
byte[] footer = getFooter();
|
||||
mainStream.Write(footer, 0x00, footer.Length);
|
||||
|
||||
blockStream.Close();
|
||||
mainStream.Close();
|
||||
}
|
||||
|
||||
public PSVIMGBuilder(Stream dst, byte[] Key)
|
||||
{
|
||||
totalBytes = 0;
|
||||
shaCtx = new Sha256Digest();
|
||||
mainStream = dst;
|
||||
KEY = Key;
|
||||
|
||||
rnd.NextBytes(IV);
|
||||
mainStream.Write(IV, 0x00, IV.Length);
|
||||
totalBytes += IV.Length;
|
||||
|
||||
startNewBlock();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,122 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static PSVIMGTOOLS.SceIoStat;
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
|
@ -131,6 +18,36 @@ namespace PSVIMGTOOLS
|
|||
psvStream = psv;
|
||||
findFile(Path);
|
||||
}
|
||||
|
||||
public void WriteToFile(string FilePath)
|
||||
{
|
||||
using (FileStream fs = File.OpenWrite(FilePath))
|
||||
{
|
||||
fs.SetLength(0);
|
||||
int written = 0;
|
||||
long left = (length - written);
|
||||
byte[] work_buf;
|
||||
this.Seek(0x00, SeekOrigin.Begin);
|
||||
while (left > 0)
|
||||
{
|
||||
left = (length - written);
|
||||
if (left < 0x10000)
|
||||
{
|
||||
work_buf = new byte[left];
|
||||
}
|
||||
else
|
||||
{
|
||||
work_buf = new byte[0x10000];
|
||||
}
|
||||
this.Read(work_buf, 0x00, work_buf.Length);
|
||||
fs.Write(work_buf, 0x00, work_buf.Length);
|
||||
written += work_buf.Length;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public override bool CanRead
|
||||
{
|
||||
get
|
||||
|
@ -185,7 +102,7 @@ namespace PSVIMGTOOLS
|
|||
int read = 0;
|
||||
while(true)
|
||||
{
|
||||
int remainBlock = Convert.ToInt32(psvStream.BlockRemaining - psvStream.SHA256_BLOCK_SIZE);
|
||||
int remainBlock = Convert.ToInt32(psvStream.BlockRemaining - PSVIMGConstants.SHA256_BLOCK_SIZE);
|
||||
int remainRead = count - read;
|
||||
|
||||
if (remainRead < remainBlock)
|
||||
|
@ -201,7 +118,7 @@ namespace PSVIMGTOOLS
|
|||
byte[] tmp = new byte[remainBlock];
|
||||
psvStream.Read(tmp, 0x00, remainBlock);
|
||||
ms.Write(tmp, 0x00, tmp.Length);
|
||||
psvStream.Seek(psvStream.SHA256_BLOCK_SIZE, SeekOrigin.Current);
|
||||
psvStream.Seek(PSVIMGConstants.SHA256_BLOCK_SIZE, SeekOrigin.Current);
|
||||
read += Convert.ToInt32(remainBlock);
|
||||
}
|
||||
}
|
||||
|
@ -215,7 +132,7 @@ namespace PSVIMGTOOLS
|
|||
{
|
||||
long ToSeek = 0;
|
||||
long SeekAdd = 0;
|
||||
long remainBlock = psvStream.BlockRemaining - psvStream.SHA256_BLOCK_SIZE;
|
||||
long remainBlock = psvStream.BlockRemaining - PSVIMGConstants.SHA256_BLOCK_SIZE;
|
||||
while (true)
|
||||
{
|
||||
long remainSeek = amount - ToSeek;
|
||||
|
@ -228,9 +145,9 @@ namespace PSVIMGTOOLS
|
|||
else
|
||||
{
|
||||
ToSeek += remainBlock;
|
||||
SeekAdd += psvStream.SHA256_BLOCK_SIZE;
|
||||
SeekAdd += PSVIMGConstants.SHA256_BLOCK_SIZE;
|
||||
}
|
||||
remainBlock = psvStream.PSVIMG_BLOCK_SIZE;
|
||||
remainBlock = PSVIMGConstants.PSVIMG_BLOCK_SIZE;
|
||||
}
|
||||
ToSeek += SeekAdd;
|
||||
return psvStream.Seek(ToSeek,orig);
|
||||
|
@ -333,8 +250,8 @@ namespace PSVIMGTOOLS
|
|||
private SceIoStat readStats()
|
||||
{
|
||||
SceIoStat stat = new SceIoStat();
|
||||
stat.Mode = readUInt32();
|
||||
stat.Attributes = readUInt32();
|
||||
stat.Mode = (Modes)readUInt32();
|
||||
stat.Attributes = (AttributesEnum)readUInt32();
|
||||
stat.Size = readUInt64();
|
||||
stat.CreationTime = readDatetime();
|
||||
stat.AccessTime = readDatetime();
|
||||
|
@ -374,17 +291,7 @@ namespace PSVIMGTOOLS
|
|||
{
|
||||
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;
|
||||
}
|
||||
long padding = PSVIMGPadding.GetPadding(size);
|
||||
|
||||
if (header.Path == path)
|
||||
{
|
|
@ -8,13 +8,9 @@ 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 long _position = 0;
|
||||
private byte[] key;
|
||||
public Stream BaseStream
|
||||
{
|
||||
|
@ -24,6 +20,29 @@ 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
|
||||
|
@ -87,7 +106,7 @@ namespace PSVIMGTOOLS
|
|||
{
|
||||
get
|
||||
{
|
||||
return baseStream.Length - AES_BLOCK_SIZE;
|
||||
return baseStream.Length - PSVIMGConstants.AES_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +122,7 @@ namespace PSVIMGTOOLS
|
|||
{
|
||||
get
|
||||
{
|
||||
return baseStream.Position - AES_BLOCK_SIZE;
|
||||
return position;
|
||||
}
|
||||
set
|
||||
{
|
||||
|
@ -112,61 +131,94 @@ 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())
|
||||
{
|
||||
throw new Exception("Invalid KEY!");
|
||||
}
|
||||
blockStream = new MemoryStream();
|
||||
baseStream.Seek(AES_BLOCK_SIZE, SeekOrigin.Begin);
|
||||
this.Seek(0x00, SeekOrigin.Begin);
|
||||
update();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int remaining = (int)getRemainingBlock();
|
||||
int read = 0;
|
||||
|
||||
if (count < remaining)
|
||||
long totalRead = 0;
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
read += blockStream.Read(buffer, offset, count);
|
||||
baseStream.Seek(count, SeekOrigin.Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
while (true)
|
||||
{
|
||||
while (true)
|
||||
|
||||
if (this.Position >= this.Length)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
ms.Seek(0x00, SeekOrigin.Begin);
|
||||
ms.Read(buffer, offset, count);
|
||||
}
|
||||
}
|
||||
return read;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return Convert.ToInt32(totalRead);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
update();
|
||||
baseStream.Flush();
|
||||
blockStream.Flush();
|
||||
}
|
||||
|
@ -174,35 +226,26 @@ namespace PSVIMGTOOLS
|
|||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
long ret = 0;
|
||||
if(origin == SeekOrigin.Begin)
|
||||
if (origin == SeekOrigin.Begin)
|
||||
{
|
||||
ret = baseStream.Seek(offset + AES_BLOCK_SIZE, 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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
long currentPos = this.Position;
|
||||
this.Seek(currentPos + offset, SeekOrigin.Begin);
|
||||
}
|
||||
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);
|
||||
}
|
||||
long len = this.Length;
|
||||
this.Seek(Length + offset, SeekOrigin.Begin);
|
||||
}
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -225,52 +268,44 @@ namespace PSVIMGTOOLS
|
|||
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.Dispose();
|
||||
blockStream = new MemoryStream(decryptedBlock, 0x00, decryptedBlock.Length);
|
||||
blockStream.Write(decryptedBlock, 0x00, decryptedBlock.Length);
|
||||
blockStream.Seek(0x00, SeekOrigin.Begin);
|
||||
|
||||
seekToBlock(blockIndex);
|
||||
baseStream.Seek(offset, SeekOrigin.Current);
|
||||
blockStream.Seek(offset, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
private long getBlockIndex()
|
||||
private long getBlockIndex(long pos = -1)
|
||||
{
|
||||
long i = 0;
|
||||
long curPos = baseStream.Position;
|
||||
long fullBlock;
|
||||
long blockOffset;
|
||||
|
||||
while (true)
|
||||
long blockOffset = 0;
|
||||
long blockEnd = blockOffset + PSVIMGConstants.FULL_PSVIMG_SIZE;
|
||||
long blockIndex = 0;
|
||||
if (pos < 0)
|
||||
{
|
||||
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++;
|
||||
pos = this.Position;
|
||||
}
|
||||
return i;
|
||||
while (blockOffset < this.Length)
|
||||
{
|
||||
blockOffset = (blockIndex * PSVIMGConstants.FULL_PSVIMG_SIZE);
|
||||
blockEnd = blockOffset + PSVIMGConstants.FULL_PSVIMG_SIZE;
|
||||
|
||||
|
||||
if (pos >= blockOffset && pos < blockEnd)
|
||||
{
|
||||
return blockIndex;
|
||||
}
|
||||
blockIndex++;
|
||||
}
|
||||
throw new Exception("Not found somehow..");
|
||||
}
|
||||
|
||||
private long getRemainingBase()
|
||||
{
|
||||
return baseStream.Length - baseStream.Position;
|
||||
|
@ -283,7 +318,7 @@ namespace PSVIMGTOOLS
|
|||
{
|
||||
byte[] iv = new byte[0x10];
|
||||
seekToBlock(blockindex);
|
||||
baseStream.Seek(baseStream.Position - AES_BLOCK_SIZE, SeekOrigin.Begin);
|
||||
baseStream.Seek(baseStream.Position - PSVIMGConstants.AES_BLOCK_SIZE, SeekOrigin.Begin);
|
||||
baseStream.Read(iv, 0x00, iv.Length);
|
||||
return iv;
|
||||
}
|
||||
|
@ -306,15 +341,12 @@ namespace PSVIMGTOOLS
|
|||
|
||||
private void seekToBlock(long blockIndex)
|
||||
{
|
||||
long blockOffset;
|
||||
blockOffset = (blockIndex * FULL_PSVIMG_SIZE) + AES_BLOCK_SIZE;
|
||||
long blockOffset = (blockIndex * PSVIMGConstants.FULL_PSVIMG_SIZE) + PSVIMGConstants.AES_BLOCK_SIZE;
|
||||
|
||||
if (blockOffset > baseStream.Length)
|
||||
{
|
||||
blockOffset = baseStream.Length;
|
||||
}
|
||||
|
||||
|
||||
baseStream.Seek(blockOffset, SeekOrigin.Begin);
|
||||
}
|
||||
private byte[] getBlock(long blockIndex)
|
||||
|
@ -322,17 +354,15 @@ namespace PSVIMGTOOLS
|
|||
byte[] iv = getIV(blockIndex);
|
||||
long remaining = getRemainingBase();
|
||||
byte[] encryptedBlock;
|
||||
if (FULL_PSVIMG_SIZE < remaining)
|
||||
if (PSVIMGConstants.FULL_PSVIMG_SIZE < remaining)
|
||||
{
|
||||
encryptedBlock = new byte[FULL_PSVIMG_SIZE];
|
||||
encryptedBlock = new byte[PSVIMGConstants.FULL_PSVIMG_SIZE];
|
||||
}
|
||||
else
|
||||
{
|
||||
encryptedBlock = new byte[remaining];
|
||||
}
|
||||
|
||||
|
||||
baseStream.Read(encryptedBlock, 0x00, encryptedBlock.Length);
|
||||
baseStream.Read(encryptedBlock, 0x00, encryptedBlock.Length);
|
||||
byte[] decryptedBlock = aes_ecb_decrypt(encryptedBlock, iv);
|
||||
return decryptedBlock;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
using System;
|
||||
|
||||
namespace PSVIMGTOOLS
|
||||
{
|
||||
|
||||
internal class PSVIMGConstants
|
||||
{
|
||||
public const int AES_BLOCK_SIZE = 0x10;
|
||||
public const int SHA256_BLOCK_SIZE = 0x20;
|
||||
public const int PSVIMG_BLOCK_SIZE = 0x8000;
|
||||
public const int PSVIMG_ENTRY_ALIGN = 0x400;
|
||||
|
||||
public const string PSVIMG_HEADER_END = "EndOfHeader\n";
|
||||
public const string PSVIMG_TAILOR_END = "EndOfTailer\n";
|
||||
public const string PSVIMG_PADDING_END = "\n";
|
||||
|
||||
public const int FULL_PSVIMG_SIZE = PSVIMG_BLOCK_SIZE + SHA256_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
internal class StringReader
|
||||
{
|
||||
internal static string ReadUntilTerminator(byte[] StringBytes)
|
||||
{
|
||||
string str = "";
|
||||
foreach (byte sByte in StringBytes)
|
||||
{
|
||||
if (sByte != 0x00)
|
||||
{
|
||||
str += (char)sByte;
|
||||
}
|
||||
else
|
||||
{
|
||||
return str;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
internal 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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class SceIoStat
|
||||
{
|
||||
public enum Modes{
|
||||
/** Format bits mask */
|
||||
FormatBits = 0xF000,
|
||||
/** Symbolic link */
|
||||
SymbLink = 0x4000,
|
||||
/** Directory */
|
||||
Directory = 0x1000,
|
||||
/** Regular file */
|
||||
File = 0x2000,
|
||||
|
||||
/** Set UID */
|
||||
SetUid = 0x0800,
|
||||
/** Set GID */
|
||||
SetGid = 0x0400,
|
||||
/** Sticky */
|
||||
Sticky = 0x0200,
|
||||
|
||||
/** Others access rights mask */
|
||||
OthersAcesssMask = 0x01C0,
|
||||
/** Others read permission */
|
||||
OthersRead = 0x0100,
|
||||
/** Others write permission */
|
||||
OthersWrite = 0x0080,
|
||||
/** Others execute permission */
|
||||
OthersExecute = 0x0040,
|
||||
|
||||
/** Group access rights mask */
|
||||
GroupAcessMask = 0x0038,
|
||||
/** Group read permission */
|
||||
GroupRead = 0x0020,
|
||||
/** Group write permission */
|
||||
GroupWrite = 0x0010,
|
||||
/** Group execute permission */
|
||||
GroupExecute = 0x0008,
|
||||
|
||||
/** User access rights mask */
|
||||
UserAcessMask = 0x0007,
|
||||
/** User read permission */
|
||||
UserRead = 0x0004,
|
||||
/** User write permission */
|
||||
UserWrite = 0x0002,
|
||||
/** User execute permission */
|
||||
UserExecute = 0x0001,
|
||||
};
|
||||
public enum AttributesEnum
|
||||
{
|
||||
/** Format mask */
|
||||
FormatMask = 0x0038, // Format mask
|
||||
/** Symlink */
|
||||
SymbLink = 0x0008, // Symbolic link
|
||||
/** Directory */
|
||||
Directory = 0x0010, // Directory
|
||||
/** Regular file */
|
||||
File = 0x0020, // Regular file
|
||||
|
||||
/** Hidden read permission */
|
||||
Read = 0x0004, // read
|
||||
/** Hidden write permission */
|
||||
Write = 0x0002, // write
|
||||
/** Hidden execute permission */
|
||||
Execute = 0x0001, // execute
|
||||
};
|
||||
|
||||
public Modes Mode;
|
||||
public AttributesEnum 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()
|
||||
{
|
||||
for(int i = 0; i < Private.Length; i++)
|
||||
{
|
||||
Private[i] = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
internal class PsvImgTailer
|
||||
{
|
||||
public UInt64 Flags;
|
||||
public Byte[] Padding = new Byte[1004];
|
||||
public Byte[] bEnd = new Byte[12];
|
||||
|
||||
public String End
|
||||
{
|
||||
get
|
||||
{
|
||||
return StringReader.ReadUntilTerminator(bEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
internal class PSVIMGPadding
|
||||
{
|
||||
public static long GetPadding(long size)
|
||||
{
|
||||
long padding;
|
||||
if ((size & (PSVIMGConstants.PSVIMG_ENTRY_ALIGN - 1)) >= 1)
|
||||
{
|
||||
padding = (PSVIMGConstants.PSVIMG_ENTRY_ALIGN - (size & (PSVIMGConstants.PSVIMG_ENTRY_ALIGN - 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
padding = 0;
|
||||
}
|
||||
return padding;
|
||||
}
|
||||
}
|
||||
|
||||
internal 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 StringReader.ReadUntilTerminator(bPath);
|
||||
}
|
||||
}
|
||||
|
||||
public String End
|
||||
{
|
||||
get
|
||||
{
|
||||
return StringReader.ReadUntilTerminator(bEnd);
|
||||
}
|
||||
}
|
||||
|
||||
public String ParentPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return StringReader.ReadUntilTerminator(bParentPath);
|
||||
}
|
||||
}
|
||||
public PsvImgHeader()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using PSVIMGTOOLS;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CHOVY
|
||||
|
@ -14,6 +13,28 @@ 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();
|
||||
*/
|
||||
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new CHOVY());
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="BouncyCastle" version="1.8.5" targetFramework="net45" />
|
||||
<package id="Discutils" version="0.11.0.2" targetFramework="net452" />
|
||||
</packages>
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,30 @@
|
|||
# The Bouncy Castle Crypto Package For C Sharp
|
||||
|
||||
The Bouncy Castle Crypto package is a C\# implementation of cryptographic algorithms and protocols, it was developed by the Legion of the Bouncy Castle, a registered Australian Charity, with a little help! The Legion, and the latest goings on with this package, can be found at [http://www.bouncycastle.org](http://www.bouncycastle.org). In addition to providing basic cryptography algorithms, the package also provides support for CMS, TSP, X.509 certificate generation and a variety of other standards such as OpenPGP.
|
||||
|
||||
The Legion also gratefully acknowledges the contributions made to this package by others (see [here](http://www.bouncycastle.org/csharp/contributors.html) for the current list). If you would like to contribute to our efforts please feel free to get in touch with us or visit our [donations page](https://www.bouncycastle.org/donate), sponsor some specific work, or purchase a support contract through [Crypto Workshop](http://www.cryptoworkshop.com).
|
||||
|
||||
Except where otherwise stated, this software is distributed under a license based on the MIT X Consortium license. To view the license, [see here](http://www.bouncycastle.org/licence.html). The OpenPGP library also includes a modified BZIP2 library which is licensed under the [Apache Software License, Version 2.0](http://www.apache.org/licenses/).
|
||||
|
||||
**Note**: this source tree is not the FIPS version of the APIs - if you are interested in our FIPS version please contact us directly at [office@bouncycastle.org](mailto:office@bouncycastle.org).
|
||||
|
||||
## Mailing Lists
|
||||
|
||||
For those who are interested, there are 2 mailing lists for participation in this project. To subscribe use the links below and include the word subscribe in the message body. (To unsubscribe, replace **subscribe** with **unsubscribe** in the message body)
|
||||
|
||||
* [announce-crypto-csharp-request@bouncycastle.org](mailto:announce-crypto-csharp-request@bouncycastle.org)
|
||||
This mailing list is for new release announcements only, general subscribers cannot post to it.
|
||||
* [dev-crypto-csharp-request@bouncycastle.org](mailto:dev-crypto-csharp-request@bouncycastle.org)
|
||||
This mailing list is for discussion of development of the package. This includes bugs, comments, requests for enhancements, questions about use or operation.
|
||||
|
||||
**NOTE:**You need to be subscribed to send mail to the above mailing list.
|
||||
|
||||
## Feedback
|
||||
|
||||
If you want to provide feedback directly to the members of **The Legion** then please use [feedback-crypto@bouncycastle.org](mailto:feedback-crypto@bouncycastle.org), if you want to help this project survive please consider [donating](https://www.bouncycastle.org/donate).
|
||||
|
||||
For bug reporting/requests you can report issues here on github, via feedback-crypto if required, and we also have a [Jira issue tracker](http://www.bouncycastle.org/jira). We will accept pull requests based on this repository as well.
|
||||
|
||||
## Finally
|
||||
|
||||
Enjoy!
|
Binary file not shown.
Loading…
Reference in New Issue