本文主要介紹常用的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游戲的腳本開(kāi)發(fā)語(yǔ)言為C#,dll腳本反編譯后的語(yǔ)言即為IL,,也被稱為微軟中間語(yǔ)言MSIL,。
0x2.常用指令
我將IL分析中常用的指令分為了五種,分別是用于加載的ld開(kāi)頭指令,、用于存儲(chǔ)的st開(kāi)頭指令,、用于跳轉(zhuǎn)的b開(kāi)頭指令、用于調(diào)用的call開(kāi)頭指令,、運(yùn)算指令,。
2.1 用于加載的ld開(kāi)頭指令
ld是load的意思,是將操作數(shù)推送/加載到堆棧中,,等待下一個(gè)語(yǔ)句調(diào)用或者存儲(chǔ)。下面介紹幾種常見(jiàn)的指令:
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開(kāi)頭指令
st是store的意思,是將操作數(shù)從堆棧中彈出,,相當(dāng)于將其賦值給某些變量的意思,。
stfld → 用新值替換在對(duì)象引用或指針的字段中存儲(chǔ)的值。
例如:stfld string name 意思就是將堆棧中的字符串對(duì)象賦值給字符串變量name,。
2.3 用于跳轉(zhuǎn)的b開(kāi)頭指令
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開(kāi)頭指令
call是調(diào)用的意思,,常見(jiàn)的兩種,帶返回值的和不帶返回值的,。
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中
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