首页
社区
课程
招聘
[原创]android so文件攻防实战-百度加固免费版libbaiduprotect.so反混淆
发表于: 2022-2-3 19:10 35798

[原创]android so文件攻防实战-百度加固免费版libbaiduprotect.so反混淆

2022-2-3 19:10
35798

计划是写一个android中so文件反混淆的系列文章,目前只写了这一篇。
样本libbaiduprotect_dump.so来自看雪上的帖子:百度加固免费版分析及VMP修复

原文把整个流程已经分析很清楚了,这里就不分析了,只说怎么处理libbaiduprotect_dump.so里面的混淆。

很多函数里面都插了垃圾代码,比如JNI_OnLoad:
JNI_OnLoad1
两个相邻的数相乘肯定是偶数,while条件永远false,if条件永远true。这里我的方法就是直接把ADRP X8, #dword_C0144@PAGE(ADRP X8, 0xC0000)这样的指令改成ADRP X8, 0xA0000,因为0xC0124在bss段没有初始化,0xA0124在eh_frame段已经初始化,所以这样改了以后IDA F5的时候就会把这些垃圾代码自动优化掉。
注意:需要自己去装一个keystone,因为脚本用到了kstool.exe生成机器码。

处理以后:
JNI_OnLoad2

加密后的字符串基本都长这个样子:
decryptedstr
每个字符串的解密函数虽然都不一样,但是逻辑都差不多。处理字符串加密可以用的工具有很多,我习惯用frida。
第一步是通过交叉引用拿到加密后的字符串和它对应的解密函数的表:

结果:
encryptedstr2func
第二步是把这个表丢给frida,让frida去调一遍,拿到解密后的字符串。为了代码简洁这个表就没有列完,只有两项:

结果:
decryptedstr
第三步就是把加密后的字符串直接patch成加密前的字符串,因为如果用set_cmt(也就是IDA7.4以前的MakeComm)把加密前的字符串当成注释加上的话F5的窗口是没有的,这样直接patch看起来更清晰直观。加密后的字符串总是比加密前的字符串长,多出来的就patch成0。同样为了代码简洁加密前的字符串没有列完,只有两项:

还是前面的sub_12274,来看处理完以后的效果:
decryptedstr

sub_B3B4动态获取libc中的函数并保存,我们这里做一下符号重命名即可。
首先把F5中的sub_B3B4保存下来,然后写个脚本把qword_BE238命名为_exit_libc,qword_BE240命名为exit_libc,qword_BE248命名为pthread_create_libc,依次类推即可。

结果:
decryptedstr
用这些函数的地方也看的比较清楚。
decryptedstr

百度加固免费版libbaiduprotect.so里面基本上就是这些花样,还是比较好搞定的。

 
from idautils import *
from idaapi import *
from idc import *
 
import subprocess
 
