吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6066|回复: 19
收起左侧

[Android 原创] lua脚本的sfp脱壳(fa数据保护的加固lua)

[复制链接]
nwdxlgzs 发表于 2020-12-22 01:56
本帖最后由 nwdxlgzs 于 2020-12-22 01:59 编辑

加固是我写的,因为我是FusionApp官方群管理员,我想给群员一个代码保护https://nwdxlgzs.lanzouj.com/iQY4jge7oab,于是在java层写了一个中继,从而实现加密。代码很简单,只有20.56kb,为了增加难度,用了arm pro的dex2c于是组成现在的套壳加密程序。我这里分享解密算法,因为我收到了有人用他加固恶意代码勒索钱财的事,这个和我想象的背道而驰,之前在酷安下头https://www.coolapk.com/feed/23542290?shareKey=YzY1N2UzYTY4MTRmNWZlMGRmMjE~&shareUid=2769995&shareFrom=com.coolapk.market_10.5.3我就说明了,现在我想了想,为了阻止这个产业的扩大,我决定分享解密算法。程序分两种存储,dex和sfpc文件。
--path="dex路径"
--loader=activity.loadDex(path)
--dumpSimpleFreeProtect().dumpClass(loader,"com.sfp.data.lua",File("/storage/emulated/0/out"))

--path="sfpc文件夹路径"
--dumpSimpleFreeProtect().dumpDir(File(path),File("/storage/emulated/0/out"))
有这两种批量解密方法。
java的解密算法如下

package com;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.content.pm.Signature;

public class dumpSimpleFreeProtect {
    public dumpSimpleFreeProtect(){}
    public void dump(File[] files,File out) {
        int i=0;
        for (File file:files) {
            i++;
            try {
                Object[] result= newInvoke(file);
                write(new File(out, String.valueOf(i) + ".lua"), (String)result[0]);
                write(new File(out, String.valueOf(i) + ".signature"), (String)result[1]);
            } catch (Exception e) {}
        }
    }
    public void dump(Class[] classes,File out) {
        int i=0;
        for (Class cls:classes) {
            i++;
            try {
                Object[] result= newInvoke(cls);
                write(new File(out, String.valueOf(i) + ".lua"), (String)result[0]);
                write(new File(out, String.valueOf(i) + ".signature"), (String)result[1]);
            } catch (Exception e) {}
        }
    }
    public void dumpDir(File fileDir,File out) {
        dump(fileDir.listFiles(), out);
    }
    public void dumpClass(ClassLoader loader,String CLS,File out) {
        int i=0;
        while (true) {
            i++;
            try {
                Class cls=loader.loadClass(CLS + i);
                try {
                    Object[] result= newInvoke(cls);
                    write(new File(out, String.valueOf(i) + ".lua"), (String)result[0]);
                    write(new File(out, String.valueOf(i) + ".signature"), (String)result[1]);
                } catch (Exception e) {}
            } catch (ClassNotFoundException e) {
                break;
            }
        }
    }
    public Object[] newInvoke(File path) throws FileNotFoundException, IOException {
        FileInputStream is=new FileInputStream(path);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte buff[] = new byte[1024];
        int len = 0;
        while ((len = is.read(buff)) != -1) {
            baos.write(buff, 0, len);
        }
        baos.flush();
        byte[] byteData = baos.toByteArray();
        baos.close();
        return newInvoke(byteData);
    }
    public  Object[] newInvoke(Class cls) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        Object clsO=cls.newInstance();
        Method m=cls.getMethod("getBytes");
        byte[] b=(byte[]) m.invoke(clsO);
        return newInvoke(b);
    }
    public Object[] newInvoke(byte[] byteData) {
        //类base64解密
        int iSrcIdx;
        int reviSrcIdx;
        int iDestIdx;
        byte[] byteTemp = new byte[byteData.length];
        for (reviSrcIdx = byteData.length; reviSrcIdx - 1 > 0 && byteData[reviSrcIdx - 1] == '='; reviSrcIdx--) {;}
        if (reviSrcIdx - 1 == 0) { return null;}
        byte byteDest[] = new byte[((reviSrcIdx * 3) / 4)];
        for (iSrcIdx = 0; iSrcIdx < reviSrcIdx; iSrcIdx++) {
            if (byteData[iSrcIdx] == '+')
                byteTemp[iSrcIdx] = 62;
            else if (byteData[iSrcIdx] == '/')
                byteTemp[iSrcIdx] = 63;
            else if (byteData[iSrcIdx] < 2 + 10)
                byteTemp[iSrcIdx] = (byte) (byteData[iSrcIdx] + 52 - 2);//0
            else if (byteData[iSrcIdx] < (12 + 26))
                byteTemp[iSrcIdx] = (byte) (byteData[iSrcIdx] - 12);//A
            else if (byteData[iSrcIdx] < (100 + 26))
                byteTemp[iSrcIdx] = (byte) (byteData[iSrcIdx] + 26 - 100);//a
        }
        for (iSrcIdx = 0, iDestIdx = 0; iSrcIdx < reviSrcIdx
            && iDestIdx < ((byteDest.length / 3) * 3); iSrcIdx += 4) {
            byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx] << 2) & 0xFC | (byteTemp[iSrcIdx + 1] >>> 4) & 0x03);
            byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx + 1] << 4) & 0xF0 | (byteTemp[iSrcIdx + 2] >>> 2) & 0x0F);
            byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx + 2] << 6) & 0xC0 | byteTemp[iSrcIdx + 3] & 0x3F);
        }
        if (iSrcIdx < reviSrcIdx) {
            if (iSrcIdx < reviSrcIdx - 2) {
                byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx] << 2) & 0xFC | (byteTemp[iSrcIdx + 1] >>> 4) & 0x03);
                byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx + 1] << 4) & 0xF0 | (byteTemp[iSrcIdx + 2] >>> 2) & 0x0F);
            } else if (iSrcIdx < reviSrcIdx - 1) {
                byteDest[iDestIdx++] = (byte) ((byteTemp[iSrcIdx] << 2) & 0xFC | (byteTemp[iSrcIdx + 1] >>> 4) & 0x03);
            }
        }
        //处理解码后数据
        String str=new String(byteDest);
        String tmp=str.substring(0, 1);
        int index=Integer.valueOf(tmp);
        String lengthS=str.substring(1, 1 + index);//截取签名块长度
        int lengthI=Integer.valueOf(lengthS);//长度
        String sign=str.substring(index + 1, index + 1 + lengthI);
        str = str.substring(index + 1 + lengthI, str.length());
        Object[] result=new Object[]{str,sign};
        return result;
    }

    public static void write(File out,String xml) throws FileNotFoundException, IOException {
        FileOutputStream fileOutputStream = new FileOutputStream(out);
        fileOutputStream.write(xml.getBytes());
        fileOutputStream.close();
    }
    public static void write(File out,byte[] by) throws FileNotFoundException, IOException {
        FileOutputStream fileOutputStream = new FileOutputStream(out);
        fileOutputStream.write(by);
        fileOutputStream.close();
    }
}
加固了恶意代码我也很烦。如果谁遇到需要解密那些病毒,用这个解密就好,不必研究机制。

