分析伏羲万年历

news/2025/2/3 0:03:47 标签: 逆向

功能分析

日历功能
https://github.com/6tail/lunar-java
Lunar
https://6tail.cn/calendar/api.html

Http抓包

使用Charles进行HTTPS抓包
https://zhaojian.blog.csdn.net/article/details/130281149

找到代理的ip地址

ifconfig | grep inet | grep 192

设置手机代理

常用命令

脱壳

360加固脱壳实战
https://blog.csdn.net/AdrianAndroid/article/details/137523091?sharetype=blogdetail&sharerId=137523091&sharerefer=PC&sharesource=AdrianAndroid&spm=1011.2480.3001.8118

057-基于frida的一键脱壳+反编译
https://anjia0532.github.io/2021/02/04/frida-android-decompile/

基于Frida的脱壳工具frida-unpack使用教程
https://blog.csdn.net/gitblog_00459/article/details/141846873

Frida 脱壳
https://blog.csdn.net/m0_57836225/article/details/144680309

逆向调试利器:Frida
https://book.crifan.org/books/reverse_debug_frida/website/

Hook神器: frida超详细安装教程
https://blog.csdn.net/qq_41179280/article/details/112467196

Kali 1.Frida环境搭建
https://blog.csdn.net/weixin_43197623/article/details/125116972

unpack.js

/*
# Author: samle
# CreateTime: 2024/09/03

*/


function get_self_package_name(){
    var openPtr = Module.getExportByName("libc.so","open");
    var open = new NativeFunction(openPtr,'int',['pointer','int']);

    var readPtr = Module.getExportByName("libc.so","read");
    var read = new NativeFunction(readPtr,'int',['int','pointer','int']);

    var closePtr = Module.getExportByName("libc.so","close");
    var close = new NativeFunction(closePtr,'int',['int']);
    //申请字符串空间,声明字符串
    var path = Memory.allocUtf8String("/proc/self/cmdline");
    /*
    cmdline内容:
    6F 72 67 2E 73 61 6D 6C 65 2E 74 65 73 74 64 65                 org.samle.testdex
    78 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00
    */
    var fd = open(path,0);
    if(fd != -1){
        var buffer = Memory.alloc(0x1000);
        var result = read(fd,buffer,0x1000);
        close(fd);
        result = ptr(buffer).readCString();      //读取c风格字符串,会被/0截断字符串,从而拿到包名
        return result;
    }
    return -1;

}

