您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關so靜態分析中CreakeMe的分析思路是什么 ,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
拿到一個CreakeMe,寫一個分析思路。CreakMe主要是對.so文件內容進行分析,當然很多學習Android逆向的在分析到smali代碼的時候就已經停止腳步了。在接觸到.so文件的時候才是開始進一步的逆向學習,當然這里就要學習ARM匯編了。關于ARM匯編在網上有很多的資料,這里就不再贅述。
請使用:HAI手冊
嘗試使用App得出這些結論。
1.我們需要一個key。
2.這個key是數字。
逆向拿到smali代碼。
工具:Android Killer。
找到入口MainActivity。
我們看到這里有一段代碼:
這段代碼的作用就是調用so文件庫。我們猜測這個App很有可能把關鍵key寫在了so文件里。
我們從onClick方法定位到關鍵點。
這里是判斷正誤的地方,這里看到如果v0和v2的值不相等的話就跳轉。并且這里v2的值是1。
我們向上看。
這里有一個調用方法。
在這里我們看到這個是Native層的方法。并且這個方法會返回一個int數據,這里猜測可能會是0或者1。在這里還有一個就是傳入的是一個int型數據,根據我們之前的測試,知道這里就是我們從輸入框輸入的內容。
監聽事件——輸入key——key方法判斷——返回0或1
1為正確,0為錯誤。
但是我們依然沒有找到Key的是指內容。
so逆向
使用工具:ida
找到關鍵的Key函數。
這里可以看到ARM匯編比smali難的可不是一個度兩個度。
為了提升能力,我們還是一句一句的分析。如果是學習的話,請不要依賴F5。
PUSH {R7,LR}
把R7寄存器和LR入棧。
R7的含義就是指向前一個保存的棧幀和鏈接寄存器在棧上的地址。
這里可能會對LR的作用不知道,簡單的說一下,LR的作用一個是保存子程序的返回地址。還有一個是當異常發生時,LR中保存的值等于異常發生時PC的值減4。LR相當于是一個備份。
MOV R7, SP
這里的含義就是標志著caller棧幀的結束及callee的棧幀的開始。相當于是參數準備就緒,我們可以開始執行程序了。
SUB SP, SP, #0x20
這里是給子程序開辟空間。
以上三步結束的時候ARM開始調用部分就結束了。
MOV R3, R2
R2的值給R3。
MOV R12, R1
R1的值給R12
MOV LR, R0
R0=LR。
STR R0, [SP,#0x28+var_10]STR R1, [SP,#0x28+var_14]STR R2, [SP,#0x28+var_18]
這三句一起看,意思就是把R0,R1,R2放入棧中。位置分別是,18,14,10。
LDR R0, [SP,#0x28+var_18]
把棧上10位置的內容拿下來給R0寄存器,我們棧上10的位置是R2。相當于是R0=R2。
MOVS R1, #0x80
R1賦值為80,這里movs和mov的區別在于movs會更改N,Z,C標志。N=0代表整數或者0,N=1代表是整數。此時R1>30,所以N為0。Z表示運算結果。R1不為0則z=1;C標志位一般不會通過加減改變。
STR R0, [SP,#0x28+var_1C]
把R0的內容放在棧C。
MOV R0, R1 ; int
R1的值給R0。
STR R3, [SP,#0x28+var_20]
R3的值原本為R2,這里把這個值放在棧8。
STR.W R12, [SP,#0x28+var_24]
把R12的值放入棧4中。
這里的.W 是wide。指定匯編器必須為這條指令選擇一個32位的編碼模式。如果辦不到,匯編器報錯。
STR.W LR, [SP,#0x28+var_28]
LR存入棧0中
BLX j__Z2uri
跳轉到 j__Z2uri。這里的注釋是ur(int),說明這個函數原型是ur(int)
LDR R1, [SP,#0x28+var_1C]
這里把棧c里的內容放到R1中。這個時候其實我們拿到是我們輸入的key。
CMP R1, R0
然后用我們的key 和R0進行比較,這里的R0是最后ur的返回結果。
BNE loc_4490
不一樣跳轉loc_4490
B loc_448A
否則跳轉到loc_448A
這里我們就知道了關鍵方法就是ur(int)這個了。
最后我們來看一下流程圖。
說真的。。。分析這個是真的累,不過進步起來還是非常快的。
PUSH {R7,LR}MOV R7, SPSUB SP, SP, #0x28
這三行之前說過,相當于ARM在準備階段。
MOV R1, R0STR R0, [SP,#0x30+var_C]LDR R0, [SP,#0x30+var_C]STR R0, [SP,#0x30+var_10]
這一小部分完成之后的效果就是,R1=R0,棧24的部分存為R0,并且給R0重新復制為棧20
LDR R0, [SP,#0x30+var_C]
把R0從棧24拿出來
STR R0, [SP,#0x30+var_14]
然后把R0的值給棧2C的位置。
這里我們先來看一下流程圖。
如果之前自己分析過循環的話就知道這個肯定是一個循環邏輯。而且再循環里還嵌套了循環和if語句。
MOVS R0, #2
把立即數2賦值給R0。
STR R0, [SP,#0x30+var_18]
把2這個立即數給棧18位置。
STR R1, [SP,#0x30+var_1C]
我們的R1原本是R0的值,現在把R1的值給棧14位置。
B loc_42E2
無條件跳轉到loc_42E2。
目前位置,總結一下,相當于寫了
i=2sp[5]=128
來看loc_42E2部分。
LDR R0, [SP,#0x30+var_18]
從棧18中拿到立即數#2。并且給R0。
MULS R0, R0
將兩個理解書相乘。現在狀態R0=R0*R0,R0=4;
LDR R1, [SP,#0x30+var_14]
從棧1C中拿出數據,這里的數據之前存的是R0的數據,R0則是128。這里有一個小疑問,為什么這里不從棧14出拿數據。
CMP R0, R1
比較R0和R1
BGT loc_433E
如果大于則跳轉loc_433E
B loc_42EE
否則跳轉到loc_42EE
這個時候我們來再看看流程圖。
主要看框起來的內容,這里有一個分支結束了,證明這一個部分結束了。
而另外一邊則會返回loc_42E2,這說明什么情況,這個就是典型的for循環。
如果之后有需要就對所有可能出現的狀態邏輯圖進行一個梳理。
我們這里先來分析一下 loc_42EE部分。
LDR R0, [SP,#0x30+var_14]
從棧1c處拿到數據。此時棧1c出存的數據是128。16進制顯示為80
LDR R1, [SP,#0x30+var_18]
從棧18處拿到數據,此時棧18存儲的內容是2。
BL sub_13FCC
跳轉到sub_13FCC,并且保存下一條的地址,可以使用mov PC,LR返回原處。
我們先來看sub_13FCC這個子程序。
CMP R1, #0
R1和立即數0進行比較。我們來確定一下R1的數值。
BEQ loc_13FBA
如果相等則跳轉loc_13FBA
PUSH.W {R0,R1,LR}
把R0,R1,LR入棧
BL sub_13F0C
跳轉sub_13F0C,保存LR。
之后還有很長一串,這里有興趣的可以繼續分析下去。這里直接說明結果就是對128進行取余操作。
128%i
我們還是回到之前的ur方法處繼續分析。
CMP R1, #0
比較我們取余的結果。
STR R0, [SP,#0x30+var_20]
把R0的值放入棧10,R0的值是128
BNE loc_4334
如果不相等,則跳轉至loc_4334。
B loc_42FE
否則跳轉loc_42FE
如果是跳轉到loc_4334。
直接進入第二次循環。
如果是跳轉到loc_42FE,則進行深一層次的判斷。
總的來說這個CreakMe是這樣子的
for(int i;i*i<128) { if(128%i==0) { while() { } } }if() { }return ...
整體邏輯結構就是這個了。如果在這個時候進行動態分析的話,也可以很輕松的解決。
經過一些分析,發現這個CreakMe是在進行一個歐拉函數的計算。
就是在計算一個數的和這個數互質的個數。
這里也可以確定到128就是其中內嵌的一個歐拉函數。
那我們很簡單自己寫一個歐拉函數的計算方法就可以了。
所謂的注冊機,就是根據一定的邏輯來推算出正確結果。
這里我們需要寫一個程序來完成歐拉函數的計算。
int oula(int number) { int res=number; int a=number; for(int i=2;i*i<=a;i++) { if(a%i==0){ res=res/i*(i-1); while(a%i==0) a/=i; } } if(a>1) res=res/a*(a-1); return res; }
最后128的歐拉函數結果是64。
輸入之后
上述就是小編為大家分享的so靜態分析中CreakeMe的分析思路是什么 了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。