ZenHAX

Free Game Research Forum | Official QuickBMS support | twitter @zenhax | SSL HTTPS://zenhax.com
It is currently Sun May 27, 2018 5:36 am

All times are UTC




Post new topic  Reply to topic  [ 18 posts ] 
Author Message
PostPosted: Fri May 04, 2018 9:12 pm 

Joined: Tue Jan 26, 2016 12:45 pm
Posts: 48
hey,

so I currently messing arround with Pantheon a bit and I wounder, if you can help me get a Script to unpack the Patch Files.
I am not sure if it actually just Patch files or if it simply replace them.

The Compression of the Archives is Pack1. The Patcher that is used is:

https://github.com/patchkit-net/patchkit-patcher-unity

Code:
   if (compressionMethod == "pack1")
            {
               usedSuffix = "_";
               return new Pack1Unarchiver(this._packagePath, this._pack1Meta, destinationDir, this._packagePassword, "_");
            }
         }
         throw new UnknownPackageCompressionModeException(string.Format("Unknown compression method: {0}", this._diffSummary.CompressionMethod));
      }



Code:
{
   // Token: 0x02000018 RID: 24
   public class Pack1Unarchiver : IUnarchiver
   {
      // Token: 0x0600007A RID: 122 RVA: 0x00002538 File Offset: 0x00000738
      public Pack1Unarchiver(string packagePath, Pack1Meta metaData, string destinationDirPath, string key, string suffix = "") : this(packagePath, metaData, destinationDirPath, Encoding.ASCII.GetBytes(key), suffix, new BytesRange(0L, -1L))
      {
      }

      // Token: 0x0600007B RID: 123 RVA: 0x0000255A File Offset: 0x0000075A
      public Pack1Unarchiver(string packagePath, Pack1Meta metaData, string destinationDirPath, string key, string suffix, BytesRange range) : this(packagePath, metaData, destinationDirPath, Encoding.ASCII.GetBytes(key), suffix, range)
      {
      }

      // Token: 0x0600007C RID: 124 RVA: 0x00006874 File Offset: 0x00004A74
      public Pack1Unarchiver(string packagePath, Pack1Meta metaData, string destinationDirPath, byte[] key, string suffix, BytesRange range)
      {
         Checks.ArgumentFileExists(packagePath, "packagePath");
         Checks.ArgumentDirectoryExists(destinationDirPath, "destinationDirPath");
         Checks.ArgumentNotNull(suffix, "suffix");
         if (range.Start == 0L)
         {
            Assert.AreEqual<MagicBytes.FileType>(MagicBytes.Pack1, MagicBytes.ReadFileType(packagePath), "Is not Pack1 format");
         }
         Pack1Unarchiver.DebugLogger.LogConstructor();
         Pack1Unarchiver.DebugLogger.LogVariable(packagePath, "packagePath");
         Pack1Unarchiver.DebugLogger.LogVariable(destinationDirPath, "destinationDirPath");
         Pack1Unarchiver.DebugLogger.LogVariable(suffix, "suffix");
         this._packagePath = packagePath;
         this._metaData = metaData;
         this._destinationDirPath = destinationDirPath;
         this._suffix = suffix;
         this._range = range;
         using (SHA256 sha = SHA256.Create())
         {
            this._key = sha.ComputeHash(key);
         }
         this._iv = Convert.FromBase64String(this._metaData.Iv);
      }

      // Token: 0x14000002 RID: 2
      // (add) Token: 0x0600007D RID: 125 RVA: 0x00006978 File Offset: 0x00004B78
      // (remove) Token: 0x0600007E RID: 126 RVA: 0x000069B0 File Offset: 0x00004BB0
      [DebuggerBrowsable(DebuggerBrowsableState.Never)]
      public event UnarchiveProgressChangedHandler UnarchiveProgressChanged;

      // Token: 0x0600007F RID: 127 RVA: 0x000069E8 File Offset: 0x00004BE8
      public void Unarchive(CancellationToken cancellationToken)
      {
         int num = 1;
         Pack1Unarchiver.DebugLogger.Log("Unpacking " + this._metaData.Files.Length + " files...");
         Pack1Meta.FileEntry[] files = this._metaData.Files;
         for (int i = 0; i < files.Length; i++)
         {
            Pack1Meta.FileEntry fileEntry = files[i];
            this.OnUnarchiveProgressChanged(fileEntry.Name, fileEntry.Type == "regular", num, this._metaData.Files.Length, 0.0);
            Pack1Meta.FileEntry currentFile = fileEntry;
            int currentEntry = num;
            if (this.CanUnpack(fileEntry))
            {
               this.Unpack(fileEntry, delegate(double progress)
               {
                  this.OnUnarchiveProgressChanged(currentFile.Name, currentFile.Type == "regular", currentEntry, this._metaData.Files.Length, progress);
               }, cancellationToken, null);
            }
            else
            {
               Pack1Unarchiver.DebugLogger.LogWarning(string.Format("The file {0} couldn't be unpacked.", fileEntry.Name));
            }
            this.OnUnarchiveProgressChanged(fileEntry.Name, fileEntry.Type == "regular", num, this._metaData.Files.Length, 1.0);
            num++;
         }
         Pack1Unarchiver.DebugLogger.Log("Unpacking finished succesfully!");
      }

      // Token: 0x06000080 RID: 128 RVA: 0x00006B20 File Offset: 0x00004D20
      public void UnarchiveSingleFile(Pack1Meta.FileEntry file, CancellationToken cancellationToken, string destinationDirPath = null)
      {
         this.OnUnarchiveProgressChanged(file.Name, file.Type == "regular", 0, 1, 0.0);
         if (!this.CanUnpack(file))
         {
            throw new ArgumentOutOfRangeException("file", file, null);
         }
         this.Unpack(file, delegate(double progress)
         {
            this.OnUnarchiveProgressChanged(file.Name, file.Type == "regular", 1, 1, progress);
         }, cancellationToken, destinationDirPath);
         this.OnUnarchiveProgressChanged(file.Name, file.Type == "regular", 0, 1, 1.0);
      }

      // Token: 0x06000081 RID: 129 RVA: 0x00006BE0 File Offset: 0x00004DE0
      private bool CanUnpack(Pack1Meta.FileEntry file)
      {
         if (file.Type != "regular")
         {
            return true;
         }
         if (this._range.Start == 0L && this._range.End == -1L)
         {
            return true;
         }
         bool result;
         if (file.Offset >= this._range.Start)
         {
            long? offset = file.Offset;
            bool flag = offset != null;
            long? size = file.Size;
            result = (((!(flag & size != null)) ? null : new long?(offset.GetValueOrDefault() + size.GetValueOrDefault())) <= this._range.End);
         }
         else
         {
            result = false;
         }
         return result;
      }

      // Token: 0x06000082 RID: 130 RVA: 0x00006CD8 File Offset: 0x00004ED8
      private void Unpack(Pack1Meta.FileEntry file, Action<double> progress, CancellationToken cancellationToken, string destinationDirPath = null)
      {
         string type = file.Type;
         if (type != null)
         {
            if (type == "regular")
            {
               this.UnpackRegularFile(file, progress, cancellationToken, destinationDirPath);
               return;
            }
            if (type == "directory")
            {
               progress(0.0);
               this.UnpackDirectory(file);
               progress(1.0);
               return;
            }
            if (type == "symlink")
            {
               progress(0.0);
               this.UnpackSymlink(file);
               progress(1.0);
               return;
            }
         }
         Pack1Unarchiver.DebugLogger.LogWarning("Unknown file type: " + file.Type);
      }

      // Token: 0x06000083 RID: 131 RVA: 0x00006DAC File Offset: 0x00004FAC
      private void UnpackDirectory(Pack1Meta.FileEntry file)
      {
         string text = Path.Combine(this._destinationDirPath, file.Name);
         Pack1Unarchiver.DebugLogger.Log("Creating directory " + text);
         Directory.CreateDirectory(text);
         Pack1Unarchiver.DebugLogger.Log("Directory " + text + " created successfully!");
      }

      // Token: 0x06000084 RID: 132 RVA: 0x00006E04 File Offset: 0x00005004
      private void UnpackSymlink(Pack1Meta.FileEntry file)
      {
         string str = Path.Combine(this._destinationDirPath, file.Name);
         Pack1Unarchiver.DebugLogger.Log("Creating symlink: " + str);
      }

      // Token: 0x06000085 RID: 133 RVA: 0x00006E38 File Offset: 0x00005038
      private void UnpackRegularFile(Pack1Meta.FileEntry file, Action<double> onProgress, CancellationToken cancellationToken, string destinationDirPath = null)
      {
         string text = Path.Combine((destinationDirPath != null) ? destinationDirPath : this._destinationDirPath, file.Name + this._suffix);
         Pack1Unarchiver.DebugLogger.LogFormat("Unpacking regular file {0} to {1}", new object[]
         {
            file,
            text
         });
         Files.CreateParents(text);
         RijndaelManaged rijndaelManaged = new RijndaelManaged
         {
            Mode = CipherMode.CBC,
            Padding = PaddingMode.None,
            KeySize = 256
         };
         ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(this._key, this._iv);
         using (FileStream fileStream = new FileStream(this._packagePath, FileMode.Open))
         {
            fileStream.Seek(file.Offset.Value - this._range.Start, SeekOrigin.Begin);
            using (LimitedStream limitedStream = new LimitedStream(fileStream, file.Size.Value))
            {
               using (FileStream fileStream2 = new FileStream(text, FileMode.Create))
               {
                  this.ExtractFileFromStream(limitedStream, fileStream2, file, decryptor, onProgress, cancellationToken);
               }
               if (Platform.IsPosix())
               {
                  Chmod.SetMode(file.Mode.Substring(3), text);
               }
            }
         }
         Pack1Unarchiver.DebugLogger.Log("File " + file.Name + " unpacked successfully!");
      }

      // Token: 0x06000086 RID: 134 RVA: 0x00006FCC File Offset: 0x000051CC
      private void ExtractFileFromStream(Stream sourceStream, Stream targetStream, Pack1Meta.FileEntry file, ICryptoTransform decryptor, Action<double> onProgress, CancellationToken cancellationToken)
      {
         using (CryptoStream cryptoStream = new CryptoStream(sourceStream, decryptor, CryptoStreamMode.Read))
         {
            using (GZipStream gzipStream = new GZipStream(cryptoStream, CompressionMode.Decompress))
            {
               long num = 0L;
               byte[] buffer = new byte[131072];
               int num2;
               while ((num2 = gzipStream.Read(buffer, 0, 131072)) != 0)
               {
                  cancellationToken.ThrowIfCancellationRequested();
                  targetStream.Write(buffer, 0, num2);
                  num += (long)num2;
                  onProgress((double)gzipStream.Position / (double)file.Size.Value);
               }
            }
         }
      }

      // Token: 0x06000087 RID: 135 RVA: 0x0000708C File Offset: 0x0000528C
      protected virtual void OnUnarchiveProgressChanged(string name, bool isFile, int entry, int amount, double entryProgress)
      {
         UnarchiveProgressChangedHandler unarchiveProgressChanged = this.UnarchiveProgressChanged;
         if (unarchiveProgressChanged != null)
         {
            unarchiveProgressChanged(name, isFile, entry, amount, entryProgress);
         }
      }

      // Token: 0x04000035 RID: 53
      private static readonly DebugLogger DebugLogger = new DebugLogger(typeof(Pack1Unarchiver));

      // Token: 0x04000036 RID: 54
      private readonly string _packagePath;

      // Token: 0x04000037 RID: 55
      private readonly Pack1Meta _metaData;

      // Token: 0x04000038 RID: 56
      private readonly string _destinationDirPath;

      // Token: 0x04000039 RID: 57
      private readonly string _suffix;

      // Token: 0x0400003A RID: 58
      private readonly byte[] _key;

      // Token: 0x0400003B RID: 59
      private readonly byte[] _iv;

      // Token: 0x0400003C RID: 60
      private readonly BytesRange _range;
   }
}


