首页
社区
课程
招聘
[原创]蛮犀加固免费版脱壳
发表于: 2023-9-20 20:49 12690

[原创]蛮犀加固免费版脱壳

2023-9-20 20:49
12690

样本只作为脱壳学习的一个样本,样本的内部逻辑并没有仔细分析,且样本较为简单,通用性差。本帖仅作为学习记录,欢迎大家一同交流。

首先先来官网看一下免费版包括的内容
图片描述
图片描述
图片描述
上传一个Demo用于加固,Demo反编译结果如下
图片描述
加固只针对Dex进行,且对类进行抽取,其效果如下
图片描述
图片描述

首先Shell创建了Application获取程序的起始控制权,之后在attachBaseContext通过Helper类加载manxi.so文件
图片描述
图片描述
图片描述
之后的步骤都是在So层进行,所以需要对So层进行分析

So通过ollvm进行混淆,首先我们先通过Qiling模拟执行去除最简单的字符串混淆
首先我们需要提取到init_array所有函数起始地址和结束地址,这里我通过IDAPython进行提取

提取到地址之后即可进行模拟执行,监听内存读写,由于字符串解密函数通过OLLVM进行混淆,所以存在对于状态变量的写入,这会导致对内存写入的Hook产生多余的结果,只需要通过判断偏移是否在.data段或者.rodata段即可判断是否对加密字符串进行写入,过滤掉不需要修改的内容后把解密内存写入文件中即可(如果某个函数不能模拟执行只需要从列表中去除即可)

解密之后就可以看到很多敏感字符串,但实际上该程序没有检测Root、Fart,只在程序启动时对Frida检测,也就是说可通过Attach来进行附加
图片描述
图片描述
图片描述

首先需要绕过启动时的Frida检测,奇怪的是我Hook dlopenandroid_dlopen_ext都无法获取到libmanxi.so的加载,但是通过Process.enumerateModules()可以得到so,这也导致了后续难以定位到检测的位置和绕过。于是使用魔改Frida https://github.com/Ylarod/Florida/releases (可绕过检测)
简单Hook了一下程序中的SVC指令,通过Radare2/adj svc可导出所有SVC指令的地址
图片描述
其中addr是导出的结果,这里只针对openat进行过滤

发现其创建线程不断打开status文件进而查询TracerPID字段
图片描述

首先尝试Hook LoadMethod进而进行脱壳

然而脱下来的壳依旧只有Shell代码,即便我们通过延迟脱壳(即首先获取DexFile的begin和size,之后通过命令行调用脱壳函数)依旧如此
图片描述
所以尝试别的办法,首先我们知道整体加固的原理是替换ClassLoader来加载原Dex,而Shell Dex尾部恰好存在着大量数据,可以猜测这就是被加密的Dex。由于Shell加载完成之后会将程序控制权归还给原程序,所以我们可以Hook performLaunchActivity,在Activity启动之前获取系统ClassLoader进而得到其加载的Dex文件进行Dump。经过测试,最后一个覆盖的Dex文件为原Dex

反编译结果如下,可以发现onCreate的方法内容未被填充
图片描述
图片描述
所以尝试延迟Dump的时机,通过Hook ArtMethod::Invoke来Dump,最终代码如下

反编译效果如下
图片描述

import idaapi
import lief
import struct
from pwn import elf, pack, unpack, u64
 
idaapi.msg_clear()
 
elf_raw = elf.ELF("D:/new/frida-agent-example-main/agent/node_modules/libmanxi_copy.so")
elf_patch = elf.ELF(
    "D:/new/frida-agent-example-main/agent/node_modules/libmanxi_copy.so"
)
print(elf_raw.entrypoint)
init_array = None
binary = lief.parse(
    "D:/new/frida-agent-example-main/agent/node_modules/libmanxi_copy.so"
)
for sec in binary.sections:
    if sec.name == ".init_array":
        init_array = sec
