Analysis of the Anti-Debugging Technology of Question 2 of the 2015 Ali Android Challenge

Keywords: Programming

Analysis of part 3 Back-debugging Principle

Taking on the previous blog post, there are two problems left when cracking, one is when the static password was modified, the other is the anti-debugging part of the content. Personally, I think the anti-debugging part of the content is more critical, so I will pick up the secret behind it. In this paper, assembly code analysis is the main method, combined with dynamic debugging, my goal is to train and read arm code, improve efficiency is also worth our time.

Or starting with JNI_OnLoad, OnLoad functions mainly do two things:

1. Decrypt dlsym, getpid, sprintf, fopen, fgets, strstr, sscanf, kill, sleep, pthread_create, mprotect, cacheflush, lrand48 and other API strings dynamically, and call dlsym functions to obtain the address of the appeal api, then fill in get (GLOBAL_OFFSET_TABLE) form.

.text:00001BDC                 ADD     R7, R5, #4
.text:00001BE0                 MOV     R6, #0
.text:00001BE4
.text:00001BE4 loc_1BE4                                ; CODE XREF: JNI_OnLoad+5Cj
 Text: 00001BE4 LDR R0, [R7, R6, LSL_ 2]; Get function pointer
 Text: 00001BE8 BLX R0; _GLOBAL_OFFSET_TABLE_; Call initIATTable function to decrypt string, initialize get table function, get PID sprintf API address ready after function call.

2. After the api is ready, call pthread_create() to start the debugging detection thread.

.text:00001C28                 SUB     R5, SP, #8
.text:00001C2C                 MOV     SP, R5
.text:00001C30                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1C48)
.text:00001C34                 LDR     R1, =(ThreadCallback - 0x5FBC)
.text:00001C38                 MOV     R3, #0
.text:00001C3C                 STR     R8, [R5]
.text:00001C40                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001C44                 ADD     R2, R1, R0 ; ThreadCallback
.text:00001C48                 ADD     R0, R9, R0 ; unk_6290
.text:00001C4C                 MOV     R1, #0          ; name
.text:00001C50                 LDR     R7, [R0,#(pthread_create_IAT - 0x6290)]
.text:00001C54                 SUB     R0, R11, #-handle ; handle
.text:00001C58                 BLX R7 ;  pthread_create(r0,r1,r2);Start Debugging Threads

Here's the Jni_OnLoad function code

.text:00001B9C JNI_OnLoad
.text:00001B9C
.text:00001B9C handle          = -0x20
.text:00001B9C
.text:00001B9C                 STMFD   SP!, {R4-R9,R11,LR}
.text:00001BA0                 ADD     R11, SP, #0x18
.text:00001BA4                 SUB     SP, SP, #8
.text:00001BA8                 MOV     R4, R0
.text:00001BAC                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1BC0)
.text:00001BB0                 LDR     R9, =(unk_6290 - 0x5FBC)
.text:00001BB4                 MOV     R8, #0
.text:00001BB8                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
Text: 00001BBC ADD R0, R9, R0; unk_6290; get the address of unk_6290 function in get table
 This is equivalent to the "first address" of the get table.
