0x3.U3D游戲逆向修改深化-1

U3D游戲逆向修改深化-1 : IL指令介紹


本文主要介紹常用的IL指令,主要分一下幾個(gè)類型來(lái)進(jìn)行介紹。



常用IL指令文檔 鏈接: https://pan.baidu.com/s/1dp507PpZfhofud9LDAp8lQ 密碼: arhh

官方介紹地址:https://msdn.microsoft.com/zh-cn/library/system.reflection.emit.opcodes(v=vs.110).aspx

接下來(lái)我們分類進(jìn)行介紹。


0x1.IL是什么

U3D游戲的腳本開發(fā)語(yǔ)言為C#,dll腳本反編譯后的語(yǔ)言即為IL,也被稱為微軟中間語(yǔ)言MSIL。


0x2.常用指令

我將IL分析中常用的指令分為了五種,分別是用于加載的ld開頭指令、用于存儲(chǔ)的st開頭指令、用于跳轉(zhuǎn)的b開頭指令、用于調(diào)用的call開頭指令、運(yùn)算指令。


2.1   用于加載的ld開頭指令

ld是load的意思,是將操作數(shù)推送/加載到堆棧中,等待下一個(gè)語(yǔ)句調(diào)用或者存儲(chǔ)。下面介紹幾種常見的指令:

2.1.1  ldc指令

ldc.i4 → 將所提供的int32類型的值推送到堆棧上,簡(jiǎn)言之,就是在內(nèi)存中加載一個(gè)整數(shù)。

        例如:ldc.i4     0x10      意思就是將十六進(jìn)制數(shù)0x10加載到內(nèi)存中,也有l(wèi)dc.i4.0~ldc.i4.8代表整數(shù)1到8加載到內(nèi)存中。

2.1.2  ldstr指令

ldstr → 將字符串對(duì)象推送到堆棧中,簡(jiǎn)言之,就是在內(nèi)存中加載一個(gè)字符串對(duì)象。

        例如:ldstr     “hello world”     意思就是將字符串“hello world”加載到內(nèi)存中。

2.1.2  ldfld指令

ldfld →  查找對(duì)象中其引用的當(dāng)前位于計(jì)算堆棧的字段的值。

        例如:ldfld     string name     意思就是將字符串變量name中的值查找出來(lái)待用。


2.2   用于存儲(chǔ)的st開頭指令

st是store的意思,是將操作數(shù)從堆棧中彈出,相當(dāng)于將其賦值給某些變量的意思。

stfld →  用新值替換在對(duì)象引用或指針的字段中存儲(chǔ)的值。

        例如:stfld     string name    意思就是將堆棧中的字符串對(duì)象賦值給字符串變量name。


2.3   用于跳轉(zhuǎn)的b開頭指令

b是branch的意思,可以理解為分支或者跳轉(zhuǎn)。

2.3.1  beq指令

beq → 如果兩個(gè)值相等,則將控制轉(zhuǎn)移到目標(biāo)指令。這個(gè)與smali中的是類似的。

        例如:beq     IL_0020     意思就是如果前面提供的兩個(gè)值相等,就跳轉(zhuǎn)到IL_0020這一行執(zhí)行。

2.3.2  br指令

br → 無(wú)條件的將控制轉(zhuǎn)移到目標(biāo)指令。

        例如:br     IL_0020     意思就是不進(jìn)行任何判斷直接跳轉(zhuǎn)到IL_0020這一行執(zhí)行。


2.4   用于調(diào)用的call開頭指令

call是調(diào)用的意思,常見的兩種,帶返回值的和不帶返回值的。

2.4.1 call指令

call →  調(diào)用由傳遞的方法說(shuō)明符指示的方法。

2.4.2 callvirt指令

callvirt →  對(duì)對(duì)象調(diào)用后期綁定方法,并且將返回值推送到計(jì)算堆棧上。


兩者有區(qū)別但是我們現(xiàn)在并不必深究,僅做了解知道是調(diào)用函數(shù)即可。

【    僅作了解:

1)call可以調(diào)用靜態(tài)方法,實(shí)例方法和虛方法

     callvirt只能調(diào)用實(shí)例方法和虛方法,不能調(diào)用靜態(tài)方法

2)call一般是以非虛的方式來(lái)調(diào)用函數(shù)的

     callvirt是以已多態(tài)的方式來(lái)調(diào)用函數(shù)的      】


2.5   運(yùn)算指令

運(yùn)算分為兩類,算術(shù)運(yùn)算和邏輯運(yùn)算。

2.5.1  算術(shù)運(yùn)算

算術(shù)運(yùn)算主要是加減乘除,分別為 add、sub、mul、div。

2.5.2  邏輯運(yùn)算

邏輯運(yùn)算主要是與或非,分別為 and、or、not;異或也常用到,為xor。


0x3.舉例分析

例子1:

ldc.i4     0x2
stfld     int32 value1
ldc.i4     0x3
ldfld     int32 value1
mul
stfld     int32 value2
上述代碼的意思是:
//將數(shù)值2加載到內(nèi)存
//將其存儲(chǔ)整型變量value1
//將數(shù)值3加載到內(nèi)存
//將value1的值加載到內(nèi)存
//數(shù)值3和value1的值進(jìn)行乘法運(yùn)算
//運(yùn)算結(jié)果存儲(chǔ)到value2中
例子2:
ldc.r4     0.5
stfld     float32 value1
ldc.r4     0.6
ldfld     float32 value1
beq     IL_0020
call    void function()
br     IL_0020
上述代碼的意思是:
//將浮點(diǎn)數(shù)0.5加載到內(nèi)存中
//將0.5存儲(chǔ)到float32變量value1中
//將浮點(diǎn)數(shù)0.6加載到內(nèi)存中
//將value1的值加載到內(nèi)存中
//比較0.6和value1的值,如果相等就跳轉(zhuǎn)到IL_0020
//如果不相等就執(zhí)行call來(lái)調(diào)用函數(shù)function()
//直接跳轉(zhuǎn)到IL_0020

?