tgstc-2021-Android-初赛

分析

寻找Assembly-Csharp

​ 上手看了下,是个unity写的游戏,那么找游戏逻辑首先要考虑的就是Assembly-Csharp.dll,找到之后丢到dnspy,发现打不开,用010Editor打开一看。

​ 明显是被加密了,大量的0xAF,怀疑全文异或0xAF,异或之后发现还有些0xC2,0xC3有问题,这些是由于编码问题,python脚本恢复后用dnspy打开。

​ 能反编译了,但是细看发现里面的东西不对劲,很少,不像真正的游戏代码。

​ 那估计是在mono加载的地方动了手脚,接下来想办法从这里入手。

去除反调试

​ 为了方便的断在mono_image_open_from_data_with_name,这里选择干掉程序中的反调试代码。

​ 检测到调试会有弹窗 “hack detected”

​ JAVA层里没有什么特别的东西。

​ 重点分析libsec2021.so,发现大量的字符串信息被加密了,通过一个函数解密并返回字符串。

​ 使用IDApython脚本主动调用解密,并批量标注

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
import idautils

stringTable = {}

def active_get_res_by_index(func_ea, index):
cpu.r0 = index
oldlr = cpu.lr
oldr0 = cpu.r0

add_bpt(cpu.pc)

cpu.lr = cpu.pc
cpu.pc = func_ea

idaapi.continue_process()
wait_for_next_event(WFNE_SUSP, -1)

ret = cpu.r0
cpu.r0 = oldr0
cpu.lr = oldlr
return ret


# for arm
def active_get_res(func_ea, max = 1000000):
idx = 0
while idx <= max:
print(idx)
straddr = active_get_res_by_index(func_ea, idx)
size = idaapi.get_byte(straddr - 1)
s = get_bytes(straddr, size)
print(idx, s)
stringTable[idx] = s
idx += size+4

def getResArg(inst):
if not GetDisasm(inst).startswith("MOV"):
return False
if not idc.print_operand(inst, 0) == "R0":
return False
if not get_operand_type(inst, 1) == 5:
return False
return True

def auto_mark(func_ea):
for i in idautils.CodeRefsTo(func_ea, 0):
bpaddr = i
inst = idc.prev_head(i)
while not getResArg(inst):
inst = idc.prev_head(inst)

print(GetDisasm(inst))

idx = int(idc.print_operand(inst, 1)[1:], 16)
add_bpt(bpaddr)
ida_dbg.disable_bpt(bpaddr)
set_bpt_cond(bpaddr, 'print("'+stringTable[idx]+'")')
set_cmt(bpaddr, stringTable[idx], False)

​ 效果:

​ 找“hack detected”字符串找到反调试自杀的地方

​ 交叉引用往上跟下发现最原始是这个地方

​ 找它的交叉引用找到反调试代码全部过掉,大概patch了6个地方。

​ 就可以正常调试了。

再寻Assembly-Csharp

​ 断在libmono.so的open_image里面,发现又调用了libsec2021中的一个函数

​ 如果文件名是Assembly-Csharp.dll,就从sec2021.png后截取后部分解密传入mono_image_open_from_data_with_name。

​ 这里已经很明显了,外面的Assembly-Csharp是个假的,真的藏在图片里。

​ 解密也就是个简单的异或解密。

​ 至此就拿到了真实的Assembly-Csharp.dll

修改无敌版

​ 剩下的工作就很简单了,丢到dnspy里找到关键逻辑,patch之后重加密丢回图片里完事。

​ 关键函数(修改后)