[C] 使用pcaplib的pacp_next_ex()针对TCAP开发时要注意的数组越界问题

在使用pcaplib 做针对7号信令 TCAP层开发的时候,针对Indefinite form容易发生一个数组越界的隐性问题的一个说明。


前一段时间出了一个Release 失败的问题,让客户大为光火,上线失败的确是是非常让人难堪的问题。

在这里把教训记下来,也希望看到的兄弟不要重蹈我的覆辙。


一片分析文章,因为没有代码可能比较生涩,希望能帮助到有用的人。


参考文档  : 

[1] Q.773 : Transaction capabilities formats and encoding  ——ITU (International Telecommunication Union) 


1. 项目背景

我们的项目是是针对核心网的7号信令的离线pcap文件进行解析,然后进行通讯统计的功能模块。

这个功能模块以前就有,但是以前的系统没有针对TCAP协议的 Indefinite form进行处理。

我们这次的开发就是针对

※TCAP是 7号信令协议栈中的Transcation Control Application Part 也就是控制事务的协议层。


2.技术背景

在这里针对 TCAP 协议里的BER编码做一个说明。

[C] 使用pcaplib的pacp_next_ex()针对TCAP开发时要注意的数组越界问题

                                                图 1  TCAP层消息构成


我们可以看到这里面 基本上都是以 xxxTag, xxx Length, Data 三部分 构成的。

 

ITU定下来3种基于BER( Basic Encoding Rules)来对 TCAP层消息的长度来进行进行编码,也就是刚才说道的xxx Length的部分,这一部分标识的



(1) Short Form 

第一种是 Short Form 顾名思义 ,这个是用来传输较少数据的,这个数据是多少呢?

[C] 使用pcaplib的pacp_next_ex()针对TCAP开发时要注意的数组越界问题

图 2  SHORT FORM

在BER的编码中每一个 ANS. 1类型都被描述成一个8  bit的字符串 Octet. 。图2 就描述的是一个Octet 这个 Octet就代表着 刚才所提到 xxx Length的部分,描述着后面 Data部分的长度。

从图上我们可以看到,Short Form 所能描述的后面Data的长度(Octet个数相当于字节)就是。

8 bit - 1bit (最高位的0一位)= 7 bit 也就是 2的7次方 128个Octet


(2) Long Form 

第二种是 Long Form

[C] 使用pcaplib的pacp_next_ex()针对TCAP开发时要注意的数组越界问题

图 3  Long FORM

和Short Form 不一样 最高位是1,后7位则代表的是Data长度的长度。也就是说如果xxx Length位置上出现比 0x80 大的数据,那么大出的部分也就是后7位的组成的

数字的大小代表了Data长度的数值。

 

例:  length位置开始 第一个Octet  = 10000001 (0x81) 第二个 Octet = 00001111

          Data长度是多少呢?  应该是 15,可是为什么不是1呢,这是以为long form和short form一样的地方是放的是Data长度的长度,也就是

            0x81 - 0x80 = 1 ,这里1的意思说后面的一个Octet代表的是Data长度。



(3) Indefinite  Form 

[C] 使用pcaplib的pacp_next_ex()针对TCAP开发时要注意的数组越界问题

          

图 4  INDIFINITE FORM


Indefinite Form 和 short form 和long form 不一样的地方是,它没有Length来标识整个Data的长度,其结构有点像XML的结构,采用定位标识来标识出数据的结尾。

从图4上我们可以看到, Length的部分没有,L =10000000 标识为Indefinite form数据的开始。EOC TAG和 EOC Length代表着 Indefinite form的结束。

而且Indefinite form 里面还可以嵌套Indefinite form



3.Bug内容:


我拿到的以前代码,因为没有对 Indefinite form 进行处理。所以在长度上都是对Length解析,然后根据长度来取出数据。以前的代码在取出IMSI的时候,由于TC-COTINUE是没有IMSI的数据,这个时候IMSI TAG是并不存在。既存的处理是 以 sprintf(buf, "%.2x", pcap_data[position])尝试判断一下Tag是否存在,如果存在就 sprintf(buf, "%.4u", pcap_data[position])取出长度。由于TAG不存在,一般情况下会判断Tag不存在。

但是 有些时候 pcaplib的pcap_next_ex()取出来的数组,是一个动态分配的内存,很有可能在IMSI Tag不存在的情况下,在IMSI TAG应该出现的地方出现一个和IMSI TAG一样的值,这种情况下,既存的处理会认为这个地方就是IMSI TAG,然后就到后面去取长度。在Short Form,Long Form的情况下,即使错误取出的长度也只是128~ 2的1024次方

那么去取数据的时候 pcap_data[position]的position 最大值冲破内存限制的可能性比较小。


但是对于想定情况处理了Indefinite form 之后,这个有可能出错的长度就不可预知了。从一个0x80开始到连续 两个 0x00 结束,那么这个值就有可能变的无比巨大,如果再按照这个Length 从内存取东西就有可能出错。


pcap_next_ex(pcapfile, &header, &pcap_data)

caplen = header->caplen;

所以一定要在每次取Tag 和Length的时候用 pcaplib 提供的caplen属性来做check ,看position超过了 pcap_data 的边界没有。要不然就有可能悲剧,关键是在数据量小的情况下,这个错误不一定能出来。






[C] 使用pcaplib的pacp_next_ex()针对TCAP开发时要注意的数组越界问题

上一篇:poj1850


下一篇:UVa 11426 GCD - Extreme (II) / 素数筛选 + 欧拉函数