逆向和调试Unity3D游戏手记之一

一、背景和意义

Unity3D是手游领域的主要游戏引擎,熟练掌握对其的逆向方法,对我们而言十分重要。目前主流的方法是对其dll进行反汇编,然而越来越多游戏对其dll进行加密。因此本文的目的在于从另外一个方向对Unity3D游戏进行逆向和调试,第一步是要找到自定义函数的代码。

二、准备工作
  1. 逆向对象,Unity3D官方例程 ——SpaceShooter,发布于Android平台
  2. 工具:ida 6.5
三、相关代码分析
  1. 调用自定义函数的总体过程
    <pre><code>
    info->compiled_method
    runtime_invoke()
    mono_jit_runtime_invoke() at mini.c:4,789 0x8065cc1
    mono_runtime_invoke() at object.c:2,613 0x8195d35
    create_exception_two_strings() at exception.c:133 0x81e6a9f
    mono_exception_from_name_two_strings() at exception.c:156 0x81e6adf
    create_exceptions() at appdomain.c:185 0x818b9e4
    mono_runtime_init() at appdomain.c:262 0x818bc0d
    mini_init() at mini.c:5,520 0x806734a
    mono_main() at driver.c:1,623 0x80ec127
    main() at main.c:34 0x805b950
    </code></pre>
    主要要关注的是从mono_runtime_invoke()到info->compile_method()的这样一个调用过程

  2. 分析mono_runtime_invoke()
    相关汇编代码
    <pre><code>
    .text:001FA9AC ; MonoObject *__cdecl mono_runtime_invoke(MonoMethod *method, void *obj, void **params, MonoObject **exc)
    .text:001FA9AC EXPORT mono_runtime_invoke
    .text:001FA9AC mono_runtime_invoke ; CODE XREF: mono_jit_compile_method_inner+7B0�p
    .text:001FA9AC ; load_agent+240�p ...
    .text:001FA9AC
    .text:001FA9AC exc = -0x1C
    .text:001FA9AC params = -0x18
    .text:001FA9AC obj = -0x14
    .text:001FA9AC method = -0x10
    .text:001FA9AC result = -8
    .text:001FA9AC
    .text:001FA9AC STMFD SP!, {R11,LR}
    .text:001FA9B0 ADD R11, SP, #4
    .text:001FA9B4 SUB SP, SP, #0x18
    .text:001FA9B8 STR R0, [R11,#method]
    .text:001FA9BC STR R1, [R11,#obj]
    .text:001FA9C0 STR R2, [R11,#params]
    .text:001FA9C4 STR R3, [R11,#exc]
    .text:001FA9C8 BL mono_runtime_get_no_exec
    .text:001FA9CC MOV R3, R0
    .text:001FA9D0 CMP R3, #0
    .text:001FA9D4 BEQ loc_1FA9FC
    .text:001FA9D8 LDR R0, [R11,#method] ; method
    .text:001FA9DC MOV R1, #1 ; signature
    .text:001FA9E0 BL mono_method_full_name
    .text:001FA9E4 MOV R3, R0
    .text:001FA9E8 MOV R0, #0 ; log_domain
    .text:001FA9EC MOV R1, #0x10 ; log_level
    .text:001FA9F0 LDR R2, =(aInvokingMethod - 0x1FA9FC)
    .text:001FA9F4 ADD R2, PC, R2 ; "Invoking method '%s' when running in no"...
    .text:001FA9F8 BL g_log
    .text:001FA9FC
    .text:001FA9FC loc_1FA9FC ; CODE XREF: mono_runtime_invoke+28�j
    .text:001FA9FC BL mono_profiler_get_events
    .text:001FAA00 MOV R3, R0
    .text:001FAA04 AND R3, R3, #0x10000
    .text:001FAA08 CMP R3, #0
    .text:001FAA0C BEQ loc_1FAA18
    .text:001FAA10 LDR R0, [R11,#method] ; method
    .text:001FAA14 BL mono_profiler_method_start_invoke
    .text:001FAA18
    .text:001FAA18 loc_1FAA18 ; CODE XREF: mono_runtime_invoke+60�j
    .text:001FAA18 LDR R3, =(default_mono_runtime_invoke - 0x1FAA24)
    .text:001FAA1C ADD R3, PC, R3 ; default_mono_runtime_invoke
    .text:001FAA20 LDR R12, [R3]
    .text:001FAA24 LDR R0, [R11,#method]
    .text:001FAA28 LDR R1, [R11,#obj]
    .text:001FAA2C LDR R2, [R11,#params]
    .text:001FAA30 LDR R3, [R11,#exc]
    .text:001FAA34 BLX R12
    .text:001FAA38 STR R0, [R11,#result]
    .text:001FAA3C BL mono_profiler_get_events
    .text:001FAA40 MOV R3, R0
    .text:001FAA44 AND R3, R3, #0x10000
    .text:001FAA48 CMP R3, #0
    .text:001FAA4C BEQ loc_1FAA58
    .text:001FAA50 LDR R0, [R11,#method] ; method
    .text:001FAA54 BL mono_profiler_method_end_invoke
    .text:001FAA58
    .text:001FAA58 loc_1FAA58 ; CODE XREF: mono_runtime_invoke+A0�j
    .text:001FAA58 LDR R3, [R11,#result]
    .text:001FAA5C MOV R0, R3
    .text:001FAA60 SUB SP, R11, #4
    .text:001FAA64 LDMFD SP!, {R11,PC}
    .text:001FAA64 ; End of function mono_runtime_invoke
    </code></pre>
    核心代码就是
    <pre><code>
    .text:001FAA20 LDR R12, [R3]
    .text:001FAA24 LDR R0, [R11,#method]
    .text:001FAA28 LDR R1, [R11,#obj]
    .text:001FAA2C LDR R2, [R11,#params]
    .text:001FAA30 LDR R3, [R11,#exc]
    .text:001FAA34 BLX R12
    </code></pre>
    在mono源码中对应的就是
    <pre><code>
    result = default_mono_runtime_invoke (method, obj, params, exc);
    </code></pre>

3.分析mono_jit_runtime_invoke()
这一层代码太长,就不全贴了
核心代码是在函数尾部
<pre><code>
.text:000238F4 loc_238F4 ; CODE XREF: mono_jit_runtime_invoke+908�j
.text:000238F4 LDR R2, [R11,#obj]
.text:000238F8 LDR R3, [R11,#info]
.text:000238FC LDR R3, [R3,#4]
.text:00023900 LDR R12, [R11,#runtime_invoke]
.text:00023904 MOV R0, R2
.text:00023908 LDR R1, [R11,#params]
.text:0002390C LDR R2, [R11,#exc]
.text:00023910 BLX R12
.text:00023914 MOV R3, R0
</code></pre>
对应的mono源码是
<pre><code>
return runtime_invoke (obj, params, exc, info->compiled_method);
</code></pre>

  1. 分析runtime_invoke()
    <pre><code>
    debug117:589E0300 MOV R12, SP
    debug117:589E0304 STMFD SP!, {R8,R11,R12,LR}
    debug117:589E0308 SUB SP, SP, #0x30
    debug117:589E030C MOV R11, SP
    debug117:589E0310 STR R0, [R11,#0x1C]
    debug117:589E0314 STR R1, [R11,#0x20]
    debug117:589E0318 STR R2, [R11,#0x24]
    debug117:589E031C STR R3, [R11,#0x28]
    debug117:589E0320 MOV R0, #0
    debug117:589E0324 STR R0, [R11]
    debug117:589E0328 MOV R0, #0
    debug117:589E032C STR R0, [R11,#4]
    debug117:589E0330 LDR R0, [R11,#0x24]
    debug117:589E0334 CMP R0, #0
    debug117:589E0338 BEQ loc_589E0348
    debug117:589E033C LDR R0, [R11,#0x24]
    debug117:589E0340 MOV R1, #0
    debug117:589E0344 STR R1, [R0]
    debug117:589E0348
    debug117:589E0348 loc_589E0348 ; CODE XREF: debug117:589E0338�j
    debug117:589E0348 MOV R0, #0x5CE151C8
    debug117:589E0350 LDR R0, [R0]
    debug117:589E0354 CMP R0, #0
    debug117:589E0358 BEQ loc_589E0360
    debug117:589E035C BL unk_589E0060
    debug117:589E0360
    debug117:589E0360 loc_589E0360 ; CODE XREF: debug117:589E0358�j
    debug117:589E0360 LDR R0, [R11,#0x28]
    debug117:589E0364 BLX R0
    debug117:589E0368 MOV R0, #0
    debug117:589E036C STR R0, [R11]
    debug117:589E0370 B loc_589E03C0
    </code></pre>
    核心代码是
    <pre><code>
    debug117:589E0360 LDR R0, [R11,#0x28]
    debug117:589E0364 BLX R0
    </code></pre>
    也就是调用info->compiled_method

  2. 最后就是自定义函数的ARM汇编代码了
    C#源码是
    <pre><code>
    void Update ()
    {
    if (restart)
    {
    if (Input.GetKeyDown (KeyCode.R))
    {
    Application.LoadLevel (Application.loadedLevel);
    }
    }
    }
    </code></pre>
    相应的汇编代码
    <pre><code>
    debug118:589E54A8 MOV R12, SP
    debug118:589E54AC STMFD SP!, {R8,R11,R12,LR}
    debug118:589E54B0 SUB SP, SP, #8
    debug118:589E54B4 MOV R11, SP
    debug118:589E54B8 STR R0, [R11]
    debug118:589E54BC LDR R0, [R11]
    debug118:589E54C0 LDRB R0, [R0,#0x35]//获取bool restart
    debug118:589E54C4 CMP R0, #0
    debug118:589E54C8 BEQ loc_589E54E4//为假跳转
    debug118:589E54CC MOV R0, #0x72//KeyCode.R的常量值?
    debug118:589E54D0 BL unk_589E7408//应该是input.getKeyDown(KeyCode.R)
    debug118:589E54D4 CMP R0, #0
    debug118:589E54D8 BEQ loc_589E54E4//结果为假跳转
    debug118:589E54DC BL unk_589E54F8
    debug118:589E54E0 BL unk_589E54EC
    debug118:589E54E4
    debug118:589E54E4 loc_589E54E4 ; CODE XREF: debug118:589E54C8�j
    debug118:589E54E4 ; debug118:589E54D8�j
    debug118:589E54E4 ADD SP, R11, #8
    debug118:589E54E8 LDMFD SP, {R8,R11,SP,PC}
    </code></pre>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 她的老伴去世十几年了,我感觉她的脾气有点古怪。好起来,比如体检的时候,每次都让人排在自己前面。坏起来,比如有时候邀...
    水淇淋阅读 517评论 0 0
  • 午後的陽光讓我更加溫暖 透過汙濁的紗窗看見外面的世界 只好孤單的封閉在一個空間 只有鐘擺和我為伴,滴答,滴答 記錄...
    馬拉桑之旅阅读 147评论 0 6
  • 关于今天心情,莫名不爽,原因未知。或许,男人也有那么几天,不过仅限心理层面,无关生理。 高中,是这段心情过得最漫长...
    一个人的独行阅读 214评论 0 0