for segea in Segments():
    for funcea in Functions(segea, get_segm_end(segea)):
        for (startea, endea) in Chunks(funcea):
            for line in Heads(startea, endea):
 
                if idc.GetDisasm(line) in ["ADRP            X8, #dword_C0144@PAGE", \
                                        "ADRP            X8, #dword_C0140@PAGE", \
                                        "ADRP            X8, #dword_C013C@PAGE", \
                                        "ADRP            X8, #dword_C0138@PAGE", \
                                        "ADRP            X8, #dword_C0134@PAGE", \
                                        "ADRP            X8, #dword_C0130@PAGE", \
                                        "ADRP            X8, #dword_C012C@PAGE", \
                                        "ADRP            X8, #dword_C0128@PAGE", \
                                        "ADRP            X8, #dword_C0124@PAGE", \
                                        "ADRP            X8, #dword_C0120@PAGE", \
                                        "ADRP            X8, #dword_C011C@PAGE", \
                                        "ADRP            X8, #dword_C0118@PAGE"]:
                    pi = subprocess.Popen(['D:\\keystone-0.9.2-win64\\kstool.exe', 'arm64', 'ADRP X8, 0xA0000', hex(line)], shell=True, stdout=subprocess.PIPE)
                    output = pi.stdout.read()
                    asmcode = str(output[20:33])[:-1]
                    asmcode = asmcode.split(" ")
                    asmcode = "0x" + asmcode[4] + asmcode[3] + asmcode[2] + asmcode[1]
                    print(asmcode)
                    patch_dword(line, int(asmcode, 16))
                elif idc.GetDisasm(line) in ["ADRP            X9, #dword_C0140@PAGE", \
                                            "ADRP            X9, #dword_C013C@PAGE", \
                                            "ADRP            X9, #dword_C0138@PAGE", \
                                            "ADRP            X9, #dword_C0134@PAGE", \
                                            "ADRP            X9, #dword_C0130@PAGE", \
                                            "ADRP            X9, #dword_C012C@PAGE", \
                                            "ADRP            X9, #dword_C0128@PAGE", \
                                            "ADRP            X9, #dword_C0124@PAGE", \
                                            "ADRP            X9, #dword_C0120@PAGE", \
                                            "ADRP            X9, #dword_C011C@PAGE", \
                                            "ADRP            X9, #dword_C0118@PAGE"]:
                    pi = subprocess.Popen(['D:\\keystone-0.9.2-win64\\kstool.exe', 'arm64', 'ADRP X9, 0xA0000', hex(line)], shell=True, stdout=subprocess.PIPE)
                    output = pi.stdout.read()
                    asmcode = str(output[20:33])[:-1]
                    asmcode = asmcode.split(" ")
                    asmcode = "0x" + asmcode[4] + asmcode[3] + asmcode[2] + asmcode[1]
                    print(asmcode)
                    patch_dword(line, int(asmcode, 16))
                elif idc.GetDisasm(line) in ["ADRP            X10, #dword_C0140@PAGE", \
                                            "ADRP            X10, #dword_C013C@PAGE", \
                                            "ADRP            X10, #dword_C0138@PAGE", \
                                            "ADRP            X10, #dword_C0134@PAGE", \
                                            "ADRP            X10, #dword_C0130@PAGE", \
                                            "ADRP            X10, #dword_C012C@PAGE", \
                                            "ADRP            X10, #dword_C0128@PAGE", \
                                            "ADRP            X10, #dword_C0124@PAGE", \
                                            "ADRP            X10, #dword_C0120@PAGE", \
                                            "ADRP            X10, #dword_C011C@PAGE", \
                                            "ADRP            X10, #dword_C0118@PAGE"]:
                    pi = subprocess.Popen(['D:\\keystone-0.9.2-win64\\kstool.exe', 'arm64', 'ADRP X10, 0xA0000', hex(line)], shell=True, stdout=subprocess.PIPE)
                    output = pi.stdout.read()
                    asmcode = str(output[20:33])[:-1]
                    asmcode = asmcode.split(" ")
                    asmcode = "0x" + asmcode[4] + asmcode[3] + asmcode[2] + asmcode[1]
                    print(asmcode)
                    patch_dword(line, int(asmcode, 16))
from idautils import *
from idaapi import *
from idc import *
 
import subprocess
 
for segea in Segments():
    for funcea in Functions(segea, get_segm_end(segea)):
        for (startea, endea) in Chunks(funcea):
            for line in Heads(startea, endea):
 
                if idc.GetDisasm(line) in ["ADRP            X8, #dword_C0144@PAGE", \
                                        "ADRP            X8, #dword_C0140@PAGE", \
                                        "ADRP            X8, #dword_C013C@PAGE", \
                                        "ADRP            X8, #dword_C0138@PAGE", \
                                        "ADRP            X8, #dword_C0134@PAGE", \
                                        "ADRP            X8, #dword_C0130@PAGE", \
                                        "ADRP            X8, #dword_C012C@PAGE", \
                                        "ADRP            X8, #dword_C0128@PAGE", \
                                        "ADRP            X8, #dword_C0124@PAGE", \
                                        "ADRP            X8, #dword_C0120@PAGE", \
                                        "ADRP            X8, #dword_C011C@PAGE", \
                                        "ADRP            X8, #dword_C0118@PAGE"]:
                    pi = subprocess.Popen(['D:\\keystone-0.9.2-win64\\kstool.exe', 'arm64', 'ADRP X8, 0xA0000', hex(line)], shell=True, stdout=subprocess.PIPE)
                    output = pi.stdout.read()
                    asmcode = str(output[20:33])[:-1]
                    asmcode = asmcode.split(" ")
                    asmcode = "0x" + asmcode[4] + asmcode[3] + asmcode[2] + asmcode[1]
                    print(asmcode)
                    patch_dword(line, int(asmcode, 16))
                elif idc.GetDisasm(line) in ["ADRP            X9, #dword_C0140@PAGE", \
                                            "ADRP            X9, #dword_C013C@PAGE", \
                                            "ADRP            X9, #dword_C0138@PAGE", \
                                            "ADRP            X9, #dword_C0134@PAGE", \
                                            "ADRP            X9, #dword_C0130@PAGE", \
                                            "ADRP            X9, #dword_C012C@PAGE", \
                                            "ADRP            X9, #dword_C0128@PAGE", \
                                            "ADRP            X9, #dword_C0124@PAGE", \
                                            "ADRP            X9, #dword_C0120@PAGE", \
                                            "ADRP            X9, #dword_C011C@PAGE", \
                                            "ADRP            X9, #dword_C0118@PAGE"]:
                    pi = subprocess.Popen(['D:\\keystone-0.9.2-win64\\kstool.exe', 'arm64', 'ADRP X9, 0xA0000', hex(line)], shell=True, stdout=subprocess.PIPE)
                    output = pi.stdout.read()
                    asmcode = str(output[20:33])[:-1]
                    asmcode = asmcode.split(" ")
                    asmcode = "0x" + asmcode[4] + asmcode[3] + asmcode[2] + asmcode[1]
                    print(asmcode)
                    patch_dword(line, int(asmcode, 16))
                elif idc.GetDisasm(line) in ["ADRP            X10, #dword_C0140@PAGE", \
                                            "ADRP            X10, #dword_C013C@PAGE", \
                                            "ADRP            X10, #dword_C0138@PAGE", \
                                            "ADRP            X10, #dword_C0134@PAGE", \
                                            "ADRP            X10, #dword_C0130@PAGE", \
                                            "ADRP            X10, #dword_C012C@PAGE", \
                                            "ADRP            X10, #dword_C0128@PAGE", \
                                            "ADRP            X10, #dword_C0124@PAGE", \
                                            "ADRP            X10, #dword_C0120@PAGE", \
                                            "ADRP            X10, #dword_C011C@PAGE", \
                                            "ADRP            X10, #dword_C0118@PAGE"]:
                    pi = subprocess.Popen(['D:\\keystone-0.9.2-win64\\kstool.exe', 'arm64', 'ADRP X10, 0xA0000', hex(line)], shell=True, stdout=subprocess.PIPE)
                    output = pi.stdout.read()
                    asmcode = str(output[20:33])[:-1]
                    asmcode = asmcode.split(" ")
                    asmcode = "0x" + asmcode[4] + asmcode[3] + asmcode[2] + asmcode[1]
                    print(asmcode)
                    patch_dword(line, int(asmcode, 16))