function mkdir(path){

    var mkdirPtr = Module.getExportByName("libc.so","mkdir");
    var mkdirFun = new NativeFunction(mkdirPtr,'int',['pointer','int']);

    var opendirPtr = Module.getExportByName("libc.so",'opendir');
    var opendir = new NativeFunction(opendirPtr,'pointer',['pointer']);

    var closedirPtr = Module.getExportByName('libc.so','closedir');
    var closedir = new NativeFunction(closedirPtr,'int',['pointer']);

    var cPath = Memory.allocUtf8String(path);
    var dir = opendir(cPath);
    //打开指定路径文件夹失败就退出
    if(dir != 0){
        closedir(dir);
        return 0;
    }
    //创建文件夹
    mkdirFun(cPath,755);
    //修改权限
    chmod(path);
    //已经是755权限了,干嘛还是调用chmod,???
}
function chmod(path){
    var chmodPtr = Module.getExportByName('libc.so','chmod');
    var chmodFun = new NativeFunction(chmodPtr,'int',['pointer','int']);
    var cPath = Memory.allocUtf8String(path);
    chmodFun(cPath,755);


}
function dump_dex(){

    console.log("dump_dex");
    //查找libart.so的模块基址
    var libart = Process.findModuleByName("libart.so");
    var addr_DefineClass  = null;
    //枚举函数符号,查找defineclass的函数签名
    var symbols = libart.enumerateSymbols();
    for(var index = 0; index < symbols.length; index++){
        var symbol = symbols[index];
        var symbol_name = symbol.name;
        //这个DefineClass的函数签名是android 9的
        //_ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS9_8ClassDefE

        //android 10的DefineClass函数签名
        //_ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS_3dex8ClassDefE
        /*mirror::Class* ClassLinker::DefineClass(Thread* self,
                                        const char* descriptor,
                                        size_t hash,
                                        Handle<mirror::ClassLoader> class_loader,
                                        const DexFile& dex_file,
                                        const DexFile::ClassDef& dex_class_def) 
        可以看到DefineClass的参数有一个dexfile对象                                                      
                                        */
        if( symbol_name.indexOf("ClassLinker") >= 0 && 
            symbol_name.indexOf("DefineClass") >= 0 &&
            symbol_name.indexOf("Thread") >= 0 &&
            symbol_name.indexOf("DexFile") >= 0){

                console.log(symbol_name,symbol.address);
                addr_DefineClass = symbol.address;
            }
        //console.log("libart.so symbols_name",symbol_name)
    }
    
    if(addr_DefineClass == null){
        console.log("没有找到defineClass函数符号信息,退出!");
        return;
    }

    var dex_maps = { };
    var dex_count = 1;
    console.log("[DefineClass:]",addr_DefineClass);
    if(addr_DefineClass){
        Interceptor.attach(addr_DefineClass,{
            onEnter: function(args) {
    
                var dex_file = args[5];
                //console.log(Process.pointerSize) = 4
                //var magic = dex_file.readByteArray(10)
                //var dex_file_addr = ptr(dex_file)
                //console.log("dex_file_addr ",dex_file_addr);

                //var addr_P = ptr(dex_file).add(Process.pointerSize)
                //console.log("addr_P ",addr_P);

                //var addr_PP = ptr(dex_file).add(Process.pointerSize + Process.pointerSize)
                //console.log("addr_PP ",addr_PP);

                var base = ptr(dex_file).add(Process.pointerSize).readPointer();
                var size = ptr(dex_file).add(Process.pointerSize + Process.pointerSize).readUInt();
                //console.log("magic  " ,Memory.readUtf8String(base)) 读出”dex换行035“

                //console.log("base " , base);
                //console.log("size ", size)
                //var size = 0x60; // 要读取的字节长度
                //var bytes = Memory.readByteArray(base, size);
                //console.log(hexdump(bytes, {
                //offset: 0,
                //length: bytes.byteLength,
                //header: true,
                //ansi: true
                //}));

                //ptr(dex_file).add(Process.pointerSize) is "const uint8_t* const begin_;"
                //ptr(dex_file).add(Process.pointerSize + Process.poniterSize) is "const size_t size_ "

                //Short-hand for `new NativePointer(value)`.
                //将这个地址解析一个native指针
            /*
            DexFile::DexFile(const uint8_t* base,
                            size_t size,    dex文件长度
                            const uint8_t* data_begin,
                            size_t data_size,
                            const std::string& location,
                            uint32_t location_checksum,
                            const OatDexFile* oat_dex_file,
                            std::unique_ptr<DexFileContainer> container,
                            bool is_compact_dex)
            */
                //dex_maps是一个空对象,被size赋值后变成了Object {1193046: 26505},避免再次进入后重复dump,过滤器的作用
                if(dex_maps[base] == undefined){
                    dex_maps[base] = size;
                    var magic = ptr(base).readCString();
                    if(magic.indexOf("dex") == 0){
                        var package_name  = get_self_package_name();
                        if(package_name != "-1"){
                            var dex_dir_path = "/data/data/" + package_name + "/files/dump_dex_" + package_name;
                            mkdir(dex_dir_path);
                            var dex_path = dex_dir_path + "/class" + (dex_count == 1 ? "" : dex_count) + ".dex";
                            //console.log("[find dex]: ", dex_path);
                            var fd = new File(dex_path, "wb");
                            if(fd && fd != null){
                                dex_count++;
                                var dex_buffer = ptr(base).readByteArray(size);
                                fd.write(dex_buffer);
                                fd.flush();
                                fd.close();
                                console.log("[dump dex]: ",dex_path);
    
                            }
                        }
                        
                    }
                }
    
            },
            onLeave:function(retval) {}
        });
    }
    
}