# Read Init_array
funcArray = []
funcArray_Address = []
index = 0
while index < init_array.size:
    offset = u64(elf_raw.read(init_array.virtual_address + index, 8))
    funcArray.append(offset)
    index += 8
funcArray.pop()
 
for func in funcArray:
    function = []
    function.append(func)
    function.append(idaapi.get_func(func).end_ea)
    funcArray_Address.append(function)
print(funcArray_Address)
import idaapi
import lief
import struct
from pwn import elf, pack, unpack, u64
 
idaapi.msg_clear()
 
elf_raw = elf.ELF("D:/new/frida-agent-example-main/agent/node_modules/libmanxi_copy.so")
elf_patch = elf.ELF(
    "D:/new/frida-agent-example-main/agent/node_modules/libmanxi_copy.so"
)
print(elf_raw.entrypoint)
init_array = None
binary = lief.parse(
    "D:/new/frida-agent-example-main/agent/node_modules/libmanxi_copy.so"
)
for sec in binary.sections:
    if sec.name == ".init_array":
        init_array = sec
# Read Init_array
funcArray = []
funcArray_Address = []
index = 0
while index < init_array.size:
    offset = u64(elf_raw.read(init_array.virtual_address + index, 8))
    funcArray.append(offset)
    index += 8
funcArray.pop()
 
for func in funcArray:
    function = []
    function.append(func)
    function.append(idaapi.get_func(func).end_ea)
    funcArray_Address.append(function)
print(funcArray_Address)
import lief
from qiling.os.const import POINTER, UINT, STRING
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_INTERCEPT
from qiling import os
from qiling.os.mapper import QlFsMappedObject
import struct
from pwn import elf, pack, unpack, u64
 
soData = lief.parse("libmanxi.so")
 
datasec = None
rodatasec = None
for sec in soData.sections:
    if sec.name == ".data":
        datasec = sec
    elif sec.name == ".rodata":
        rodatasec = sec
 
data_str = ""
elf_patch = elf.ELF(
    "D:/new/frida-agent-example-main/agent/node_modules/libmanxi_copy.so"
)
 
def write_hook(ql: Qiling, access: int, address: int, size: int, value: int):
    Addr = address - base_addr
    if (
        Addr >= datasec.virtual_address
        and Addr <= datasec.virtual_address + datasec.size
    ) or (
        Addr >= rodatasec.virtual_address
        and Addr <= rodatasec.virtual_address + rodatasec.size
    ):
        # if value >= 32 and value <= 128:
        print(
            f"Write Address: {hex(address-base_addr)} Value:{hex(value)} Size:{hex(size)}"
        )
        if size == 1:
            data = ql.pack8(value)
        elif size == 2:
            data = ql.pack16(value)
        elif size == 4:
            data = ql.pack32(value)
        elif size == 8:
            data = ql.pack64(value)
        elf_patch.write(Addr, data)
 
