首页
论坛
课程
招聘
[原创]android so文件攻防实战-libDexHelper.so反混淆
2022-7-10 21:45 23855

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

2022-7-10 21:45
23855

计划是写一个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了。

1
2
3
4
5
6
7
8
9
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
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)

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

1
2
3
4
5
6
7
8
9
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
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()

更恶心的是还有很多字符串是自己在函数内解密的,这种情况我也没想到有什么好的方法。
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)的分析在最后。

0x15960

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

1
2
3
4
5
6
7
8
9
10
11
12
libDexHelper.so
libDexHelper-x86.so
libDexHelper-x86_64.so
/system/lib64/libart.so
/system/lib64/libLLVM.so
/system/framework/arm64/boot-framework.oat
/system/lib64/libskia.so
/system/lib64/libhwui.so
.oat
ff c3 01 d1 f3 03 04 aa f4 03 02 aa f5 03 01 aa e8 03 00 aa
GumInvocationListener
GSocketListenerEvent

0x16A30

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

1
2
3
4
5
6
7
ro.yunos.version
ro.yunos.version.release
persist.sys.dalvik.vm.lib
persist.sys.dalvik.vm.lib.2
/system/bin/dex2oat
LD_OPT_PACKAGENAME
LD_OPT_ENFORCE_V1

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

0x17A70

md5。

0x186C4

字符串解密函数。

0x19674

返回字符串rw。

0x19778

返回字符串su。

0x1987C

返回字符串mount。

0x19998

写classes.dve文件。

0x19b48

读取目录中的文件。

0x19E08

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

0x1A058

调用0x19E08创建数组:

1
2
3
4
5
6
7
/etc
/sbin
/system
/system/bin
/vendor/bin
/system/sbin
/system/xbin

0x1A740

调用0x19E08创建数组:

1
2
3
4
5
6
com.yellowes.su
eu.chainfire.supersu
com.noshufou.android.su
com.thirdparty.superuser
com.koushikdutta.superuser
com.noshufou.android.su.elite

0x1AF1C

调用0x19E08创建数组:

1
2
3
4
5
6
com.chelpus.lackypatch
com.ramdroid.appquarantine
com.koushikdutta.rommanager
com.dimonvideo.luckypatcher
com.ramdroid.appquarantinepro
com.koushikdutta.rommanager.license

0x1B7D0

调用0x19E08创建数组:

1
2
3
4
5
6
7
8
9
com.saurik.substrate
com.formyhm.hideroot
com.amphoras.hidemyroot
com.devadvance.rootcloak
com.formyhm.hiderootPremium
com.devadvance.rootcloakplus
com.amphoras.hidemyrootadfree
com.zachspong.temprootremovejb
de.robv.android.xposed.installer

0x1C40C

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

0x1C61C

查看classes.dve是否存在。

0x1C8D8

调用0x19E08创建数组:

1
2
3
4
5
6
7
8
9
10
11
/sbin/
/su/bin/
/data/local/
/system/bin/
/system/xbin/
/data/local/bin/
/system/sd/xbin/
/data/local/xbin/
/system/bin/.ext/
/system/bin/failsafe/
/system/usr/we-need-root/

0x1D518

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

1
2
3
4
5
6
7
8
9
10
11
12
.cache
oat
.payload
v1filter.jar
classes.odex
classes.vdex
classes.dex
assets/classes.jar
.cache/classes.jar
.cache/classes.dex
.cache/classes.odex
.cache/classes.vdex

0x1E520

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

1
2
3
4
5
6
7
0x137BB0 fopen
0x137BB8 fclose
0x137BC0 fgets
0x137BC8 fwrite
0x137BD0 fread
0x137BD8 sprintf
0x137BE0 pthread_create

0x1F250

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

0x1F710

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

0x1FDC8