免费评分

参与人数 4吾爱币 +19 热心值 +4 收起 理由
内瑟斯 + 1 + 1 热心回复!
北极狼Clifton + 1 + 1 谢谢@Thanks!
007nbqaq + 1 + 1 我很赞同!
涛之雨 + 16 + 1 自制加密的都是大佬啊

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

天咗 发表于 2020-12-23 02:04
大佬 求 一个完整的 landlua+的         读写   还原  

类似 这样的a=activity.getLuaDir("/res/放置需要取得文本")
    LuaUtil.copyDir(a,"//写入的绝对路径/文件名")-
    print("开启替换")
我只会写替换 不会写  写入  好多代码需要写入一个文件里 替换就做不到了

万分感谢  求大佬支援
 楼主| nwdxlgzs 发表于 2020-12-22 21:18
绫音 发表于 2020-12-22 08:56
这个可以解密lua脚本吗

不行,这个是解我的那个加壳的数据的程序。解开还是字节码。。。
okgjkk 发表于 2020-12-22 07:00
panielhong 发表于 2020-12-22 07:20
感谢分享
yuan6975 发表于 2020-12-22 08:31
真大佬啊
枫叶飞向海 发表于 2020-12-22 08:37
看不懂系列
绫音 发表于 2020-12-22 08:56
这个可以解密lua脚本吗
长江流域 发表于 2020-12-22 09:10
牛逼,不懂,还在自学中
lx771602764 发表于 2020-12-22 09:11
谢谢分享
zouludaifeng 发表于 2020-12-22 11:08
学习了 谢谢大佬
cqlk001 发表于 2020-12-22 12:16
真大佬 好好研究一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-27 12:23

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表