MTK 手机BIN文件加密的一点心得

工具:IDA, UltraEdit, ARM250(ARM Project Manager 我专用来编译补丁文件), 打补丁工具(公司编的小工具)
第一次写这种东东,文笔又不好。见笑了。

    MTK手机的Bin文件就是某款手机所对应的一整套原代码编译的目标程序(灼烧文件)。
    在PC机上我们是把系统与应用程序分得很清楚的。但是MTK中则不同,系统与应用程序捆绑在一起的;当然这只对编译出来的系统BIN文件而言的,硬要单独加入应用程序也不是不可以。当然可以,那就要单独‘挂载’。前提是不要过度依赖硬件,如GPIO引脚之类的。
    
    一般来说,当公司搞到MTK源工程文件后就可以修改所需内容,完之后就可以编译产生系统BIN文件,这时公司怕别人盗走成果往往会采用默认的加密方法。而这种加密方法现在很容易就可以破解的(当然针对这种形式破解补丁自己要先写好,以后就是死搬硬套)。所以想说说我现在加密的方法(当然这是从前辈那儿学来的,不是纯摸索的)。
        
    加密效果:被加密的BIN文件只能运行在第一次烧录进的手机上!从手机里读出来的BIN,烧录到另一台手机上,则不开机!
    思    路:第一次烧录时,BIN文件原样读入进手机FLASH中,但要做个标记,用来确认是否本机器!可以把指定的关键代码(关键代码很多,如调用寄存器的代码一般都比较关键)提到补丁中去执行? MTK芯片上都有唯一的一个ID,我们就是用这个ID来加密关键代码的。当手机开机时,ROM先运行我们先前打进行去的一段检测代码补丁,内部密码判是否与标志相符。不符则关机!
    总的来说就是用这个MTK芯片ID在ROM中加密和解密一段关键代码判断是否与标志匹配。被读出来的BIN文件关键代码将是与ID对应的密文!
    
    我加密的过程随便描述一下。
        1:找补丁位置,我找的是 INT_InitRegions 函数里面的 zi_init_32 函数。IDA显示如下:
        
ROM4:00418E94                             EXPORT INT_InitRegions
ROM4:00418E94             INT_InitRegions                         ; CODE XREF: ROM:
ROM4:00418E94 0E 70 A0 E1                 MOV     R7, LR
ROM4:00418E98 10 01 9F E5                 LDR     R0, =0xDC2ECC
ROM4:00418E9C 10 11 9F E5                 LDR     R1, =_32khz_gpio_pin
ROM4:00418EA0 01 20 A0 E1                 MOV     R2, R1
ROM4:00418EA4 0C 41 9F E5                 LDR     R4, =unk_939C
ROM4:00418EA8 04 20 82 E0                 ADD     R2, R2, R4
ROM4:00418EAC 19 00 00 EB                 BL      copy
ROM4:00418EAC
ROM4:00418EB0 04 21 9F E5                 LDR     R2, =unk_264660
ROM4:00418EB4 04 01 9F E5                 LDR     R0, =MPUChannelStatus
ROM4:00418EB8 00 10 A0 E1                 MOV     R1, R0
ROM4:00418EBC 02 10 81 E0                 ADD     R1, R1, R2
ROM4:00418EC0 1E 00 00 EB                 BL      zi_init_32
ROM4:00418EC0
ROM4:00418EC4 F8 20 9F E5                 LDR     R2, =unk_16C6CC
ROM4:00418EC8 F8 00 9F E5                 LDR     R0, =g_applib_mem_ap_pool
ROM4:00418ECC 00 10 A0 E1                 MOV     R1, R0
ROM4:00418ED0 02 10 81 E0                 ADD     R1, R1, R2
ROM4:00418ED4 19 00 00 EB                 BL      zi_init_32
ROM4:00418ED4
ROM4:00418ED8 EC 00 9F E5                 LDR     R0, =x$fpl$trapveneer
ROM4:00418EDC EC 10 9F E5                 LDR     R1, =x$fpl$trapveneer
ROM4:00418EE0 01 20 A0 E1                 MOV     R2, R1
ROM4:00418EE4 E8 40 9F E5                 LDR     R4, =x$fpl$trapveneer
ROM4:00418EE8 04 20 82 E0                 ADD     R2, R2, R4
ROM4:00418EEC 09 00 00 EB                 BL      copy
ROM4:00418EEC
ROM4:00418EF0 E0 20 9F E5                 LDR     R2, =x$fpl$trapveneer
ROM4:00418EF4 E0 00 9F E5                 LDR     R0, =x$fpl$trapveneer
ROM4:00418EF8 00 10 A0 E1                 MOV     R1, R0
ROM4:00418EFC 02 10 81 E0                 ADD     R1, R1, R2
ROM4:00418F00 0E 00 00 EB                 BL      zi_init_32  ;goto patch1 这儿将是我打补丁位置之一,在此把补丁代码引入ROM中进行标志判断
ROM4:00418F00
ROM4:00418F04 17 FF 2F E1                 BX      R7

  注意:上面的代码我是用编译完生成的调试信息文件反汇编而得的。这样才会有真实函数名,全局变量名等的提示信息!
  你真正在目标BIN文件中反汇编时,上面的实名就不复存在了,取代的将是IDA指定的名称。

  2:关键代码:
  把下面代码提取到补丁中加密,一定要变成密文,只有当与ID判断成功时,再转成明文!