注册如下native函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
RegisterNative(com/secneo/apkwrapper/H, attach(Landroid/app/Application;Landroid/content/Context;)V, RX@0x4002f6e4[libDexHelper.so]0x2f6e4)
RegisterNative(com/secneo/apkwrapper/H, b(Landroid/content/Context;Landroid/app/Application;)V, RX@0x400247c0[libDexHelper.so]0x247c0)
RegisterNative(com/secneo/apkwrapper/H, c()V, RX@0x40024c08[libDexHelper.so]0x24c08)
RegisterNative(com/secneo/apkwrapper/H, d(Ljava/lang/String;)Ljava/lang/String;, RX@0x40023d04[libDexHelper.so]0x23d04)
RegisterNative(com/secneo/apkwrapper/H, e(Ljava/lang/Object;Ljava/util/List;Ljava/lang/String;)[Ljava/lang/Object;, RX@0x40035ab0[libDexHelper.so]0x35ab0)
RegisterNative(com/secneo/apkwrapper/H, f()[Ljava/lang/String;, RX@0x4001a740[libDexHelper.so]0x1a740)
RegisterNative(com/secneo/apkwrapper/H, g()[Ljava/lang/String;, RX@0x4001af1c[libDexHelper.so]0x1af1c)
RegisterNative(com/secneo/apkwrapper/H, h()[Ljava/lang/String;, RX@0x4001b7d0[libDexHelper.so]0x1b7d0)
RegisterNative(com/secneo/apkwrapper/H, n()[Ljava/lang/String;, RX@0x4001c8d8[libDexHelper.so]0x1c8d8)
RegisterNative(com/secneo/apkwrapper/H, j()[Ljava/lang/String;, RX@0x4001a058[libDexHelper.so]0x1a058)
RegisterNative(com/secneo/apkwrapper/H, k()Ljava/lang/String;, RX@0x40019778[libDexHelper.so]0x19778)
RegisterNative(com/secneo/apkwrapper/H, l()Ljava/lang/String;, RX@0x4001987c[libDexHelper.so]0x1987c)
RegisterNative(com/secneo/apkwrapper/H, m()Ljava/lang/String;, RX@0x40019674[libDexHelper.so]0x19674)
RegisterNative(com/secneo/apkwrapper/H, bb(Landroid/content/Context;Landroid/app/Application;Landroid/app/Application;)V, RX@0x4002921c[libDexHelper.so]0x2921c)
RegisterNative(com/secneo/apkwrapper/H, o(Landroid/content/Context;)I, RX@0x4002f158[libDexHelper.so]0x2f158)
RegisterNative(com/secneo/apkwrapper/H, p()V, RX@0x4001875c[libDexHelper.so]0x1875c)
RegisterNative(com/secneo/apkwrapper/H, q()I, RX@0x40023568[libDexHelper.so]0x23568)
RegisterNative(com/secneo/apkwrapper/H, mu()I, RX@0x4001f250[libDexHelper.so]0x1f250)

0x218A8

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

0x22068

创建一些目录:

1
2
3
/data/usr/0/包名/.cache/oat
/data/usr/0/包名/.cache/oat/arm64
/data/usr/0/包名/.payload

0x22a90

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

1
2
3
4
5
vboxsf
/mnt/shared/install_apk
nemusf
/mnt/shell/emulated/0/Music sharefolder
/sdcard/windows/BstSharedFolder

0x23568

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

0x247C0

调用setOuterContext。

0x24C08

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

0x26278

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

0x27290

修改mInitialApplication和mClassLoader。

0x2921C

修改mAllApplications(remove和add)。

0x29CE8

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

1
2
3
4
5
6
com.bignox.app.store.hd
com.bluestacks.appguidance
com.bluestacks.settings
com.bluestacks.home
com.bluestack.BstCommandProcessor
com.bluestacks.appmart

0x2B670

通过FLAG_DEBUGGABLE判断是debug还是release。

0x2CAE0

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

0x2F158

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

1
2
3
4
/sbin/.magisk/
/sbin/.core/img
/sbin/.core/mirror
/sbin/.core/db-0/magisk.db

0x2F6E4

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

0x31474

调用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:

0x3371C

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

0x339FC

currentActivityThread-mPackages-LoadedApk-mResources-getAssets。

0x34A00

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

0x351DC

读取assets文件。

0x35AB0

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

0x3766C

初始化下列字符串:

1
2
3
/data/user/0/cn.missfresh.application/.cache/classes.jar
/data/user/0/cn.missfresh.application/.cache/classes.dex
/data/user/0/cn.missfresh.application/.cache/v1filter.jar

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

0x398F8/0x3A08C

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

1
2
3
4
5
_Z16hprofDumpClassesP15hprof_context_t
_Z12dvmDumpClassPK11ClassObjecti
_Z9dumpClassP7DexFilei
dumpclass
dump_class

0x3BF10

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

0x3BF7C

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

1
2
3
4
5
ueventd.ttVM_x86.rc
init.ttVM_x86.rc
fstab.ttVM_x86
bluestacks
BlueStacks

0x3CE14

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

0x3D814

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

0x42378

md5。

0x44708

hook下列函数(反调试):

1
2
3
vmDebug::notifyDebuggerActivityStart(hook后:0x446C0)
art::Dbg::GoActive(hook后:0x446E4)
art::Runtime::AttachAgent(hook后:0x45CF8)

0x46194

system_property_get ro.yunos.version。

0x4C2F0

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

1
2
3
art::ClassLinker::DefineClass(hook后:0x46BB8)
art::ClassLinker::LoadMethod(hook后:0x46ED4/0x47BB8/0x488C0/0x491F8/0x49B0C)
art::OatFile::OatMethod::LinkMethod(hook后:0x46BD8/0x46DB0)

0x4DB80

md5。

0x50280

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

0x5074C

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

0x50B60

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

0x57424

加载assets中的classes.dgg。

0x598FC

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

0x59CE8

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

0x5C600

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

0x61E3C

hook libc中的下列函数:

1
2
3
4
5
6
7
8
9
10
fstatat64(hook后:0x5E778)
stat(hook后:0x5E858)
close(hook后:0x5EA20)
openat(hook后:0x5ED20)
open(hook后:0x5ED9C)
pread(hook后:0x5FAB8)
read(hook后:0x5FC14)
mmap64(hook后:0x5FDDC)
__openat_2(hook后:0x5FEF4)
__open_2(hook后:0x5FF74)

0x64AE8

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

0x65FE4

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

0x67544

hook下列函数:

1
2
art::DexFileLoader::open(hook后:0x6D39C/0x6D3E8)
art::OatFileManager::OpenDexFilesFromOat(hook后:0x6A2C0/0x6AF14/0x6B9B0/0x6C188/0x6CB5C)

0x6D4A0

patch掉art::Runtime::IsVerificationEnabled。

0x6DAD8

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

0x6E40C

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

0x70410

hook下列函数:

1
2
3
art::DexFileVerifier::Verify(hook后:0x6EB04/0x6EB0C/0x6EB14,直接返回1)
art::DexFile::OpenMemory(hook后:0x74EE8/0x74E90/0x74F38)
Art::DexFile(hook后:0x74E30/0x74F88)

0x75054

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

0x75AA8

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

0x767F8

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

0x76C8C

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

0x76CCC

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

0x76D90

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

0x76DD4

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

0x76E18

md5。

0x7783C

字符串解密函数。

0x79270

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

0x7A240

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

1
2
3
4
5
nuwa
andfix
hotfix
.RiskStu
tinker

0x80458

调用0x79270。

0x804A8

hook libc中的下列函数:

1
2
3
4
5
6
7
8
9
10
11
12
msync(hook后:0x78470)
close(hook后:0x7AF50)
munmap(hook后:0x7A568)
openat64(hook后:0x7DC48)
__open_2(hook后:0x7DC80)
_open64(hook后:0x7DCB8)
_openat_2(hook后:0x7DCF0)
ftruncate64(hook后:0x7DD30)
mmap64(hook后:0x7EF60)
pread64(hook后:0x7F5D0)
read(hook后:0x7F7DC)
write(hook后:0x8022C)

0x87F98

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

0x889B0

patch掉art::Runtime::UseJitCompilation。

0x8A794/0x8B71C/0x8B890

hook函数实现。

0x917E8

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

0x91848

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

0x918A8

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

0x95778

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

0x95A28

字符串查找函数。

0x95B9C

字符串解密函数。

0x95D60

socket连接。

0x96398

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

0x995D0

xposed检测,特征字符串:

1
2
3
.xposed.
xposedbridge
xposed_art

0x99D28

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
frida
ddi_hook
dexposed
substrate
adbi_hook
MSFindSymbol
hook_precall
hook_postcall
MSHookFunction
DexposedBridge
MSCloseFunction
dexstuff_loaddex
dexposedIsHooked
ALLINONEs_arthook
dexstuff_resolv_dvm
dexposedCallHandler
art_java_method_hook
artQuickToDispatcher
dexstuff_defineclass
dalvik_java_method_hook
art_quick_call_entrypoint
frida_agent_main

0x9C0BC

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

0x9CFCC

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

0x9D878

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

0x9DCF4

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

0x9ED44

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

0x9F770

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

0x9FD88

调用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)
检测方法是判断下列类或者方法是否存在:

1
2
3
4
5
6
7
8
dumpMethodCode
fartthread
fart
android/app/fupk3/Fupk
android/app/fupk3/Global
android/app/fupk3/UpkConfig
android/app/fupk3/FRefInvoke
cn/youlor/Unpacker

0xA18D4

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

0xA7D3C

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

0xB4B94

hook libc中的下列函数:

1
2
3
4
5
6
7
8
9
10
write(hook后:0xAA2CC)
pwrite64(hook后:0xAA51C)
close(hook后:0xAA774)
read64(hook后:0xAAA9C)
openat64(hook后:0xAACB8)
__openat_2(hook后:0xAB6D4)
__open_2(hook后:0xAC0F4)
open64(hook后:0xACB10)
read(hook后:0xAFE18)
mmap64(hook后:0xB1C54)

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是为了透明加密,具体没仔细看,之前论坛也有人分析过,估计应该没有太大的变化:梆梆加固之透明加密分析

0xB9BEC

sha1。

0xBAE64

md5init。

0xC3378

base64。

0xC5DDC

base64。

0xC7B18

APK签名相关。

0xD024C

sha1。

0xD1C04

sha1init。

0xD2E98

md5。

0xD6484

调用0xD75A0。

0xD5CDC

读/proc/self/cmdline。

0xD6578

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

0xD68A8

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

0xD75A0

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

0x3EA68

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

1
2
3
4
JNIEnv->FindClass(com/secneo/apkwrapper/H)
JNIEnv->GetStaticFieldID(com/secneo/apkwrapper/H.PKGNAMELjava/lang/String;)
JNIEnv->GetStaticObjectField(class com/secneo/apkwrapper/H, PKGNAME Ljava/lang/String; => "cn.missfresh.application")
JNIEnv->GetStringUtfChars("cn.missfresh.application")

6.将包名存于0x138040
7.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
JNIEnv->FindClass(android/app/ActivityThread)
JNIEnv->GetStaticMethodID(android/app/ActivityThread.currentActivityThread()Landroid/app/ActivityThread;)
JNIEnv->CallStaticObjectMethodV(class android/app/ActivityThread, currentActivityThread())
JNIEnv->GetMethodID(android/app/ActivityThread.getSystemContext()Landroid/app/ContextImpl;)
JNIEnv->CallObjectMethodV(android.app.ActivityThread, getSystemContext())
JNIEnv->FindClass(android/app/ContextImpl)
JNIEnv->GetMethodID(android/app/ContextImpl.getPackageManager()Landroid/content/pm/PackageManager;)
JNIEnv->CallObjectMethodV(android.app.ContextImpl, getPackageManager())
JNIEnv->GetMethodID(android/content/pm/PackageManager.getPackageInfo(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;)
JNIEnv->NewStringUTF("cn.missfresh.application")
JNIEnv->CallObjectMethodV(android.content.pm.PackageManager, getPackageInfo("cn.missfresh.application", 0x0))
JNIEnv->GetFieldID(android/content/pm/PackageInfo.applicationInfo Landroid/content/pm/ApplicationInfo;)
JNIEnv->GetObjectField(android.content.pm.PackageInfo, applicationInfo Landroid/content/pm/ApplicationInfo;)
JNIEnv->GetFieldID(android/content/pm/ApplicationInfo.sourceDir Ljava/lang/String;)
JNIEnv->GetObjectField(android.content.pm.ApplicationInfo, sourceDir Ljava/lang/String; => "/data/app/cn.missfresh.application-1")
JNIEnv->GetStringUtfChars("/data/app/cn.missfresh.application-1")
JNIEnv->GetFieldID(android/content/pm/ApplicationInfo.dataDir Ljava/lang/String;)
JNIEnv->GetObjectField(android.content.pm.ApplicationInfo, dataDir Ljava/lang/String; => "/data/data/cn.missfresh.application")
JNIEnv->GetStringUtfChars("/data/data/cn.missfresh.application")

8.调用0x218A8
9.

1
2
3
JNIEnv->GetFieldID(android/content/pm/ApplicationInfo.nativeLibraryDir Ljava/lang/String;)
JNIEnv->GetObjectField(android.content.pm.ApplicationInfo@36d64342, nativeLibraryDir Ljava/lang/String; => "/data/app/cn.missfresh.application-1/lib/arm64")
JNIEnv->GetStringUtfChars("/data/app/cn.missfresh.application-1/lib/arm64")

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

1
2
3
4
JNIEnv->FindClass(com/secneo/apkwrapper/H)
JNIEnv->GetStaticFieldID(com/secneo/apkwrapper/H.ISMPAASLjava/lang/String;)
JNIEnv->GetStaticObjectField(class com/secneo/apkwrapper/H, ISMPAAS Ljava/lang/String; => "###MPAAS###")
JNIEnv->GetStringUtfChars("###MPAAS###")

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.初始化下列字符串:

1
2
3
4
/data/user/0/cn.missfresh.application/.cache
/data/user/0/cn.missfresh.application/.cache/oat/arm64
/data/user/0/cn.missfresh.application/.cache/classes.dve
/data/app/cn.missfresh.application-xxx/oat/arm64/base.odex

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.初始化下列字符串:

1
2
3
4
/data/user/0/cn.missfresh.application/.cache/libDexHelper32
/lib/armeabi-v7a/libDexHelper.so
/lib/armeabi/libDexHelper.so
assets/libDexHelper32

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

总结

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


[2023春季班]《安卓高级研修班(网课)》月薪两万班招生中~

最后于 2022-7-20 14:14 被houjingyi编辑 ,原因:
上传的附件:
收藏
点赞16
打赏
分享
打赏 + 150.00雪花
打赏次数 1 雪花 + 150.00
 
赞赏  Editor   +150.00 2022/08/08 恭喜您获得“雪花”奖励,安全圈有你而精彩!
最新回复 (13)
雪    币: 1933
活跃值: 活跃值 (1449)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huangjw 活跃值 2022-7-10 23:14
2
0
谢谢分享,学习中。 目测是精华贴
雪    币: 174
活跃值: 活跃值 (2325)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huaerxiela 活跃值 2022-7-11 12:01
3
0
666
雪    币: 779
活跃值: 活跃值 (2413)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
王麻子本人 活跃值 2022-7-11 12:54
4
0
雪    币: 4338
活跃值: 活跃值 (548)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
wpwpahj 活跃值 2022-7-14 10:14
5
0
大佬能来一期so反调试、hook的吗
雪    币: 208
活跃值: 活跃值 (928)
能力值: ( LV5,RANK:73 )
在线值:
发帖
回帖
粉丝
falconnnn 活跃值 2022-7-14 17:25
6
0
能否发一下原apk?,只有so无法dump分析
雪    币: 5838
活跃值: 活跃值 (5307)
能力值: ( LV15,RANK:531 )
在线值:
发帖
回帖
粉丝
houjingyi 活跃值 11 2022-7-17 10:57
7
0
falconnnn 能否发一下原apk?,只有so无法dump分析
文章里面有包名的
雪    币: 19
活跃值: 活跃值 (595)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
轻快笑着行 活跃值 2022-7-21 13:58
8
0
mark
雪    币: 248
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
@=llfly 活跃值 2022-7-23 16:55
9
0
mark
雪    币: 232
活跃值: 活跃值 (108)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_逝去流星 活跃值 2022-9-3 15:20
10
0
大佬 牛 
雪    币: 258
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
小明32120 活跃值 2022-9-14 16:30
11
0
牛,mark
雪    币: 205
活跃值: 活跃值 (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xtor 活跃值 2022-10-13 10:44
12
0

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;
    }
  }
}


雪    币: 20
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
bj_ldzspace 活跃值 2023-1-4 11:36
13
0
nb
雪    币: 1556
活跃值: 活跃值 (989)
能力值: ( LV3,RANK:37 )
在线值:
发帖
回帖
粉丝
s1lenc3沉默 活跃值 2023-1-10 13:35
14
0
大佬太强了,最近也在对抗这个so,文中去混淆那一部分看上去像一个switch case结构但是ida没有识别,可以手动还原一下switch case,我参考了https://www.nuke666.cn/2021/08/Specify-switch-statement-in-IDA-Pro/这篇文章。
游客
登录 | 注册 方可回帖
返回