# Read Init_array
funcArray = [
    [22616, 23116],
    [28832, 29460],
    [39664, 40264],
    [42856, 43124],
    [43932, 44020],
    [46660, 46664],
    [55196, 62940],
    [63672, 63756],
    [63756, 63840],
    [63840, 63924],
    [73424, 73428],
    [73516, 73600],
    [87628, 88064],
    [122504, 122588],
    [123876, 124208],
    [124208, 124292],
    [125200, 125288],
    [127652, 128176],
    [131420, 131828],
    [135164, 135876],
    [153412, 154708],
    [164120, 167816],
    [175060, 175332],
    [183120, 183124],
    [183124, 183128],
    [186856, 186940],
    [193592, 193732],
    [215616, 216696],
    [219564, 219648],
    [232264, 232352],
    [232920, 232924],
    [233080, 233352],
    [244248, 253964],
    [255484, 256504],
    [258116, 258424],
    [259408, 262080],
    [262080, 262432],
    [264236, 264696],
    [268872, 269224],
    [269688, 270484],
    [274292, 276648],
    [283864, 284264],
    [286580, 287280],
    [288384, 288656],
    [291236, 291596],
    [292296, 293676],
    [294012, 295272],
    [295272, 295520],
    [295976, 296248],
    [299480, 299788],
    [300236, 307192],
    [307500, 307504],
    [311600, 312672],
    [313304, 313308],
    [316048, 316052],
    [324380, 325624],
    [378800, 380220],
    [382004, 382008],
    [389160, 389520],
    [390088, 390092],
    [392360, 392444],
    [407960, 407964],
    [410060, 410064],
    [414476, 415160],
    [448668, 457116],
    [464888, 464972],
    [469092, 469444],
    [471132, 471388],
    [472156, 472160],
    [472180, 472264],
    [472512, 472596],
    [472596, 472680],
    [472680, 472684],
    [472684, 472772],
    [485160, 489068],
    [491672, 493608],
    [493608, 493692],
    [506756, 506988],
    [520552, 521200],
    [523132, 523532],
    [528344, 528576],
    [533168, 539904],
    [548616, 550592],
    [568596, 569860],
    [573168, 575808],
    [579536, 579792],
    [589616, 589620],
    [610480, 610484],
    [626444, 626916],
    [636500, 636504],
    [641936, 643184],
    [644460, 644464],
    [644816, 644820],
    [42852, 42856],
]
 
# # Init Binary File
ql = Qiling(
    ["D:/new/frida-agent-example-main/agent/node_modules/libmanxi.so"],
    r"D:/new/rootfs/arm64_android",
    verbose=QL_VERBOSE.DISASM,
)
 
base_addr = ql.mem.get_lib_base("libmanxi.so")
str = f"Base Address: {hex(base_addr)}"
ql.hook_mem_write(write_hook)
 
for func in funcArray:
    ql.run(func[0] + base_addr, func[1] + base_addr - 4)
elf_patch.save("aaa.so")
import lief
from qiling.os.const import POINTER, UINT, STRING
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.const import QL_INTERCEPT
from qiling import os
from qiling.os.mapper import QlFsMappedObject
import struct
from pwn import elf, pack, unpack, u64
 
soData = lief.parse("libmanxi.so")
 
datasec = None
rodatasec = None
for sec in soData.sections:
    if sec.name == ".data":
        datasec = sec
    elif sec.name == ".rodata":
        rodatasec = sec
 
data_str = ""
elf_patch = elf.ELF(
    "D:/new/frida-agent-example-main/agent/node_modules/libmanxi_copy.so"
)
 
def write_hook(ql: Qiling, access: int, address: int, size: int, value: int):
    Addr = address - base_addr
    if (
        Addr >= datasec.virtual_address
        and Addr <= datasec.virtual_address + datasec.size
    ) or (
        Addr >= rodatasec.virtual_address
        and Addr <= rodatasec.virtual_address + rodatasec.size
    ):
        # if value >= 32 and value <= 128:
        print(
            f"Write Address: {hex(address-base_addr)} Value:{hex(value)} Size:{hex(size)}"
        )
        if size == 1:
            data = ql.pack8(value)
        elif size == 2:
            data = ql.pack16(value)
        elif size == 4:
            data = ql.pack32(value)
        elif size == 8:
            data = ql.pack64(value)
        elf_patch.write(Addr, data)
 
