Decryption, encryption and opening 7z call function removal in Angry Birds v4.0.0 (.exe)

Extraction and unpacking of game archives and compression, encryption, obfuscation, decoding of unknown files
gamelandresearch
Posts: 13
Joined: Sun Feb 09, 2020 11:35 am

Decryption, encryption and opening 7z call function removal in Angry Birds v4.0.0 (.exe)

Post by gamelandresearch »

Hey, can you remove call function that decrypts, encrypts and opens 7z before loading file.
Here's why you remove decrypt and encrypt and open 7z call function:

- To make game load and easily mod LUA. (To keep unencrypted files and extracted 7z file)
- Files must be decrypted and extracted 7z first before editing EXE.
- Non-EXE has no decrypt, encrypt and opening 7z function, you don't need it.
- Both saves and assets is used differently encryption key.
- Encryption key is: save (Variable) and assets (Static)

I tried with x86dbg but it doesn't work, I'm guessing that too complex to edit .exe.
It would be appreciated if you remove decrypt and encrypt and open 7z call function.

Here 4.0.0 installer:
https://web.archive.org/web/20140905054331/http://download.angrybirds.com/games/AngryBirds/AngryBirdsInstaller_4.0.0.exe
Disclaimer: It's not pirated software, it's free game and original EXE from developers so it's legal.
atom0s
Posts: 250
Joined: Sat Dec 27, 2014 8:49 pm

Re: Decryption, encryption and opening 7z call function removal in Angry Birds v4.0.0 (.exe)

Post by atom0s »

Lua files are 7-zipped then encrypted with AES256.

AES is setup with:
- Key: USCaPQpA4TSNVxMI1v9SK9UC0yZuAnb2
- IV: Empty 16 byte buffer of 00's.
- Key Size: 256
- BlockSize: 128
- Padding: PKCS7

AES functions involved are:

Code: Select all

    - sub_411070        - Singleton caller that sets up and returns the AES key.
        - sub_410EB0    - Sets the AES key if not set yet.

    - sub_416D60        - Decryptor wrapper function.
        - sub_4D2830    - AES setup function. (Sets up the key, key size, block size, etc.)
        - sub_4D24D0    - AES decryptor function.

    - sub_4D2C90        - Encryptor wrapper function.


7Zip functions involved are:

Code: Select all

    - sub_416CB0        - The main 7zip wrapper function.


The AES functions are used in multiple places.

Code: Select all

    - sub_416D60 (Calls sub_4D2830 and sub_4D24D0.) [Decrypts]
    - sub_427240 (Calls sub_4D2830 and sub_4D24D0.) [Decrypts]
    - sub_437770 (Calls sub_4D2830 and sub_4D24D0.) [Decrypts]
    - sub_4D3830 (Calls sub_4D2830 and sub_4D24D0.) [Decrypts]

    - sub_421230 (Calls sub_4D2830 and sub_4D2C90.) [Encrypts]
    - sub_4D35E0 (Calls sub_4D2830 and sub_4D2C90.) [Encrypts]

    - sub_416E50 (Calls sub_416D60 and sub_416CB0.) [Decrypts + 7zip usage.]
        - This appears to setup and use any expected file that will be decrypted + unzipped.


Tracing back around these calls, then there are other handlers for loading Lua.

Code: Select all

    - sub_421030 - Calls the sub_416E50 handler for dealing with specific Lua files.
        - Seen to be used with at least:
            - blocks.lua
            - options.lua
        - Used with custom Lua calls:
            - loadLuaFile (Uses custom handlers to eventually call sub_416E50 and similar.)
            - loadLuaFileToObject (Calls sub_422470 which calls sub_421030.)


This isn't something I have time to invest into further but this should be enough info to get someone else started, or able to complete the desired result. You can approach this multiple ways though without having to patch the exe.

You can easily hook onto the Lua state and just overwrite scripts as they are loaded from the defaults with non-encrypted ones for example.

Or just run code at any time as you wish (keeping thread safey in mind as Lua is not thread safe.) to alter what has already been loaded etc.

The Lua script executor is located at: sub_47C060

Code: Select all

/**
 * 'this' is passed via ECX.
 *
 * a2 - Pointer to loaded compiled script data.
 * a3 - Size of a2 buffer.
 * a4 - Name of the script being loaded. (std::string object)
 * a5 - Lua object instance pointer.
 */
int __thiscall sub_47C060(_DWORD *this, int a2, int a3, _DWORD *a4, int a5)
{
  bool v6; // cf
  _DWORD *v7; // eax
  int v8; // eax
  char v10[8]; // [esp+Ch] [ebp-1Ch] BYREF
  int v11[2]; // [esp+14h] [ebp-14h] BYREF
  int v12; // [esp+24h] [ebp-4h]

  sub_47C450(this[3]);
  v6 = a4[5] < 0x10u;
  v12 = 0;
  v11[0] = a2;
  v11[1] = a3;
  if ( v6 )
    v7 = a4;
  else
    v7 = (_DWORD *)*a4;
  v8 = sub_47FC30(this[3], sub_47B5B0, v11, v7);
  sub_47BD40(v8, a4, a5);
  v12 = -1;
  return sub_47C470(v10);
}