silentmj原创文章,转载请保留署名,谢谢:)

一、事情的开始,本部分解释

1)bin文件时如何进入我们程序的

2)bin文件进入程序以后在哪里

一切都开始于ZY_CODE\M2378-CFNS20\Startup.s Line 87

----------------------------------------------------------------------------

        CODE32 
    IF :DEF: LOW                                                         
        AREA    boots,CODE,READONLY                               ;定义boots节
                ENTRY                                                        ;标识程序执行的第一条指令        
      IF :DEF: CRP      
        incbin  ZY_CODE\M2378-CFNS20\BOOT\boot_CRP.bin
      ELSE     
        incbin  ZY_CODE\M2378-CFNS20\BOOT\boot.bin
      ENDIF
    ENDIF      
        AREA    vectors,CODE,READONLY                            ;定义vectors节
begin                                                                         ;标号begin
    IF :DEF: HIGH 
        ENTRY                                                                ;标识程序执行的第一条指令     
        incbin  ZY_CODE\M2378-CFNS20\High\lpc2300.bin
    ELSE
        incbin  ZY_CODE\M2378-CFNS20\Low\lpc2300.bin
    ENDIF

------------------------------------------------------------------------------

从以上可以看出Startup.s的编译结果取决于不同的汇编器设置

DebugInLowAddr模式下ARM Assembler的设置

image 

DebugInHighAddr模式下ARM Assembler的设置

image 

Release模式下ARM Assembler的设置

image

从上面3副图,我们可以看出在Equivalent Command Line定义的伪指令决定了开头的汇编代码如何编译,

下面我们均已DebugInLowAddr模式为例进行分析,由

-keep -PD "LOW SETL {TRUE}" -g -apcs /interwork

可知开头的汇编代码短等于

----------------------------------------------------------------------------

        CODE32 
        AREA    boots,CODE,READONLY                               ;定义boots节
                ENTRY                                                        ;标识程序执行的第一条指令           
incbin  ZY_CODE\M2378-CFNS20\BOOT\boot.bin                ;包含boot.bin

AREA    vectors,CODE,READONLY                                     ;定义vectors节
begin                                                                          ;标号begin

incbin  ZY_CODE\M2378-CFNS20\Low\lpc2300.bin               ;包含lpc2300.bin文件
------------------------------------------------------------------------------

于是我们得到如下关系

在startup.o中

boot.bin---------->boots节

lpc2300.bin------->vector节

这可以从IDA中和scf文件中得到印证:

startup.o的节分布情况

image

最终的axf文件中的节分布情况

image

scf文件内容:

-------------------------------------------------------------------------------
;** File Name:           inchipL.scf
;** Last modified Date:  2004-09-17
;** Last Version:        1.0
;** Descriptions:        Scatter File
;**
;**------------------------------------------------------------------------------------------------------
;** Created By:          Chenmingji
;** Created date:        2004-09-17
;** Version:             1.0
;** Descriptions:        First version
;**
;**------------------------------------------------------------------------------------------------------
;**------------------------------------------------------------------------------------------------------
;** Modified by:        LinEnqiang
;** Modified date:        2007-11-22
;** Version:            1.1
;** Descriptions:       For MiniARM2378
;**
BOOT_LOAD 0x00000000   
{
    BOOT_EXEC 0x00000000
    {
        Startup.o (boots,+First)       
    }
}
ROM_LOAD 0x00002000   
{
    LowAddr 0x00002000
    {
        Startup.o (vectors,+First)
        * (+RO)
    }

    IRAM 0x80000000
    {
        Startup.o (MyStacks)
        * (+RW,+ZI)
    }

    HEAP +0 UNINIT
    {
        Startup.o (Heap)
    }

    STACKS_BOTTOM +0
    {
        Startup.o (StackBottom)
    }

    STACKS 0x80010000 UNINIT
    {
        Startup.o (HeapTop)
        Startup.o (Stacks)
    }
}

-------------------------------------------------------------------------------

二、bin文件中导出函数的定位

图1,IDA中startup.o中ResetInit之前的代码反汇编结果

image

图2,ADS中startup.s中ResetInit之前的代码部分

image

从以上2幅图片我们可以知道lpc2300.bin中的内容确实以代码和数据的方式进入了我们的程序中。那么下面我们要做的就是已知某个函数的名称,得到反汇编后的代码了

我们可以从DebugInLowAddr\a.sym文件得到某函数的入口地址, a.sym文件中的内容看起来类似这个样子

-------------------------------------------------------------

#<SYMDEFS># ARM Linker, ADS1.2 [Build 805]: Last Updated: Wed May 05 12:52:30 2010
0x00000024 D UndefinedAddr
0x0000002c D PrefetchAddr
0x00000030 D DataAbortAddr
0x0000003c D FIQ_Addr
0x00002000 A RunFirst
0x00002040 A OSIntCtxSw
0x00002048 T functionEnter
0x00002058 T GetVersion
0x00002068 T SysInit
0x00002078 T upgradeBegin
0x00002088 T upgradeDataWrite
0x00002098 T upgradeBreak
0x000020a8 T upgradeEnd
0x000020b8 T upgradeBegin2
0x000020c8 T upgradeDataWrite2
0x000020d8 T upgradeBreak2
0x000020e8 T upgradeEnd2
0x000020f8 T crc8Cal
0x00002108 T crc16Cal
0x00002118 T eccCal
0x00002128 T eccDataCorrect
0x00002138 T MD5Init
0x00002148 T MD5Update
0x00002158 T MD5Final
0x00002168 T SHA1Init
0x00002178 T SHA1Update
0x00002188 T SHA1Final

 

……………………………………

-------------------------------------------------------------

下面,我们以其中的htonl这个函数为例来进行分析,首先从

0x000029e8 T htonl

这一行我们可以得知,htonl函数的入口地址应该自29e8处

image

从以上代码片段我们可以知道,真正的函数入口在B872处,前往B872处,由于htonl函数所完成的功能是为我们所熟知的,我们马上可以确定这确实是htonl的一个实现。

image

有兴趣的朋友可以结合IDA,多验证几个函数,呵呵。

三、一点感想:

进一步的分析还表明,这些固件程序中还结合了安全芯片来验证硬件确实为ZLG所生产。结合了软件(通过库文件隐藏源码),硬件(安全芯片)的方法,应该说此种保护方式确实能较好的起到防止抄板者盗用ZLG工程模板的目的。

但由于bin文件中的ARM指令本身并未加密,给定充足的时间,“意志鉴定”的破解者还是能够逆向出bin文件中真正有价值的信息,如网络、文件系统部分的关键算法的。

最后希望这篇文章能对搞ARM开发的朋友们开发自己的源码保护方案起到一定的借鉴作用,谢谢。

posted on 2010-05-05 16:27  silentmj  阅读(953)  评论(0编辑  收藏  举报