# Read Init_array
funcArray = [
    [22616, 23116],
    [28832, 29460],
    [39664, 40264],
    [42856, 43124],
    [43932, 44020],
    [46660, 46664],
    [55196, 62940],
    [63672, 63756],
    [63756, 63840],
    [63840, 63924],
    [73424, 73428],
    [73516, 73600],
    [87628, 88064],
    [122504, 122588],
    [123876, 124208],
    [124208, 124292],
    [125200, 125288],
    [127652, 128176],
    [131420, 131828],
    [135164, 135876],
    [153412, 154708],
    [164120, 167816],
    [175060, 175332],
    [183120, 183124],
    [183124, 183128],
    [186856, 186940],
    [193592, 193732],
    [215616, 216696],
    [219564, 219648],
    [232264, 232352],
    [232920, 232924],
    [233080, 233352],
    [244248, 253964],
    [255484, 256504],
    [258116, 258424],
    [259408, 262080],
    [262080, 262432],
    [264236, 264696],
    [268872, 269224],
    [269688, 270484],
    [274292, 276648],
    [283864, 284264],
    [286580, 287280],
    [288384, 288656],
    [291236, 291596],
    [292296, 293676],
    [294012, 295272],
    [295272, 295520],
    [295976, 296248],
    [299480, 299788],
    [300236, 307192],
    [307500, 307504],
    [311600, 312672],
    [313304, 313308],
    [316048, 316052],
    [324380, 325624],
    [378800, 380220],
    [382004, 382008],
    [389160, 389520],
    [390088, 390092],
    [392360, 392444],
    [407960, 407964],
    [410060, 410064],
    [414476, 415160],
    [448668, 457116],
    [464888, 464972],
    [469092, 469444],
    [471132, 471388],
    [472156, 472160],
    [472180, 472264],
    [472512, 472596],
    [472596, 472680],
    [472680, 472684],
    [472684, 472772],
    [485160, 489068],
    [491672, 493608],
    [493608, 493692],
    [506756, 506988],
    [520552, 521200],
    [523132, 523532],
    [528344, 528576],
    [533168, 539904],
    [548616, 550592],
    [568596, 569860],
    [573168, 575808],
    [579536, 579792],
    [589616, 589620],
    [610480, 610484],
    [626444, 626916],
    [636500, 636504],
    [641936, 643184],
    [644460, 644464],
    [644816, 644820],
    [42852, 42856],
]
 
# # Init Binary File
ql = Qiling(
    ["D:/new/frida-agent-example-main/agent/node_modules/libmanxi.so"],
    r"D:/new/rootfs/arm64_android",
    verbose=QL_VERBOSE.DISASM,
)
 
base_addr = ql.mem.get_lib_base("libmanxi.so")
str = f"Base Address: {hex(base_addr)}"
ql.hook_mem_write(write_hook)
 
for func in funcArray:
    ql.run(func[0] + base_addr, func[1] + base_addr - 4)
elf_patch.save("aaa.so")
function hook_svc() {
    console.log("=====Hook SVC=====")
    var base_addr = Module.findBaseAddress("libmanxi.so");
 
    addr.forEach(function (svc) {
        var offset = `0x` + svc.offset.toString(16)
        Interceptor.attach(base_addr.add(offset), {
            onEnter: function (args) {
                if (this.context.x8 == 0x38) {
                    console.log("Openat:" + ptr(this.context.x1).readCString())
                }
            },
            onLeave: function (retval) {
 
            }
        })
    })
}
function hook_svc() {

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2023-9-20 21:10 被Gift1a编辑 ,原因:
上传的附件:
收藏
免费 12
支持
分享
最新回复 (6)
雪    币: 3059
活跃值: (30876)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2023-9-21 09:04
1
雪    币: 159
活跃值: (2076)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
Gift1a!优雅的脚本
2023-9-21 09:55
0
雪    币: 197
活跃值: (1375)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
sorryla Gift1a!优雅的脚本
哦嗨哟~s0rry!
2023-9-21 13:34
0
雪    币: 2636
活跃值: (1933)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
优雅,蛮犀加固经过两年的发展,强度上了不少呢
2023-9-29 16:18
0
雪    币: 948
活跃值: (1924)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
6
给符提亚!
2023-9-29 17:57
0
雪    币: 2159
活跃值: (4097)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
7
感谢分享
2023-9-30 03:21
0
游客
登录 | 注册 方可回帖
返回
//