首页
社区
课程
招聘
[原创]android so文件攻防实战-libDexHelper.so反混淆
发表于: 2022-7-10 21:45 38714

[原创]android so文件攻防实战-libDexHelper.so反混淆

2022-7-10 21:45
38714

计划是写一个android中so文件反混淆的系列文章,目前这是第三篇。
第一篇:android so文件攻防实战-百度加固免费版libbaiduprotect.so反混淆
第二篇:android so文件攻防实战-某团libmtguard.so反混淆
今天分析的是企业版64位,我用LibChecker查了一下手机上的APP找到的,时间也还比较新。根据其他人的分析可知,libDexHelper.so是指令抽取的实现,libdexjni.so是VMP的实现。

首先因为加密过,肯定是不能直接反编译的,可以在libart.so下断点,进入JNI_onLoad以后就可以dump下来。

不过此时也不能直接F5,还存在以下混淆方式:
1.垃圾指令

这些垃圾指令是在switch的一个永远不会被执行到的分支里面,可以直接将IDA不能MakeCode的地方patch成NOP再MakeCode。
2.字符串加密
有好几个解密字符串的函数,0x186C4,0x7783C,0x95B9C。在android so文件攻防实战-百度加固免费版libbaiduprotect.so反混淆中我们是交叉引用拿到加密后的字符串和它对应的解密函数的表然后frida主动调用得到的解密后的字符串,但是在这里这个方法就不太好用了。因为这里加密后的字符串是在栈上一个byte一个byte拼起来的,和最后调用解密函数之间可能隔了很多条指令,甚至都不在一个block。
我最后用的是下面这种方案:以0x40110处调用0x186C4处的解密函数为例,这里面字符串解密的逻辑比较简单,需要三个参数。我们可以自己实现也可以用unicorn,我就用unicorn了。

总共有几百处调用,不可能全部人工去这样解出来,我写了另外以一个脚本去调用decstr.py。首先通过交叉引用找到所有调用解密函数的地方,然后把起始地址设为该block的起始地址,结束地址设为调用解密函数的地址,通过unicorn跑出decstr.py需要的三个参数之后调用decstr.py。遇到unicorn.unicorn.UcError也有两个处理策略,一个是跳过该地址( loop_call_prepare_arg1),起始地址不变;一个是将起始地址设为下一条地址(loop_call_prepare_arg2)。当然这套方案还有优化的空间,比如生成调用解密函数需要的参数的代码和最后调用解密函数的代码不在一个block,就处理不了。

更恶心的是还有很多字符串是自己在函数内解密的,这种情况我也没想到有什么好的方法。
3.控制流混淆
第一种是把正常顺序执行的指令打乱成switch的形式,这个影响倒不是太大:

第二种是动态计算跳转地址,基本上类似于在android so文件攻防实战-某团libmtguard.so反混淆见过的那种,但是要更复杂。

比如这里的指令,在0x1DA0C处给X2赋值,X2此时为.data段中的一个地址,W0为偏移,取出值后在0x1DA18处乘4加上0x1DA20,最后的值就是0x1DA1C处X0的值。那么需要解决这么几个问题:
如何确定0x1DA0C处给X2赋的值
将0x1DA00处的指令改成跳转指令,0x1DA00这个地址又该如何确定
找到所有会跳转到0x1DA1C的指令,将跳转地址改成计算出来的X0的值
第一个问题,其实和字符串解密面临的情况是类似的,比如这里需要找到和"LDR X2, [X29,#0x190+var_118]"对应的"STR XX, [X29,#0x190+var_118]"这条指令,然后再找给XX寄存器赋值的指令,然而这两条指令很可能和BR X0隔了好几个block。我的解决方法是通过IDA提供的idaapi.FlowChar功能,递归前面的block查找。不足之处在于前提条件是IDA正确识别了函数的起始地址,否则会出现我们需要的指令和BR X0不在同一个函数的情况,这样就处理不了。
第二个问题,在递归前面的block的时候就先找到0x1D9D4处这条给W0赋值的指令,然后从0x1D9D4处开始直到0x1DA1C,找到第一个存在交叉引用的地址,也就是0x1DA04。它的前一条指令0x1DA00就是需要改成跳转指令的地方。
第三个问题,确定了0x1DA00之后,那么从0x1DA00到0x1DA1C所有存在交叉引用的地址都要去交叉引用的地方修改跳转地址。不过这里有很多细节。
(1)如果W0是由CSEL,CSET,CSINC这些指令赋值的,像下面这种情况,那么需要把0x1DE80和0x1DE84修改成 B.GE和B.LT。
patch前:

patch后:

(2)0x1DE80处的CSEL W0, WZR, W8, LT,这里W8的值是在0x1D9DC MOV W8, #5赋值的,所以我的代码中有一个register_value_dict,在改掉0x1DA00处的指令之后会读取0x1DA00所在的block到0x1DA1C所在的block的所有指令,找到给寄存器赋值的指令然后把值存起来。


(3)有些地方还会有一条sub指令,这个也要考虑进去,比如下面这种情况0x33394处跳转的地址就应该按照W8为4计算。


最后的脚本放附件了。当然还有一些脚本处理不了的地方,不过问题已经不算太大了,需要的话可以动态调试确定。
4.函数地址动态计算



这个在IDA里面是能看清楚的,v35其实就是off_12EB80[0],即调用0x80FE0处的p329AAB59961F6410ABA963EF972FE303。
接下来我们就来分析libDexHelper.so,来看看它都干了些什么。精力有限,很多地方没能很详细去分析。有些地方分析的可能也不一定对,将就看吧。

JNI_OnLoad(0x3EA68)的分析在最后。

读/proc/self/maps,特征字符串:

获取系统属性,读/proc/%d/cmdline,特征字符串:

off_12EF10:为2表示yunos,art模式;为1表示yunos,dalvik模式;为0表示非yunos。

md5。

字符串解密函数。

返回字符串rw。

返回字符串su。

返回字符串mount。

写classes.dve文件。

读取目录中的文件。

创建String类型的数组,第一个参数是String列表,第二个参数是数组长度。

调用0x19E08创建数组:

调用0x19E08创建数组:

调用0x19E08创建数组:

调用0x19E08创建数组:

system_property_get ro.product.cpu.abi和读/system/lib/libc.so判断是不是x86架构。

查看classes.dve是否存在。

调用0x19E08创建数组:

初始化一些路径,特征字符串:

将libc中的一些函数的地址放到.DATA。

读/proc/self/cmdline,判断是否含有com.miui.packageinstaller从而判断是否由小米应用包管理组件启动。

先system_property_get ro.product.manufacturer和system_property_get ro.product.model判断是否是samsung,然后system_property_get ro.build.characteristics是否为emulator。

注册如下native函数:

system_property_get ro.build.version.release/ro.build.version.sdk/ro.build.version.codename,最终返回sdkversion。

创建一些目录:

模拟器检测,特征字符串:

读proc/pid/cmdline找字符串":bbs",没搞懂这是什么意思。这个函数名是is_magisk_check_process。

调用setOuterContext。

system_property_get ro.product.brand,针对华为/荣耀机型,调用startLoadFromDisk。

getDeclaredFields获取field对象数组之后调用equals,返回查找的指定的field对象。

修改mInitialApplication和mClassLoader。

修改mAllApplications(remove和add)。

模拟器检测,特征字符串:

通过FLAG_DEBUGGABLE判断是debug还是release。

通过android.content.pm.Signature获取签名的md5。

通过access以下文件判断是否被root:

读/proc/self/cmdline,调用java层的com.secneo.apkwrapper.H.j,调用bindService,获取android_id,调用android.app.Application.attach,如果包名是com.huawei.irportalapp.uat调用setOuterContext。

调用java层的com.secneo.apkwrapper.H.f(ff)加载v1filter.jar和原始dex。
查看/proc/self/maps:
anon:dalvik-classes.dex extracted in memory from v1filter.jar
anon:dalvik-DEX data
把多出来这样的段dump下来。
原始dex:

指令虚拟化是调用JniLib.cV解析执行的,最后一个参数是一个函数code索引,用来查找被虚拟化后的指令,其它是方法参数:

v1filter.jar:

hook libcutils.so/liblog.so中的android_log_write和android_log_buf_write,使其返回0。

currentActivityThread-mPackages-LoadedApk-mResources-getAssets。

调用android.content.res.Resources.getAssets,失败再调用0x339FC。

读取assets文件。

对传入参数调用makeInMemoryDexElements,修改dalvik.system.DexFile.mFileName。

初始化下列字符串:

调用0x80458计算包名hash,调用0x75AA8
调用AAssetManager_open读取assets/resthird.data写入v1filter.jar,调用0x31474
(看别人的分析应该读assets下面两个文件:classes0.jar是被加密的dex,classes.dgc是被加密的抽取后的指令。不过我分析的这个样本中没有classes0.jar和classes.dgc,可能是名字变了)

检测dexhunter,dumpclass好像是dexhunter里面的吧。特征字符串:

参数是文件名,返回文件是否存在。

模拟器检测,特征字符串:

system_property_get ro.debuggable,调用检测模拟器的函数。

通过android.hardware.usb.action.USB_STATE监听USB状态。

md5。

hook下列函数(反调试):

system_property_get ro.yunos.version。

hook下列函数(指令抽取还原):

md5。

读/proc/self/maps找到含有包名的段。

调用java层的com.secneo.apkwrapper.H1.find_dexfile。

调用java.lang.StackTraceElement.getMethodName和java.lang.StackTraceElement.getClassName。

加载assets中的classes.dgg。

读/proc/self/maps找到libDexHelper.so。

设置dex2oat的参数,--zip-fd/--oat-fd/--zip-location/--oat-location/--oat-file/--instruction-set。

hook libdvm.so中的函数(类似于0x67544),具体没仔细看,0x5BAA8-0x5BEF8都是被hook后的实现。

hook libc中的下列函数:

根据不同SDK版本返回Name Mangling之后的art::DexFileLoader::open。

根据不同SDK版本返回Name Mangling之后的art::OatFileManager::OpenDexFilesFromOat。

hook下列函数:

patch掉art::Runtime::IsVerificationEnabled。

hook art::DexFileVerifier::Verify(hook后:0x6D38C/0x6D394,直接返回1)。

hook art::DexFileLoader::open(hook后:0x6D39C/0x6D3E8)。

hook下列函数:

hook libdvm.so中的函数,具体没仔细看,0x6EB1C/0x74DEC/0x6FFBC都是被hook后的实现。

读java.lang.DexCache.dexfile(这个dexfile就是解压apk之后根目录的那个classes.dex)。

参数是so文件路径,打开该so文件。

参数是libart.so中的一个函数,返回该函数地址。

第一个参数是so中的函数名,第二个参数是so的相对路径,返回该函数在so中的地址。

参数是libdexfile.so中的一个函数,返回该函数地址。

参数是libjdwp.so中的一个函数,返回该函数地址。

md5。

字符串解密函数。

计算传入字符串的hash(不完全是md5)。

热补丁检测,特征字符串:

调用0x79270。

hook libc中的下列函数:

hook libdvm.so中的函数(类似于0x44708),具体没仔细看,0x856C0/0x87F00/0x87F4C都是被hook后的实现。

patch掉art::Runtime::UseJitCompilation。

hook函数实现。

读/proc/sys/fs/inotify/max_queued_watches。

读/proc/sys/fs/inotify/max_user_instances。

读/proc/sys/fs/inotify/max_user_watches。

看起来好像是通过判断时间实现的反调试。

字符串查找函数。

字符串解密函数。

socket连接。

frida检测,读/proc/self/task,特征字符串:gum-js-loop;读/proc/self/fd,特征字符串linjector。

xposed检测,特征字符串:

hook框架检测,特征字符串:

调用0x96398检测frida,system_property_get ro.product.model,调用0x9FD88检测xposed和自动脱壳机,hook dlopen(hook后:0x9B89C)和ptrace(hook后:0x95BF8)。

通过读取/proc/%d/status判断TracerPid等实现反调试。

通过读取/proc/%d/wchan判断是不是ptrace_stop实现反调试。

通过读取/proc/%ld/task/%ld/status判断TracerPid等实现反调试。

通过java.lang.StackTraceElement.getClassName打印函数调用栈进行xposed检测。

通过java.lang.ClassLoader.getSystemClassLoader.loadClass打印类加载器进行xposed检测。

调用0x9ED44和0x9F770,通过判断ServiceManager里是否有user.xposed.system进行xposed检测,然后检测自动脱壳机:
fart(https://github.com/hanbinglengyue/FART)
FUPK3(https://github.com/F8LEFT/FUPK3)
Youpk(https://github.com/Youlor/Youpk)
检测方法是判断下列类或者方法是否存在:

getInstalledApplications获取系统中安装的APP信息。

解密出字符串Java和JNI_OnLoad,hook了几个函数,被hook的原地址未知,新地址:0xA43A0/0xA485C/0xA48F4/0xA54B0;hook dlsym(hook后:0xA4554)和dlopen(hook后:0xA4D30)。

hook libc中的下列函数:

system_property_get debug.atrace.tags.enableflags,hook bionic_trace_begin和bionic_trace_end(hook后:0xA8EF4和0xA8EF8,直接返回),没有找到则hook g_trace_marker_fd(hook后:0xA8EFC,返回-1)。
这些hook是为了透明加密,具体没仔细看,之前论坛也有人分析过,估计应该没有太大的变化:梆梆加固之透明加密分析

sha1。

md5init。

base64。

base64。

APK签名相关。

sha1。

sha1init。

md5。

调用0xD75A0。

读/proc/self/cmdline。

hook libdvm.so中的函数(hook后:0xD6988)。

根据off_12EF10处的值判断调用0xD6484还是0xD6578。

hook libaoc.so中的函数(hook后:0xD69BC)。

JNI_OnLoad。分析环境pixel4 android10,动态分析过程中一些没有被调用的函数不再分析。
1.初始化cpuabi字符串(arm64)于0x12E7C8
2.初始化so名字符串(libDexHelper)于0x12EC38
3.初始化字符串com/secneo/apkwrapper/H于0x137B10
4.调用0x1E520
5.

6.将包名存于0x138040
7.

8.调用0x218A8
9.

10.读/proc/pid/fd,匹配包名+base.apk,0x12EA38存放指向base.apk完整路径的指针的指针
11.

12.将得到的结果和###MPAAS###比较,0x12E7F8指向0x137D9C,0x137D9C存放比较结果
13.调用0x22068
14.调用0x23568
15.调用0x1F250
16.将字符串lib/libart.so存放于0x1378A8
17.读/proc/self/maps,找权限为"r-xp"的lib/libart.so
18.初始化下列字符串:

19.fstat /data/app/cn.missfresh.application-xxx/oat/arm64/base.odex
20.计算md5(不太清楚具体算的什么),0x12EC98指向0x130080,0x130080存放计算结果
21.access /data/user/0/cn.missfresh.application/.cache/classes.dve,不存在则把之前算的md5写入该文件;存在则读取其中的值和之前算的比较,不相等则写入新计算的值
22.调用0x3371C(根据标记位决定是否调用)
23.调用0x1FDC8
24.初始化下列字符串:

25.调用0x3766C
26.调用0xB4B94
27.调用0x9C0BC
28.调用0xD5CDC
29.调用0x24C08
30.调用0x1C40C
31.调用0xA7D3C
32.结束

梆梆APP加固产品方案浅析:https://www.cnblogs.com/2014asm/p/14547218.html
某加固详细分析总结,另附该加固脱壳机:
https://bbs.pediy.com/thread-252828.htm

样本混淆强度还是比较大的,比前两篇文章中的样本要复杂很多。不过分析过程中也是有一些技巧:比如位置相邻的函数之前其实是有联系的,和另外某些壳的代码有类似的地方(估计也是抄来抄去),可以网上搜一下旧版本的分析博客,有一些函数名和字符串没有被抹去,等等。

import sys
import unicorn
import binascii
import threading
import subprocess
 
from capstone import *
from capstone.arm64 import *
 
with open("C:\\Users\\hjy\\Downloads\\out1.fix.so","rb") as f:
    sodata = f.read()
 
uc = unicorn.Uc(unicorn.UC_ARCH_ARM64, unicorn.UC_MODE_ARM)
code_addr = 0x0
code_size = 8*0x1000*0x1000
uc.mem_map(code_addr, code_size)
stack_addr = code_addr + code_size
stack_size = 0x1000000
stack_top = stack_addr + stack_size - 0x8
uc.mem_map(stack_addr, stack_size)
uc.mem_write(code_addr, sodata)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X29, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X28, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X27, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X26, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X25, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X24, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X23, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X22, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X21, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X20, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X19, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X18, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X17, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X16, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X15, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X14, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X13, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X12, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X11, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X10, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X9, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X8, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X7, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X6, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X5, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X4, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X3, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X2, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X1, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X0, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_SP, stack_top)
X0 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X0)
 
uc.mem_write(X0, bytes.fromhex(sys.argv[1]))
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X1, int(sys.argv[2], 16))
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X2, int(sys.argv[3], 16))
 
uc.emu_start(0x1777C, 0x17780)
 
X0 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X0)
decstr = uc.mem_read(X0, 80)
 
print("decstr:", decstr)
uc.mem_unmap(stack_addr, stack_size)
uc.mem_unmap(code_addr, code_size)
import sys
import unicorn
import binascii
import threading
import subprocess
 
from capstone import *
from capstone.arm64 import *
 
with open("C:\\Users\\hjy\\Downloads\\out1.fix.so","rb") as f:
    sodata = f.read()
 
uc = unicorn.Uc(unicorn.UC_ARCH_ARM64, unicorn.UC_MODE_ARM)
code_addr = 0x0
code_size = 8*0x1000*0x1000
uc.mem_map(code_addr, code_size)
stack_addr = code_addr + code_size
stack_size = 0x1000000
stack_top = stack_addr + stack_size - 0x8
uc.mem_map(stack_addr, stack_size)
uc.mem_write(code_addr, sodata)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X29, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X28, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X27, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X26, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X25, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X24, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X23, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X22, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X21, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X20, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X19, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X18, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X17, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X16, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X15, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X14, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X13, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X12, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X11, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X10, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X9, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X8, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X7, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X6, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X5, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X4, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X3, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X2, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X1, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X0, stack_addr)
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_SP, stack_top)
X0 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X0)
 
uc.mem_write(X0, bytes.fromhex(sys.argv[1]))
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X1, int(sys.argv[2], 16))
uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X2, int(sys.argv[3], 16))
 
uc.emu_start(0x1777C, 0x17780)
 
X0 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X0)
decstr = uc.mem_read(X0, 80)
 
print("decstr:", decstr)
uc.mem_unmap(stack_addr, stack_size)
uc.mem_unmap(code_addr, code_size)
import unicorn
import binascii
import threading
import subprocess
 
from capstone import *
from capstone.arm64 import *
 
inscnt = 0
start_addr = 0
end_addr = 0
stop_addr = 0
stop_addr_list = []
 
def hook_code(uc, address, size, user_data):
    global inscnt
    global end_addr
    global stop_addr
    global stop_addr_list
 
    md = Cs(CS_ARCH_ARM64, CS_MODE_ARM)
 
    for ins in md.disasm(sodata[address:address + size], address):
        #rint(">>> 0x%x:\t%s\t%s" % (ins.address, ins.mnemonic, ins.op_str))
        stop_addr = ins.address
 
        if ins.address in stop_addr_list:
            #print("will pass 0x%x:\t%s\t%s" %(ins.address, ins.mnemonic, ins.op_str))
            uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
            return
 
        inscnt = inscnt + 1
        if (inscnt > 500):
            uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, 0xffffffff)
            return
 
        if ins.mnemonic.find("b.") != -1:
            print("will pass 0x%x:\t%s\t%s" %(ins.address, ins.mnemonic, ins.op_str))
            uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
            return
 
        if ins.mnemonic.find("bl") != -1:
            print("will pass 0x%x:\t%s\t%s" %(ins.address, ins.mnemonic, ins.op_str))
            uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
            return
 
            if ins.op_str in ["x0","x1","x2","x3"]:
                    X1 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X1)
                    if X1 > 0x105A88:
                        print("will pass 0x%x:\t%s\t%s" %(ins.address, ins.mnemonic, ins.op_str))
                        uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
                        return
            if ins.op_str.startswith("#0x"):
                addr = int(ins.op_str[3:],16)
                if (addr > 0x14E50 and addr < 0x15820) \
                or addr == 0x186C4 \
                or addr > 0x105A88:
                    print("will pass 0x%x:\t%s\t%s" %(ins.address, ins.mnemonic, ins.op_str))
                    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
                    return
 
def call_prepare_arg():
    global inscnt
    global start_addr
    global end_addr
    global stop_addr
    global stop_addr_list
 
    inscnt = 0
 
    uc = unicorn.Uc(unicorn.UC_ARCH_ARM64, unicorn.UC_MODE_ARM)
    code_addr = 0x0
    code_size = 8*0x1000*0x1000
    uc.mem_map(code_addr, code_size)
    stack_addr = code_addr + code_size
    stack_size = 0x1000000
    stack_top = stack_addr + stack_size - 0x8
    uc.mem_map(stack_addr, stack_size)
    uc.hook_add(unicorn.UC_HOOK_CODE, hook_code)
 
    uc.mem_write(code_addr, sodata)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X29, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X28, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X27, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X26, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X25, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X24, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X23, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X22, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X21, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X20, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X19, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X18, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X17, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X16, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X15, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X14, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X13, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X12, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X11, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X10, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X9, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X8, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X7, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X6, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X5, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X4, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X3, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X2, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X1, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X0, stack_addr)
 
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_SP, stack_top)
    uc.emu_start(start_addr, end_addr)
 
    X0 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X0)
    decstr = uc.mem_read(X0, 80)
    end_index = decstr.find(bytearray(b'\x00'), 1)
    decstr = decstr[:end_index]
 
    decstr = binascii.b2a_hex(decstr)
    decstr = decstr.decode('utf-8')
 
    X1 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X1)
    X2 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X2)
 
    pi = subprocess.Popen(['C:\\Python38\\python.exe', 'decstr.py', decstr, hex(X1), hex(X2)], stdout=subprocess.PIPE)
    output = pi.stdout.read()
    print(output)
 
def loop_call_prepare_arg1():
    global inscnt
    global end_addr
    global stop_addr
    global stop_addr_list
 
    loopcnt = 0
    stop_addr_list = []
 
    while True:
        try:
            loopcnt = loopcnt + 1
            if(loopcnt > 200):
                break
            call_prepare_arg()
        except unicorn.unicorn.UcError:
            print("adding....")
            print(hex(stop_addr))
            stop_addr_list.append(stop_addr)
        else:
            break
 
def loop_call_prepare_arg2():
    global inscnt
    global end_addr
    global stop_addr
    global stop_addr_list
 
    global start_addr
 
    loopcnt = 0
    stop_addr_list = []
 
    while True:
        try:
            loopcnt = loopcnt + 1
            if(loopcnt > 200):
                break
            call_prepare_arg()
        except unicorn.unicorn.UcError:
            start_addr = stop_addr + 4
        else:
            break
 
with open("C:\\Users\\hjy\\Downloads\\out1.fix.so","rb") as f:
    sodata = f.read()
 
all_addr = []
with open('xref_decstr.txt', 'r', encoding='utf-8') as f:
    for line in f:
        addr = "0x" + line[2:]
        addr = int(addr, 16)
        all_addr.append(addr)
 
for i in all_addr:
 
    print("i:")
    print(hex(i))
 
    end_addr = i
    CODE = sodata[i - 4:i]
    md = Cs(CS_ARCH_ARM64, CS_MODE_ARM)
    for x in md.disasm(CODE, i - 4):
        mnemonic = x.mnemonic
 
    while mnemonic != "ret" \
        and mnemonic != "b" \
        and mnemonic != "br" \
        and mnemonic != "cbz" \
        and mnemonic != "cbnz":
        i = i - 4
        CODE = sodata[i - 4:i]
        for x in md.disasm(CODE, i - 4):
            mnemonic = x.mnemonic
 
    start_addr = i
 
    print("start_addr:")
    print(hex(start_addr))
    print("end_addr:")
    print(hex(end_addr))
 
    loop_call_prepare_arg1()
    loop_call_prepare_arg2()
import unicorn
import binascii
import threading
import subprocess
 
from capstone import *
from capstone.arm64 import *
 
inscnt = 0
start_addr = 0
end_addr = 0
stop_addr = 0
stop_addr_list = []
 
def hook_code(uc, address, size, user_data):
    global inscnt
    global end_addr
    global stop_addr
    global stop_addr_list
 
    md = Cs(CS_ARCH_ARM64, CS_MODE_ARM)
 
    for ins in md.disasm(sodata[address:address + size], address):
        #rint(">>> 0x%x:\t%s\t%s" % (ins.address, ins.mnemonic, ins.op_str))
        stop_addr = ins.address
 
        if ins.address in stop_addr_list:
            #print("will pass 0x%x:\t%s\t%s" %(ins.address, ins.mnemonic, ins.op_str))
            uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
            return
 
        inscnt = inscnt + 1
        if (inscnt > 500):
            uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, 0xffffffff)
            return
 
        if ins.mnemonic.find("b.") != -1:
            print("will pass 0x%x:\t%s\t%s" %(ins.address, ins.mnemonic, ins.op_str))
            uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
            return
 
        if ins.mnemonic.find("bl") != -1:
            print("will pass 0x%x:\t%s\t%s" %(ins.address, ins.mnemonic, ins.op_str))
            uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
            return
 
            if ins.op_str in ["x0","x1","x2","x3"]:
                    X1 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X1)
                    if X1 > 0x105A88:
                        print("will pass 0x%x:\t%s\t%s" %(ins.address, ins.mnemonic, ins.op_str))
                        uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
                        return
            if ins.op_str.startswith("#0x"):
                addr = int(ins.op_str[3:],16)
                if (addr > 0x14E50 and addr < 0x15820) \
                or addr == 0x186C4 \
                or addr > 0x105A88:
                    print("will pass 0x%x:\t%s\t%s" %(ins.address, ins.mnemonic, ins.op_str))
                    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
                    return
 
def call_prepare_arg():
    global inscnt
    global start_addr
    global end_addr
    global stop_addr
    global stop_addr_list
 
    inscnt = 0
 
    uc = unicorn.Uc(unicorn.UC_ARCH_ARM64, unicorn.UC_MODE_ARM)
    code_addr = 0x0
    code_size = 8*0x1000*0x1000
    uc.mem_map(code_addr, code_size)
    stack_addr = code_addr + code_size
    stack_size = 0x1000000
    stack_top = stack_addr + stack_size - 0x8
    uc.mem_map(stack_addr, stack_size)
    uc.hook_add(unicorn.UC_HOOK_CODE, hook_code)
 
    uc.mem_write(code_addr, sodata)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X29, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X28, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X27, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X26, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X25, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X24, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X23, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X22, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X21, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X20, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X19, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X18, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X17, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X16, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X15, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X14, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X13, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X12, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X11, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X10, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X9, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X8, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X7, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X6, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X5, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X4, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X3, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X2, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X1, stack_addr)
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_X0, stack_addr)
 
    uc.reg_write(unicorn.arm64_const.UC_ARM64_REG_SP, stack_top)
    uc.emu_start(start_addr, end_addr)
 
    X0 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X0)
    decstr = uc.mem_read(X0, 80)
    end_index = decstr.find(bytearray(b'\x00'), 1)
    decstr = decstr[:end_index]
 
    decstr = binascii.b2a_hex(decstr)
    decstr = decstr.decode('utf-8')
 
    X1 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X1)
    X2 = uc.reg_read(unicorn.arm64_const.UC_ARM64_REG_X2)
 
    pi = subprocess.Popen(['C:\\Python38\\python.exe', 'decstr.py', decstr, hex(X1), hex(X2)], stdout=subprocess.PIPE)
    output = pi.stdout.read()
    print(output)
 
def loop_call_prepare_arg1():
    global inscnt
    global end_addr
    global stop_addr
    global stop_addr_list
 
    loopcnt = 0
    stop_addr_list = []
 
    while True:
        try:
            loopcnt = loopcnt + 1
            if(loopcnt > 200):
                break
            call_prepare_arg()
        except unicorn.unicorn.UcError:
            print("adding....")
            print(hex(stop_addr))
            stop_addr_list.append(stop_addr)
        else:
            break
 
def loop_call_prepare_arg2():
    global inscnt
    global end_addr
    global stop_addr
    global stop_addr_list
 
    global start_addr
 
    loopcnt = 0
    stop_addr_list = []
 
    while True:

[注意]APP应用上架合规检测服务,协助应用顺利上架!

最后于 2022-7-20 14:14 被houjingyi编辑 ,原因:
上传的附件:
收藏
免费 22
支持
分享
打赏 + 150.00雪花
打赏次数 1 雪花 + 150.00
 
赞赏  Editor   +150.00 2022/08/08 恭喜您获得“雪花”奖励,安全圈有你而精彩!
最新回复 (15)
雪    币: 4623
活跃值: (6878)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
谢谢分享,学习中。 目测是精华贴
2022-7-10 23:14
0
雪    币: 181
活跃值: (3013)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
666
2022-7-11 12:01
0
雪    币: 893
活跃值: (4210)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
2022-7-11 12:54
0
雪    币: 5991
活跃值: (2328)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
5
大佬能来一期so反调试、hook的吗
2022-7-14 10:14
0
雪    币: 234
活跃值: (1929)
能力值: ( LV5,RANK:73 )
在线值:
发帖
回帖
粉丝
6
能否发一下原apk?,只有so无法dump分析
2022-7-14 17:25
0
雪    币: 5633
活跃值: (7349)
能力值: ( LV15,RANK:531 )
在线值:
发帖
回帖
粉丝
7
falconnnn 能否发一下原apk?,只有so无法dump分析
文章里面有包名的
2022-7-17 10:57
0
雪    币: 427
活跃值: (2584)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
8
mark
2022-7-21 13:58
0
雪    币: 248
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
mark
2022-7-23 16:55
0
雪    币: 232
活跃值: (208)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
大佬 牛 
2022-9-3 15:20
0
雪    币: 283
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
牛,mark
2022-9-14 16:30
0
雪    币: 212
活跃值: (161)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12

dump的so要修复,也不容易,还有他们的平坦化也要处理(楼主处理的方法不完美的),我用sktrace脚本和idapython配合,基本能还原平坦化。下面是我还原JNI_OnLoad,大致流程和楼主分析的一样。

jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
  unsigned __int64 v2; // x1
  const char **v3; // x28
  __int64 v4; // x1
  const char *v5; // x27
  const char *v6; // x23
  const char *v7; // x21
  int v8; // w1
  const char *v9; // x22
  char *v10; // x23
  char *v11; // x0
  int v12; // w0
  int v13; // w21
  int v14; // w0
  __int64 v15; // x1
  unsigned __int64 v16; // x8
  int v17; // w0
  void (__fastcall *v18)(_JNIEnv *, __int64, __int64); // x0
  jint result; // w0
  void (*v20)(void); // x0
  _JNIEnv *v21; // x21
  __int64 v22; // x0
  __int64 v23; // x23
  __int64 v24; // x0
  __int64 v25; // x0
  const char *v26; // x0
  char *v27; // x0
  _JNIEnv *v28; // x19
  __int64 v29; // x0
  __int64 v30; // x28
  __int64 v31; // x0
  __int64 v32; // x0
  __int64 v33; // x22
  __int64 v34; // x0
  void *v35; // x25
  __int64 v36; // x0
  __int64 v37; // x0
  __int64 v38; // x0
  __int64 v39; // x0
  __int64 v40; // x0
  const char *v41; // x20
  const char *v42; // x1
  __int64 v43; // x0
  __int64 v44; // x0
  char *v45; // x27
  char *v46; // x0
  __pid_t v47; // w0
  unsigned int v48; // w23
  DIR *v49; // x22
  int v50; // w1
  unsigned int v51; // w0
  unsigned __int64 v52; // x21
  unsigned __int64 v53; // x2
  __int64 v54; // x1
  __int64 v55; // x3
  __int64 *v56; // x22
  __int64 v57; // x21
  __int64 v58; // x2
  __int64 v59; // x3
  __int64 v60; // x4
  __int64 v61; // x5
  __int64 v62; // x6
  __int64 v63; // x7
  size_t v64; // w0
  char *v65; // x21
  _BOOL4 v66; // w5
  _JNIEnv *v67; // x21
  __int64 v68; // x0
  __int64 v69; // x25
  __int64 v70; // x0
  __int64 v71; // x0
  const char *v72; // x19
  size_t v73; // w0
  __int64 v74; // x22
  __int64 v75; // x0
  __int64 v76; // x0
  size_t v77; // w0
  char *v78; // x0
  __int64 v79; // x21
  unsigned int v80; // w20
  __int64 v81; // x19
  void (__fastcall *v82)(__int64, __int64, _QWORD, __int64, __int64); // x0
  __int64 v83; // x21
  void (__fastcall *v84)(_QWORD, _QWORD, __int64); // x0
  __int64 v85; // x0
  void (__fastcall *v86)(__int64, __int64); // x0
  void (*v87)(void); // x0
  __int64 v88; // [xsp+78h] [xbp+78h]
  __int64 v89; // [xsp+80h] [xbp+80h]
  char *v90; // [xsp+E0h] [xbp+E0h]
  char *v91; // [xsp+E0h] [xbp+E0h]
  __int64 v92; // [xsp+F0h] [xbp+F0h]
  __int64 v93; // [xsp+F0h] [xbp+F0h]
  __int64 v94; // [xsp+F0h] [xbp+F0h]
  __int64 v95; // [xsp+100h] [xbp+100h]
  __int64 v96; // [xsp+100h] [xbp+100h]
  __int64 v97; // [xsp+100h] [xbp+100h]
  __int64 v98; // [xsp+100h] [xbp+100h]
  struct dirent *v99; // [xsp+100h] [xbp+100h]
  size_t v100; // [xsp+100h] [xbp+100h]
  const char *v101; // [xsp+100h] [xbp+100h]
  __int64 v102; // [xsp+100h] [xbp+100h]
  __int64 v103; // [xsp+108h] [xbp+108h]
  __int64 v104; // [xsp+108h] [xbp+108h]
  __int64 v105; // [xsp+108h] [xbp+108h]
  _JNIEnv *v106; // [xsp+150h] [xbp+150h]
  int v107[16]; // [xsp+158h] [xbp+158h] BYREF
  int v108[16]; // [xsp+198h] [xbp+198h] BYREF
  unsigned int v109; // [xsp+1D8h] [xbp+1D8h]
  int v110; // [xsp+1DCh] [xbp+1DCh]
  _DWORD v111[4]; // [xsp+1E0h] [xbp+1E0h] BYREF
  unsigned __int8 v112; // [xsp+1F0h] [xbp+1F0h]
  unsigned __int8 v113; // [xsp+1F1h] [xbp+1F1h]
  unsigned __int8 v114; // [xsp+1F2h] [xbp+1F2h]
  unsigned __int8 v115; // [xsp+1F3h] [xbp+1F3h]
  __int64 v116; // [xsp+230h] [xbp+230h]
  __int64 v117; // [xsp+238h] [xbp+238h]
  _QWORD v118[17]; // [xsp+240h] [xbp+240h] BYREF
  int v119; // [xsp+2C8h] [xbp+2C8h] BYREF
  char v120; // [xsp+2CCh] [xbp+2CCh]
  char v121; // [xsp+2CDh] [xbp+2CDh]
  char v122; // [xsp+2CEh] [xbp+2CEh]
  __int64 v123; // [xsp+2D0h] [xbp+2D0h] BYREF
  __int16 v124; // [xsp+2D8h] [xbp+2D8h]
  __int64 v125; // [xsp+2E0h] [xbp+2E0h] BYREF
  char v126; // [xsp+2E8h] [xbp+2E8h]
  char v127; // [xsp+2E9h] [xbp+2E9h]
  char v128; // [xsp+2EAh] [xbp+2EAh]
  __int64 v129; // [xsp+2F0h] [xbp+2F0h] BYREF
  char v130; // [xsp+2F8h] [xbp+2F8h]
  char v131; // [xsp+2F9h] [xbp+2F9h]
  char v132; // [xsp+2FAh] [xbp+2FAh]
  __int64 v133; // [xsp+300h] [xbp+300h] BYREF
  int v134; // [xsp+308h] [xbp+308h]
  __int64 v135; // [xsp+310h] [xbp+310h] BYREF
  char v136; // [xsp+318h] [xbp+318h]
  char v137; // [xsp+319h] [xbp+319h]
  char v138; // [xsp+31Ah] [xbp+31Ah]
  char v139; // [xsp+31Bh] [xbp+31Bh]
  __int16 v140; // [xsp+31Ch] [xbp+31Ch]
  __int64 v141; // [xsp+320h] [xbp+320h] BYREF
  char v142; // [xsp+328h] [xbp+328h]
  char v143; // [xsp+329h] [xbp+329h]
  char v144; // [xsp+32Ah] [xbp+32Ah]
  char v145; // [xsp+32Bh] [xbp+32Bh]
  char v146; // [xsp+32Ch] [xbp+32Ch]
  char v147; // [xsp+32Dh] [xbp+32Dh]
  char v148; // [xsp+32Eh] [xbp+32Eh]
  _BYTE v149[8]; // [xsp+330h] [xbp+330h] BYREF
  __int64 v150; // [xsp+338h] [xbp+338h]
  char v151; // [xsp+340h] [xbp+340h]
  __int64 v152; // [xsp+348h] [xbp+348h] BYREF
  _QWORD v153[2]; // [xsp+350h] [xbp+350h]
  _BYTE v154[8]; // [xsp+360h] [xbp+360h] BYREF
  __int64 v155; // [xsp+368h] [xbp+368h]
  __int16 v156; // [xsp+370h] [xbp+370h]
  _QWORD v157[2]; // [xsp+378h] [xbp+378h] BYREF
  char v158; // [xsp+388h] [xbp+388h]
  char v159; // [xsp+389h] [xbp+389h]
  char v160; // [xsp+38Ah] [xbp+38Ah]
  _BYTE v161[8]; // [xsp+390h] [xbp+390h] BYREF
  __int64 v162; // [xsp+398h] [xbp+398h]
  int v163; // [xsp+3A0h] [xbp+3A0h]
  _QWORD v164[2]; // [xsp+3A8h] [xbp+3A8h] BYREF
  char v165; // [xsp+3B8h] [xbp+3B8h]
  char v166; // [xsp+3B9h] [xbp+3B9h]
  char v167; // [xsp+3BAh] [xbp+3BAh]
  __int16 v168; // [xsp+3BBh] [xbp+3BBh]
  _BYTE v169[8]; // [xsp+3C0h] [xbp+3C0h] BYREF
  __int64 v170; // [xsp+3C8h] [xbp+3C8h]
  char v171; // [xsp+3D0h] [xbp+3D0h]
  char v172; // [xsp+3D1h] [xbp+3D1h]
  char v173; // [xsp+3D2h] [xbp+3D2h]
  __int16 v174; // [xsp+3D3h] [xbp+3D3h]
  _BYTE v175[8]; // [xsp+3D8h] [xbp+3D8h] BYREF
  __int64 v176; // [xsp+3E0h] [xbp+3E0h]
  char v177; // [xsp+3E8h] [xbp+3E8h]
  char v178; // [xsp+3E9h] [xbp+3E9h]
  char v179; // [xsp+3EAh] [xbp+3EAh]
  char v180; // [xsp+3EBh] [xbp+3EBh]
  char v181; // [xsp+3ECh] [xbp+3ECh]
  char v182; // [xsp+3EDh] [xbp+3EDh]
  char v183; // [xsp+3EEh] [xbp+3EEh]
  char v184; // [xsp+3EFh] [xbp+3EFh]
  __int64 v185; // [xsp+3F0h] [xbp+3F0h]
  __int64 v186; // [xsp+3F8h] [xbp+3F8h]
  char v187; // [xsp+400h] [xbp+400h]
  char v188; // [xsp+401h] [xbp+401h]
  char v189; // [xsp+402h] [xbp+402h]
  char v190; // [xsp+403h] [xbp+403h]
  char v191; // [xsp+404h] [xbp+404h]
  char v192; // [xsp+405h] [xbp+405h]
  char v193; // [xsp+406h] [xbp+406h]
  char v194[8]; // [xsp+407h] [xbp+407h] BYREF
  _BYTE v195[8]; // [xsp+410h] [xbp+410h] BYREF
  __int64 v196; // [xsp+418h] [xbp+418h]
  char v197; // [xsp+420h] [xbp+420h]
  char v198; // [xsp+421h] [xbp+421h]
  char v199; // [xsp+422h] [xbp+422h]
  char v200; // [xsp+423h] [xbp+423h]
  char v201; // [xsp+424h] [xbp+424h]
  char v202; // [xsp+425h] [xbp+425h]
  char v203; // [xsp+426h] [xbp+426h]
  char v204; // [xsp+427h] [xbp+427h]
  __int16 v205; // [xsp+428h] [xbp+428h]
  _QWORD v206[2]; // [xsp+430h] [xbp+430h] BYREF
  char v207; // [xsp+440h] [xbp+440h]
  char v208; // [xsp+441h] [xbp+441h]
  char v209; // [xsp+442h] [xbp+442h]
  char v210; // [xsp+443h] [xbp+443h]
  char v211; // [xsp+444h] [xbp+444h]
  char v212; // [xsp+445h] [xbp+445h]
  char v213; // [xsp+446h] [xbp+446h]
  char v214; // [xsp+447h] [xbp+447h]
  char v215; // [xsp+448h] [xbp+448h]
  char v216; // [xsp+449h] [xbp+449h]
  char v217; // [xsp+44Ah] [xbp+44Ah]
  char v218; // [xsp+44Bh] [xbp+44Bh]
  char v219; // [xsp+44Ch] [xbp+44Ch]
  __int64 v220; // [xsp+450h] [xbp+450h] BYREF
  __int64 v221; // [xsp+458h] [xbp+458h]
  char v222; // [xsp+460h] [xbp+460h]
  char v223; // [xsp+461h] [xbp+461h]
  char v224; // [xsp+462h] [xbp+462h]
  char v225; // [xsp+463h] [xbp+463h]
  char v226; // [xsp+464h] [xbp+464h]
  char v227; // [xsp+465h] [xbp+465h]
  char v228; // [xsp+466h] [xbp+466h]
  char v229; // [xsp+467h] [xbp+467h]
  char v230; // [xsp+468h] [xbp+468h]
  char v231; // [xsp+469h] [xbp+469h]
  char v232; // [xsp+46Ah] [xbp+46Ah]
  char v233; // [xsp+46Bh] [xbp+46Bh]
  __int16 v234; // [xsp+46Ch] [xbp+46Ch]
  __int64 v235; // [xsp+470h] [xbp+470h] BYREF
  __int64 v236; // [xsp+478h] [xbp+478h]
  __int64 v237; // [xsp+480h] [xbp+480h]
  char v238; // [xsp+488h] [xbp+488h]
  char v239; // [xsp+489h] [xbp+489h]
  char v240; // [xsp+48Ah] [xbp+48Ah]
  char v241; // [xsp+48Bh] [xbp+48Bh]
  char v242; // [xsp+48Ch] [xbp+48Ch]
  char v243; // [xsp+48Dh] [xbp+48Dh]
  char v244; // [xsp+48Eh] [xbp+48Eh]
  char v245; // [xsp+48Fh] [xbp+48Fh]
  char v246; // [xsp+490h] [xbp+490h]
  __int64 v247; // [xsp+498h] [xbp+498h] BYREF
  __int64 v248; // [xsp+4A0h] [xbp+4A0h]
  int v249; // [xsp+4A8h] [xbp+4A8h]
  char v250; // [xsp+4ACh] [xbp+4ACh]
  char v251; // [xsp+4ADh] [xbp+4ADh]
  char v252; // [xsp+4AEh] [xbp+4AEh]
  char v253; // [xsp+4AFh] [xbp+4AFh]
  char v254; // [xsp+4B0h] [xbp+4B0h]
  char v255; // [xsp+4B1h] [xbp+4B1h]
  char v256; // [xsp+4B2h] [xbp+4B2h]
  char v257; // [xsp+4B3h] [xbp+4B3h]
  char v258; // [xsp+4B4h] [xbp+4B4h]
  char v259; // [xsp+4B5h] [xbp+4B5h]
  char v260; // [xsp+4B6h] [xbp+4B6h]
  char v261; // [xsp+4B7h] [xbp+4B7h]
  char v262; // [xsp+4B8h] [xbp+4B8h]
  char v263; // [xsp+4B9h] [xbp+4B9h]
  char v264; // [xsp+4BAh] [xbp+4BAh]
  char v265; // [xsp+4BBh] [xbp+4BBh]
  char v266; // [xsp+4BCh] [xbp+4BCh]
  char v267; // [xsp+4BDh] [xbp+4BDh]
  char v268; // [xsp+4BEh] [xbp+4BEh]
  __int64 v269; // [xsp+4D8h] [xbp+4D8h] BYREF
  __int64 v270; // [xsp+4E0h] [xbp+4E0h]
  __int64 v271; // [xsp+4E8h] [xbp+4E8h]
  __int64 v272; // [xsp+4F0h] [xbp+4F0h]
  __int64 v273; // [xsp+4F8h] [xbp+4F8h]
  __int64 v274; // [xsp+500h] [xbp+500h]
  __int64 v275; // [xsp+508h] [xbp+508h]
  __int64 v276; // [xsp+510h] [xbp+510h]
  __int64 v277; // [xsp+518h] [xbp+518h]
  __int64 v278; // [xsp+520h] [xbp+520h]
  __int64 v279; // [xsp+528h] [xbp+528h]
  __int64 v280; // [xsp+530h] [xbp+530h]
  __int64 v281; // [xsp+538h] [xbp+538h]
  __int64 v282; // [xsp+540h] [xbp+540h]
  __int64 v283; // [xsp+548h] [xbp+548h]
  int v284; // [xsp+550h] [xbp+550h]
  __int16 v285; // [xsp+554h] [xbp+554h]
  char v286; // [xsp+556h] [xbp+556h]
  __int64 v287; // [xsp+558h] [xbp+558h] BYREF
  __int64 v288; // [xsp+560h] [xbp+560h]
  __int64 v289; // [xsp+568h] [xbp+568h]
  __int64 v290; // [xsp+570h] [xbp+570h]
  __int64 v291; // [xsp+578h] [xbp+578h]
  __int64 v292; // [xsp+580h] [xbp+580h]
  __int64 v293; // [xsp+588h] [xbp+588h]
  __int64 v294; // [xsp+590h] [xbp+590h]
  __int64 v295; // [xsp+598h] [xbp+598h]
  __int64 v296; // [xsp+5A0h] [xbp+5A0h]
  __int64 v297; // [xsp+5A8h] [xbp+5A8h]
  __int64 v298; // [xsp+5B0h] [xbp+5B0h]
  __int64 v299; // [xsp+5B8h] [xbp+5B8h]
  __int64 v300; // [xsp+5C0h] [xbp+5C0h]
  __int64 v301; // [xsp+5C8h] [xbp+5C8h]
  int v302; // [xsp+5D0h] [xbp+5D0h]
  __int16 v303; // [xsp+5D4h] [xbp+5D4h]
  char v304; // [xsp+5D6h] [xbp+5D6h]
  __int64 v305; // [xsp+5D8h] [xbp+5D8h] BYREF
  __int64 v306; // [xsp+5E0h] [xbp+5E0h]
  __int64 v307; // [xsp+5E8h] [xbp+5E8h]
  __int64 v308; // [xsp+5F0h] [xbp+5F0h]
  __int64 v309; // [xsp+5F8h] [xbp+5F8h]
  __int64 v310; // [xsp+600h] [xbp+600h]
  __int64 v311; // [xsp+608h] [xbp+608h]
  __int64 v312; // [xsp+610h] [xbp+610h]
  __int64 v313; // [xsp+618h] [xbp+618h]
  __int64 v314; // [xsp+620h] [xbp+620h]
  __int64 v315; // [xsp+628h] [xbp+628h]
  __int64 v316; // [xsp+630h] [xbp+630h]
  __int64 v317; // [xsp+638h] [xbp+638h]
  __int64 v318; // [xsp+640h] [xbp+640h]
  __int64 v319; // [xsp+648h] [xbp+648h]
  int v320; // [xsp+650h] [xbp+650h]
  __int16 v321; // [xsp+654h] [xbp+654h]
  char v322; // [xsp+656h] [xbp+656h]
  unsigned __int64 v323; // [xsp+658h] [xbp+658h] BYREF
  unsigned __int64 v324; // [xsp+660h] [xbp+660h]
  __int64 v325; // [xsp+668h] [xbp+668h]
  __int64 v326; // [xsp+670h] [xbp+670h]
  __int64 v327; // [xsp+678h] [xbp+678h]
  __int64 v328; // [xsp+680h] [xbp+680h]
  __int64 v329; // [xsp+688h] [xbp+688h]
  __int64 v330; // [xsp+690h] [xbp+690h]
  __int64 v331; // [xsp+698h] [xbp+698h]
  __int64 v332; // [xsp+6A0h] [xbp+6A0h]
  __int64 v333; // [xsp+6A8h] [xbp+6A8h]
  __int64 v334; // [xsp+6B0h] [xbp+6B0h]
  __int64 v335; // [xsp+6B8h] [xbp+6B8h]
  __int64 v336; // [xsp+6C0h] [xbp+6C0h]
  __int64 v337; // [xsp+6C8h] [xbp+6C8h]
  __int64 v338; // [xsp+6D0h] [xbp+6D0h]
  unsigned __int64 v339; // [xsp+A58h] [xbp+A58h] BYREF
  __int64 v340; // [xsp+A60h] [xbp+A60h]
  char v341; // [xsp+A68h] [xbp+A68h]
  char v342; // [xsp+A69h] [xbp+A69h]
  char v343; // [xsp+A6Ah] [xbp+A6Ah]
  __int16 v344; // [xsp+A6Bh] [xbp+A6Bh]
  __int64 v345; // [xsp+E58h] [xbp+E58h]

  v345 = *off_132C60;
  do
  {
    do
      v2 = __ldaxr((unsigned __int64 *)&qword_13CA80);
    while ( !v2 && __stlxr(1uLL, (unsigned __int64 *)&qword_13CA80) );
  }
  while ( v2 == 1 );
  if ( v2 != 2 )
  {
    byte_13CA8B = 54;
    byte_13CA8D = 0;
    byte_13CA8A = 109;
    byte_13CA8C = 52;
    byte_13CA88 = 97;
    byte_13CA89 = 114;
    qword_13CA80 = 2LL;
  }
  strcpy((char *)qword_1327D8, &byte_13CA88);
  v141 = 0xEBF6D7F1FAFF5000LL;
  v143 = -10;
  v144 = -1;
  v146 = -10;
  v142 = -37;
  v147 = -31;
  v145 = -29;
  v148 = 0;
  sub_18F58(&v141, 12LL, 4294967235LL);
  strcpy((char *)qword_132BE0, (const char *)&v141);
  v192 = 0;
  v185 = 0x164A080A06FD00LL;
  v186 = 0xE15044A0A000B06LL;
  v187 = 18;
  v188 = 23;
  v189 = 4;
  v190 = 21;
  v191 = 21;
  v193 = 23;
  strcpy(v194, "J-");
  v106->functions->GetJavaVM(&v106->functions, (JavaVM **)off_132A60);
  v20 = (void (*)(void))sub_190B0((char *)&loc_1E00C + 1, 537LL);
  v20();
  v21 = v106;
  v22 = (__int64)v106->functions->FindClass(&v106->functions, (const char *)qword_132830);
  v323 = 0xCEC2CDC4C8D30C00LL;
  v23 = v22;
  LOWORD(v324) = 198;
  sub_18F58(&v323, 7LL, 4294967183LL);
  v339 = 0xE7A9BEA9A2847A00LL;
  v340 = 0xBABC9BE7AFA6A9A4LL;
  v341 = -95;
  v342 = -90;
  v343 = -81;
  v344 = 243;
  sub_18F58(&v339, 18LL, 4294967218LL);
  v24 = (__int64)v21->functions->GetStaticFieldID(
                   &v21->functions,
                   (jclass)v23,
                   (const char *)&v323,
                   (const char *)&v339);
  v25 = (__int64)v21->functions->GetStaticObjectField(&v21->functions, (jclass)v23, (jfieldID)v24);
  v26 = v21->functions->GetStringUTFChars(&v21->functions, (jstring)v25, 0LL);
  v27 = strcpy((char *)qword_132A20, v26);
  sub_18530(v27);
  v206[0] = 0x7011C0A000FB800LL;
  v206[1] = 0xD2F411E1E0F410ALL;
  v208 = 7;
  v210 = 7;
  v213 = 58;
  v28 = v106;
  v214 = 6;
  v207 = 26;
  v211 = 26;
  v215 = 28;
  v212 = 23;
  v209 = 24;
  v216 = 11;
  v219 = 0;
  v217 = 15;
  v218 = 10;
  sub_18F58(v206, 26LL, 4294967254LL);
  v29 = (__int64)v28->functions->FindClass(&v28->functions, (const char *)v206);
  v184 = 0;
  v175[0] = 0;
  v176 = 0xB1ACB3ACB1A684B1LL;
  v30 = v29;
  v178 = -111;
  v175[2] = -90;
  v175[7] = -85;
  v179 = -83;
  v175[3] = -80;
  v180 = -73;
  v175[4] = -73;
  v175[5] = -73;
  v182 = -92;
  v183 = -95;
  v175[1] = 85;
  v175[6] = -96;
  v177 = -68;
  v181 = -96;
  sub_18F58(v175, 21LL, 4294967184LL);
  v235 = 0x1218173A5F5EBC00LL;
  v236 = 0x6061759121F1904LL;
  v237 = 0x21F001F02153759LL;
  v238 = 15;
  v239 = 34;
  v240 = 30;
  v246 = 0;
  v241 = 4;
  v242 = 19;
  v243 = 23;
  v244 = 18;
  v245 = 77;
  sub_18F58(&v235, 30LL, 4294967242LL);
  v28->functions->GetStaticMethodID(&v28->functions, (jclass)v30, v175, (const char *)&v235);
  v96 = _JNIEnv::CallStaticObjectMethod(v106, v30);
  v157[0] = 0xF1FBD1F6E7E50200LL;
  v157[1] = 0xE7F6ECEDC1EFE7F6LL;
  v158 = -6;
  v159 = -10;
  v160 = 0;
  sub_18F58(v157, 16LL, 4294967168LL);
  v220 = 0xFBF1FED3B6B71E00LL;
  v221 = 0xEFEFFEB0FBF6F0EDLL;
  v222 = -80;
  v228 = -25;
  v223 = -36;
  v231 = -14;
  v227 = -6;
  v226 = -21;
  v229 = -21;
  v232 = -17;
  v224 = -16;
  v225 = -15;
  v230 = -42;
  v234 = 164;
  v233 = -13;
  sub_18F58(&v220, 27LL, 4294967169LL);
  v28->functions->GetMethodID(&v28->functions, (jclass)v30, (const char *)v157, (const char *)&v220);
  v97 = _JNIEnv::CallObjectMethod(v106, v96);
  v195[0] = 0;
  v196 = 0xF1DDB1EEEEFFB1FALL;
  v195[1] = 123;
  v195[5] = -20;
  v195[7] = -9;
  v198 = -22;
  v200 = -26;
  v201 = -22;
  v202 = -41;
  v204 = -18;
  v205 = 242;
  v195[4] = -6;
  v199 = -5;
  v195[3] = -16;
  v197 = -16;
  v195[6] = -15;
  v203 = -13;
  v195[2] = -1;
  sub_18F58(v195, 23LL, 4294967269LL);
  v31 = (__int64)v28->functions->FindClass(&v28->functions, v195);
  v161[0] = 0;
  v162 = 0x1E111E321A181E14LL;
  v161[2] = 24;
  v161[1] = -54;
  v161[4] = 11;
  v161[5] = 47;
  v161[6] = 30;
  v92 = v31;
  v163 = 858648;
  v161[3] = 26;
  v161[7] = 28;
  sub_18F58(v161, 17LL, 4294967221LL);
  v269 = 0xEAE0EFC2A7A66800LL;
  v270 = 0xE0E1EDA1EAE7E1FCLL;
  v271 = 0xA1E3FEA1FAE0EBFALL;
  v272 = 0xC3EBE9EFE5EDEFDELL;
  v273 = 0xB5FCEBE9EFE0EFLL;
  sub_18F58(&v269, 37LL, 4294967270LL);
  v28->functions->GetMethodID(&v28->functions, (jclass)v92, v161, (const char *)&v269);
  v93 = _JNIEnv::CallObjectMethod(v106, v97);
  v98 = (__int64)v28->functions->GetObjectClass(&v28->functions, (jobject)v93);
  v149[0] = 0;
  v150 = 0xFBF2FADDF1F3F5FFLL;
  v149[1] = 125;
  v149[4] = -32;
  v149[5] = -60;
  v149[7] = -9;
  v149[2] = -13;
  v149[3] = -15;
  v151 = 0;
  v149[6] = -11;
  sub_18F58(v149, 14LL, 4294967273LL);
  v287 = 0xFFE8FFF4D2B63F00LL;
  v288 = 0xEACDB1F9F0FFF2B1LL;
  v289 = 0xD2B7D7A5F9F0F7ECLL;
  v290 = 0xB1FAF7F1ECFAF0FFLL;
  v293 = 0xA5F1F8F0D7FBF9LL;
  v291 = 0xB1EAF0FBEAF0F1FDLL;
  v292 = 0xFFF5FDFFCEB1F3EELL;
  sub_18F58(&v287, 53LL, 4294967201LL);
  v28->functions->GetMethodID(&v28->functions, (jclass)v98, v149, (const char *)&v287);
  v28->functions->NewStringUTF(&v28->functions, (const char *)qword_132A20);
  v90 = (char *)_JNIEnv::CallObjectMethod(v106, v93);
  v94 = (__int64)v28->functions->GetObjectClass(&v28->functions, v90);
  v154[0] = 0;
  v155 = 0xF0F8DFF8F9FFE2F7LL;
  v154[2] = -9;
  v154[1] = 80;
  v154[3] = -26;
  v154[4] = -26;
  v154[5] = -6;
  v156 = 249;
  v154[6] = -1;
  v154[7] = -11;
  sub_18F58(v154, 15LL, 4294967238LL);
  v247 = 0xFDE0F6FCF3DE1E00LL;
  v248 = 0xF7E6FCFDF1BDF6FBLL;
  v252 = -45;
  v253 = -30;
  v254 = -30;
  v256 = -5;
  v249 = -490871044;
  v251 = -67;
  v255 = -2;
  v257 = -15;
  v268 = 0;
  v250 = -1;
  v258 = -13;
  v259 = -26;
  v263 = -37;
  v265 = -12;
  v260 = -5;
  v261 = -3;
  v266 = -3;
  v262 = -4;
  v264 = -4;
  v267 = -87;
  sub_18F58(&v247, 36LL, 4294967180LL);
  v32 = (__int64)v28->functions->GetFieldID(&v28->functions, (jclass)v94, v154, (const char *)&v247);
  v33 = (__int64)v28->functions->GetObjectField(&v28->functions, v90, (jfieldID)v32);
  v34 = (__int64)v28->functions->GetObjectClass(&v28->functions, (jobject)v33);
  v133 = 0xD3D5C4C3D9C52000LL;
  v134 = 12902386;
  v35 = (void *)v34;
  sub_18F58(&v133, 9LL, 4294967190LL);
  v164[0] = 0xBDF3E4F3F8DE5300LL;
  v164[1] = 0xE0E6C1BDF5FCF3FELL;
  v165 = -5;
  v166 = -4;
  v168 = 169;
  v167 = -11;
  sub_18F58(v164, 18LL, 4294967233LL);
  v36 = (__int64)v28->functions->GetFieldID(&v28->functions, v35, (const char *)&v133, (const char *)v164);
  v37 = (__int64)v28->functions->GetObjectField(&v28->functions, (jobject)v33, (jfieldID)v36);
  v28->functions->GetStringUTFChars(&v28->functions, (jstring)v37, 0LL);
  v123 = 0x1D3015001510F800LL;
  v124 = 6;
  sub_18F58(&v123, 7LL, 4294967180LL);
  v169[0] = 0;
  v170 = 0xF2F4D3AFE7EEE1ECLL;
  v169[1] = 98;
  v169[7] = -81;
  v169[2] = -52;
  v169[3] = -22;
  v169[5] = -10;
  v171 = -23;
  v172 = -18;
  v169[4] = -31;
  v169[6] = -31;
  v173 = -25;
  v174 = 187;
  sub_18F58(v169, 18LL, 4294967266LL);
  v38 = (__int64)v28->functions->GetFieldID(&v28->functions, v35, (const char *)&v123, v169);
  v39 = (__int64)v28->functions->GetObjectField(&v28->functions, (jobject)v33, (jfieldID)v38);
  v40 = (__int64)v28->functions->GetStringUTFChars(&v28->functions, (jstring)v39, 0LL);
  v41 = (const char *)qword_132AB8;
  v42 = (const char *)v40;
  v43 = qword_132AB8;
  *(_QWORD *)qword_132AB8 = 0LL;
  *(_QWORD *)(v43 + 8) = 0LL;
  *(_QWORD *)(v43 + 16) = 0LL;
  *(_QWORD *)(v43 + 24) = 0LL;
  *(_QWORD *)(v43 + 32) = 0LL;
  *(_QWORD *)(v43 + 40) = 0LL;
  *(_QWORD *)(v43 + 48) = 0LL;
  *(_QWORD *)(v43 + 56) = 0LL;
  *(_QWORD *)(v43 + 64) = 0LL;
  *(_QWORD *)(v43 + 72) = 0LL;
  *(_QWORD *)(v43 + 80) = 0LL;
  *(_QWORD *)(v43 + 88) = 0LL;
  *(_QWORD *)(v43 + 96) = 0LL;
  *(_QWORD *)(v43 + 104) = 0LL;
  *(_QWORD *)(v43 + 112) = 0LL;
  *(_QWORD *)(v43 + 120) = 0LL;
  strcpy((char *)v43, v42);
  v44 = strlen(v41);
  if ( v41[v44 - 1] != 47 )
    v41[v44] = 47;
  v45 = (char *)off_132EB8;
  memset(off_132EB8, 0, 0x100u);
  v125 = 0xD2C1C3C4D38F7900LL;
  v126 = -60;
  v128 = 0;
  v127 = -113;
  sub_18F58(&v125, 8LL, 4294967257LL);
  v46 = strcpy(v45, (const char *)&v125);
  sub_1EAEC(v46);
  v323 = 0xA0B3ACB1A4AB0900LL;
  v324 = 0x81BCB7A4B7A7AC89LL;
  LOBYTE(v325) = -84;
  *(_WORD *)((char *)&v325 + 1) = 183;
  sub_18F58(&v323, 16LL, 4294967244LL);
  v339 = 0x88C6D1C6CDEB2800LL;
  v340 = 0xD5D3F488C0C9C6CBLL;
  v341 = -50;
  v342 = -55;
  v343 = -64;
  v344 = 156;
  sub_18F58(&v339, 18LL, 4294967183LL);
  v75 = (__int64)v106->functions->GetFieldID(&v106->functions, v35, (const char *)&v323, (const char *)&v339);
  v76 = (__int64)v106->functions->GetObjectField(&v106->functions, (jobject)v33, (jfieldID)v75);
  v101 = v106->functions->GetStringUTFChars(&v106->functions, (jstring)v76, 0LL);
  v77 = strlen(v101);
  v78 = (char *)malloc(v77 + 1);
  *(_QWORD *)off_132DE0 = v78;
  strcpy(v78, v101);
  v47 = getpid();
  v135 = 0x581418050758E900LL;
  v48 = v47;
  v138 = 88;
  v305 = 0LL;
  v306 = 0LL;
  v307 = 0LL;
  v308 = 0LL;
  v309 = 0LL;
  v310 = 0LL;
  v311 = 0LL;
  v312 = 0LL;
  v140 = 19;
  v136 = 82;
  v137 = 19;
  v139 = 17;
  sub_18F58(&v135, 11LL, 4294967198LL);
  sprintf((char *)&v305, (const char *)&v135, v48);
  v49 = opendir((const char *)&v305);
  if ( !v49 )
    JUMPOUT(0x42738LL);  //已经nop掉,不会走的流程。
  v152 = 0x8FC3CFD2D08F4B00LL;
  v153[0] = 0x858FC4C68FC485LL;
  *(_WORD *)((char *)v153 + 7) = 196;
  v99 = 0LL;
  sub_18F58(&v152, 14LL, 4294967275LL);
  v119 = -441840640;
  v122 = 0;
  v120 = -12;
  v121 = -17;
  sub_18F58(&v119, 4LL, 4294967176LL);
  v129 = 0xFDB2F9EFFDFE6C00LL;
  v50 = 2;
  v130 = -20;
  v132 = 0;
  v131 = -9;
  while ( 1 )
  {
    switch ( v50 )
    {
      case 0:
      case 4:
      case 5:
      case 8:
        do
        {
          do
          {
            v51 = atoi(v99->d_name);
            sprintf((char *)&v323, (const char *)&v152, v48, v51);
            *((_BYTE *)&v339 + readlink((const char *)&v323, (char *)&v339, 0x3FFu)) = 0;
          }
          while ( !strstr((const char *)&v339, (const char *)qword_132A20) );
          v52 = strlen((const char *)&v339);
          v53 = strlen((const char *)&v119);
        }
        while ( v52 < v53 || v53 == 0 );
        strncmp((const char *)&v339 + v52 - v53, (const char *)&v119, v53);
        goto LABEL_42;
      case 1:
        JUMPOUT(0x4228CLL);
      case 2:
        sub_18F58(&v129, 8LL, 4294967280LL);
        goto LABEL_41;
      case 3:
        closedir(v49);
        v100 = strlen((const char *)&v339) + 1;
        v91 = (char *)malloc(v100);
        memcpy(v91, &v339, v100);
        v64 = strlen(v91);
        v65 = (char *)malloc(v64 + 1);
        *off_132BA8 = (__int64)v65;
        strcpy(v65, v91);
        v66 = strstr(v65, (const char *)qword_132A20) == 0LL;
        LOBYTE(v323) = 0;
        v67 = v106;
        *off_132EF8 = v66;
        BYTE1(v323) = -102;
        strcpy((char *)&v323 + 2, "\\\\\\2/>>,\\\\\\");
        sub_18F58(&v323, 11LL, 4294967269LL);
        v68 = (__int64)v67->functions->FindClass(&v67->functions, (const char *)qword_132830);
        v305 = 0x2C2C3D203E248400LL;
        v69 = v68;
        LOWORD(v306) = 62;
        sub_18F58(&v305, 7LL, 4294967273LL);
        v339 = 0x56180F181335D500LL;
        v340 = 0xB0D2A561E171815LL;
        v341 = 16;
        v342 = 23;
        v343 = 30;
        v344 = 66;
        sub_18F58(&v339, 18LL, 4294967212LL);
        v70 = (__int64)v67->functions->GetStaticFieldID(
                         &v67->functions,
                         (jclass)v69,
                         (const char *)&v305,
                         (const char *)&v339);
        v71 = (__int64)v67->functions->GetStaticObjectField(&v67->functions, (jclass)v69, (jfieldID)v70);
        v72 = v67->functions->GetStringUTFChars(&v67->functions, (jstring)v71, 0LL);
        v73 = strlen((const char *)&v323);
        *off_132938 = strncmp(v72, (const char *)&v323, v73) != 0;
        sub_205CC();
        if ( (unsigned int)is_magisk_check_process(v106) == 1 || (unsigned int)is_miuiinstaller_process(v106) == 1 )
          JUMPOUT(0x41314LL);
        sub_3D9C8();
        v3 = (const char **)off_132BA8;
        v269 = 0LL;
        v270 = 0LL;
        v271 = 0LL;
        v272 = 0LL;
        v273 = 0LL;
        v274 = 0LL;
        v4 = *off_132BA8;
        v287 = 0LL;
        v288 = 0LL;
        v289 = 0LL;
        v290 = 0LL;
        v291 = 0LL;
        v292 = 0LL;
        v293 = 0LL;
        v294 = 0LL;
        v295 = 0LL;
        v296 = 0LL;
        v297 = 0LL;
        v298 = 0LL;
        v299 = 0LL;
        v300 = 0LL;
        v301 = 0LL;
        v302 = 0;
        v303 = 0;
        v304 = 0;
        v89 = v4;
        v275 = 0LL;
        v276 = 0LL;
        v277 = 0LL;
        v278 = 0LL;
        v279 = 0LL;
        v280 = 0LL;
        v281 = 0LL;
        v282 = 0LL;
        v283 = 0LL;
        v284 = 0;
        v285 = 0;
        v286 = 0;
        v323 = 0LL;
        v324 = 0LL;
        v325 = 0LL;
        v326 = 0LL;
        v327 = 0LL;
        v328 = 0LL;
        v329 = 0LL;
        v330 = 0LL;
        v331 = 0LL;
        v332 = 0LL;
        v333 = 0LL;
        v334 = 0LL;
        v335 = 0LL;
        v336 = 0LL;
        v337 = 0LL;
        v338 = 0LL;
        v5 = (const char *)qword_132AB8;
        v6 = (const char *)qword_132C80;
        sprintf((char *)&v269, "%s%s", (const char *)qword_132AB8, (const char *)qword_132C80);
        v7 = (const char *)qword_1327D8;
        sprintf((char *)&v287, "%s%s/%s/%s", v5, v6, (const char *)qword_132BF0, (const char *)qword_1327D8);
        v220 = 0xF0E6E6F4F9F64100LL;
        LODWORD(v221) = -470696986;
        WORD2(v221) = 240;
        sub_18F58(&v220, 11LL, 4294967252LL);
        sprintf((char *)&v323, "%s%s/%s", v5, v6, (const char *)&v220);
        v305 = 0LL;
        v306 = 0LL;
        v307 = 0LL;
        v308 = 0LL;
        v8 = *off_132CF8;
        v309 = 0LL;
        v310 = 0LL;
        v311 = 0LL;
        v312 = 0LL;
        v313 = 0LL;
        v314 = 0LL;
        v315 = 0LL;
        v316 = 0LL;
        v317 = 0LL;
        v318 = 0LL;
        v319 = 0LL;
        v320 = 0;
        v321 = 0;
        v322 = 0;
        if ( v8 <= 27 )
          JUMPOUT(0x413D4LL);
        v9 = *v3;
        strcpy((char *)&v305, *v3);
        v10 = strrchr((const char *)&v305, 47);
        v11 = strrchr(v9, 47);
        sprintf(v10, "/%s/%s/%s", "oat", v7, v11 + 1);
        strcpy((char *)&v305 + strlen((const char *)&v305) - 3, "odex");
        if ( !(_BYTE)v305 || (v12 = open((const char *)&v305, 0), v13 = v12, (v12 & 0x80000000) != 0) )
          JUMPOUT(0x41F90LL);
        v14 = fstat(v12, (struct stat *)v118);
        v15 = 0LL;
        if ( !v14 )
          v15 = v118[13];
        v88 = v15;
        close(v13);
        v111[2] = -1732584194;
        v110 = 0;
        LODWORD(v16) = 0;
        v109 = 0;
        v17 = 6;
        v111[0] = 1732584193;
        v111[1] = -271733879;
        v111[3] = 271733878;
        while ( 1 )
        {
          switch ( v17 )
          {
            case 0:
            case 2:
              goto LABEL_31;
            case 1:
              JUMPOUT(0x41A04LL);
            case 3:
            case 5:
              goto LABEL_30;
            case 4:
            case 9:
            case 11:
              goto LABEL_40;
            case 6:
              v16 = ((unsigned __int64)v109 >> 3) & 0x3F;
              if ( v109 <= v109 + 512 )
                v17 = 7;
              else
                v17 = 8;
              continue;
            case 7:
              v109 += 512;
LABEL_31:
              *(&v112 + (int)v16) = *off_132D88;
LABEL_40:
              v108[0] = (v114 << 16) | (v115 << 24) | v112 | (v113 << 8);
LABEL_30:
              sub_17830(v111, v108);
              v107[0] = (v114 << 16) | (v115 << 24) | v112 | (v113 << 8);
              sub_17830(v111, v107);
              LODWORD(v116) = v111[0];
              v54 = off_132D88;
              v55 = v117;
              *off_132D88 = v116;
              *(_QWORD *)(v54 + 8) = v55;
              *(_QWORD *)((char *)&word_10 + off_132D88) = v88;
              if ( access((const char *)&v323, 0) )  //check magisk.db等
                JUMPOUT(0x425C4LL);
              v56 = off_132C18;
              v57 = ((__int64 (__fastcall *)(unsigned __int64 *, const char *))*off_132C18)(&v323, "r");
              if ( v57 )
              {
                ((void (__fastcall *)(__int64 *, __int64, __int64, __int64))v56[4])(&v305, 1LL, 24LL, v57);
                ((void (__fastcall *)(__int64))v56[1])(v57);
              }
              if ( memcmp(&v305, off_132D88, 0x10u) )
                JUMPOUT(0x42CACLL);
              v74 = off_132DD0;
              dword_13C878 = 0;
              //p1C651410144BB9EA57658E3CB4A76FFC hook日志
              p1C651410144BB9EA57658E3CB4A76FFC(
                *((unsigned __int8 *)&dword_0 + off_132DD0 + 3),
                (__int64)&unk_132000,
                v58,
                v59,
                v60,
                v61,
                v62,
                v63);
              if ( (*((_BYTE *)&dword_0 + v74 + 3) & 0x80) != 0 )
                JUMPOUT(0x42F6CLL);
              ((void (__fastcall *)())sub_22254)();
              v79 = qword_132BE0;
              v287 = 0LL;
              v288 = 0LL;
              v289 = 0LL;
              v290 = 0LL;
              v291 = 0LL;
              v292 = 0LL;
              v293 = 0LL;
              v294 = 0LL;
              v295 = 0LL;
              v296 = 0LL;
              v297 = 0LL;
              v298 = 0LL;
              v299 = 0LL;
              v300 = 0LL;
              v301 = 0LL;
              v302 = 0;
              v303 = 0;
              v304 = 0;
              sprintf(
                (char *)&v287,
                "%s%s/%s32",
                (const char *)qword_132AB8,
                (const char *)qword_132C80,
                (const char *)qword_132BE0);
              v269 = 0xCDDE90DDD6D36900LL;
              v270 = 0x88C992D6DDDEDAD2LL;
              v271 = 0xD0CC91CC9A90DELL;
              sub_18F58(&v269, 21LL, 4294967254LL);
              sprintf((char *)&v305, (const char *)&v269, v79);
              v249 = 15855024;
              v247 = 0xECFFB1FCF7F21B00LL;
              v248 = 0xEDBBB1F7FCFFFBF3LL;
              sub_18F58(&v247, 17LL, 4294967173LL);
              sprintf((char *)&v323, (const char *)&v247, v79);
              v235 = 0xE0E7F6E0E0F23D00LL;
              LOBYTE(v236) = -68;
              BYTE3(v236) = -96;
              WORD2(v236) = 161;
              *(_WORD *)((char *)&v236 + 1) = -8010;
              sub_18F58(&v235, 11LL, 4294967214LL);
              sprintf((char *)&v339, (const char *)&v235, v79);
              
              //_Z33pDDBBEAE1814F167EA39B819F31AFFA1Bv  off_132CA8  p68DFD134BAA83023AB62FB119A599BBE hook相关函数,加载被偷的方法
              sub_38598(v106, v89);  //hook _ZNK3art16ArtDexFileLoader4OpenERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEjNS1_10unique_ptrINS_6MemMapENS1_14default_deleteISB_EEEEbbPS7_
              if ( !byte_8[off_132DD0] )
              {
                if ( !byte_9[off_132DD0 + 5] )
                  JUMPOUT(0x42CC8LL);
                v87 = (void (*)(void))sub_190B0((char *)off_132CA8 + 532, 532LL);
                v87();  //hook libart
                p3E944ED2E71E0E61D7F42C7D75CABC05(v89, qword_132A20, v106); / 参数1base.apk, 参数2com.eshore.ejust
              }
              v80 = dword_13C878;
              v81 = *off_132BA8;
              v102 = (unsigned int)dword_13C87C;
              v104 = *off_1328F0[0];
              v82 = (void (__fastcall *)(__int64, __int64, _QWORD, __int64, __int64))sub_190D0(
                                                                                       (char *)off_132B00 + 454,
                                                                                       454LL);
              // LDR             X22, [X23,#off_132D50@PAGEOFF]        运行这里的函数                                                                
                                                                                       
                                                                                       
              v83 = qword_132A20;
              //p9610C637CB6ACA595D4AFE445A604F46
              v82(qword_132A20, v81, v80, v102, v104); //proc/self/task/8772/status,sr2:524288 openx
              v105 = (unsigned int)*off_132CF8;
              
              
              v84 = (void (__fastcall *)(_QWORD, _QWORD, __int64))sub_190D8((char *)off_132D50 + 615, 615LL);
              
              
             
              
              v84((unsigned __int8)byte_9[off_132DD0 + 2], (unsigned __int8)byte_9[off_132DD0 + 3], v105);
              v86 = (void (__fastcall *)(__int64, __int64))sub_190E0((char *)off_1329C0 + 376, 376LL);
              
               //p26EB757DFE66B89DE39BFD380E11B8E4
              v86(v83, v89); //用Inflat解压进行文件校验
              v85 = ((__int64 (__fastcall *)())sub_2545C)();  //这个函数有和java交互 校验签名
              sub_1EAEC(v85);
              v95 = (unsigned int)sub_1B0F0();
              v103 = (unsigned int)*off_132CF8;
              v18 = (void (__fastcall *)(_JNIEnv *, __int64, __int64))sub_190F0((char *)off_132FE0[0] + 298);
              
              //p49038B1E51B37042EFF0885354B44D45
              v18(v106, v95, v103);
              result = 65540;
              if ( v345 != *off_132C60 )
                JUMPOUT(0x42FC0LL);
              return result;                //结束函数
            case 8:
              JUMPOUT(0x4191CLL);
            case 10:
              JUMPOUT(0x41978LL);
            default:
              continue;
          }
        }
      case 6:
LABEL_41:
        v99 = readdir(v49);
        v50 = v99 == 0LL;
        break;
      case 7:
LABEL_42:
        if ( *(_BYTE *)(*off_1328F0[0] + 444) )
          JUMPOUT(0x42CE8LL);
        v50 = 3;
        break;
      default:
        continue;
    }
  }
}



