Skip to content

Instantly share code, notes, and snippets.

@barncastle
Last active November 13, 2023 10:28
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save barncastle/30e4261dbc956b1eb2404480f2112b4e to your computer and use it in GitHub Desktop.
Save barncastle/30e4261dbc956b1eb2404480f2112b4e to your computer and use it in GitHub Desktop.
Code for decrypting Pokémon HOME v2.0 Unity AssetBundles
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
namespace ConsoleAppFramework
{
public static class ABA
{
private const string Key_0 = "lrZ6++Ln5tLnBsJk.ae6J8BLaLbMhVn@";
private const string IV_0 = "X6TU@VYU$HyqKy57PfwWg7.t7wk2oqtg";
private const int DEFAULT_KEYSIZE = 256;
private const int DEFAULT_BLOCKSIZE = 256;
public static FileHeader ExtractPackage(string abapPath, string outDirectory)
{
Directory.CreateDirectory(outDirectory);
using (var fs = File.OpenRead(abapPath))
using (var br = new BinaryReader(fs))
{
// read the header
var header = new FileHeader()
{
Magic = br.ReadUInt32(),
RootHeadOffset = br.ReadInt32(),
NameHeadOffset = br.ReadInt32(),
DataHeadOffset = br.ReadInt32()
};
header.Bundles = new BundleInfo[header.DataCount];
// read each package
for (var i = 0; i < header.DataCount; i++)
{
// seek to package info offset
fs.Seek(i * 16 + header.RootHeadOffset, SeekOrigin.Begin);
// read package info details
var bundle = header.Bundles[i] = new BundleInfo()
{
NameOffset = br.ReadInt32(),
NameSize = br.ReadInt32(),
DataOffset = br.ReadInt32(),
DataSize = br.ReadInt32(),
};
// seek to name offset and read
fs.Seek(header.NameHeadOffset + bundle.NameOffset, SeekOrigin.Begin);
bundle.Name = Encoding.UTF8.GetString(br.ReadBytes(bundle.NameSize));
// seek to data offset and read
fs.Seek(header.DataHeadOffset + bundle.DataOffset, SeekOrigin.Begin);
bundle.Data = br.ReadBytes(bundle.DataSize);
// decrypt package contents
Decrypt(bundle, outDirectory);
}
return header;
}
}
public static void Decrypt(BundleInfo package, string outPath)
{
var filename = Path.Combine(outPath, package.Name + ".unity3d");
using (var ms = new MemoryStream(package.Data))
DecryptImplementation(ms, filename);
}
public static void Decrypt(string abaPath, string outPath)
{
using (var fsInput = File.OpenRead(abaPath))
DecryptImplementation(fsInput, outPath);
}
private static void DecryptImplementation(Stream stream, string outPath)
{
using (var algo = new RijndaelManaged())
using (var strInput = stream)
using (var strOutput = File.Create(outPath))
{
// set up our params
algo.Padding = PaddingMode.PKCS7;
algo.Mode = CipherMode.CBC;
algo.BlockSize = DEFAULT_BLOCKSIZE;
algo.KeySize = DEFAULT_KEYSIZE;
algo.Key = Encoding.UTF8.GetBytes(Key_0);
algo.IV = Encoding.UTF8.GetBytes(IV_0);
// calculate our buffer size
var bufferLen = Math.Min(strInput.Length, 1024);
var buffer = new byte[bufferLen];
// create a crypto stream and process bufferLen bytes
using (var transform = new CryptoStream(strInput, algo.CreateDecryptor(), CryptoStreamMode.Read, true))
transform.Read(buffer, 0, buffer.Length);
// write the decrypted bytes to our output
strOutput.Write(buffer, 0, buffer.Length);
// finally, copy the remaining unread bytes from the input to the output
strInput.CopyTo(strOutput);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct FileHeader
{
public uint Magic; // "ppir" aka "pupitar"
public int RootHeadOffset;
public int NameHeadOffset;
public int DataHeadOffset;
public BundleInfo[] Bundles; // [DataCount]
public int RootBufferSize => NameHeadOffset - RootHeadOffset;
public int NameBufferSize => DataHeadOffset - NameHeadOffset;
public int DataCount => RootBufferSize >> 4;
}
[StructLayout(LayoutKind.Sequential)]
public struct BundleInfo
{
public int NameOffset; // + header.NameHeadOffset
public int NameSize;
public int DataOffset; // + header.DataHeadOffset
public int DataSize;
public string Name;
public byte[] Data;
}
}
}
@Lilothestitch16
Copy link

How do I use this?

@barncastle
Copy link
Author

barncastle commented May 27, 2022

I've uploaded ABA_Decryptor.zip which contains an app that supports bulk extracting (from *.abap files) and decrypting of *.aba files, renaming them to *.unity3d. Place it in a folder full of files and run it.

Copy link

ghost commented Sep 1, 2022

I cplace it where are the aba files, but it only shows the following error:

https://prnt.sc/ShfG_PiiAeff

Thx for solving to fix this issue. =]

@barncastle
Copy link
Author

I cplace it where are the aba files, but it only shows the following error:

My fault, I left my testing path in there! I've uploaded a new version that should work.

Copy link

ghost commented Sep 2, 2022

It works now! Great work!

@Lilothestitch16
Copy link

Awesome. I didn’t know there was a bug in it.

@DahniMae
Copy link

DahniMae commented May 30, 2023

hello there, is it possible to update this script?
Pokemon home in its 3.0.0 changed some stuff i guess and its not working on the newest version
i can send an example of a new .aba file if needed, were thinking they changed the encryption part a lil? but i dont understand much about it so i dont know

@barncastle
Copy link
Author

Just tested on a few *.aba files and it is still working for me. If you have a sample for me to test with; feel free to share.

@DahniMae
Copy link

https://d2gf339i9nrwgc.cloudfront.net/Models/Android/Mitake15sv/pokemons/pm0906_00_00

this url if you go to it will give you sprigatitio's bundle, but i tried running your script on this bundle and it didnt make a valid unity file, it renamed it, but i wasnt able to open that file with any unity asset programs, they just all crashed

@barncastle
Copy link
Author

I'm not sure what file format that is but it isn't a *.aba or *.abap - they always have a file extension supplied and contain the following encrypted header bytes (provided they're using the above Key and IV):

82 50 24 4D AD F5 79 4A 75 14 07 2C A5 D6 93 58 C3 80 24 81 B2 74 5F B1 8B 5A 6F F0 CC F8 3C F1

This does appear to be a Unity file though as I can see Unity Asset information in it but unfortunately I can't say how to read it, sorry.

@DahniMae
Copy link

I'm not sure what file format that is but it isn't a *.aba or *.abap - they always have a file extension supplied and contain the following encrypted header bytes (provided they're using the above Key and IV):

82 50 24 4D AD F5 79 4A 75 14 07 2C A5 D6 93 58 C3 80 24 81 B2 74 5F B1 8B 5A 6F F0 CC F8 3C F1

This does appear to be a Unity file though as I can see Unity Asset information in it but unfortunately I can't say how to read it, sorry.

the thing is were thinking they just changed the key is all, thats the problem, is there a way you might be able to help reverse it?

because these Should be the assetbundles for the models that home uses

@DahniMae
Copy link

for some reason with the newer gen the assetbundles for the models just have a different encryption that the older files dont

@ChicoEevee
Copy link

When they get saved on the Cache they are "readable" we could say

@ChicoEevee
Copy link

image
image
Comparison with the one in the Cache and the one from website

@DahniMae
Copy link

DahniMae commented May 30, 2023

image
they are definitely unity3d assets as we can see the cab names

maybe these pictures inside will help figure it out?
does this help at all?

@ChicoEevee
Copy link

https://d2gf339i9nrwgc.cloudfront.net/Models/Android/MitakeCommon/projects/mitake15sv Also this one seems to include a manifest in it or something maybe it contains model strings to know which one to pull

@ChicoEevee
Copy link

image
ok 100% the ones stored in the Cache are Decrypted

@ChicoEevee
Copy link

image
dependencies seems to be where textures are stored

@ChicoEevee
Copy link

k i found out something

https://d2gf339i9nrwgc.cloudfront.net/Models/Android/Mitake15sv/pokemons/dependencies/c4d435139b9c26c13982992aee0f00dd <-- this is sprigatito decrypted the one stored in cache

@DahniMae
Copy link

did some more research, we think we found out basically whats going on, format for the home bundles has essentially that theyve been split into 3 bundles
A compressed file named pm0980_00_00 something like that, which needs help/decompressing or decrypting or something, this contains the rig and the materials and such

and it has two other files that accompany it that are uncompressed, one that contains textures, and one that contain the mesh, so its not a before and after of compressed to decompressed, its that we have three files that work together to create a pokemon

but we still need to figure out and decompress that first core bundle

@ChicoEevee
Copy link

image
found this in ram

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment