新建了一个Android群,有兴趣可以加一下:555054687
讨论一下数字公司的反调试方案,我使用的调试工具是ida,就以ida来说。一共有两个检测点:
1、读取/proc/self/status文件,查找TracerPid对应的值,调试状态下这个值是不为0的,所以只要程序判断为0就行了
2、读取/proc/net/tcp文件,察看端口号为:0x5D8A 也就是(23946),这个端口是android_server的通讯端口
数字公司在做检测的时候,把这两个检测封装成了两个独立的函数:
1、检测1
anti_debug_find_tracer_pid ; CODE XREF: uncompress_some_data+Cp
LOAD:00007B2C ; sub_A760+4p ...
LOAD:00007B2C STMFD SP!, {R4-R8,LR} ; 这是一个函数
LOAD:00007B30 LDR R5, =(dword_2AD34 - 0x7B44)
LOAD:00007B34 LDR R8, =(dword_267B4 - 0x7B4C)
LOAD:00007B38 SUB SP, SP, #0xF8
LOAD:00007B3C LDR R5, [PC,R5] ; dword_2AD34
LOAD:00007B40 LDR R3, [R5]
LOAD:00007B44 ADD R8, PC, R8 ; dword_267B4
LOAD:00007B48 ADD R6, SP, #0x20
LOAD:00007B4C MOV R1, R8
LOAD:00007B50 MOV R2, #0x12
LOAD:00007B54 MOV R0, R6
LOAD:00007B58 ADD R4, SP, #4
LOAD:00007B5C STR R3, [SP,#0xF4]
LOAD:00007B60 ADD R7, SP, #0x10
LOAD:00007B64 BL memcpy_0
LOAD:00007B68 ADD R1, R8, #0x14
LOAD:00007B6C MOV R2, #0xA
LOAD:00007B70 MOV R0, R4
LOAD:00007B74 BL memcpy_0
LOAD:00007B78 ADD R1, R8, #0x20
LOAD:00007B7C MOV R0, R7
LOAD:00007B80 MOV R2, #0xF
LOAD:00007B84 BL memcpy_0
LOAD:00007B88 MOV R3, R6
LOAD:00007B8C ADD R1, SP, #0x32
LOAD:00007B90
LOAD:00007B90 loc_7B90 ; CODE XREF: LOAD:00007BA4j
LOAD:00007B90 LDRB R2, [R3]
LOAD:00007B94 EOR R2, R2, #0x5A
LOAD:00007B98 MVN R2, R2
LOAD:00007B9C STRB R2, [R3],#1
LOAD:00007BA0 CMP R3, R1
LOAD:00007BA4 BNE loc_7B90 ; 解密:/proc/self/status
LOAD:00007BA8 ADD R2, SP, #3
LOAD:00007BAC ADD R1, SP, #0xD
LOAD:00007BB0
LOAD:00007BB0 loc_7BB0 ; CODE XREF: LOAD:00007BC0j
LOAD:00007BB0 LDRB R3, [R2,#1]
LOAD:00007BB4 EOR R3, R3, #0xA5
LOAD:00007BB8 STRB R3, [R2,#1]!
LOAD:00007BBC CMP R2, R1
LOAD:00007BC0 BNE loc_7BB0 ; 解密:TracerPid
LOAD:00007BC4 MOV R3, R7
LOAD:00007BC8 ADD R1, SP, #0x1F
LOAD:00007BCC
LOAD:00007BCC loc_7BCC ; CODE XREF: LOAD:00007BE0j
LOAD:00007BCC LDRB R2, [R3]
LOAD:00007BD0 EOR R2, R2, #0x5A
LOAD:00007BD4 MVN R2, R2
LOAD:00007BD8 STRB R2, [R3],#1
LOAD:00007BDC CMP R3, R1
LOAD:00007BE0 BNE loc_7BCC ; 解密:%[a-zA-Z]:\t%s
LOAD:00007BE4 ADD R7, SP, #0x74
LOAD:00007BE8 MOV R1, #0
LOAD:00007BEC MOV R2, #0x80 ; '€'
LOAD:00007BF0 MOV R0, R7
LOAD:00007BF4 ADD R8, SP, #0x34
LOAD:00007BF8 BL memset_0
LOAD:00007BFC MOV R1, #0
LOAD:00007C00 MOV R2, #0x40 ; '@'
LOAD:00007C04 MOV R0, R8
LOAD:00007C08 BL memset_0
LOAD:00007C0C MOV R0, R6
LOAD:00007C10 MOV R1, #0
LOAD:00007C14 BL open_0 ; 打开proc/self/status文件
LOAD:00007C18 SUBS R6, R0, #0
LOAD:00007C1C BEQ loc_7CE0
LOAD:00007C20 MOV R1, R7
LOAD:00007C24 MOV R2, #0x80 ; '€'
LOAD:00007C28 BL read_file_line ; 按行读取当前proc/self/status文件中的内容,存放在第二个参数中,返回的值是读取字符串的大小
LOAD:00007C2C CMP R0, #0
LOAD:00007C30 BLT loc_7D00
LOAD:00007C34 BNE loc_7C60 ; 在这里跳转
LOAD:00007C38 B loc_7CDC
LOAD:00007C3C ; ---------------------------------------------------------------------------
LOAD:00007C3C
LOAD:00007C3C loc_7C3C ; CODE XREF: LOAD:00007C70j
LOAD:00007C3C MOV R2, #0x80 ; '€'
LOAD:00007C40 MOV R0, R7
LOAD:00007C44 BL memset_0
LOAD:00007C48 MOV R0, R6
LOAD:00007C4C MOV R1, R7
LOAD:00007C50 MOV R2, #0x80 ; '€'
LOAD:00007C54 BL read_file_line
LOAD:00007C58 CMP R0, #0
LOAD:00007C5C BLE loc_7CDC
LOAD:00007C60
LOAD:00007C60 loc_7C60 ; CODE XREF: LOAD:00007C34j
LOAD:00007C60 MOV R1, R4 ; 此时r1=r4=TracerPid
LOAD:00007C64 MOV R0, R7
LOAD:00007C68 BL strstr ; 检测文件中TracerPid这一行字符串
LOAD:00007C6C SUBS R1, R0, #0
LOAD:00007C70 BEQ loc_7C3C ; 如果不包含就跳转,接着读下一行,直到包含为止
LOAD:00007C74 MOV R1, #0
LOAD:00007C78
LOAD:00007C78 loc_7C78 ; CODE XREF: LOAD:00007CB4j
LOAD:00007C78 LDRB R3, [R7]
LOAD:00007C7C SUB R2, R3, #0x30
LOAD:00007C80 CMP R2, #9 ; 检测包含TracerPid这一行的字符串是否包含数字,也就是检测是否有调试
LOAD:00007C84 BHI loc_7CAC
LOAD:00007C88
LOAD:00007C88 loc_7C88 ; CODE XREF: LOAD:00007CA8j
LOAD:00007C88 ADD R0, SP, #0xF8
LOAD:00007C8C ADD R2, R0, R1
LOAD:00007C90 ADD R7, R7, #1
LOAD:00007C94 STRB R3, [R2,#-0xC4] ; 把获得的TracerPid放入其中
LOAD:00007C98 LDRB R3, [R7]
LOAD:00007C9C ADD R1, R1, #1
LOAD:00007CA0 SUB R2, R3, #0x30
LOAD:00007CA4 CMP R2, #9
LOAD:00007CA8 BLS loc_7C88
LOAD:00007CAC
LOAD:00007CAC loc_7CAC ; CODE XREF: LOAD:00007C84j
LOAD:00007CAC CMP R3, #0
LOAD:00007CB0 ADD R7, R7, #1
LOAD:00007CB4 BNE loc_7C78
LOAD:00007CB8 MOV R1, SP
LOAD:00007CBC MOV R2, #0xA
LOAD:00007CC0 MOV R0, R8 ; r0=r8=pointer TracerPid
LOAD:00007CC4 BL strtol
LOAD:00007CC8 MOV R4, R0 ; r4=r0=TreacerPid的数字
LOAD:00007CCC MOV R0, R6
LOAD:00007CD0 BL close_0 ; 关闭proc/self/status文件
LOAD:00007CD4 MOV R0, R4
LOAD:00007CD8 B loc_7CE8
LOAD:00007CDC ; ---------------------------------------------------------------------------
LOAD:00007CDC
LOAD:00007CDC loc_7CDC ; CODE XREF: LOAD:00007C38j
LOAD:00007CDC ; LOAD:00007C5Cj
LOAD:00007CDC MOV R0, R6
LOAD:00007CE0
LOAD:00007CE0 loc_7CE0 ; CODE XREF: LOAD:00007C1Cj
LOAD:00007CE0 BL close_0
LOAD:00007CE4 MOV R0, #0
LOAD:00007CE8
LOAD:00007CE8 loc_7CE8 ; CODE XREF: LOAD:00007CD8j
LOAD:00007CE8 ; LOAD:00007D0Cj
LOAD:00007CE8 LDR R2, [SP,#0xF4]
LOAD:00007CEC LDR R3, [R5]
LOAD:00007CF0 CMP R2, R3
LOAD:00007CF4 BNE loc_7D10
LOAD:00007CF8 ADD SP, SP, #0xF8
LOAD:00007CFC LDMFD SP!, {R4-R8,PC} ;在这个地方下断点,r0=0即可
2、检测2
anti_debug_find_tcp_port_23946 ; CODE XREF: sub_A760:loc_A770p
LOAD:00007D1C STMFD SP!, {R4-R7,LR}
LOAD:00007D20 LDR R5, =(dword_2AD34 - 0x7D34)
LOAD:00007D24 LDR R6, =(dword_267B4 - 0x7D40)
LOAD:00007D28 SUB SP, SP, #0x22C
LOAD:00007D2C LDR R5, [PC,R5] ; dword_2AD34
LOAD:00007D30 LDR R3, [R5]
LOAD:00007D34 ADD R7, SP, #4
LOAD:00007D38 ADD R6, PC, R6 ; dword_267B4
LOAD:00007D3C ADD R1, R6, #0x30
LOAD:00007D40 MOV R2, #0xE
LOAD:00007D44 MOV R0, R7
LOAD:00007D48 ADD R4, SP, #0x14
LOAD:00007D4C STR R3, [SP,#0x224]
LOAD:00007D50 BL memcpy_0
LOAD:00007D54 ADD R1, R6, #0x40
LOAD:00007D58 MOV R0, R4
LOAD:00007D5C MOV R2, #0xE
LOAD:00007D60 BL memcpy_0
LOAD:00007D64 MOV R3, R7
LOAD:00007D68 ADD R1, R7, #0xE
LOAD:00007D6C
LOAD:00007D6C loc_7D6C ; CODE XREF: LOAD:00007D80j
LOAD:00007D6C LDRB R2, [R3]
LOAD:00007D70 EOR R2, R2, #0x5A
LOAD:00007D74 MVN R2, R2
LOAD:00007D78 STRB R2, [R3],#1
LOAD:00007D7C CMP R3, R1
LOAD:00007D80 BNE loc_7D6C ; 解密:/proc/net/tcp
LOAD:00007D84 MOV R3, R4
LOAD:00007D88 ADD R1, R4, #0xE
LOAD:00007D8C
LOAD:00007D8C loc_7D8C ; CODE XREF: LOAD:00007DA0j
LOAD:00007D8C LDRB R2, [R3]
LOAD:00007D90 EOR R2, R2, #0x5A
LOAD:00007D94 MVN R2, R2
LOAD:00007D98 STRB R2, [R3],#1
LOAD:00007D9C CMP R3, R1
LOAD:00007DA0 BNE loc_7D8C ; 解密:00000000:5D8A
LOAD:00007DA4 ADD R6, SP, #0x24
LOAD:00007DA8 MOV R1, #0
LOAD:00007DAC MOV R2, #0x200
LOAD:00007DB0 MOV R0, R6
LOAD:00007DB4 BL memset_0
LOAD:00007DB8 MOV R0, R7
LOAD:00007DBC MOV R1, #0
LOAD:00007DC0 BL open_0
LOAD:00007DC4 SUBS R7, R0, #0
LOAD:00007DC8 BEQ loc_7E34
LOAD:00007DCC MOV R1, R6
LOAD:00007DD0 MOV R2, #0x200
LOAD:00007DD4 BL read_file_line
LOAD:00007DD8 CMP R0, #0
LOAD:00007DDC BLT loc_7E30
LOAD:00007DE0 BNE loc_7E0C
LOAD:00007DE4 B loc_7E30
LOAD:00007DE8 ; ---------------------------------------------------------------------------
LOAD:00007DE8
LOAD:00007DE8 loc_7DE8 ; CODE XREF: LOAD:00007E1Cj
LOAD:00007DE8 MOV R2, #0x200
LOAD:00007DEC MOV R0, R6
LOAD:00007DF0 BL memset_0
LOAD:00007DF4 MOV R0, R7
LOAD:00007DF8 MOV R1, R6
LOAD:00007DFC MOV R2, #0x200
LOAD:00007E00 BL read_file_line
LOAD:00007E04 CMP R0, #0
LOAD:00007E08 BLE loc_7E30
LOAD:00007E0C
LOAD:00007E0C loc_7E0C ; CODE XREF: LOAD:00007DE0j
LOAD:00007E0C MOV R1, R4
LOAD:00007E10 MOV R0, R6
LOAD:00007E14 BL strstr
LOAD:00007E18 SUBS R1, R0, #0
LOAD:00007E1C BEQ loc_7DE8
LOAD:00007E20 MOV R0, R7
LOAD:00007E24 BL close_0
LOAD:00007E28 MOV R0, #1
LOAD:00007E2C B loc_7E3C
LOAD:00007E30 ; ---------------------------------------------------------------------------
LOAD:00007E30
LOAD:00007E30 loc_7E30 ; CODE XREF: LOAD:00007DDCj
LOAD:00007E30 ; LOAD:00007DE4j ...
LOAD:00007E30 MOV R0, R7
LOAD:00007E34
LOAD:00007E34 loc_7E34 ; CODE XREF: LOAD:00007DC8j
LOAD:00007E34 BL close_0
LOAD:00007E38 MOV R0, #0
LOAD:00007E3C
LOAD:00007E3C loc_7E3C ; CODE XREF: LOAD:00007E2Cj
LOAD:00007E3C LDR R2, [SP,#0x224]
LOAD:00007E40 LDR R3, [R5]
LOAD:00007E44 CMP R2, R3
LOAD:00007E48 BNE loc_7E54
LOAD:00007E4C ADD SP, SP, #0x22C
LOAD:00007E50 LDMFD SP!, {R4-R7,PC};在这个地方下断点,r0=0即可
下面给出一个idapython的动态脚本来实现过反调的功能:
from idaapi import *
from idc import *
so_base = AskAddr(0x77364000,'libjiagu.so base addr') #libjiagu.so base addr
class DumpHook(DBG_Hooks):
def dbg_bpt(self,tid,ea):
global so_base
offset = ea - so_base
#if the offset is the end of anti_debug_find_tracer_pid
if offset == 0x7cfc:
#print 'anti_debug_find_tracer_pid'
SetRegValue(0,"r0")
#if the offset is the end of anti_debug_find_tcp_port_23946
if offset == 0x7e50:
SetRegValue(0,"r0")
#print 'anti_debug_find_tcp_port_23946'
ResumeProcess()
return 0
#hook anti debug
AddBpt(so_base+0x7cfc)
AddBpt(so_base+0x7e50)
print "anti debug...\n"
debug = DumpHook()
debug.hook()
下面是我的轻博客,有兴趣可以关注一下,希望多交流,找到志同道合的朋友。
http://fccload.lofter.com/
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)