from idautils import *
from idaapi import *
from idc import *
 
import string
 
rodata_start = 0x959B0
rodata_end = 0x9AF68
 
def get_string(addr):
    out = ""
    while True:
        if get_byte(addr) != 0:
            out += chr(get_byte(addr))
        else:
            break
        addr += 1
    return out
 
addr = rodata_start
index = 0
 
while addr < rodata_end:
    str = get_string(addr)
    str_len = len(str) + 1
    if all(c in string.hexdigits for c in str) and str_len > 8:
 
        xrefaddrs = XrefsTo(addr, flags=0)
        for xrefaddr in xrefaddrs:
            call_addr = xrefaddr.frm
            while print_insn_mnem(call_addr) != "BL":
                call_addr = next_head(call_addr)
        decode_func_addr = print_operand(call_addr, 0)
        print("\"" + decode_func_addr + '***' + str + "\"" + ",")
 
    addr += str_len
from idautils import *
from idaapi import *
from idc import *
 
import string
 
rodata_start = 0x959B0
rodata_end = 0x9AF68
 
def get_string(addr):
    out = ""
    while True:
        if get_byte(addr) != 0:
            out += chr(get_byte(addr))
        else:
            break
        addr += 1
    return out
 
addr = rodata_start
index = 0
 
while addr < rodata_end:
    str = get_string(addr)
    str_len = len(str) + 1
    if all(c in string.hexdigits for c in str) and str_len > 8:
 
        xrefaddrs = XrefsTo(addr, flags=0)
        for xrefaddr in xrefaddrs:
            call_addr = xrefaddr.frm
            while print_insn_mnem(call_addr) != "BL":
                call_addr = next_head(call_addr)
        decode_func_addr = print_operand(call_addr, 0)
        print("\"" + decode_func_addr + '***' + str + "\"" + ",")
 
    addr += str_len

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (8)
雪    币: 116
活跃值: (1012)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
支持一下
2022-2-4 11:16
0
雪    币: 334
活跃值: (392)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
tql
2022-2-4 20:40
0
雪    币: 248
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
感谢大佬,学习了!
so反混淆
1. 过滤垃圾代码(恒等式等) 修改未初始化变量为有初始化变量
2. 字符串解密  通过交叉引用拿到加密函数地址,通过frida native层调用获取解密后字符串
2022-2-16 14:09
0
雪    币: 576
活跃值: (2035)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
mark,感谢分享
2022-7-11 17:30
0
雪    币: 4583
活跃值: (6836)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
拜师拜师
2022-7-11 23:36
0
雪    币: 5330
活跃值: (5479)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
7
感谢大佬!学习了。
2022-7-14 10:04
0
雪    币: 928
活跃值: (1878)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
8
学习学习
2024-9-1 15:21
0
雪    币: 1426
活跃值: (3105)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2024-10-16 14:05
0
游客
登录 | 注册 方可回帖
返回
//