本文涉及到的apk。請在github下載https://github.com/jltxgcy/AliCrack/AliCrackme_2.apk。html
0x00git
怎樣在JNI_ONLOAD下斷點。參考安卓逆向學習筆記(5) - 在JNI_Onload 函數處下斷點避開針對IDA Pro的反調試。最好使用模擬器調試,確保 Attach to process後,相應進程在DDMS中出現小紅蜘蛛。github
如下將怎樣在init_array下斷點,首先要找到so的init_array端。把so拖入ida,而後按Crtl+s,會出現該so的所有段。例如如下:安全
進入.init_array。例如如下:ide
當中sub_2378就是init_array的代碼。函數
咱們在這裏下斷點,詳細調試的步驟和在JNI_ONLOAD下斷點調試是同樣的。參考安卓逆向學習筆記(5) - 在JNI_Onload 函數處下斷點避開針對IDA Pro的反調試。網上有很是多其它方法在init_array下斷點。好比Android安全–linker載入so流程。在.init下斷點。我仍是認爲上面的方法比較方便。post
調試時使用jdb -connect com.sun.jdi.SocketAttach:port=8700,hostname=localhost,有時會報例如如下錯誤:學習
此時,咱們先觀察DDMS。ui
使用jdb -connect com.sun.jdi.SocketAttach:port=8622,hostname=localhost就能夠。this
0x01
也講一下ida靜態分析so。
首先列出C++源代碼:
#include "com_example_jnidemo_JniGg.h" int switch1(int a, int b, int i, int j, int k,int q){ char *w = "i am winner in this year"; switch (i){ case 1: return a + b + j + k; break; case 2: return a - b; break; case 3: return a * b; break; case 4: return a / b; break; default: return a + b; break; } } JNIEXPORT jstring JNICALL Java_com_example_jnidemo_JniGg_ggPrintHello (JNIEnv * env, jobject this) { return (*env)->NewStringUTF(env, "Current Coin is -- "); } JNIEXPORT jint JNICALL Java_com_example_jnidemo_JniGg_getCoin (JNIEnv * env, jobject this) { return switch1(1,2,1,4,5,6); }編譯成so。而後拖進ida進行分析。
.text:00000E38 EXPORT Java_com_example_jnidemo_JniGg_getCoin .text:00000E38 Java_com_example_jnidemo_JniGg_getCoin .text:00000E38 .text:00000E38 var_10 = -0x10 .text:00000E38 var_C = -0xC .text:00000E38 .text:00000E38 PUSH {LR} .text:00000E3A SUB SP, SP, #0xC .text:00000E3C MOVS R3, #5 .text:00000E3E STR R3, [SP,#0x10+var_10] .text:00000E40 MOVS R3, #6 .text:00000E42 STR R3, [SP,#0x10+var_C] .text:00000E44 MOVS R0, #1 .text:00000E46 MOVS R1, #2 .text:00000E48 MOVS R2, #1 .text:00000E4A MOVS R3, #4 .text:00000E4C BL switch1 .text:00000E50 ADD SP, SP, #0xC .text:00000E52 POP {PC} .text:00000E52 ; End of function Java_com_example_jnidemo_JniGg_getCoinarm的參數傳遞規範,和函數中的局部變量定義規範,請參考 ARM子函數定義中的參數放入寄存器的規則。
這裏使用R0,R1。R2,R3來傳遞前4個參數,使用堆棧來傳遞後兩個參數。
.text:00000DEC .text:00000DEC EXPORT switch1 .text:00000DEC switch1 ; CODE XREF: Java_com_example_jnidemo_JniGg_getCoin+14p .text:00000DEC .text:00000DEC arg_0 = 0 .text:00000DEC .text:00000DEC PUSH {R4,LR} .text:00000DEE ; 6: v5 = a3 - 1; .text:00000DEE SUBS R2, #1 .text:00000DF0 ; 7: v6 = a1; .text:00000DF0 MOVS R4, R0 .text:00000DF2 ; 8: result = a1 + a2; .text:00000DF2 ADDS R0, R0, R1 .text:00000DF4 ; 9: if ( (unsigned int)v5 <= 3 ) .text:00000DF4 CMP R2, #3 ; switch 4 cases .text:00000DF6 BHI def_DFA ; jumptable 00000DFA default case .text:00000DF8 ; 11: result = v5; .text:00000DF8 MOVS R0, R2 .text:00000DFA ; 12: switch ( v5 ) .text:00000DFA BL __gnu_thumb1_case_uqi ; switch jump .text:00000DFA ; --------------------------------------------------------------------------- .text:00000DFE jpt_DFA DCB 2 ; jump table for switch statement .text:00000DFF DCB 0xA .text:00000E00 DCB 7 .text:00000E01 DCB 0xC .text:00000E02 ; --------------------------------------------------------------------------- .text:00000E02 ; 15: result = v6 + a2 + a4 + a5; .text:00000E02 .text:00000E02 loc_E02 ; CODE XREF: switch1+Ej .text:00000E02 LDR R2, [SP,#8+arg_0] ; jumptable 00000DFA case 0 .text:00000E04 ADDS R4, R4, R1 .text:00000E06 ADDS R3, R4, R3 .text:00000E08 ; 16: break; .text:00000E08 ADDS R0, R3, R2 .text:00000E0A .text:00000E0A def_DFA ; CODE XREF: switch1+Aj .text:00000E0A ; switch1+24j ... .text:00000E0A POP {R4,PC} ; jumptable 00000DFA default case .text:00000E0C ; --------------------------------------------------------------------------- .text:00000E0C ; 18: result = a2 * v6; .text:00000E0C .text:00000E0C loc_E0C ; CODE XREF: switch1+Ej .text:00000E0C MOVS R0, R1 ; jumptable 00000DFA case 2 .text:00000E0E MULS R0, R4 .text:00000E10 ; 19: break; .text:00000E10 B def_DFA ; jumptable 00000DFA default case .text:00000E12 ; --------------------------------------------------------------------------- .text:00000E12 ; 21: result = v6 - a2; .text:00000E12 .text:00000E12 loc_E12 ; CODE XREF: switch1+Ej .text:00000E12 SUBS R0, R4, R1 ; jumptable 00000DFA case 1 .text:00000E14 ; 22: break; .text:00000E14 B def_DFA ; jumptable 00000DFA default case .text:00000E16 ; --------------------------------------------------------------------------- .text:00000E16 ; 24: result = v6 / a2; .text:00000E16 .text:00000E16 loc_E16 ; CODE XREF: switch1+Ej .text:00000E16 MOVS R0, R4 ; jumptable 00000DFA case 3 .text:00000E18 BLX __divsi3 .text:00000E1C ; 25: break; .text:00000E1C ; 26: default: .text:00000E1C B def_DFA ; jumptable 00000DFA default case .text:00000E1C ; End of function switch1在這個函數中由於使用了R4做爲局部變量,因此在開始時要把R4放入堆棧,爲了返回後程序可以繼續執行,因此把LR也壓入了堆棧。
這樣堆棧地址就減去了8個字節(R4,LR都被壓入堆棧)。因此取第一個參數要使用指令LDR R2, [SP,#8+arg_0]。