Top
   
PostPosted: Fri May 04, 2018 11:05 pm 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 8139
Try to use the reimport feature of quickbms (not reimport2):
http://aluigi.org/bms/patchkit_pack1.bms


Top
   
PostPosted: Sat May 05, 2018 11:39 am 

Joined: Tue Jan 26, 2016 12:45 pm
Posts: 48
aluigi wrote:
Try to use the reimport feature of quickbms (not reimport2):
http://aluigi.org/bms/patchkit_pack1.bms



Reimport to Patch Files? Or to extract?

The Files are normaly installed like : Game_Data/Mono/Managed/RANDOM.dll stuff

I uploaded an example Patch File.

https://www17.zippyshare.com/v/rw9fALed/file.html


Top
   
PostPosted: Sat May 05, 2018 11:52 am 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 8139
I have updated the script in the meantime.

First you must set the key in the variable at the beginning of the script (currently it's "test123")
Then you can use the script to extract the files and later to reimport those you edited.


Top
   
PostPosted: Sat May 05, 2018 11:54 am 

Joined: Tue Jan 26, 2016 12:45 pm
Posts: 48
Is the Key : "iv":"jkfcbf6u2HP39cSH96dWTQ==" ? (Meta Files always provide this and it is different for every file)

Or is it store in the Patcher somewhere? I through they dont use any Key or such. Prob. my Key is wrong.

Code:
KEY  jkfcbf6u2HP39cSH96dWTQ==
KEY  4ea5c38ee2535cef83bd4d8c53bc45300de6d8d5760a0bae42965e78b0c01ff1
IVEC d7a6a2bbab215f40c3a4036e437a3338
  00000009 112        Pantheon.exe
Info:  algorithm   14
       offset      00000009
       input size  0x00000070 112
       output size 0x00000070 112
       result      0xffffffff -1

Error: the uncompressed data (-1) is bigger than the allocated buffer (112)

Last script line before the error or that produced the error:
  61  clog FNAME FOFFSET FSIZE FSIZE 1


Top
   
PostPosted: Sat May 05, 2018 12:05 pm 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 8139
KEY is mandatory and not stored in the files.
No key, no files.
(just in case I already tried with KEY "")


Top
   
PostPosted: Sat May 05, 2018 12:24 pm 

Joined: Tue Jan 26, 2016 12:45 pm
Posts: 48
aluigi wrote:
KEY is mandatory and not stored in the files.
No key, no files.
(just in case I already tried with KEY "")



How long is the Key? The Launcher passing a Patcher-Key:

--secret nf+d/zv/Of89/5n/Nf+V/zP/l/+P/5f/lf+V/5n/O/+T/zf/N/+T/4//j/+N/5n/mf+d/53/j/+P/5X/k/+T/w==

If I print the Password Variable (on Unpacking): it shows me different Passwords:

Current Version: $MTFiY2EzZTVmNDg0NTUzYjZkZDY4ODkzMzExODg1NjYxNDk=
PAtch 61/62: $MTFiY2EzZTVmNDg0NTUzYjZkZDY4ODkzMzExODg1NjY2MQ==
$MTFiY2EzZTVmNDg0NTUzYjZkZDY4ODkzMzExODg1NjY2Mg==
Patch 101: $MTFiY2EzZTVmNDg0NTUzYjZkZDY4ODkzMzExODg1NjYxMDE=


Top
   
PostPosted: Sat May 05, 2018 1:03 pm 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 8139
Very close but not right yet.
The only remaining field is VersionId, it's not 1 or 0 apparently in that sample.


Top
   
PostPosted: Sat May 05, 2018 1:24 pm 

Joined: Tue Jan 26, 2016 12:45 pm
Posts: 48
aluigi wrote:
Very close but not right yet.
The only remaining field is VersionId, it's not 1 or 0 apparently in that sample.



Jump $MTFiY2EzZTVmNDg0NTUzYjZkZDY4ODkzMzExODg1NjY2MQ== 61

VersionID is 61 as the Package File :) if this was the Question?

