#逆向
简介
接到取证任务,提取违法游戏中的图片资源文件。
操作
分析
该游戏为apk安装包,使用apktool和jadx-gui进行简单的反编译,找到res目录中的图片打开,提示已损坏。
逆向
使用记事本打开该照片,发现文件头存在可疑字符串 shiyuegame
分析逆向后的apk文件结构,得知此游戏使用cocos2dx开发。每张加密图片下方均存在plist文件,末尾存在texturepacker标识,表明该图片资源使用了texturepacker加密:这就有了
IDA pro
在源码\app\src\main\lib\armeabi找到了libcocos2dlua.so
通过IDA打开,搜索字符串,找到了解密key
编写解密脚本
- 安装python虚拟环境,以便安装xxtea
python3 -m venv lua #开启虚拟python环境,以便安装xxtea。Mac默认python3环境无法安装xxtea
source lua/bin/activate
pip install xxtea
- 选择一个图片目录进行单张图片调试。先编写脚本:
import xxtea
def lua_decrypt(infile, outfile, sign, key):
try:
with open(infile, 'rb') as f:
buf = f.read()
signlen = len(sign)
keylen = len(key)
# Verify that the file starts with the given sign
if not buf.startswith(sign.encode()):
print(f"File does not start with the expected sign: {sign}")
print(f"First 32 bytes of the file: {buf[:32]}")
return
# Remove the sign from the buffer
buf = buf[signlen:]
# Decrypt the remaining data using XXTEA
decrypted_data = xxtea.decrypt(buf, key.encode())
# Check the decrypted data length and print the first 32 bytes for debugging
print(f"Decrypted data length: {len(decrypted_data)}")
print(f"Decrypted first 32 bytes: {decrypted_data[:32]}")
# Save the decrypted data to the output file
with open(outfile, 'wb') as f:
f.write(decrypted_data)
print(f"{infile} decrypt successful")
except Exception as e:
print(f"{infile} decrypt fail: {e}")
if 'decrypted_data' in locals():
print(f"Decrypted data length: {len(decrypted_data)}")
print(f"Decrypted first 32 bytes: {decrypted_data[:32]}")
print(f"First 32 bytes of the original file: {buf[:32]}")
if __name__ == '__main__':
if len(sys.argv) < 5:
print("usage: lua_decrypt infile outfile sign key")
sys.exit(1)
infile = sys.argv[1]
outfile = sys.argv[2]
sign = sys.argv[3]
key = sys.argv[4]
lua_decrypt(infile, outfile, sign, key)
在resource/set目录下执行:
python3 lua.py set.png out.png shiyuegame JYDYdpyRecDuHQc8
发现图片已成功解密
解密所有图片
如果把所有.png图片取出再解密,会出现文件名冲突等问题。于是遍历各个文件夹,如果存在png图片则解密,替换原图片
signlen = len(sign)
keylen = len(key)
# Verify that the file starts with the given sign
if not buf.startswith(sign.encode()):
print(f"File does not start with the expected sign: {sign}")
print(f"First 32 bytes of the file: {buf[:32]}")
return
# Remove the sign from the buffer
buf = buf[signlen:]
# Decrypt the remaining data using XXTEA
decrypted_data = xxtea.decrypt(buf, key.encode())
# Check the decrypted data length and print the first 32 bytes for debugging
print(f"Decrypted data length: {len(decrypted_data)}")
print(f"Decrypted first 32 bytes: {decrypted_data[:32]}")
# Save the decrypted data to the output file
with open(outfile, 'wb') as f:
f.write(decrypted_data)
print(f"{infile} decrypt successful")
except Exception as e:
print(f"{infile} decrypt fail: {e}")
if 'decrypted_data' in locals():
print(f"Decrypted data length: {len(decrypted_data)}")
print(f"Decrypted first 32 bytes: {decrypted_data[:32]}")
print(f"First 32 bytes of the original file: {buf[:32]}")
def decrypt_images_in_folder(folder, sign, key):
for root, _, files in os.walk(folder):
for file in files:
if file.endswith('.png'):
filepath = os.path.join(root, file)
lua_decrypt(filepath, filepath, sign, key)
if __name__ == '__main__':
if len(sys.argv) < 4:
print("usage: python script.py folder sign key")
sys.exit(1)
folder = sys.argv[1]
sign = sys.argv[2]
key = sys.argv[3]
decrypt_images_in_folder(folder, sign, key)
其他方案
组员使用C编写的解密脚本:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"xxtea.h"
int main(int argc,char*argv[]){
FILE*fp;
char*key;
char*sign;
char*infile;
char*outfile;
char*buf,*data;
unsigned long size;
int keylen,signlen,retlen;
if(argc<5){
printf("usage:lua_decrypt infile outfile sign key\n");
return -1;
}
else{
infile=argv[1];
outfile=argv[2];
sign=argv[3];
key=argv[4];
keylen=strlen(key);
signlen=strlen(sign);
}
if((fp=fopen(infile,"rb"))==NULL){
perror("can't open the input file");
return -1;
}
fseek(fp, 0L, SEEK_END);
size=ftell(fp);
rewind(fp);
buf=(char*)malloc(size);
fread(buf,size,1,fp);
fclose(fp);
data=xxtea_decrypt(buf+signlen,size-signlen,key,keylen,&retlen);
if(data==NULL){
printf("%s decrypt fail\n",infile);
return -1;
}
if((fp=fopen(outfile,"wb+"))==NULL){
perror("can't open the output file");
return -1;
}
fwrite(data,retlen,1,fp);
fclose(fp);
free(data);
printf("%s decrypt successful\n",infile);
return 0;
}
遍历破解:
#!/bin/bash
# 父目录路径
parent_dir="/home/kali/xxtea/png/FGOBT_YNBT_v1.2.7_0514/"
# 加密解密工具路径和参数
decrypt_tool="./lua_decrypt"
key="shiyuegame"
iv="JYDYdpyRecDuHQc8"
# 查找所有包含 PNG 图片的目录
find "$parent_dir" -type d -exec sh -c '
for dir do
# 检查目录中是否有 PNG 图片
if ls "$dir"/*.xml 1> /dev/null 2>&1; then
echo "处理目录: $dir"
# 迭代目录中的所有 PNG 图片
for file in "$dir"/*.xml; do
# 获取文件名(不包含路径部分)
filename=$(basename -- "$file")
# 解密并覆盖原文件
'"$decrypt_tool"' "$file" "$file" "'"$key"'" "'"$iv"'"
echo "文件 $filename 解密完成"
done
fi
done' sh {} +
echo "解密完成"
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END