setImmediate(dump_dex)

/*
总结以下dump_dex函数的流程

    1. 获取libart.so的地址,枚举符号找到DefineClass的函数地址
    2. 使用Interceptor内联hook DefineClass函数,获取dexFile对象的base和size
    3. 在包名的files目录下创建一个dump_dex_包名的文件夹,从dexfile的base读取size个字节写入文件


*/

http://www.niftyadmin.cn/n/5840384.html

相关文章

1979-2021年 全国各省、地级市、区县空气流通系数

1979-2021年 全国各省、地级市、区县空气流通系数.ziphttps://download.csdn.net/download/2401_84585615/89649517 https://download.csdn.net/download/2401_84585615/89649517 1979-2021年&#xff0c;全国各省、地级市、区县空气流通系数的研究数据&#xff0c;对于分析我国…

【LeetCode】5. 贪心算法:买卖股票时机

太久没更了&#xff0c;抽空学习下。 看一道简单题。 class Solution:def maxProfit(self, prices: List[int]) -> int:cost -1profit 0for i in prices:if cost -1:cost icontinueprofit_ i - costif profit_ > profit:profit profit_if cost > i:cost iret…

蓝桥杯之c++入门(二)【输入输出(上)】

目录 前言1&#xff0e;getchar和 putchar1.1 getchar()1.2 putchar() 2&#xff0e;scanf和 printf2.1 printf2.1.1基本用法2.1.2占位符2.1.3格式化输出2.1.3.1 限定宽度2.1.3.2 限定小数位数 2.2 scanf2.2.1基本用法2.2.2 占位符2.2.3 scanf的返回值 2.3练习练习1&#xff1a…

DIFY源码解析

偶然发现Github上某位大佬开源的DIFY源码注释和解析&#xff0c;目前还处于陆续不断更新地更新过程中&#xff0c;为大佬的专业和开源贡献精神点赞。先收藏链接&#xff0c;后续慢慢学习。 相关链接如下&#xff1a; DIFY源码解析

基于改进的强跟踪技术的扩展Consider Kalman滤波算法在无人机导航系统中的应用研究

在无人机组合导航系统中&#xff0c;精确的状态估计对于任务的成功执行至关重要。然而&#xff0c;系统面临的非线性特性和不确定性&#xff0c;如传感器的量测偏差和动态环境变化&#xff0c;常常导致传统Kalman滤波算法失效。因此&#xff0c;提出一种鲁棒且有效的滤波算法&a…

二级C语言:二维数组每行最大值与首元素交换、删除结构体的重复项、取出单词首字母

目录 一、程序填空 --- 二维数组每行最大值与首元素交换 题目 分析 知识点 --- 交换语句 二、程序修改 --- 删除结构体的重复项 题目 分析 三、程序设计 --- 取出单词首字母 题目 分析 前言 本章讲解&#xff1a;二维数组每行最大值与首元素交换、删除结构体的重复项…

玉米苗和杂草识别分割数据集labelme格式1997张3类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;1997 标注数量(json文件个数)&#xff1a;1997 标注类别数&#xff1a;3 标注类别名称:["corn","weed","Bean…

【Redis】set 和 zset 类型的介绍和常用命令

1. set 1.1 介绍 set 类型和 list 不同的是&#xff0c;存储的元素是无序的&#xff0c;并且元素不允许重复&#xff0c;Redis 除了支持集合内的增删查改操作&#xff0c;还支持多个集合取交集&#xff0c;并集&#xff0c;差集 1.2 常用命令 命令 介绍 时间复杂度 sadd …