- 积分
- 813
- 实力分
- 点
- 金钱数
- 两
- 技术分
- 分
- 贡献分
- 分
|
楼主 |
发表于 2005-8-9 00:01:00
|
显示全部楼层
三、常见工具的基本用法。
1、IDA。
如果你想要进行Flash的修改,那么一个FullFlash的全文件汇编是必不可少的,更进一步,你需要有55和56的全文件汇编来进行对照。首先是处理一下Flash文件。因为Flash被映射到0xA00000,所以应该在前面填充上10M的空间,这样在反汇编后可以直接双击函数调用来跳转到相应的函数位置。填充可以用UltraEdit的Hex Insert/Delete。之后用IDA打开这个16M的文件进行反汇编。汇编后如果不打包大约有124M。这个步骤需要的时间较长,完成后你会发现很多的代码段没能识别,被表示为数据段。你需要强制反汇编。可以选中0xA00000-0x1000000的部分,然后点击Code,或按C,在弹出的对话框中选择Force,而不是Analyze,然后是等待。完成后数据段已经不正确了,以后需要你手动得来识别代码(按C)或数据(按D)。在程序中,你可以用N来为一个函数重命名,用Alt+M标注一个位置,用;来增加注释。更详细的用法需要你使用中来摸索了。
2、ADIS16X
这个主要用来汇编小的程序段,因为它是别的地址空间只有一个页。所以在程序中的段间跳转和调用不能被识别。他可以用F1打开Bin文件或He文件进行汇编,其他的如obj和IEEE的格式我不熟悉,并可以选择打开文件的偏移地址。打开后用F4来反汇编,F5打开HEX格式编辑。用F4打开反汇编界面时可以直接在里面修改指令,并可以把反汇编的结果按F10保存为文本文件。
3、Fmenu
它的用法RizaPN有说明,他可以由相邻两个菜单项的字串ID来查找同级下的所有菜单项。首先需要语言文件,如下
;
; Language data
;
.....
String 348, "Callsmissed"
String 349, "Calls missed"
String 350, "C.missed"
String 351, "Job is completed!"
String 352, "Alarmsmissed"
String 353, "Alarms missed"
String 354, "The stock market is going up."
......
其中表示不能显示的字符,比如是回车。前面的就是10进制的字串ID,系统中读取这些字串就是通过字串ID(有点像Windows的资源ID)。
fmenu的格式是:fmenu FileName MenuItem_1_StringID,MenuItem_2_StringID
这里面MenuItem_1_StringID必须是16进制的。比如fmenu v55.bin 246,312 (分别是商务助理和上网与娱乐),显示如下:
Found index at address 36460E
- menu items address : D6443E
- subroutine address : D64368
- number of item : 12 (decimal)
1. 03A8 0359 13B7 13B6 0000 0000 0000 0003 0545 => D64368: Goto_D64656
2. 03A8 0359 13BB 13BA 0000 0000 0000 0003 0545 => D6436C: Goto_D6465A
3. 03C4 0359 0246 0245 0000 0000 0000 0003 053A => D64370: Goto_D6468E
4. 03B6 0359 0312 0311 0000 0000 0000 0003 053A => D64374: Goto_D6469E
5. 03D2 0359 021B 0218 0000 0000 0000 0003 053B => D64378: Goto_D6465E
6. 03E2 0359 029A 0299 0000 0000 0000 0003 053C => D6437C: Goto_D6466E
7. 03F2 0359 0294 0292 0000 0000 0000 0003 053D => D64380: Goto_D646AE
8. 0400 0359 008C 008A 0000 0000 0000 0003 0064 => D64384: Goto_D646BE
9. 0410 0359 0385 0383 0000 0000 0000 0003 0258 => D64388: Goto_D646CE
10. 041E 0359 0353 0352 0000 0000 0000 0003 012C => D6438C: Goto_D646DE
11. 042C 0359 014C 0148 0000 0000 0000 0003 03E8 => D64390: Goto_D6467E
12. 0398 0359 0342 0341 0000 0000 0000 0003 053A => D64394: Goto_F4BE32
共有12个菜单项,是住菜单的所有字串和入口地址。其中前面的两个字是主菜单前面动画的图片ID的地址,后面是普通模式下和大字符格式下的字串。最后的一个字一些状态相关的,我不是很清楚。最后Goto给出的是入口地址。
4、fbytes
用法如下:fbytes FileName x1,x2,x3,,x4,,,
待查找的字节以“,”隔开,如果不确定的字节可以为空。比如查找mov,Rx,#1234。Rx表示你不知存入那个寄存器。你可以用如下的语法查找:fbytes v55.bin E6,,34,12
四、一个简单的例子
我们先以一个简单的例子开始,说一下修改的思路和方法,那么就以增加背景灯图标为例。
首先我们要得到处理待机图标的函数,这个函数的地址是0x3637C8。我们简单的看一下这个函数:
seg214:37C8 Idle_Icon_Switch:
seg214:37C8 mov [-r0], r9 //保存旧址
seg214:37CA mov [-r0], r8
seg214:37CC sub r0, #0Ch //处理栈顶指针
seg214:37D0 calls 0DCh, Signal_Icon_Switch //DCF788,处理信号的函数,得到信号量,并处理返回值(对应图标ID)
seg214:37D4 mov r12, r4 //判断返回值
seg214:37D6 cmp r12, #0FFFFh //如果为-1,则如下处理
seg214:37DA jmpr cc_NZ, loc_D637F2 //否则,显示信号
seg214:37DC mov r8, #0
seg214:37DE mov [-r0], r8
seg214:37E0 mov r12, r8
seg214:37E2 mov r13, r8
seg214:37E4 mov r14, #1Fh
seg214:37E8 mov r15, #7
seg214:37EA calls 0B3h, sub_B3BB1C
seg214:37EE add r0, #2
seg214:37F0 jmpr cc_UC, loc_D637FE
seg214:37F2
seg214:37F2 loc_D637F2:
seg214:37F2 mov r8, r12
seg214:37F4 mov r12, #0 //x=0
seg214:37F6 mov r13, #0 //y=0
seg214:37F8 mov r14, r8
seg214:37FA calls 0B3h, DrawImageByIndex //B3DF04
seg214:37FE
seg214:37FE loc_D637FE:
seg214:37FE mov r8, #0
seg214:3800 mov r9, #0FFFFh
seg214:3804 mov [r0], r9
seg214:3806 mov r12, #1
seg214:3808 calls 0A2h, sub_A2F456 //判断状态量
seg214:380C cmp r4, #5
seg214:380E jmpr cc_NZ, loc_D63818 //如果不等于5则跳到下一个判断,否则Draw图标345:GPS
seg214:3810 mov r8, #158h //存与R8
seg214:3814 mov [r0], r8 //压栈
seg214:3816 mov r8, #1 //图标数量
........
seg214:3830 loc_D63830:
seg214:3830 mov r12, #1
seg214:3832 calls 0C4h, sub_C4B9BA //判断状态量
seg214:3836 cmp r4, #0 //如为TRUE
seg214:3838 jmpr cc_Z, loc_D63848
seg214:383A
seg214:383A loc_D6383A:
seg214:383A mov r9, #15Bh
seg214:383E mov r12, r8
seg214:3840 shl r12, #1 //将栈顶指针加2赋予R12
seg214:3842 add r12, r0 //
seg214:3844 mov [r12], r9 //压栈
seg214:3846 add r8, #1 //图标数量加1
.........
//开始显示图标
seg214:39D4 mov r9, #0
seg214:39D6 mov [-r0], r9
seg214:39D8 mov r12, #1Fh
seg214:39DC mov r13, r9
seg214:39DE mov r14, #2Ch ; ','
seg214:39E2 mov r15, #7
seg214:39E4 calls 0B3h, sub_B3BB1C
seg214:39E8 add r0, #2
seg214:39EA cmp r8, #0 //比较图标数量
seg214:39EC jmpa cc_Z, loc_D63AEE
seg214:39F0 cmp r8, #1 //如为1,则直接显示
seg214:39F2 jmpr cc_NZ, loc_D63A04
seg214:39F4 mov r12, #2Ah ; //位置x=2A
seg214:39F8 mov r13, #0 //y=0
seg214:39FA mov r14, [r0] //出栈
seg214:39FC calls 0B3h, DrawImageByIndex //Draw对应图标
seg214:3A00 jmpa cc_UC, loc_D63AEE
seg214:3A04
seg214:3A04 loc_D63A04:
seg214:3A04 cmp r8, #2 //如果图标数量为2的处理,
seg214:3A06 jmpr cc_Z, loc_D63A2E //如果图标数量多于两个,则会处理,使之交替显示。
seg214:3A08 mov r12, #3FBAh
seg214:3A0C mov r13, #372h
seg214:3A10 add r12, r8
seg214:3A12 extp r13, #1
seg214:3A14 movb rl1, [r12]
seg214:3A16 movbz r9, rl1
seg214:3A18 extp #36h, #1 ; '6'
seg214:3A1C mov r14, word_DBF1C
seg214:3A20 mov word_FE0E, r14
seg214:3A24 divu r9
seg214:3A26 mov r14, word_FE0C
seg214:3A2A cmp r14, #2
seg214:3A2C jmpr cc_NC, loc_D63A4C
..........
seg214:3B68 loc_D63B68:
seg214:3B68 add r0, #0Ch //返回,调整栈顶指针
seg214:3B6C mov r8, [r0+] //恢复R8,R9
seg214:3B6E mov r9, [r0+]
seg214:3B70 rets
这个函数很长,我已经略过一些,放上了一些主要的部分。这里先看一下重要的函数B3DF04 ,DrawImageByIndex(x:R12,y:R13,ImageID:R14)。大家如果看到的修改较多的话,会发现他的重要性。比较漂亮的功能都是通过它来实现的。它的功能是在指定的坐标处Draw一个固有图片。而图标处理程序就是通过对状态量的判断,来决定Draw那些图标上去。开始部分是把使用到的寄存器压栈。R8,R9经常被作为通用寄存器使用。上面我注释了一部分程序,大家可以自己理解一下。我们的做法就是用一个图标替换不使用的GPS图标(反正我是没见过)。要做到这一点,我们需要把状态量的判断函数改为对背景灯的判断函数,就是seg214:3808这个位置。现在我们就去找背景灯的状态函数GetLightStat。
如何入手呢,我们知道在菜单项里可以开关背景灯的选项,那我们就用fmenu从那入手。在setup->Device->Display下面,iLLumination和Big Letters的ID分别是BF和1AC,可以找到如下:
Found index at address 3775D2
- menu items address : D7752E
- subroutine address : D7759A
- number of item : 6 (decimal)
1. 39C2 0399 00BF 00C0 0000 39AE 0399 0003 03F7 => D7759A: Goto_D77384
2. 39C2 0399 01AC 01AD 0000 39AA 0399 0003 053A => D7759E: Goto_D77394
3. 39C2 0399 0400 0401 0000 39AA 0399 0003 03F3 => D775A2: Goto_D773A8
4. 39C2 0399 0402 0403 0000 39A6 0399 0003 053A => D775A6: Goto_D773A4
5. 39C2 0399 0404 0405 0000 39A6 0399 0003 053A => D775AA: Goto_D773B8
6. 39D2 0399 01B0 0341 0000 39A6 0399 0003 0542 => D775AE: Goto_F4BE32
背景灯对应的函数入口为D77384,我们到377384这个位置看一下。
seg215:7384 mov [-r0], r12
seg215:7386 mov [-r0], r13
seg215:7388 calls 0D7h, sub_D7765C
seg215:738C mov r13, [r0+]
seg215:738E mov r12, [r0+]
seg215:7390 jmps 0E5h, sub_E5D6AA
看到每个功能最后都会跳转到 sub_E5D6AA,所以可能是菜单的处理,而前面的一个Calls应该是我们需要的。进去看看,双击,如下:
seg215:765C sub_D7765C:
seg215:765C mov [-r0], r8
seg215:765E mov r8, #0Ah
seg215:7660 calls 0B4h, j_Get_LightStat //一个判断
seg215:7664 cmp r4, #0
seg215:7666 jmpr cc_Z, loc_D7766A
seg215:7668 mov r8, #9
seg215:766A
seg215:766A loc_D7766A:
seg215:766A calls 0D9h, sub_D9EBA0 //另一个判断,常返回真,可以忽略。
seg215:766E cmp r4, #0
seg215:7670 jmpr cc_Z, loc_D77684 //跳转失效。
seg215:7672 cmp r8, #9
seg215:7676 jmpr cc_NZ, loc_D7767E
seg215:7678 calls 0B4h, sub_B4D888
seg215:767C jmpr cc_UC, loc_D776A4
seg215:767E
seg215:767E loc_D7767E:
seg215:767E calls 0B4h, sub_B4D880
seg215:7682 jmpr cc_UC, loc_D776A4
seg215:7684
seg215:7684 loc_D77684:
seg215:7684 mov [-r0], r8
seg215:7686 mov r12, #35F0h
seg215:768A mov r13, #35Dh
seg215:768E mov [-r0], r13
seg215:7690 mov [-r0], r12
seg215:7692 mov r12, #35F4h
seg215:7696 mov r13, #35Dh
seg215:769A mov r14, #0
seg215:769C mov r15, #0
seg215:769E calls 0DDh, sub_DD98E2
seg215:76A2 add r0, #6
seg215:76A4
seg215:76A4 loc_D776A4:
seg215:76A4
seg215:76A4 mov r8, [r0+]
seg215:76A6 rets
我们可以看到在7660有一个状态判断,而766A也有一个,进入到766A看看,发现是一个空函数,类似于{return TRUE;}
seg217:EBA0 sub_D9EBA0:
seg217:EBA0 mov r4, #1
seg217:EBA2 rets
这样可以去掉这些,简化为。
seg215:7660 calls 0B4h, j_Get_LightStat //一个判断
seg215:7664 cmp r4, #0
seg215:7666 jmpr cc_Z, StatFalse
StatTrue
seg215:7678 calls 0B4h, sub_B4D888
seg215:767C jmpr cc_UC, loc_D776A4
seg215:767E
seg215:767E StatFalse:
seg215:767E calls 0B4h, sub_B4D880
seg215:7682 jmpr cc_UC, Other_Fun
Other_Fun
这样可以看出,7660处应该是我们需要的状态判断函数,双击后发现是一个跳转,再次双击进入如下函数:
seg217:EB4E Get_LightStat:
seg217:EB4E mov DPP0, #36h ; '6'
seg217:EB52 nop
seg217:EB54 movb rl1, byte_D8ED1 //offset:ED1
seg217:EB58 jnb r1.2, loc_D9EB60
seg217:EB5C mov r4, #1
seg217:EB5E jmpr cc_UC, loc_D9EB62
seg217:EB60
seg217:EB60 loc_D9EB60:
seg217:EB60 mov r4, #0
seg217:EB62
seg217:EB62 loc_D9EB62:
seg217:EB62 rets
至此,我们认为这就是我们需要的Get_LightStat函数,他是对D8ED1的bit2进行判断.我们就用AT+CGSN:36,ED1察看一下,返回结果是:
取消选项:
F:\sinmens\tools>siemtest /36,ed1
AT+CGSN:36,ed1
+CGSN: DD
FB 9F FB FF FE 53 69 65 6D 65 6E 73 20 36 36 38
选中选项:
+CGSN: DD
FF 9F FB FF FE 53 69 65 6D 65 6E 73 20 36 36 38
这就证明了我们的猜测.得到GetLightStat的地址为D9EB4E.
接着我们可以改写我们的Patch,修改如下位置:
seg214:3808 calls 0A2h, sub_A2F456 ->calls D9,EB4E :DAD94EEB
seg214:380C cmp r4, #5 ->cmp R4,#1 :4841
seg214:380E jmpr cc_NZ, loc_D63818
这样这个补丁就完成了,是不是很简单。当然,这是在知道了图标处理函数的前提下。接下来,我会讲一个复杂的程序
[此贴子已经被作者于2003-11-22 17:41:42编辑过]
|
|