Sorry, just very tired, hope I dont tell any shit. Where is the Key suposed to be stored?


Top
   
PostPosted: Sat May 05, 2018 2:36 pm 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 8139
Yeah 61 is correct :)
Script 0.1.2, remember to set appSecret and VersionId and now you can extract and reimport the files of that sample


Top
   
PostPosted: Mon May 07, 2018 8:59 am 

Joined: Tue Jan 26, 2016 12:45 pm
Posts: 48
Working perfectly. The ZIP Format (they used it in the first few Clients) is just a normal ZIP right?

Sadly they are all diff files or so, since I cant open the Files with NetDecompiler.

Do the Meta File contain Information how the files are patched? Or do the Patcher simply merge them?

(maybe you can take a loot at both files, I already corrected the File-Header)

the Csharp3 = Original and the 4 MB File is the one from the Patcher (actually from the very first Zip Patcher)

If you check both files in Hex Editor, they look exactly same so :X

https://www95.zippyshare.com/v/veJbJjEd/file.html


Top
   
PostPosted: Mon May 07, 2018 10:00 am 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 8139
The zip files are normal password encrypted zip archives indeed, at least as stated in the source code.

Regarding csharp, no thanks I have limited time and no desire, sorry.


Top
   
PostPosted: Tue May 08, 2018 10:58 am 

