吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 10826|回复: 100
收起左侧

[Android 原创] 67行代码写个脱壳机

    [复制链接]
Richor 发表于 2020-8-18 10:00
身为一只菜鸡,代码分析不出来没关系,但是壳一定要是会脱,不会脱壳的菜鸡那跟咸鱼有什么区别?
写代码是不可能写代码的,只能靠抄代码才能维持一下生活。所以呢,我觉得用最少的代码写一个脱壳机还是有必要的。

1.加壳原理
讲糙一点就是,apk里套apk,把真实的apk套在壳程序apk里。(母猪戴胸罩,一套又一套,听懂掌声)

听懂掌声

听懂掌声

2.脱壳原理
不管壳程序怎么搞,最终还是要又真实的dex可以运行对吧?那我们把内存中运行的真实dex导出来不会好了(什么是dex?别问,问就是自己百度)
3.art脱壳机编写:
(1)环境:1.frIDA
        2.真机
(2)dlopen.so
dlopen()是一个强大的库函数。该函数将打开一个新库,并把它装入内存。该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的。这种机制使得在系统中添加或者删除一个模块时,都不需要重新编译了。可以在自己的程序中使用 dlopen()。dlopen() 在 dlfcn.h 中定义,并在 dl 库中实现。它需要两个参数:一个文件名和一个标志。文件名就是一个动态库so文件,标志指明是否立刻计算库的依赖性。如果设置为 RTLD_NOW 的话,则立刻计算;如果设置的是 RTLD_LAZY,则在需要的时候才计算。另外,可以指定 RTLD_GLOBAL,它使得那些在以后才加载的库可以获得其中的符号。当库被装入后,可以把 dlopen() 返回的句柄作为给 dlsym() 的第一个参数,以获得符号在库中的地址。使用这个地址,就可以获得库中特定函数的指针,并且调用装载库中的相应函数。就是说所有的So都会在这里进行加载,那么我们先来分析一下这个so
dlopen Hook
[JavaScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
function hook_dlopen() {
    Interceptor.attach(Module.findExportByName(null, "dlopen"), {
        onEnter: function (args) {
            var pathptr = args[0];
            if (pathptr !== undefined && pathptr != null) {
                var path = ptr(pathptr).readCString();
                console.log("dlopen:", path);
            }
        },
        onLeave: function (retval) {
 
        }
    })
 
}
 
setImmediate(hook_dlopen);

运行结果
frida -U --no-pause -f com.xxx.xxxx-l dexDump.js

1

1


这个libart.so就是我们接下要分析的so
(3)libart.so
libart.so是4.4以上art虚拟机的,最终的dex将会在art虚拟机上运行
[JavaScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
function hook_art(){
    var libart = Process.findModuleByName("libart.so");
    var symbols = libart.enumerateSymbols();     //枚举模块的符号
    var addr_classloaer=null;
    for (var i = 0; i < symbols.length; i++) {
        var name = symbols[i].name;
        // console.log(name)  //有需要打印一下,但是太长了我就不打印了
        if (name.indexOf("ClassLinker") >= 0 && name.indexOf("DefineClass") >= 0 && name.indexOf("Thread") >= 0 && name.indexOf("DexFile") >= 0 ) {
            console.log("找到了classloader,打印一下呗");  
            console.log(name, symbols[i].address);
            addr_classloaer =symbols[i].address;
        }
    }
     
 
}
 
 
 
function hook_dlopen() {
    var hooked = false;//hooked作为判断标识,是否已hook
     
    var dlname="dlopen";
    // var dlname="android_dlopen_ext"; // 高版本Android系统使用android_dlopen_ext
    Interceptor.attach(Module.findExportByName(null, dlname), {
        onEnter: function (args) {
            var pathptr = args[0];
            if (pathptr !== undefined && pathptr != null) {
                var path = ptr(pathptr).readCString();
                if (path.indexOf("libart.so") >= 0) {
                    this.bb = true;//bb作为判断标识,是否art已载入
                }
            }
        },
        onLeave: function (retval) {
            if (this.bb& !hooked){
                console.log("开始hook art")
                hook_art();
                hooked=true;
            }
        }
    })
 
     
 
}
 
setImmediate(hook_dlopen);

运行结果

2

2

(4)classloader Dump dex
最终的dex文件是在classloader函数中的参数中,我们只需要把文件dump出来就可以了
[JavaScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//frida -U --no-pause -f com.xx.xxxx -l dexDump.js
 
function Wrifile(dex_path,dex_buffer){
    var fd = new File(dex_path, "wb");
    if (fd && fd != null) {
        fd.write(dex_buffer);
        fd.flush();
        fd.close();
        console.log("导出文件:", dex_path);
    }
}
 
function hook_art(){
    var libart = Process.findModuleByName("libart.so");
    var symbols = libart.enumerateSymbols();     //枚举模块的符号
    var addr_classloaer=null;
    for (var i = 0; i < symbols.length; i++) {
        var name = symbols[i].name;
        // console.log(name)  //有需要打印一下,但是太长了我就不打印了
        if (name.indexOf("ClassLinker") >= 0 && name.indexOf("DefineClass") >= 0 && name.indexOf("Thread") >= 0 && name.indexOf("DexFile") >= 0 ) {
            console.log("找到了classloader,打印一下呗");  
            console.log(name, symbols[i].address);
            addr_classloaer =symbols[i].address;
        }
    }
    var dex_maps = {};//用一个map来作为判断是否已读取的标识
    if (addr_classloaer) {
        Interceptor.attach(addr_classloaer, {
            onEnter: function (args) {
                var dex_file = args[5];
                var base = ptr(dex_file).add(Process.pointerSize).readPointer();
                var size = ptr(dex_file).add(Process.pointerSize + Process.pointerSize).readUInt();
                if (dex_maps[base] == undefined) {
                    dex_maps[base] = size;
                    var magic = ptr(base).readCString();
                    if (magic.indexOf("dex") == 0) {
                        var path = "/sdcard/DCIM/";//这边可以随便定义一个路径,建议是以包名为路径
                        var dex_path = path + base.toString(16) + "_" + size.toString(16) + ".dex";
                        var dex_buffer = ptr(base).readByteArray(size);
                        Wrifile(dex_path,dex_buffer)  
                    }
                }
            }, onLeave: function (retval) {
            }
        });
 
    }
     
 
}
 
 
 
function hook_dlopen() {
    var hooked = false;//hooked作为判断标识,是否已hook
     
    var dlname="dlopen";
    // var dlname="android_dlopen_ext"; // 高版本Android系统使用android_dlopen_ext
    Interceptor.attach(Module.findExportByName(null, dlname), {
        onEnter: function (args) {
            var pathptr = args[0];
            if (pathptr !== undefined && pathptr != null) {
                var path = ptr(pathptr).readCString();
                if (path.indexOf("libart.so") >= 0) {
                    this.bb = true;//bb作为判断标识,是否art已载入
                }
            }
        },
        onLeave: function (retval) {
            if (this.bb& !hooked){
                console.log("开始hook art")
                hook_art();
                hooked=true;
            }
        }
    })
 
     
 
}
 
setImmediate(hook_dlopen);

运行结果

3

3



dexDump.rar

1.27 KB, 下载次数: 253, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 31威望 +1 吾爱币 +45 热心值 +29 收起 理由
zhuzhuxia111 + 1 + 1 我很赞同!
cumtboy + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
qtfreet00 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
wang3166wang + 1 + 1 用心讨论,共获提升!
y18348897781 + 1 谢谢@Thanks!
陈世界 + 1 + 1 我很赞同!
小哥9527 + 1 + 1 热心回复!
CPSAndy + 1 + 1 谢谢@Thanks!
2165998 + 1 用心讨论,共获提升!
Tomatoman + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
z1346789 + 1 我学的专业是python 但是现在还没看懂以后在学
hydai520 + 1 谢谢@Thanks!
stars-one + 1 + 1 emm 只会脱壳,不会修复
MUMUAA + 1 热心回复!
card628 + 1 + 1 谢谢@Thanks!
青色菩提 + 1 + 1 热心回复!
By阿清 + 1 + 1 我很赞同!
chinawolf2000 + 1 + 1 热心回复!
笙若 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
aisinill + 1 + 1 用心讨论,共获提升!
yudian + 1 + 1 我很赞同!
庸世俗人罢勒 + 1 + 1 谢谢@Thanks!
jwbdr1230123 + 1 + 1 我很赞同!
5_love + 1 + 1 我很赞同!
RemMai + 1 + 1 第一张表情包就看笑了,哈哈哈
Gumping + 1 + 1 我很赞同!
dragonhappy6 + 1 + 1 用心讨论,共获提升!
ycuvuuui1L + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
生有涯知无涯 + 1 + 1 我很赞同!
dayer + 1 我很赞同!
涛之雨 + 2 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

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

口袋C 发表于 2020-8-18 13:02
感谢楼主分享 不过我这有个更少代码量的 也分享出来吧
[Python] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
'use strict';
 
Interceptor.attach(Module.findExportByName("libart.so", "_ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_10OatDexFileEPS9_"), {
    onEnter: function (args) {
       
        //dex起始位置
        var begin = args[1]
        //打印magic
        console.log("magic : " + Memory.readUtf8String(begin))
        //dex fileSize 地址
        var address = parseInt(begin,16) + 0x20
        //dex 大小
        var dex_size = Memory.readInt(ptr(address))
 
        console.log("dex_size :" + dex_size)
        //dump dex 到/data/data/pkg/目录下
        var file = new File("/storage/emulated/0/Pictures/*.*.*/" + dex_size + ".dex", "wb")
        file.write(Memory.readByteArray(begin, dex_size))
        file.flush()
        file.close()
    },
    onLeave: function (retval) {
        if (retval.toInt32() > 0) {
            /* do something */
        }
    }
});

免费评分

参与人数 5吾爱币 +4 热心值 +5 收起 理由
SharsDela + 1 + 1 我很赞同!
Dragon_214 + 1 + 1 用心讨论,共获提升!
Tomatoman + 1 用心讨论,共获提升!
wangxd + 1 + 1 已经处理,感谢您对吾爱破解论坛的支持!
fengbolee + 1 + 1 用心讨论,共获提升!

查看全部评分

涛之雨 发表于 2020-8-18 10:10
顺手看了一眼,是安卓的大佬啊!

frida想学的。。
环境搭起来就没继续看
有空学习一下
BaiTuGe 发表于 2020-8-18 10:15
zisain 发表于 2020-8-18 10:42
牛逼啊兄弟
a6608816 发表于 2020-8-18 11:02
封面就可以给满分了
校长小哥哥 发表于 2020-8-18 11:13
只能脱360吧
Cra2yZer0 发表于 2020-8-18 11:19

有空学习一下有空学习一下
dglbl 发表于 2020-8-18 11:27
看不懂,要多加学习才行
mitchzh 发表于 2020-8-18 11:29
牛啊,mark一下,回头学习
zsjalive 发表于 2020-8-18 11:52
安卓的不是太懂,但是还是觉得可以的,感觉网上应该有挺多的吧。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2025-4-13 21:12

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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