- 积分
- 813
- 实力分
- 点
- 金钱数
- 两
- 技术分
- 分
- 贡献分
- 分
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
[B]语言包的结构和IDC文件的使用[/B]
作者:coollang
在家里过年的时候收到张斌的Email,问起语言包的结构,那是因为手边没有资料,而且上网很不方便,只能作罢。我是11号才开始上班的,开始一直没有时间,所以积在周末把它发上来。
这里主要说一下语言包的结构,同时还有IDC文件的使用。IDC是IDA支持的一种类C的脚本语言,我以前也没有用过,恰好在国外的网站上发现了几个例子,于是发上来,给大家提供参考。这确实是很实用的一种东西。
西门子的语言包里面可能包含多个语言,而字串是压缩过的,其主要是对高频词组进行了压缩。同时对字串采用索引存储,即建立一个索引表。索引表中存放一个字串组(8个字串)的地址,字串组内部是一个字串链表。通过字串ID可以得到字串所在的字串组在索引表中的位置,然后根据索引找到字串组的地址。在字串组的内部通过顺序的查找链表来找到压缩后的字串。需要注意的是从压缩后的字串解压缩后的得到的并不是真正的字符串(GB或UNICODE),而是Siemens的内部格式的东西,还要作相应的转换才能得到Unicode字串。我写过的Sie2Uni就是作这个用的。西门子的这种存储方式兼顾了效率与空间的平衡,是一种不错的做法。细节如下,更多可参照Siemens Language Editor和Flash程序。
[upload=jpg]UploadFile/200422118592389018.jpg[/upload]
这个例子Lang_unpack_data.idc是一个解包siemens语言包的IDC文件,可以在IDA中生成对应的字串以及在Names window中生成标示(通过内值函数)。具体的语法可以查看IDA的帮助中IDC部分,熟悉C的应该没什么难度。而且可以很容易的转换为C程序。此程序我已经作了相当多的注释,应该很容易看懂。其实这个程序的算法就是Flash中的对应部分,我会把它一并附上。程序如下(抱歉,对应网站是非英语论坛,我不能得到作者,但是类似的程序我早已独立实现过):
使用方法是在IDA的File->IDC File(或F2),加载相应的IDC文件
- #include <idc.idc>
- //请根据需要除去对应的注释,其他未列出的可以通过在FuBu中查找Hex格式Byte
- //“BBBB0000“,这是语言包的标志,需要注意的是这里的地址是对应16M空间的地址,
- //请自行调整。
- #define LGP_BASE 0xE6C000 //6688
- //#define LGP_BASE 0xB00000 //x618
- //#define LGP_BASE 0x7A0000 //M55c
- //#define LGP_BASE 0xE00000 //S57c
- //解压缩函数,lang->语言ID,ea->字串开始地址 字串的存储格式为BYTE(字串长度,字串内容。。。)
- static unpack(lang,ea){
- auto lgp_ea,lgp_ea2,uni,o_lginfo,len,pos,s,blen,c,dec,ea1;
- lgp_ea=LGP_BASE;
-
- o_lginfo=Word(lgp_ea+0xA); //语言Info表Offset
-
- len=Byte(ea); //取得字串长度(并不是真实的长度,而是压缩后的长度)
-
- //以下几行是在IDA中处理对应BYTE的格式
- for (pos=ea;pos<ea+len;pos++)MakeUnkn(pos,1);
- if(len<=4)
- MakeArray(ea,len);
- else{
- MakeArray(ea,4);
- MakeArray(ea+4,len-4);
- }
-
- lgp_ea=LGP_BASE+o_lginfo; //语言Info表的Base地址
- lgp_ea2=lgp_ea+14*lang; //对应语言的的Info表地址,每个Info表的大小是14个Byte
-
- //解压缩字串
- s="";uni=0; //s为最终字串
- for(pos=1;pos<len;pos++){
- c=Byte(ea+pos); //取得压缩后的Byte
- blen=0; //压缩前的Byte长度
- dec=0;
- while(c>=Word(lgp_ea2+2+blen*4)){ //取得压缩后Byte所对应的压缩表中的信息
- dec=Word(lgp_ea2+2+blen*4); //取得压缩表中的对应地址。压缩过程一般最多压缩4字符。压缩表分别是
- //四字符压缩表,三字符压缩表,二、一字符压缩表
- blen++;
- if(blen==4) break;
- }
-
- ea1=LGP_BASE+Word(lgp_ea2+4*blen)+(c-dec)*(blen+1); //取得压缩Byte所对应的解压缩后的字符(1到4个字符)地址
- //以下输出压缩Byte所对应的解压缩后字符,并对特殊字符作相应的转换
- do{
- c=Byte(ea1);
- if((c>=0x20 && c<0x80 && uni==0) || (c>0x10 && c<0x80 && uni>0)){
- if (c+uni<0x1B0)
- s=s+form("%c",c+uni);
- else
- s=s+form("%c",c+uni+0x30);
- } else {
- s=s+form("<%02X>",c); //先用<>输出特殊字符的BYTE值
- //以下或者是一些前导字符或者是特殊字符,需要作相应的转换
- if (c==0x9B) uni=0x170;
- if (c==0x96) uni=0x80;
- if (c==0x97) uni=0x100;
- if (c==0x95 || c==0x91) uni=0x0;
- if (c==0x8a || c==0x0d) s=s+"\n";
- }
- ea1++;
- blen--;
- } while(blen>=0);
- }
-
- MakeRptCmt(ea,s); //在标示名字的地址出输出对应的字符
- if (lang>0) MakeName(ea,""); //非英语语言输出空(可能考虑到Unicode字符问题)
- }
- //在字串组内查找次序为n的字串的地址
- static shift(ea,n){
- while(n--){
- ea=ea+Byte(ea);
- }
- return ea;
- }
- static main(void){
- auto nLangs,lang_id,lll,ref,ea1,ceil,mnem,op1,op2,msg_id,idx1,idx2,ea2,eap,i,sadd,npara,o_msgidx,mea,v,max_id;
- npara =Word(LGP_BASE+6); //语言包的Page数量(C166不能跨Page边界)
- o_msgidx=Word(LGP_BASE+0x12); //字串组索引表的Offset,字串索引表以Word为单位,存储字串组的Page内Offset。
- max_id=Word(LGP_BASE+0x2a); //最大字串ID
- nLangs=Word(LGP_BASE+0xE); //语言数量(英文、简体中文…)
-
-
- for (msg_id=0;msg_id<=max_id;msg_id++){
- for (lang_id=0;lang_id<nLangs;lang_id++){
- eap=LGP_BASE+0x3c; //ID范围->Page表
- sadd=0; //Page
- for(i=1;i<npara;i++){ //查找字串的所在Page
- if((msg_id*nLangs+lang_id)<Word(eap)) break;
- eap=eap+2;
- sadd++;
- }
-
- v=(msg_id*nLangs+lang_id)/8; //字串组索引表的ID,每8个一组。每组内用链表存储
- idx2=(msg_id*nLangs+lang_id)%8; //组内次序
- mea=Word(LGP_BASE+o_msgidx+v*2)+LGP_BASE+sadd*0x4000; //计算字串内容开始地址,基地址+Page地址+OffsetInPage,
- //最后一项是从字串组索引表中查询得到
- mea=shift(mea,idx2); //找到对应字串的地址
- unpack(lang_id,mea); //解压缩相应字串。因为语言包对字符进行了压缩,对高频词组进行了压缩。
- if (lang_id==0)
- //如果需要10进制的ID,可以在下面修改。
- if(!MakeName(mea,form("Lgp_str_%03X",msg_id)))return; //如果是英文(默认是语言0),则输出Name。
- Jump(mea);
- }
- }
- }
复制代码
- //在6688Flash中的实现
- 0xE0:3EFA ; ★★★★★★★★ S U B R O U T I N E ★★★★★★★★★★★★★★★★★★★
- 0xE0:3EFA GetStringByID: ; CODE XREF: 0xC7:88B6P
- 0xE0:3EFA ; sub_E1FCE8+30P
- 0xE0:3EFA push r6
- 0xE0:3EFC mov r6, #0FE04h
- 0xE0:3F00 extp #37h, #1 ; '7'
- 0xE0:3F04 mov r10, word_DCEF2 ; R10 -> Cur LgInfo Table
- 0xE0:3F08 extp #37h, #1 ; '7'
- 0xE0:3F0C mov r2, word_DCEF8 ; R2 -> CurrentLgID
- 0xE0:3F10 scxt DPP0, #39Bh
- 0xE0:3F14 ; assume dpp0: 39Bh (page 0xE6C000)
- 0xE0:3F14 push DPP2
- 0xE0:3F16 mov r1, #0Eh ; Language Count
- 0xE0:3F18 mov r3, [r1]
- 0xE0:3F1A mulu r12, r3
- 0xE0:3F1C mov r12, MDL
- 0xE0:3F20 add r12, r2
- 0xE0:3F22 or r13, #8000h
- 0xE0:3F26 mov r15, #39Bh
- 0xE0:3F2A mov r1, #6 ; Paragraphs Count
- 0xE0:3F2C mov r2, [r1]
- 0xE0:3F2E sub r2, #1
- 0xE0:3F30 mov r3, #3Ch ; '<' ; Current paragraphs
- 0xE0:3F34 loc_E03F34: ; CODE XREF: GetStringByID+48j
- 0xE0:3F34 mov r5, [r3] ; 找到对应的段
- 0xE0:3F36 cmpd1 r2, #0
- 0xE0:3F38 jmpr cc_Z, loc_E03F44
- 0xE0:3F3A cmp r12, r5 ; R12 -> ID*LgCount + LgID
- 0xE0:3F3C jmpr cc_C, loc_E03F44
- 0xE0:3F3E add r15, #1 ; R15 -> Current Page
- 0xE0:3F40 add r3, #2
- 0xE0:3F42 jmpr cc_UC, loc_E03F34 ; 找到对应的段
- 0xE0:3F44 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
- 0xE0:3F44 loc_E03F44: ; CODE XREF: GetStringByID+3Ej
- 0xE0:3F44 ; GetStringByID+42j
- 0xE0:3F44 mov [r6], r15
- 0xE0:3F46 mov r1, r12
- 0xE0:3F48 shr r1, #3
- 0xE0:3F4A shl r1, #1
- 0xE0:3F4C mov r2, #12h ; Offset of All MsgID Offset
- 0xE0:3F50 add r1, [r2]
- 0xE0:3F52 mov r4, [r1]
- 0xE0:3F54 or r4, #8000h
- 0xE0:3F58 mov r5, r12
- 0xE0:3F5A and r5, #7
- 0xE0:3F5C jmpr cc_UC, loc_E03F64
- 0xE0:3F5E ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
- 0xE0:3F5E loc_E03F5E: ; CODE XREF: GetStringByID+6Cj
- 0xE0:3F5E movb rl1, [r4] ; 遍历链表,查找String位置
- 0xE0:3F60 movbz r1, rl1
- 0xE0:3F62 add r4, r1
- 0xE0:3F64 loc_E03F64: ; CODE XREF: GetStringByID+62j
- 0xE0:3F64 cmpd1 r5, #0
- 0xE0:3F66 jmpr cc_NZ, loc_E03F5E ; 遍历链表,查找String位置
- 0xE0:3F68 movb rl3, [r4+] ; RL3 -> Length,FirstByte
- 0xE0:3F6A mov r11, [r10] ; R11 -> InfoTable
- 0xE0:3F6C calls 0E0h, UnpackLngString
- 0xE0:3F70 mov [r6], r14
- 0xE0:3F72 nop
- 0xE0:3F74 movb [r13], word_FF1C
- 0xE0:3F78 pop DPP2
- 0xE0:3F7A pop DPP0
- 0xE0:3F7C ; assume dpp0: 0FFFFh (page 0x3FFFC000)
- 0xE0:3F7C pop r6
- 0xE0:3F7E rets
- 0xE0:3F80 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
- 0xE0:3F80 loc_E03F80: ; CODE XREF: UnpackLngString+4j
- 0xE0:3F80 movb rl2, [r4+]
- 0xE0:3F82 movbz r2, rl2
- 0xE0:3F84 mov [r6], r14
- 0xE0:3F86 mov r1, [r10+2]
- 0xE0:3F8A cmp r2, r1
- 0xE0:3F8C jmpr cc_NC, loc_E03F94
- 0xE0:3F8E mov r5, r11
- 0xE0:3F90 add r5, r2
- 0xE0:3F92 jmpr cc_UC, loc_E03FE8
- 0xE0:3F94 ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
- 0xE0:3F94 loc_E03F94: ; CODE XREF: 0xE0:3F8Cj
- 0xE0:3F94 mov r1, [r10+6]
- 0xE0:3F98 cmp r2, r1
- 0xE0:3F9A jmpr cc_NC, loc_E03FAE
- 0xE0:3F9C mov r5, r2
- 0xE0:3F9E mov r1, [r10+2]
- 0xE0:3FA2 sub r5, r1
- 0xE0:3FA4 shl r5, #1
- 0xE0:3FA6 mov r1, [r10+4]
- 0xE0:3FAA add r5, r1
- 0xE0:3FAC jmpr cc_UC, loc_E03FE4
- 0xE0:3FAE ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
- 0xE0:3FAE loc_E03FAE: ; CODE XREF: 0xE0:3F9Aj
- 0xE0:3FAE mov r1, [r10+0Ah]
- 0xE0:3FB2 cmp r2, r1
- 0xE0:3FB4 jmpr cc_NC, loc_E03FCC
- 0xE0:3FB6 mov r5, r2
- 0xE0:3FB8 mov r1, [r10+6]
- 0xE0:3FBC sub r5, r1
- 0xE0:3FBE mov r1, r5
- 0xE0:3FC0 shl r5, #1
- 0xE0:3FC2 add r5, r1
- 0xE0:3FC4 mov r1, [r10+8]
- 0xE0:3FC8 add r5, r1
- 0xE0:3FCA jmpr cc_UC, loc_E03FE0
- 0xE0:3FCC ; ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
- 0xE0:3FCC loc_E03FCC: ; CODE XREF: 0xE0:3FB4j
- 0xE0:3FCC mov r5, r2
- 0xE0:3FCE mov r1, [r10+0Ah]
- 0xE0:3FD2 sub r5, r1
- 0xE0:3FD4 shl r5, #2
- 0xE0:3FD6 mov r1, [r10+0Ch]
- 0xE0:3FDA add r5, r1
- 0xE0:3FDC movb [r13+], [r5]
- 0xE0:3FDE add r5, #1
- 0xE0:3FE0 loc_E03FE0: ; CODE XREF: 0xE0:3FCAj
- 0xE0:3FE0 movb [r13+], [r5]
- 0xE0:3FE2 add r5, #1
- 0xE0:3FE4 loc_E03FE4: ; CODE XREF: 0xE0:3FACj
- 0xE0:3FE4 movb [r13+], [r5]
- 0xE0:3FE6 add r5, #1
- 0xE0:3FE8 loc_E03FE8: ; CODE XREF: 0xE0:3F92j
- 0xE0:3FE8 movb [r13+], [r5]
- 0xE0:3FEA ; ★★★★★★★★ S U B R O U T I N E ★★★★★★★★★★★★★★★★★★★
- 0xE0:3FEA UnpackLngString: ; CODE XREF: GetStringByID+72P
- 0xE0:3FEA mov [r6], r15
- 0xE0:3FEC subb rl3, #1
- 0xE0:3FEE jmpr cc_NZ, loc_E03F80
- 0xE0:3FF0 rets
- 0xE0:3FF0 ; End of function UnpackLngString
复制代码
附件:
Lang_unpack_data.idc[upload=rar]viewfile.asp?ID=9889[/upload]
[此贴子已经被作者于2004-2-21 19:00:18编辑过] |
|