Text: 00001BC0 STR R8, [R0, (dword_62C8-0x6290)]; Initialize the global variable dword_62C8 with a value of 0
.text:00001BC4                 LDR     R5, [R0,#(dword_62C4 - 0x6290)] ; 
.text:00001BC8                 CMP     R5, #0
.text:00001BCC                 BEQ     loc_1C28 if(!dword_62C4) {}
.text:00001BD0
.text:00001BD0 loc_1BD0                                ; CODE XREF: JNI_OnLoad+74j
.text:00001BD0                 LDR     R0, [R5]
.text:00001BD4                 CMP     R0, #1
.text:00001BD8                 BLT     loc_1BFC
.text:00001BDC                 ADD     R7, R5, #4
.text:00001BE0                 MOV     R6, #0
.text:00001BE4
.text:00001BE4 loc_1BE4                                ; CODE XREF: JNI_OnLoad+5Cj
 Text: 00001BE4 LDR R0, [R7, R6, LSL_ 2]; Get function pointer
 Text: 00001BE8 BLX R0; _GLOBAL_OFFSET_TABLE_; Call initIATTable function to decrypt string, initialize get table function, get PID sprintf API address ready after function call.
.text:00001BEC                 LDR     R0, [R5]
.text:00001BF0                 ADD     R6, R6, #1
.text:00001BF4                 CMP     R6, R0
.text:00001BF8                 BLT     loc_1BE4        ; 
.text:00001BFC
.text:00001BFC loc_1BFC                                ; CODE XREF: JNI_OnLoad+3Cj
.text:00001BFC                 LDR     R6, [R5,#0x2C]
.text:00001C00                 MOV     R0, R5          ; ptr
.text:00001C04                 BL      free_0
.text:00001C08                 MOV     R5, R6
.text:00001C0C                 CMP     R6, #0
.text:00001C10                 BNE     loc_1BD0
.text:00001C14                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1C24)
.text:00001C18                 MOV     R1, #0
.text:00001C1C                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001C20                 ADD     R0, R9, R0 ; unk_6290
.text:00001C24                 STR     R1, [R0,#(dword_62C4 - 0x6290)]
.text:00001C28
.text:00001C28 loc_1C28                                ; CODE XREF: JNI_OnLoad+30j
.text:00001C28                 SUB     R5, SP, #8
.text:00001C2C                 MOV     SP, R5
.text:00001C30                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1C48)
.text:00001C34                 LDR     R1, =(ThreadCallback - 0x5FBC)
.text:00001C38                 MOV     R3, #0
.text:00001C3C                 STR     R8, [R5]
.text:00001C40                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001C44                 ADD     R2, R1, R0 ; ThreadCallback
.text:00001C48                 ADD     R0, R9, R0 ; unk_6290
.text:00001C4C                 MOV     R1, #0          ; name
.text:00001C50                 LDR     R7, [R0,#(pthread_create_IAT - 0x6290)]
.text:00001C54                 SUB     R0, R11, #-handle ; handle
 Text: 00001C58 BLX R7; pthread_create (r0, r1, r2); start debugging thread

initIATTable () function
Main work:
1. Call DecrptionIATTable with decryption key, or DecrptionIATTable 1, or DecrptionIATTable 2. DecrptionIATTable 3 decrypts dlsym, getpid, sprintf, fopen, fgets, strstr, sscanf, kill, sleep, pthread_create, mprotect, etc.
cacheflush, lrand48 string, and mark has been decrypted. Four decryption algorithms are used here, some of them are fantastic.

The following code dlsym has a key of "9HbB" and decrypts the "dlsym" string by calling DecrptionIATTable (). The isDlsymInited global variable is used to set the decrypted flag bit, that is to say, before the next decryption, it will determine whether the string is decrypted or not. If decrypted, it will not need to decrypt again.

.text:00001CDC                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1CEC)
.text:00001CE0                 LDR     R1, =(encrpty_dlsym - 0x5FBC)
.text:00001CE4                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001CE8                 ADD     R2, R1, R0
.text:00001CEC                 LDR     R1, =(a9hbb - 0x5FBC)key = "9HbB"
.text:00001CF0                 ADD     R4, R5, R0 ; unk_6290
.text:00001CF4                 ADD     R3, R1, R0      ; dlsym Decryption key
.text:00001CF8                 ADD     R0, R4, #0x47
.text:00001CFC                 MOV     R1, #6
.text:00001D00                 BL      DecrptionIATTable ;Decryption algorithm 1
.text:00001D04                 MOV     R0, #1
.text:00001D08                 STRB    R0, [R4,#(isDlsymInited - 0x6290)]

2. Call dlsym(), get the actual memory address one by one, and fill in the get table

.text:00001D74                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1D80)
.text:00001D78                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001D7C                 ADD     R6, R5, R0 ; unk_6290
.text:00001D80                 MOV     R0, #0xFFFFFFFF
.text:00001D84                 ADD     R1, R6, #0x5F
.text:00001D88                 BLX     R4 ; _GLOBAL_OFFSET_TABLE_
.text:00001D8C                 STR     R0, [R6,#(getpid_IAT-0x6290)] Stored in getpid_IAT address

The initIATTable () function code is as follows

 initIATTable                            ; DATA XREF: sub_2378+10o
.text:00001CA8                                         ; .text:off_2398o
.text:00001CA8
.text:00001CA8 var_20          = -0x20
.text:00001CA8 var_1C          = -0x1C
.text:00001CA8
.text:00001CA8                 STMFD   SP!, {R4-R7,R11,LR}
.text:00001CAC                 SUB     SP, SP, #8
.text:00001CB0                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1CC0)
.text:00001CB4                 LDR     R5, =(unk_6290 - 0x5FBC)
.text:00001CB8                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001CBC                 ADD     R0, R5, R0 ; unk_6290
.text:00001CC0                 LDRB    R0, [R0,#(isDlsymInited - 0x6290)]
.text:00001CC4                 CMP     R0, #0
.text:00001CC8                 BNE     loc_1D0C
.text:00001CCC                 MOV     R1, #4
.text:00001CD0                 MOV     R0, #0xC5
.text:00001CD4                 STR     R1, [SP,#0x20+var_20]
.text:00001CD8                 STR     R0, [SP,#0x20+var_1C]
.text:00001CDC                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1CEC)
.text:00001CE0                 LDR     R1, =(encrpty_dlsym - 0x5FBC)
.text:00001CE4                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001CE8                 ADD     R2, R1, R0
.text:00001CEC                 LDR     R1, =(a9hbb - 0x5FBC)
.text:00001CF0                 ADD     R4, R5, R0 ; unk_6290
.text:00001CF4                 ADD     R3, R1, R0      ; dlsym Decryption key
.text:00001CF8                 ADD     R0, R4, #0x47
.text:00001CFC                 MOV     R1, #6
.text:00001D00                 BL      DecrptionIATTable ;Decryption algorithm 1
.text:00001D04                 MOV     R0, #1
.text:00001D08                 STRB    R0, [R4,#(isDlsymInited - 0x6290)]
.text:00001D0C
.text:00001D0C loc_1D0C                                ; CODE XREF: initIATTable+20j
.text:00001D0C                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1D18)
.text:00001D10                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001D14                 ADD     R6, R5, R0 ; unk_6290
.text:00001D18                 MOV     R0, #0xFFFFFFFF ; handle
.text:00001D1C                 ADD     R1, R6, #0x47   ; name
.text:00001D20                 BL      dlsym_0
.text:00001D24                 MOV     R4, R0          ; RO by dlsym Code address
.text:00001D28                 LDRB    R0, [R6,#(isGetpidInited - 0x6290)]
.text:00001D2C                 CMP     R0, #0
.text:00001D30                 BNE     loc_1D74
.text:00001D34                 MOV     R1, #2
.text:00001D38                 MOV     R0, #0xD5
.text:00001D3C                 STR     R1, [SP,#0x20+var_20]
.text:00001D40                 STR     R0, [SP,#0x20+var_1C]
.text:00001D44                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1D54)
.text:00001D48                 LDR     R1, =(unk_448B - 0x5FBC)
.text:00001D4C                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001D50                 ADD     R2, R1, R0
.text:00001D54                 LDR     R1, =(aM7 - 0x5FBC)
.text:00001D58                 ADD     R6, R5, R0 ; unk_6290
.text:00001D5C                 ADD     R3, R1, R0      ; getpid Decryption key
.text:00001D60                 ADD     R0, R6, #0x5F
.text:00001D64                 MOV     R1, #7
.text:00001D68                 BL      DecrptionIATTable
.text:00001D6C                 MOV     R0, #1
.text:00001D70                 STRB    R0, [R6,#(isGetpidInited - 0x6290)]
.text:00001D74
.text:00001D74 loc_1D74                                ; CODE XREF: initIATTable+88j
.text:00001D74                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1D80)
.text:00001D78                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001D7C                 ADD     R6, R5, R0 ; unk_6290
.text:00001D80                 MOV     R0, #0xFFFFFFFF
.text:00001D84                 ADD     R1, R6, #0x5F
.text:00001D88                 BLX     R4 ; _GLOBAL_OFFSET_TABLE_
.text:00001D8C                 STR     R0, [R6,#(getpid_IAT - 0x6290)]
.text:00001D90                 LDRB    R0, [R6,#(isSprintfInited - 0x6290)]
.text:00001D94                 CMP     R0, #0
.text:00001D98                 BNE     loc_1DDC
.text:00001D9C                 MOV     R1, #4
.text:00001DA0                 MOV     R0, #0xE9
.text:00001DA4                 STR     R1, [SP,#0x20+var_20]
.text:00001DA8                 STR     R0, [SP,#0x20+var_1C]
.text:00001DAC                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1DBC)
.text:00001DB0                 LDR     R1, =(unk_44F3 - 0x5FBC)
.text:00001DB4                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001DB8                 ADD     R2, R1, R0
.text:00001DBC                 LDR     R1, =(aLnat - 0x5FBC)
.text:00001DC0                 ADD     R6, R5, R0 ; unk_6290
.text:00001DC4                 ADD     R3, R1, R0      ; Decrypt sprintf Of key
.text:00001DC8                 ADD     R0, R6, #0x7C
.text:00001DCC                 MOV     R1, #8
.text:00001DD0                 BL      DecrptionIATTable1 Decryption algorithm2
.text:00001DD4                 MOV     R0, #1
.text:00001DD8                 STRB    R0, [R6,#(isSprintfInited - 0x6290)]
.text:00001DDC
.text:00001DDC loc_1DDC                                ; CODE XREF: initIATTable+F0j
.text:00001DDC                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1DE8)
.text:00001DE0                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001DE4                 ADD     R6, R5, R0 ; unk_6290
.text:00001DE8                 MOV     R0, #0xFFFFFFFF
.text:00001DEC                 ADD     R1, R6, #0x7C
.text:00001DF0                 BLX     R4 ; _GLOBAL_OFFSET_TABLE_
.text:00001DF4                 STR     R0, [R6,#(sprintf_IAT - 0x6290)]
.text:00001DF8                 LDRB    R0, [R6,#(isFopenInited - 0x6290)]
.text:00001DFC                 CMP     R0, #0
.text:00001E00                 BNE     loc_1E44
.text:00001E04                 MOV     R1, #4
.text:00001E08                 MOV     R0, #0xE7
.text:00001E0C                 STR     R1, [SP,#0x20+var_20]
.text:00001E10                 STR     R0, [SP,#0x20+var_1C]
.text:00001E14                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1E24)
.text:00001E18                 LDR     R1, =(a0WE - 0x5FBC)
.text:00001E1C                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001E20                 ADD     R2, R1, R0      ; "0 A kind of w Chung"
.text:00001E24                 LDR     R1, =(aCoxt - 0x5FBC)
.text:00001E28                 ADD     R6, R5, R0 ; unk_6290
.text:00001E2C                 ADD     R3, R1, R0      ; Decrypt fopen Of key
.text:00001E30                 ADD     R0, R6, #0x4D
.text:00001E34                 MOV     R1, #6
.text:00001E38                 BL      DecrptionIATTable1
.text:00001E3C                 MOV     R0, #1
.text:00001E40                 STRB    R0, [R6,#(isFopenInited - 0x6290)]
.text:00001E44
.text:00001E44 loc_1E44                                ; CODE XREF: initIATTable+158j
.text:00001E44                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1E50)
.text:00001E48                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001E4C                 ADD     R6, R5, R0 ; unk_6290
.text:00001E50                 MOV     R0, #0xFFFFFFFF
.text:00001E54                 ADD     R1, R6, #0x4D
.text:00001E58                 BLX     R4 ; _GLOBAL_OFFSET_TABLE_
.text:00001E5C                 STR     R0, [R6,#(fopen_IAT - 0x6290)]
.text:00001E60                 LDRB    R0, [R6,#(isFgetsdInited - 0x6290)]
.text:00001E64                 CMP     R0, #0
.text:00001E68                 BNE     loc_1EA4
.text:00001E6C                 MOV     R6, #1
.text:00001E70                 MOV     R0, #3
.text:00001E74                 LDR     R1, =(aIU - 0x5FBC)
.text:00001E78                 STMEA   SP, {R0,R6}
.text:00001E7C                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1E88)
.text:00001E80                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001E84                 ADD     R2, R1, R0      ; "┑Fu"
.text:00001E88                 LDR     R1, =(aBmt - 0x5FBC)
.text:00001E8C                 ADD     R7, R5, R0 ; unk_6290
.text:00001E90                 ADD     R3, R1, R0      ; Decrypt fgets Of key
.text:00001E94                 ADD     R0, R7, #0x53
.text:00001E98                 MOV     R1, #6
.text:00001E9C                 BL      DecrptionIATTable
.text:00001EA0                 STRB    R6, [R7,#(isFgetsdInited - 0x6290)]
......
.text:000021D8                 ADD     SP, SP, #8
.text:000021DC                 LDMFD   SP!, {R4-R7,R11,PC}

The contents of the get table after the execution of the appeal code are as follows:

After the previous preparations have been completed, pthread_create() is called, and the body of the function is in ThreadCallback.
The assembly code restored here in the previous file is a while loop, one calling the Anit Deubging code, and the other sleep ing (3) with threads dormant for three seconds.

.text:000016A4 ThreadCallback                          ; DATA XREF: JNI_OnLoad+A8o
.text:000016A4                                         ; .text:off_1CA4o
.text:000016A4                 STMFD   SP!, {R4,LR}
.text:000016A8                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x16B8)
.text:000016AC                 LDR     R1, =(unk_6290 - 0x5FBC)
.text:000016B0                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:000016B4                 ADD     R4, R1, R0 ; unk_6290
.text:000016B8
.text:000016B8 loc_16B8                                ; CODE XREF: ThreadCallback+24j
.text:000016B8                 BL      AnitDeubging
.text:000016BC                 LDR     R1, [R4,#(sleep_IAT - 0x6290)]
.text:000016C0                 MOV     R0, #3
.text:000016C4                 BLX     R1              ; call sleep(3),Sleep for 3 seconds
.text:000016C8                 B       loc_16B8

Thread function c code restore

while(true){
     AnitDeubging();
     sleep(3);//Call function 
}

Next is the point. We're about to unravel the anti-debugging secret.
Main work:
1,fopen("/proc/pid/status")
2. Loop fgets() to read the file content
3. Call strstr to locate "TracerPid" and get the value of the following TracerPid
4. TracerPid is 0, which means that the program has not been debugged. If it is larger than 1, it means that the process is attached.
5. When TracerPid is not 0, kill (my_pid) is executed, and the program exits.

Debugger Detection Business Logic 1

Call getpid api to get the process id of the current app, and then determine whether "/ proc/%d/status" has been decrypted or not, then call the decryption function to decrypt dynamically, and set the decrypted flag bit.

.text:0000130C                 STMFD   SP!, {R4-R11,LR}
.text:00001310                 SUB     SP, SP, #0x324
.text:00001314                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1328) ; Dynamic debugging becomes 0 xF3CA6328
.text:00001318                 MOV     R1, #0x64
.text:0000131C                 MOV     R2, #0
.text:00001320                 ADD     R4, PC, R0 ; _GLOBAL_OFFSET_TABLE_ ; got One of the tables"Head address"
.text:00001324                 LDR     R0, =(__stack_chk_guard_ptr - 0x5FBC)
.text:00001328                 LDR     R0, [R0,R4] ; __stack_chk_guard
.text:0000132C                 LDR     R0, [R0]
.text:00001330                 STR     R0, [SP,#0x348+checkStack]; store the content pointed to by chk_guard in the current stack
.text:00001334                 ADD     R0, SP, #0x348+lpstrArry
.text:00001338                 BL      __aeabi_memset_0 ; call memset Initialize 100-size stack space
.text:0000133C                 LDR     R7, =(unk_6290 - 0x5FBC)
.text:00001340                 ADD     R5, R7, R4 ; unk_6290
.text:00001344                 LDR     R0, [R5,#(getpid_IAT-0x6290)]; dynamic debugging found that this is the address of getpid (import table 0xF7010D1B)
.text:00001348                 BLX     R0              ; call getpid,Returning to the current process pid
.text:0000134C                 MOV     R8, R0
.text:00001350                 LDR     R4, [R5,#(sprintf_IAT - 0x6290)] ; sprintf(0xF703E34B)
.text:00001354                 LDRB    R0, [R5,#(byte_635B - 0x6290)]
.text:00001358                 CMP     R0, #0; whether the content of byte_635b is 1
.text:0000135C                 BNE     loc_13A0        ; if(byte_635b == 0){
.text:0000135C                                         ; }
.text:00001360                 MOV     R1, #4
.text:00001364                 MOV     R0, #0x57
.text:00001368                 STR     R1, [SP,#0x348+local1]
.text:0000136C                 STR     R0, [SP,#0x348+local2]
.text:00001370                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1380)
.text:00001374                 LDR     R1, =(dword_4550 - 0x5FBC)
.text:00001378                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:0000137C                 ADD     R2, R1, R0 ; dword_4550
.text:00001380                 LDR     R1, =(aSL - 0x5FBC)
.text:00001384                 ADD     R5, R7, R0 ; unk_6290
.text:00001388                 ADD     R3, R1, R0      ; "s!#L"
.text:0000138C                 ADD     R0, R5, #0xB9
.text:00001390                 MOV     R1, #0x10
.text:00001394                 BL      DecrptionIATTable1 ; Decrypted string"/proc/%d/status"
.text:00001398                 MOV     R0, #1; Set the global variable byte_635b flag bit to 1
.text:0000139C                 STRB    R0, [R5,#(byte_635B - 0x6290)]

Debugger Detection Business Logic 2

Call sprintf("/proc/%d/status", PID) to construct the full path string of the status file of the current app process. Then decrypt
"TracerPid" string and set the decrypted flag bit

.text:000013A0 loc_13A0                                ; CODE XREF: AnitDeubging+50j
.text:000013A0                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x13B0)
.text:000013A4                 MOV     R2, R8
.text:000013A8                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:000013AC                 ADD     R6, R7, R0 ; unk_6290
.text:000013B0                 ADD     R0, SP, #0x348+lpstrArry
.text:000013B4                 ADD     R1, R6, #0xB9
.text:000013B8                 BLX     R4              ; call sprintf(lpstrArry,"/proc/%d/status",r2)
.text:000013BC                 LDR     R5, [R6,#(fopen_IAT - 0x6290)]
.text:000013C0                 LDRB    R0, [R6,#(byte_635C - 0x6290)]
.text:000013C4                 CMP     R0, #0
.text:000013C8                 BNE     loc_1404
.text:000013CC                 MOV     R6, #1
.text:000013D0                 MOV     R0, #0
.text:000013D4                 LDR     R1, =(unk_454A - 0x5FBC)
.text:000013D8                 STMEA   SP, {R0,R6}
.text:000013DC                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x13E8)
.text:000013E0                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:000013E4                 ADD     R2, R1, R0 ; unk_454A
.text:000013E8                 LDR     R1, =(unk_44FC - 0x5FBC)
.text:000013EC                 ADD     R4, R7, R0 ; unk_6290
.text:000013F0                 ADD     R3, R1, R0 ; unk_44FC
.text:000013F4                 MOV     R0, R4
.text:000013F8                 MOV     R1, #2
.text:000013FC                 BL      DecrptionIATTable2 ; Decrypt TracerPid Character string
.text:00001400                 STRB    R6, [R4,#(byte_635C - 0x6290)]
.text:00001404
.text:00001404 loc_1404

Debugger Detection Business Logic 3

Call fopen to open the "/proc/34352/status" file and read the content of 0x200 size.

.text:00001404 loc_1404                                ; CODE XREF: AnitDeubging+BCj
.text:00001404                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1414)
.text:00001408                 STR     R8, [SP,#0x348+var_338]
.text:0000140C                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001410                 ADD     R4, R7, R0 ; unk_6290
.text:00001414                 ADD     R0, SP, #0x348+lpstrArry
.text:00001418                 MOV     R1, R4
.text:0000141C                 BLX     R5              ; fopen("/proc/34352/status")
.text:00001420                 ADD     R6, SP, #0x348+var_28C
.text:00001424                 MOV     R5, R0          ; Function returns results
.text:00001428                 MOV     R1, #0x200
.text:0000142C                 MOV     R2, #0
.text:00001430                 MOV     R0, R6
.text:00001434                 STR     R5, [SP,#0x348+statusFileFd]
.text:00001438                 BL      __aeabi_memset_0 ; memset(local_28c,0x200,0);It feels like this should be memset(local_28c,0,0x200)Only then
.text:0000143C                 LDR     R3, [R4,#(fgets_IAT - 0x6290)]
.text:00001440                 MOV     R0, R6
.text:00001444                 MOV     R1, #0x200
.text:00001448                 MOV     R2, R5
.text:0000144C
.text:0000144C fgets__                                 ; fgets
.text:0000144C                 BLX     R3
.text:00001450                 MOV     R6, R7          ; r6 = unk_6290
.text:00001454                 CMP     R0, #0; whether the comparison result is 0
.text:00001458                 BEQ     loc_161C        ; Jumping from the point of view, not jumping executes a lot of code, you have to suspect that this is the key point.

Debugger Detection Business Logic 4

Loop call fgets to read the status file content, then call strstr("Name:.yaotong.crackme", "TracerPid") to find the substring, if found each time, continue to read the status file content until the end of the file. If TracerPid is found, the process ID in "TracerPid: 13654" is taken out, which is actually the ID of. / android_server process. Determine whether the process ID is greater than or equal to 1, and if it is greater than 1, walk out of the program process.

.text:000014F8 loc_14F8                                ; CODE XREF: AnitDeubging+2ECj
.text:000014F8                 LDR     R5, [R8,#(strstr_IAT - 0x6290)]
.text:000014FC                 LDRB    R0, [R8,#(byte_635D - 0x6290)]
.text:00001500                 CMP     R0, #0
.text:00001504                 BNE     loc_154C        ; Decrypt"%s,%d"String, if decrypted, skips
.text:00001508                 MOV     R0, #2
.text:0000150C                 LDR     R2, [SP,#0x348+var_324]
.text:00001510                 LDR     R3, [SP,#0x348+var_328]
.text:00001514                 MOV     R11, R4
.text:00001518                 MOV     R4, R6
.text:0000151C                 MOV     R1, #0xA
.text:00001520                 STR     R0, [SP,#0x348+local1]
.text:00001524                 MOV     R0, #0x9D
.text:00001528                 STR     R0, [SP,#0x348+local2]
.text:0000152C                 LDR     R0, [SP,#0x348+var_320]
.text:00001530                 ADD     R6, R4, R0
.text:00001534                 ADD     R0, R6, #0x95
.text:00001538                 BL      DecrptionIATTable
.text:0000153C                 MOV     R0, #1
.text:00001540                 STRB    R0, [R6,#0xCD]
.text:00001544                 MOV     R6, R4
.text:00001548                 MOV     R4, R11
.text:0000154C
.text:0000154C loc_154C                                ; CODE XREF: AnitDeubging+1F8j
.text:0000154C                 MOV     R0, R9
.text:00001550                 MOV     R1, R7
.text:00001554                 BLX     R5              ; example strstr("Name:.yaotong.crackme","TracerPid")
.text:00001558                 CMP     R0, #0          ; if(r0 != 0){}
.text:0000155C                 BEQ     loc_15DC        ; lookup TracerPid Character string
.text:00001560                 MOV     R0, R4
.text:00001564                 MOV     R1, #0x80
.text:00001568                 MOV     R2, #0
.text:0000156C                 BL      __aeabi_memset_0
.text:00001570                 MOV     R0, #0
.text:00001574                 STR     R0, [SP,#0x348+local_key]
.text:00001578                 LDR     R11, [R10,#(sscanf_IAT - 0x6290)]
.text:0000157C                 LDRB    R0, [R10,#(byte_635E - 0x6290)]
.text:00001580                 CMP     R0, #0
.text:00001584                 BNE     loc_15BC
.text:00001588                 MOV     R0, #3
.text:0000158C                 LDR     R2, [SP,#0x348+var_330]
.text:00001590                 LDR     R3, [SP,#0x348+var_334]
.text:00001594                 MOV     R1, #6
.text:00001598                 STR     R0, [SP,#0x348+local1]
.text:0000159C                 MOV     R0, #0x93
.text:000015A0                 STR     R0, [SP,#0x348+local2]
.text:000015A4                 LDR     R0, [SP,#0x348+var_32C]
.text:000015A8                 ADD     R5, R6, R0
.text:000015AC                 ADD     R0, R5, #0x41
.text:000015B0                 BL      DecrptionIATTable1 ; Decrypted string
.text:000015B4                 MOV     R0, #1
.text:000015B8                 STRB    R0, [R5,#0xCE]
.text:000015BC
.text:000015BC loc_15BC                                ; CODE XREF: AnitDeubging+278j
.text:000015BC                 LDR     R1, [SP,#0x348+var_31C]
.text:000015C0                 MOV     R0, R9
.text:000015C4                 MOV     R2, R4
.text:000015C8                 ADD     R3, SP, #0x348+local_key
.text:000015CC                 BLX     R11             ; 3 A parametric function
.text:000015D0                 LDR     R0, [SP,#0x348+local_key]
.text:000015D4                 CMP     R0, #1          ; TracerPid :(./android_server)
.text:000015D8                 BGE     loc_1600        ; TracerPid >= 1 Note that it is being debugged
.text:000015DC
.text:000015DC loc_15DC                                ; CODE XREF: AnitDeubging+250j
.text:000015DC                 LDR     R0, [SP,#0x348 + fgetsOffsetAddr]; R0 < 1 continues
.text:000015E0                 LDR     R2, [SP,#0x348+statusFileFd]
.text:000015E4                 MOV     R1, #0x200
.text:000015E8                 LDR     R3, [R0,#0x10]
.text:000015EC                 MOV     R0, R9          ; szBuffer
.text:000015F0                 BLX     R3              ; fgets()
.text:000015F4                 CMP     R0, #0; The result is not equal to 0 to continue the cycle, otherwise jump out of the cycle.
.text:000015F8                 BNE     loc_14F8
.text:000015FC                 B       loc_161C

Debugger Detection Business Logic 5

If the value of TracerPid is greater than or equal to 1, execute kill(pid), exit your own program, and if it is equal to 0, the process will normally end and wait for the next detection.

.text:00001600 loc_1600                                ; CODE XREF: AnitDeubging+2CCj
.text:00001600                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x1610)
.text:00001604                 MOV     R1, #9
.text:00001608                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:0000160C                 ADD     R0, R6, R0
.text:00001610                 LDR     R2, [R0,#gotOffsetOfKill]
.text:00001614                 LDR     R0, [SP,#0x348+var_338]
.text:00001618                 BLX     R2 ; __imp___stack_chk_fail ; What's actually called is kill(pid)function
.text:0000161C ; ---------------------------------------------------------------------------
.text:0000161C
.text:0000161C loc_161C                                ; CODE XREF: AnitDeubging+14Cj
.text:0000161C                                         ; AnitDeubging+2F0j
.text:0000161C                 LDR     R0, =(_GLOBAL_OFFSET_TABLE_ - 0x162C)
.text:00001620                 LDR     R1, =(__stack_chk_guard_ptr - 0x5FBC)
.text:00001624                 ADD     R0, PC, R0 ; _GLOBAL_OFFSET_TABLE_
.text:00001628                 LDR     R0, [R1,R0] ; __stack_chk_guard
.text:0000162C                 LDR     R0, [R0]
.text:00001630                 LDR     R1, [SP,#0x348+checkStack]
.text:00001634                 SUBS    R0, R0, R1
.text:00001638                 ADDEQ   SP, SP, #0x324
.text:0000163C                 LDMEQFD SP!, {R4-R11,PC}
.text:00001640                 BL      __stack_chk_fail_0

When the program is debugging, let's take a look at the status file of crackme.

Note line 6 of the figure, TracerPid: 16364

Next, verify which process 16364 is.

Line 3 of the figure, PID 16364, is the android_server process.

Summary of Back-Debugging Technology

Crame reads the value of "TracerPid" in the "/proc/self/status" file through a loop. If the value is greater than 1, the process is added. That is, there is a program debugging the app, and then killing (self_pid) is used to send a kill signal to the system so that the system can terminate the process of app.

Technical summary

Seen from the whole so library code, crackme's security programming idea is well applied. Strings are encrypted and saved, and decrypted only when used. This static analysis brings some difficulties. There are not only one decryption algorithm, but also the decryption algorithm, which feels confused. It is not difficult to guess that the decryption code is also encrypted and saved, and then decrypted when it is running. I will not analyze it here. Interested students can analyze it.

Posted by Bobulous on Mon, 17 Jun 2019 13:24:06 -0700