在Mac上构建Lua扩展模块:AES解密与Base64解码实战
今天我要分享一个实用技术:如何在Mac系统上为Lua编写和编译C扩展模块,特别是实现一个某东iOS PIN码解密功能的扩展。这对于需要在Lua环境中执行高性能计算或使用底层系统功能的开发者非常有用。
起因
某东ios环境中是对pin
,wskey
进行加密存储在plist
中的,具体可参阅我之前的文章
某电商ios版WJLoginInfo.plist和*DLoginInfo.plist文件的应用与安全机制分析
那我们常用的触动精灵
,只有aes-ecb
加解密函数,并没有aes-cbc
加解密函数,所以使用起来很不方便
想要从plist中读取加密的cookie,并还原出明文的话,更是困难重重。
所以,本文即探讨如何使用lua的配合c代码自行编译so,用来解密此cookie,方便手机中直接读取明文。
下面实操(本文仅做技术探讨,故已经抹去关键信息,仅做抛砖引玉功能)
1. 安装Lua 5.2
由于目标环境使用的是Lua 5.2,首先需要在Mac上安装相应版本:
# 下载Lua 5.2.1源码
# 下载地址:http://www.lua.org/ftp/lua-5.2.1.tar.gz
# 解压并进入目录
cd lua-5.2.1
# 编译和安装
sudo make macos
sudo make install
安装完成后,可以通过启动Lua解释器来验证安装:
$lua
Lua 5.2.1 Copyright (C) 1994-2012 Lua.org, PUC-Rio
>
2. 编写C扩展模块
接下来,我们将创建一个名为mt.c
的C源文件,实现两个主要功能:
- 一个简单的Hello World函数
- 一个更复杂的IosPinDecode函数,用于解密特定格式的数据
cd src
touch mt.c
下面是核心C代码结构(出于安全考虑,部分实现细节已隐去):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include <CommonCrypto/CommonCrypto.h>
/* 库 open 函数的前置声明 */
int luaopen_mt(lua_State *L);
/*
* Base64 URL Safe 解码函数
* [实现细节已隐藏]
*/
static unsigned char* base64_url_decode(const char* input, size_t* output_length) {
// 实现Base64 URL Safe解码
// ...
}
/*
* 将十六进制字符串转换为字节数组
*/
static void hex_to_bytes(const char* hex, unsigned char* bytes, size_t len) {
// 将十六进制字符串转换为字节数组
// ...
}
/*
* AES-CBC 解密函数 每东ios中pin和wskey的关键加解密信息
*/
static unsigned char* aes_cbc_decrypt(const unsigned char* data, size_t data_len,
const char* key_hex, const char* iv_hex, size_t* out_len) {
// 使用CommonCrypto进行AES-CBC解密
// ...
}
/*
* 从JSON字符串中提取指定字段值,直接从加密后的ck解析出完整的pin=xxxxx;wskey=xxxxxx;
*/
static char* extract_json_field(const char* json, const char* field_name) {
// 提取JSON字段
// ...
}
/*
* 检查JSON中是否同时包含pin和a2字段
*/
static int has_pin_and_a2(const char* json) {
// 检查字段存在性
// ...
}
/*
* IosPinDecode 函数实现 - 解密并格式化PIN数据
*/
static int mt_ios_pin_decode(lua_State *L) {
// 1. 获取传入的编码数据
// 2. Base64 URL安全解码
// 3. 选择合适的密钥
// 4. AES-CBC解密
// 5. 处理解密结果并返回
// ...
}
/*
* Hello World函数,本函数仅用来测试so是否正常加载和工作,并没有实际作用。
*/
static int mt_hello_world(lua_State *L)
{
const char * name_str = "hello lua so,hello world";
lua_pushstring(L, name_str);
return 1;
}
/* 注册函数库 */
static const luaL_Reg mt_lib[] = {
{"hello_world", mt_hello_world},
{"IosPinDecode", mt_ios_pin_decode},
{NULL, NULL}
};
/* 库初始化函数 */
int luaopen_mt(lua_State *L)
{
luaL_newlib(L, mt_lib);
return 1;
}
3. 编译为共享库
编译过程分为两步:
第一步:编译C源文件为目标文件
xcrun -sdk iphoneos clang -c -arch arm64 mt.c -o mt.o
第二步:链接为共享库
本次xcode
版本为Version 16.0 (16A242d)
xcrun -sdk iphoneos clang -arch arm64 -isysroot $(xcrun -sdk iphoneos --show-sdk-path) \
-I/path/to/lua/include \
-L/path/to/lua/lib \
-mios-version-min=11.0 \
-O3 \
-fmodules \
-fobjc-arc \
-shared \
-undefined dynamic_lookup \
-Wl,-install_name,@rpath/mt.so \
-o mt.so mt.c
编译过程中可能会出现以下警告,但通常不影响使用:
ld: warning: -undefined dynamic_lookup is deprecated on iOS
ld: warning: search path '/path/to/lua/lib' not found
4. 在Lua中使用扩展模块
编译完成后,可以在Lua或触动精灵脚本中使用这个模块:
-- 加载模块
local mt = require "mt"
-- 调用Hello World函数
print(mt.hello_world())
-- 使用PIN解码功能
local encoded = "PqtjjdPxnYc15Ur6a7HxuHMB4_digJ2kesa2TCMRdI3_A5vIogWxWqIwWDgpVFUw..."
local decoded = mt.IosPinDecode(encoded)
print(decoded)
最后解密结果如图
技术要点解析
Base64 URL Safe解码:处理特殊的Base64编码,其中"-“替代”+“,”_“替代”/"
AES-CBC解密:使用CommonCrypto库实现AES-CBC模式解密
JSON字段提取:简单的JSON解析实现,专注于提取特定格式的字段
Lua C API使用:
luaL_checkstring()
获取Lua传入的字符串参数lua_pushstring()
将结果返回给LualuaL_newlib()
注册函数集合
总结
通过这个项目,我们学习了如何:
- 在Mac上安装和配置Lua环境
- 编写C扩展模块实现高性能功能
- 使用XCode工具链编译iOS兼容的共享库
- 在Lua环境中调用自定义C函数
这种方法非常适合需要在Lua脚本中执行性能敏感操作或访问系统底层功能的应用场景。特别是在移动自动化测试、游戏开发或需要处理加密数据的场景中,这种扩展方式能显著提升性能和扩展功能范围。
希望这个教程对你有所帮助!如有任何问题,欢迎在评论区交流。