coollang 发表于 2005-8-10 00:00:00

【专题文章】语言包的结构和IDC文件的使用

语言包的结构和IDC文件的使用
作者:coollang

在家里过年的时候收到张斌的Email,问起语言包的结构,那是因为手边没有资料,而且上网很不方便,只能作罢。我是11号才开始上班的,开始一直没有时间,所以积在周末把它发上来。

这里主要说一下语言包的结构,同时还有IDC文件的使用。IDC是IDA支持的一种类C的脚本语言,我以前也没有用过,恰好在国外的网站上发现了几个例子,于是发上来,给大家提供参考。这确实是很实用的一种东西。

西门子的语言包里面可能包含多个语言,而字串是压缩过的,其主要是对高频词组进行了压缩。同时对字串采用索引存储,即建立一个索引表。索引表中存放一个字串组(8个字串)的地址,字串组内部是一个字串链表。通过字串ID可以得到字串所在的字串组在索引表中的位置,然后根据索引找到字串组的地址。在字串组的内部通过顺序的查找链表来找到压缩后的字串。需要注意的是从压缩后的字串解压缩后的得到的并不是真正的字符串(GB或UNICODE),而是Siemens的内部格式的东西,还要作相应的转换才能得到Unicode字串。我写过的Sie2Uni就是作这个用的。西门子的这种存储方式兼顾了效率与空间的平衡,是一种不错的做法。细节如下,更多可参照Siemens Language Editor和Flash程序。
UploadFile/200422118592389018.jpg

这个例子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,
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,
0xE0:3F2E               sub   r2, #1
0xE0:3F30               mov   r3, #3Ch ; '<' ; Current paragraphs
0xE0:3F34 loc_E03F34:                           ; CODE XREF: GetStringByID+48j
0xE0:3F34               mov   r5,       ; 找到对应的段
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   , 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,
0xE0:3F52               mov   r4,
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,    ; 遍历链表,查找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,     ; RL3 -> Length,FirstByte
0xE0:3F6A               mov   r11,     ; R11 -> InfoTable
0xE0:3F6C               calls   0E0h, UnpackLngString
0xE0:3F70               mov   , r14
0xE0:3F72               nop
0xE0:3F74               movb    , 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,
0xE0:3F82               movbz   r2, rl2
0xE0:3F84               mov   , r14
0xE0:3F86               mov   r1,
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,
0xE0:3F98               cmp   r2, r1
0xE0:3F9A               jmpr    cc_NC, loc_E03FAE
0xE0:3F9C               mov   r5, r2
0xE0:3F9E               mov   r1,
0xE0:3FA2               sub   r5, r1
0xE0:3FA4               shl   r5, #1
0xE0:3FA6               mov   r1,
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,
0xE0:3FB2               cmp   r2, r1
0xE0:3FB4               jmpr    cc_NC, loc_E03FCC
0xE0:3FB6               mov   r5, r2
0xE0:3FB8               mov   r1,
0xE0:3FBC               sub   r5, r1
0xE0:3FBE               mov   r1, r5
0xE0:3FC0               shl   r5, #1
0xE0:3FC2               add   r5, r1
0xE0:3FC4               mov   r1,
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,
0xE0:3FD2               sub   r5, r1
0xE0:3FD4               shl   r5, #2
0xE0:3FD6               mov   r1,
0xE0:3FDA               add   r5, r1
0xE0:3FDC               movb    ,
0xE0:3FDE               add   r5, #1
0xE0:3FE0 loc_E03FE0:                           ; CODE XREF: 0xE0:3FCAj
0xE0:3FE0               movb    ,
0xE0:3FE2               add   r5, #1
0xE0:3FE4 loc_E03FE4:                           ; CODE XREF: 0xE0:3FACj
0xE0:3FE4               movb    ,
0xE0:3FE6               add   r5, #1
0xE0:3FE8 loc_E03FE8:                           ; CODE XREF: 0xE0:3F92j
0xE0:3FE8               movb    ,
0xE0:3FEA ; ★★★★★★★★ S U B R O U T I N E★★★★★★★★★★★★★★★★★★★
0xE0:3FEA UnpackLngString:                      ; CODE XREF: GetStringByID+72P
0xE0:3FEA               mov   , 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.idcviewfile.asp?ID=9889













[此贴子已经被作者于2004-2-21 19:00:18编辑过]

信步蓝桥 发表于 2005-8-10 00:01:00

大家风范!!!!!!
老大,就是老大!!!!!!!!!!!!!!!!!111

RainMoon 发表于 2005-8-10 00:03:00

签到,慢慢研究

wildgoose 发表于 2005-8-10 00:04:00

收下先

KoncaCN 发表于 2005-8-10 00:05:00

签到。

wdjjjin 发表于 2005-8-10 00:06:00

不愧大师!
很怀念SL456688i,他现在还好吗?

nonlyli 发表于 2005-8-10 00:07:00

触角越来越广了,小8事业发展中……

风无痕 发表于 2005-8-10 00:08:00

收到,我也要慢慢研究!!!

Eternity 发表于 2005-8-10 00:09:00


收到
多谢狼大

xxyu 发表于 2005-8-10 00:11:00

狼大就是狼大!!

lintengxue 发表于 2006-3-29 22:46:55

厉害

!!!!!!!!!!!!!!!!!

买醉生 发表于 2007-4-2 09:21:53

狼大的帖子那是必定要顶的!!!!!!!!!!!!!!!!!
页: [1]
查看完整版本: 【专题文章】语言包的结构和IDC文件的使用