dump来的dex被偷代码还要修复,最难搞的还有libdexjni.so的还原(加密的方法运行很慢,也只有核心函数才加密)。函数内的字符串加密,还是很简单的, 可以hook住函数解密,低字节永远是00(LL),然后第一个字节和参数3最低位异或为key。参数2是字符长度。+2逐个位置和key异或。

  v339 = 0xE7A9BEA9A2847A00LL;
  v340 = 0xBABC9BE7AFA6A9A4LL;
  v341 = -95;
  v342 = -90;
  v343 = -81;
  v344 = 243;
  sub_18F58(&v339, 18LL, 4294967218LL);
__int64 __fastcall sub_18F58(__int64 result, int a2, char a3, __int64 a4, __int64 a5, int a6, __int64 a7, char a8)
{
  int v8; // w3

  v8 = 1;
  while ( 1 )
  {
    switch ( v8 )
    {
      case 0:
        *(_BYTE *)(result + a6) = 0;
        return result;
      case 1:
        a6 = 0;
        v8 = 2;
        a8 = *(_BYTE *)(result + 1) ^ a3;
        break;
      case 2:
        if ( a2 <= a6 )
          v8 = 0;
        else
          v8 = 3;
        break;
      case 3:
        v8 = 4;
        *(_BYTE *)(result + a6) = a8 ^ *(_BYTE *)(result + a6 + 2);
        break;
      case 4:
        ++a6;
        v8 = 2;
        break;
      default:
        continue;
    }
  }
}


2022-10-13 10:44
0
雪    币: 20
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
nb
2023-1-4 11:36
0
雪    币: 1636
活跃值: (1272)
能力值: ( LV3,RANK:37 )
在线值:
发帖
回帖
粉丝
14
大佬太强了,最近也在对抗这个so,文中去混淆那一部分看上去像一个switch case结构但是ida没有识别,可以手动还原一下switch case,我参考了https://www.nuke666.cn/2021/08/Specify-switch-statement-in-IDA-Pro/这篇文章。
2023-1-10 13:35
0
雪    币: 228
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
大佬最近我也在研究dexjni这个so 他这个混淆各种乱跳自定义 可以加个联系方式一起讨论下
2023-9-17 00:28
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
在JNI_Onload Dump出的内存,放进IDA不识别函数,需要C识别才行,有什么办法解决吗
2024-1-24 09:42
0
游客
登录 | 注册 方可回帖
返回
//