pc微信小程序.wxapkg解密

WeChatAppHost.dll-->EncryptBufToFile

char __cdecl EncryptBufToFile_1001D19D(char *appid_1, char *path, void *Src, size_t Size)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  if ( !*((_DWORD *)appid_1 + 4) || (int)Size <= 0 )
    return 0;

  std::string::string(appid, (int)appid_1);
  v12 = v4;
  v11 = v4;
  sub_1001925F(&v11, path);
  sub_10047070(v19, v11, v12);
  sub_1001927F(&v11, v19);
  sub_100407A0(FileName, v11, v12);
  if ( isfileexist_10049860(FileName) )
  {
    bret = 1;
  }
  else
  {
    std::string::string(tmp, "saltiest");
    // 1、首先pbkdf2生成AES的key。利用微信小程序id字符串为pass,salt为saltiest 迭代次数为1000。调用pbkdf2生成一个32位的key
    pbkdf2_1002398B((int)&aeskey, 0, appid, (int)tmp, 1000, 256);
    std::string::_Tidy(tmp, 1, 0);
    std::string::string(aesiv, "the iv: 16 bytes");
    sub_10023263(v18);
    v5 = aesiv;
    if ( aesiv[5] >= 0x10u )
      v5 = (int *)aesiv[0];

    v15 = (int)v5;
    v16 = aesiv[4];
    aesinit_100237DA(v18, aeskey, 0, (int)&v15);
    v26 = 15;
    bret = 0;
    v25 = 0;
    LOBYTE(v24[0]) = 0;
    if ( (int)Size <= 1023 )
    {
      std::string::assign(v24, Src, Size);
    }
    else
    {
      std::string::assign(v24, Src, 1023u);     // 后续aes加密最大1023字节
      bret = 1;
    }

    v23[4] = 0;
    v6 = v24;
    v23[5] = 15;
    if ( v26 >= 0x10 )
      v6 = (void **)v24[0];

    v15 = (int)v6;
    v16 = v25;
    LOBYTE(v23[0]) = 0;
    // 2、首先取原始的wxapkg的包得前1023个字节通过AES通过1生成的key和iv(the iv: 16 bytes),进行加密
    if ( (unsigned __int8)aes_1002374E(v18, (int)&v15, (int)v23) )
    {
      std::string::string(tmp, "V1MMWX");
      sub_10016125(tmp, v23, 0, 0xFFFFFFFF);
      if ( bret )
      {
        unknown_libname_23(v13);
        strresize_10094CD0((int)v13, Size - 1023);
        substr_10094D17((void **)v13, (char *)Src + 1023, Size - 1023);
        unknown_libname_23(&v15);
        v12 = (unsigned __int8)getxokkey_1001D693(appid);// 3、接着利用微信小程序id字符串的倒数第2个字符为xor key,依次异或1023字节后的所有数据,如果微信小程序id小于2位,则xorkey 为 0x66
        v11 = strsize_1007EC9D(v13);
        v7 = strdata_1004F590(v13);
        if ( xor_1001D5F6((int)&v15, v7, v11, v12) )
        {
          v12 = strsize_1007EC9D(&v15);
          v8 = (void *)strdata_1004F590(&v15);
          string_10016224(tmp, v8, v12);
        }

        sub_10094CB1(&v15);
        sub_10094CB1(v13);
      }

      data = tmp;
      v12 = (int)tmp[4];                        // size
      if ( tmp[5] >= (LPCVOID)0x10 )
        data = (LPCVOID *)tmp[0];

      writefile_10049880(FileName, data, v12);  // 4、把AES加密后的数据(1024字节)和xor后的数据一起写入文件,并在文件头部添加V1MMWX标识
      std::string::_Tidy(tmp, 1, 0);
      bret = 1;
    }
    else
    {
      bret = 0;
    }

    std::string::_Tidy(v23, 1, 0);
    std::string::_Tidy(v24, 1, 0);
    sub_1002327D(v18);
    std::string::_Tidy(aesiv, 1, 0);
    if ( aeskey )
      (**(void (__thiscall ***)(int, int))aeskey)(aeskey, 1);
  }

  sub_10040820(FileName);
  std::wstring::_Tidy(v19, 1, 0);
  std::string::_Tidy(appid, 1, 0);
  return bret;
}

py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import argparse
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Hash import SHA1
from Crypto.Cipher import AES

# 微信小程序包 自定义标识
WXAPKG_FLAG = 'V1MMWX'
WXAPKG_FLAG_LEN = len(WXAPKG_FLAG)

def main():

    parser = argparse.ArgumentParser(description='PC微信小程序wxapkg包解密工具')
    parser.add_argument('--wxid', metavar='微信小程序ID', required=True)
    parser.add_argument('--iv', metavar='iv', required=False, default='the iv: 16 bytes')
    parser.add_argument('--salt', metavar='salt', required=False, default='saltiest')
    parser.add_argument('-f', '--file', metavar='加密的小程序包文件路径', required=True)
    parser.add_argument('-o', '--output', metavar='解密后的小程序包文件路径', required=True)

    args = parser.parse_args()

    key = PBKDF2(args.wxid.encode('utf-8'), args.salt.encode('utf-8'), 32, count=1000, hmac_hash_module=SHA1)

    # 读取加密的内容
    if not os.path.exists(args.file):
        raise Exception('文件不存在')

    with open(args.file, mode='rb') as f:
        dataByte = f.read()

    if dataByte[0:WXAPKG_FLAG_LEN].decode() != WXAPKG_FLAG:
        raise Exception('该文件无需解密, 或者不是微信小程序wxapkg加密包')

    # 初始化密钥
    cipher = AES.new(key, AES.MODE_CBC, args.iv.encode('utf-8'))
    
    # 解密头部1024个字节
    originData = cipher.decrypt(dataByte[WXAPKG_FLAG_LEN: 1024 + WXAPKG_FLAG_LEN])

    # 初始化xor密钥, 解密剩余字节
    xorKey = 0x66
    if len(args.wxid) >= 2:
        xorKey = ord(args.wxid[len(args.wxid) - 2])

    afData = dataByte[1024 + WXAPKG_FLAG_LEN:]

    out = bytearray()
    for i in range(len(afData)):
        out.append(afData[i] ^ xorKey)

    originData = originData[0:1023] + out

    # 保存解密后的数据
    with open(args.output, mode='wb') as f:
        f.write(originData)

    print('解密成功', args.output)

if __name__ == "__main__":
    main()

链接

pc_wxapkg_decrypt
pc_wxapkg_decrypt_python

解包工具 wxappUnpacker

posted @ 2022-10-02 17:11  DirWangK  阅读(1565)  评论(0编辑  收藏  举报