首页
社区
课程
招聘
[原创]反汇编:微信小程序 wxapkg
发表于: 2023-6-9 09:31 23117

[原创]反汇编:微信小程序 wxapkg

2023-6-9 09:31
23117

wxapkg 是微信小程序编译包格式,文件内包含小程序的源码与图像等资源文件。

将微信卸载重装,或者清空所有小程序后,重新加载要分析的小程序,
在/data/data/com.tencent.mm/MicroMsg/appbrand目录下搜索wxapkg会得到所在目录,导出即可。

wxapkg 文件的数据格式分成三个部分:
第一部分:文件的前 6 字节为 V1MMWX;
第二部分:之后的 1024 字节为 AES CBC 加密数据;
第三部分:从 1024+6 之后的所有数据为异或加密的数据。

用 010、UE 等十六进制编辑器打开一个 wxapkg,会很容易看到三个部分的界限。

文件第二部分的 AES CBC 加密,使用的 key 与对应的微信小程序id有关。

文件第三部分的异或加密,真就是简单的异或,xorkey 为微信小程序 id 的倒数第二字节的内容。

上源码,在main函数下给定dir_path即导出后wxapkg所在电脑文件夹路径。

 
 
 
# coding: utf-8
__author__ = '行简'
 
import sys, os
import struct
 
 
class WxapkgFile(object):
    nameLen = 0
    name = ""
    offset = 0
    size = 0
 
 
def main(dir_path):
    with open(dir_path, "rb") as f:
        root = os.path.dirname(os.path.realpath(f.name))
        name = os.path.basename(f.name) + '_dir'
        if len(sys.argv) > 2:
            name = sys.argv[2]
        #read header
        firstMark = struct.unpack('B', f.read(1))[0]
        print('first header mark = {}'.format(firstMark))
 
        info1 = struct.unpack('>L', f.read(4))[0]
        print('info1 = {}'.format(info1))
 
        indexInfoLength = struct.unpack('>L', f.read(4))[0]
        print('indexInfoLength = {}'.format(indexInfoLength))
 
        bodyInfoLength = struct.unpack('>L', f.read(4))[0]
        print('bodyInfoLength = {}'.format(bodyInfoLength))
 
        lastMark = struct.unpack('B', f.read(1))[0]
        print('last header mark = {}'.format(lastMark))
 
        if firstMark != 0xBE or lastMark != 0xED:
            print('its not a wxapkg file!!!!!')
            f.close()
            exit()
 
        fileCount = struct.unpack('>L', f.read(4))[0]
        print('fileCount = {}'.format(fileCount))
 
        #read index
        fileList = []
        for i in range(fileCount):
            data = WxapkgFile()
            data.nameLen = struct.unpack('>L', f.read(4))[0]
            data.name = f.read(data.nameLen)
            data.offset = struct.unpack('>L', f.read(4))[0]
            data.size = struct.unpack('>L', f.read(4))[0]
            print('readFile = {} at Offset = {}'.format(str(data.name, encoding = "utf-8"), data.offset))
            fileList.append(data)
 
        #save files
        for d in fileList:
            d.name = '/' + name + str(d.name, encoding = "utf-8")
            path = root + os.path.dirname(d.name)
            if not os.path.exists(path):
                os.makedirs(path)
            w = open(root + d.name, 'wb')
            f.seek(d.offset)
            w.write(f.read(d.size))
            w.close()
            print('writeFile = {}{}'.format(root, d.name))
        f.close()
 
 
if __name__ == '__main__':
    dir_path = r'xxxx'   # You wxapkg file path
    main(dir_path)
# coding: utf-8
__author__ = '行简'
 
import sys, os
import struct
 
 
class WxapkgFile(object):
    nameLen = 0
    name = ""
    offset = 0
    size = 0
 
 
def main(dir_path):
    with open(dir_path, "rb") as f:
        root = os.path.dirname(os.path.realpath(f.name))
        name = os.path.basename(f.name) + '_dir'
        if len(sys.argv) > 2:
            name = sys.argv[2]
        #read header
        firstMark = struct.unpack('B', f.read(1))[0]
        print('first header mark = {}'.format(firstMark))
 
        info1 = struct.unpack('>L', f.read(4))[0]
        print('info1 = {}'.format(info1))
 
        indexInfoLength = struct.unpack('>L', f.read(4))[0]
        print('indexInfoLength = {}'.format(indexInfoLength))
 
        bodyInfoLength = struct.unpack('>L', f.read(4))[0]

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2023-6-9 09:32 被行简编辑 ,原因:
收藏
免费 11
支持
分享
最新回复 (5)
雪    币: 477
活跃值: (1412)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
小程序怎么抓包
2023-6-9 13:36
0
雪    币: 960
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
mb_foyotena 小程序怎么抓包
可以试试http debugger
2023-6-9 14:19
0
雪    币: 27
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
分包怎么整?大佬
2023-6-13 16:50
0
雪    币: 3140
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
是不是PC版的解不出来
2023-6-14 20:06
0
雪    币: 672
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
code怎么获取
2023-6-21 02:35
0
游客
登录 | 注册 方可回帖
返回
//