Joined: Tue Jan 26, 2016 12:45 pm
Posts: 48
on unpacking the Full Content File 7 GB. I used 4 GB Version :

Code:
 000000008964e409 975989392  Pantheon_Data/sharedassets3.assets.resS

- error in src\extra\xalloc.c line 618: xdbg_malloc()

Error: memory allocation problem
       Fr diesen Befehl ist nicht gengend Speicher verfgbar.


press ENTER to quit


Top
   
PostPosted: Tue May 08, 2018 12:38 pm 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 8139
Is it related to the content6.meta you uploaded?
It doesn't seem like that because offset and size don't match.


Top
   
PostPosted: Thu May 10, 2018 4:26 pm 

Joined: Tue Jan 26, 2016 12:45 pm
Posts: 48
aluigi wrote:
Is it related to the content6.meta you uploaded?
It doesn't seem like that because offset and size don't match.


No actually not. It is the "Big" File. The one I uploaded is a Patch File, the one I tried now was the "Full Content" Package, it has the Same Format (Pack1 and the Meta File)

It also worked to the half way, but stopped on like 50% or so with the error above.


Top
   
PostPosted: Fri May 11, 2018 1:46 pm 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 8139
Upload the meta file.


Top
   
PostPosted: Sun May 13, 2018 10:43 am 

Joined: Tue Jan 26, 2016 12:45 pm
Posts: 48
https://www62.zippyshare.com/v/uCsgJeYO/file.html


Top
   
PostPosted: Sun May 13, 2018 11:41 am 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 8139
Ok everything is correct.
It's just a problem of memory as reported by quickbms (often that message is caused by bad scripts/files/formats).
Basically you have a file with a size of almost 1Gb compressed with gzip, so it's necessary to create another buffer in memory for the decompressed size which result in too much memory to allocate.
Doesn't exist a fix for these issues.


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 18 posts ] 

All times are UTC


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Limited