ROM:0039DE90 03 49                       LDR     R1, =0xA00088E4
ROM:0039DE92 00 20                       MOV     R0, #0
ROM:0039DE94 08 60                       STR     R0, [R1]
ROM:0039DE96 03 49                       LDR     R1, =0xA00088E8
ROM:0039DE98 08 60                       STR     R0, [R1]
ROM:0039DE9A 03 49                       LDR     R1, =0xA00088EC
ROM:0039DE9C 08 60                       STR     R0, [R1]
ROM:0039DE9E 70 47                       BX      LR

  3:自己写加密补丁(以下只是一小段样码,作为提示):
    
BLAddress       EQU         0x300E40
                       ....   
Memory1         EQU         0xA00088E4
Memory2         EQU         0xA00088E8
Memory3         EQU         0xA00088EC
         AREA      |.JMPATCH_CODE|, CODE
         CODE16
      
        %       BLAddress
        BL      MyPatch
        ..........

        CODE32
MyPatch
        STMFD    SP!, {LR}
        BL       memclear
        LDR      R0, =No_Repaired+1
loc_BL
        BLX      R0
        LDMFD    SP!, {PC}
        ALIGN
        LTORG
        
        CODE16 
PatchStart
        PUSH     {R4,LR}
        LDR      R0, = CodeMemory - (Read_CPU_ID_End - loc_ValidateAdr2)
        LDR      R1, = ValidateAdrDATA
        LDR      R2, = Read_CPU_ID_End - loc_ValidateAdr2
        BL       Move_Code
        MOV      R4, SP
        LDR      R0, = CodeMemory - (Read_CPU_ID_End - loc_ValidateAdr2) - 4
        MOV      SP, R0
        LDR      R0, = CodeMemory - (Read_CPU_ID_End - loc_ValidateAdr2)
        LDR      R1, = Read_CPU_ID_End - loc_ValidateAdr2
        BL       JM_1
        MOV      SP, R4
        LDR      R0, = CodeMemory - (Read_CPU_ID_End - loc_ValidateAdr2) +1
        BLX      R0
        POP      {R4,PC}
        ALIGN
        LTORG
;======================================
loc_ValidateAdr2
        PUSH    {LR}
        LDR     R1, =Memory1
        MOV     R0, #0
        STR     R0, [R1]
        LDR     R1, =Memory2
        STR     R0, [R1]
        LDR     R1, =Memory3
        STR     R0, [R1]
        BL      TruePatch       
        POP     {PC}
        ALIGN
        LTORG
;======================================
TruePatch
        PUSH    {R0-R3,LR}
        SUB     SP, #8
        MOV     R0, SP
        BL      Read_CPU_ID
        LDR     R1, = (ValidateAdr2+(CPU_ID-PatchStart))/4-0x60
        ADD     R1, #0x60
        LSL     R1, #2
        LDR     R2, [R1]
        LDR     R3, [R0]        
        CMP     R2, R3
        BNE     Shutdown
;======================================
Shutdown
        ADD     SP, #8
        MOV     R1, #0
        BLX     R1
        POP     {R0-R3,PC}
        ALIGN
        LTORG
;======================================
Read_CPU_ID
;R0 = Put_ID_Address
        PUSH    {R0-R5,LR}
        MOV     R4, R0
        MOV     R1, #1
        LSL     R1, #31
        MOV     R2, #0xF
        LSL     R2, #12
        ADD     R2, R1
        LDRH    R0, [R2]
        MOV     R3, R1
        LSR     R3, #16
        ORR     R0, R3
        STRH    R0, [R2]       
        MOV     R5, #0x5a
        EOR     R0, R5
        STRH    R0, [R4]
        ADD     R4, #2
        ADD     R1, #8
        LDRH    R0, [R1]
        MOV     R5, #0xa5
        EOR     R0, R5
        STRH    R0, [R4]
        LDRH    R0, [R2]
        BIC     R0, R3
        STRH    R0, [R2]
        POP     {R0-R5,PC}
        ALIGN
        LTORG
;======================================
ClearCode
        LDR     R0, = CodeMemory - (Read_CPU_ID - TruePatch)
        LDR     R1, = 0
        LDR     R2, = ClearCode - TruePatch
        BL      Move_Code_to_RAM_2    
        ADD     SP, #8       
        POP     {R0-R3,PC}
        ALIGN
        LTORG
        
        ...........
        END


  ARM250编译好补丁代码之后,就是用补丁工具打补丁了。
  只能大大概概的说这些了,因为我也只是下小菜鸟!
    只说说我个人的体会与心得,不当之处还请包涵!
    上面所谓的术语“烧录”之类的。在我们这儿一般就直接叫做刷机!呵呵。

    晕,发表时,不会对代码上色,一个个上色太麻烦了,只能这样了!