呼叫转移获取主叫,被叫和原始被叫号码外挂实现

[ 2006-8-12 18:25:00 | By: AmLinger ]


      个人心得分享,如果觉得有侵权行为,请尽早通知我,和本网站,以便及时的删除本篇文章.

假设有两部电话A,B和呼叫中心C,如果A给B打电话,而B设置了呼叫转移,转移到呼叫中心C,
那么呼叫中心C调用函数获取 A,B,C的号码就OK了.

本来是一件很容易的事情,却被 "交换机" 弄的乱七八糟.

我是一个糊涂的人,对IVR的一些概念总也搞不清楚.所以下面的话,要是听不懂,请不要见怪.
以后我会加强,专业技术的使用.-_-|||
当然那一位前辈要是能指点一下的话更好,我高兴都来不及.徒儿在这里先拜谢师父了. ^_^

下面是一条记录是用东进七号信令数据分析终瑞,获取交换机发送过来的数据.
218: 11:22:55   recv buf   84 67 2C 2A 64 2C 2A 65 00 21 0A 00 80 59 01 15 40 24 80 82 78 34 F1 C0 23 08 00 00
上面的记录,在 东进七号信令数据分析终瑞 ,只能解析出,主叫与被叫,而原始被叫却不知道为什么会被遗忘..=.=|||

问题出现了,我们就来分析一下问题好了.分享一下我的心得好了.

recv buf   84 67 2C 2A 64 2C 2A 65 00 21 0A 00 80 59 01 15 40 24 80 82 78 34 F1 C0 24 08 00 00
--------   ----------------------------------- -- ----------- -- -- ----------- -- ------------
  (1)                     (2)                  (3)    (4)     (5)(6)   (7)      (8)    (9)
                                                
下面的内容没有科学根据纯属猜想.
1.说明是 接收的缓冲区内容
2.用分析终端,可以看到号码的级别与来源等等..
编码方式,可能是与BCD码相似,(学过汇编的人,应该听说过吧..^_^)
假设所送的号码也按某种格式来存放. 实际上是它特有的格式,就像TCP/IP报头的格式类似,因为手头没有信信格式的说明,只好猜了.
3.下面号码的长度 80?? 不会有这么长的号码啦..哈哈..交换一下位置. 08 
4.被叫.59 01 15 40  <--没有见过的东西,一想本家的平台号为95105104. 嘿嘿..猜到了吧.这个位置上存方的是被叫
5. 是主叫的标识? ..
6.又是一个80 .交换一下位置08 ..假设为 主叫长度.
7 主叫 84 78 34 F1  <--又一个没有见过的东西, 再假想还原一下.. 4887431F ..嘿嘿.刚才使用的测试电话.. 结尾有一个F字样,
  我们就设置它起一下校验位的作用吧.
8.应该是标识吧..一看C0 倒一下是 0C 转成10进制为12
9. 24 08 00 00 <---不用说了吧..还原一下. 42800000   测试号码.

..假设,一下,会不会是因为 (8)  这里的标志送错呢? 当然这里只是假设..^_^

(2)这一部分,在某一条件下是固定的,就是标质,这个是拨入电话的记录..

对上面胡乱假设一通后,进入我们的正题.不管是交换机的问题还是系统平台的问题.二者任一更改,都比较困难,
当然,可能对专业人事来讲,仅仅只修改一两行代码..^_^..

因为工作还是要继续,只能自己想办法解决问题了,于是想到了外挂程序.

首先当然是外挂的可行性分析了. 不然嘴上光叫写外挂写外挂,忙活了半天还是要放弃..

recv buf   84 67 2C 2A 64 2C 2A 65 00 21 0A 00 80 59 01 15 40 24 80 82 78 34 F1 C0 24 08 00 00
--------   ----------------------------------- -- ----------- -- -- ----------- -- ------------
  (1)                     (2)                  (3)    (4)     (5)(6)   (7)      (8)    (9)

(1) 凡是接收的东西,都以这个开头..
(2) 号范围所送的内容是固定的.            (跟据ISP的服务类型和局方规定的数据产生)
(3) 号范围假设是可变,因为改据情况不同自动更改嘛..  (根据系统平台号产生)
(4) ..被叫.不用讲了. 跟据 (3)的记录 截取获得 
(5) ..经过少量数据分析,也是固定的.当然,不能排除可变的可能性,必竟手头现有的数据有限.  (因为不确定,当前值会不会,但是
    分析其它记录号发现,就算这里的内容会变, 记录数据的长度不会加大的. 最多也就 FF)
(6) 号码的长度当然是会变的.     (从(4)跳一位到这里 ,这里的数据是根据7的号码实际长度加校验位产生)
(7) 根据(6)的记录截取获得被叫  
(8) 这里因为假设它不是标志位,而是长度位.   (.....这个不太好解释了,继续假设,由目前的交换机,所送的格式,暂时只有这一种固定模式了.)
(9) 上面假设成立的话,这里的号码由(8)所记录的数量 截取原始被叫

上面是看到的内容,经过 4 条测试记录数据和20条与测试无关的记录分析,百分之百证明上面的假设成立. {@_@}!
即然假设成立,只要根据假设的格式进行记录读取就可以获取原始被叫的记录了.

大思路:
     按上述的假设,对缓冲区的记录进行单条分析,从中提取原始被叫.
小问题:
     1.如何获取CCS7Server缓冲区中的数据.
     2.如何对缓冲区中的单条记录进行"解码"操作.
     3.如何将获取到的数据,提交给 系统解释平台 使用.
经过本人,二个昼夜的奋斗,找到了一个可以解决问题的办法.虽然不是精典的编码,但最重要的是它可以工作.
     1.首先通过对进程的列举对比,找到CCS7Server的进程,因为有可能有多个CCS7Server的进程,所以,建立句柄数组保存所找到的句柄记录.
       然后,通过人工对目标的确认选择,对目标窗口(-->CCS7Server的缓冲区)角认.并将获取的窗口句柄保存.
       再通过在指定进程内分配存储空间,从而对目标的内存进行访问,读取想要获取的内容.
     2.采用定时对缓冲区内容读取,然后对每一条缓冲区的内容进行分析.获取被叫
       当,被叫是呼叫转移的服务号是,进行深层次的分析获取,(主要是为了快速反应,所以能省就省..)
       当进行深层分析后,读取到主叫和原始被叫,就会面临问题3了.
     3.大家可能会想,是不是也要建立对EasyAdmin.exe的内存访问呢?,要是想到以这个办法解决问题的,我只能讲一句"牛人",
       如果,真的可以完成,并能保证EasyAdmin.exe的正常运行,我要大叫"牛人"了.
       为了保证EasyAdmin.exe的正常运行,不会受到外挂的影响,我们可以将获取的数据写入到数据库当中.
       然后,在脚本中执行获取数据,并对,原始被叫记录表进行清理.为什么要清理.,当然要清理了,这个属于一次性用品,如果不清理
       不出10天半月,保证你的MS-SQL的库大于2G. 这里指小型用户.我也有见过,什么还没有做的大型用户日志就有20G左右..

       好了,上面的问题分析完了,下面进行编码.思路已经给大家了,具体实现,我就不用讲的太清楚,写出部分关键性的代码就可以.
对于我个人来讲,没有什么可保密的,但是我不幸在公司上班.有义务保密.
       用CreateToolhelp32Snapshot来获取对应的进程句柄,将来也可以用于对CCS7Server的监视,如果死于意外,我们还可以当回大仙,把它再还魂了.
       关于CreateToolhelp32Snapshot这个的获取,不用我多讲了,网上一大堆这样的代码.获取进程的ID和文件名,对比我们提供的文件名..确认目标.
       对于窗口句柄的确认,可以用
      
       GetCursorPos(&MousePoint);
        hWindow = WindowFromPoint(MousePoint);
       来获取. 参考代码是 MiniSpy 源码 v2.0
       这里可以下载,http://www.ccrun.com/view.asp?id=11
       里面主要用到了,用鼠标获取目标窗口的句柄操作.

       下面来讲讲关于读取ListView里的内容了. 参考代友是WWW.CCRUN.COM {读取其他应用程序中ListView中的内容}
       在这里看详细代码: http://www.ccrun.com/article.asp?i=583&d=eahk4z
  
       读取到记录后..我们开始解码.
       注释我就瞎写了一点点,耐心看的话可以看懂. 里面调用了一些函数,是我写定义的,你可以根据需要,自己填写函数的功能实现部分.
      
bool __fastcall TMainForm::UpdateOriCall(String Str)
{
        String Result;
        String OriCall;
        String Caller;
        int Fpos;
        int CallerLen;
        int OriCalllen;
        String Temp;
        char Buf[1024];
try
{
        //218: 11:22:55   recv buf   84 67 2C 2A 64 2C 2A 65 00 21 0A 00 80 59 01 15 40 24 80 82 78 34 F1 70 23 08 00 00
        if (Str==NULL) return false;
        Fpos=Str.Pos("buf")+3;
        Temp=Str.SubString(Fpos,Str.Length());
        //84 67 2C 2A 64 2C 2A 65 00 21 0A 00 80 59 01 15 40 24 80 82 78 34 F1 70 23 08 00 00
        strmemcpy(Buf,Temp.c_str(),Temp.Length() );
        CurrentProcess->Lines->Add(Temp);
        //84672C2A642C2A6500210A0080590115402480827834F17023080000      //清除空格
        Temp=String(Buf);
        swab( Temp.c_str(),Buf ,Temp.Length()) ;                        //交换位置
        Str=String(Buf);

        CurrentProcess->Lines->Add(Str);    //显示此时结果

        Fpos=Str.Pos(ServerNum);
        if (Fpos==0)
        {
        return false;
        }                                              //查找95105104具体位置
        Fpos+=StrLen(ServerNum);     //590115402480827834F17023080000
        Fpos+=3;
        //2480827834F17023080000           Fpos+=2;
        //80827834F17023080000


        CallerLen=Str2Int64(("0x"+Str.SubString(Fpos,1)).c_str() ); //获得主叫长度
        Fpos+=1;
        Caller= Str.SubString(Fpos,CallerLen-1);

        CurrentProcess->Lines->Add(Caller);   //显示此时结果

        Fpos+=CallerLen+1;
        OriCalllen=Str2Int64(("0x"+Str.SubString(Fpos,1)).c_str() ); //获得原始主叫长度
        Fpos+=1;
        OriCalllen-=1;
        OriCall=Str.SubString(Fpos,OriCalllen+1);
        CurrentProcess->Lines->Add("主叫:"+Caller+" 长度为:"+String(CallerLen-1) +"      原始主叫:"+OriCall+ " 长度为:"+String(OriCalllen));

        CurrentProcess->Lines->Add(OriCall);    //显示此时结果
      /*
        try
        {
        if (OriCall[OriCalllen]=='0') OriCall=OriCall.SubString(0,OriCalllen-1);
        }
        catch(...)
        {
                CurrentProcess->Lines->Add("原始被叫长度取值失败");  //显示此时结果
        }
         */
        bool Result=false;
        String Cmd;
        if (OriCalllen>0)
        {
        Cmd="INSERT INTO OriRecord (SpNum, UsePhoneNum, OriCaller) VALUES ('"+String(ServerNum)+"','"+String(Caller)+"','"+String(OriCall)+"')" ;
        Result=RunSql(Ado,Cmd,false);
        }
        return   Result;

}
catch(...)
{
        return false;
}
}    
      上面的代码,也提交了数据.至于如何在脚本中读取相关的数据,我个人认为不用再讲了,如果需要脚本如何读取数据的话,
      可以与我联系.

      尾声:很意外的这个外挂的程序就被我"拼"-->(拼凑) 了出来,大家有兴趣的话,也可以自己玩一玩.当然目前这个东西还有许多的BUG
      不过看着它可以将最起码的工作任务完成了,所以就转移目标,等它什么时候不能用的时候,再进一步修改.完善.
      下面附上几张图片吧.
      不知道能不能上传....汗..
     




      实验平台:WINDOWS2003 ,Borland C++ Builder 6.0 ,MS-SQL2000 ,同力信通科技发展有限公司IVR产品
      作者:耿海瑞 EMAIL:haihong5995037@163.com                             2006-04-31

Re:呼叫转移获取主叫,被叫和原始被叫号码外挂实现

[ 2008-9-1 20:22:00 | By: 呵呵(游客) ]
有点深奥拉~~~~
以下为blog主人的回复: 2008-09-02 20:55:06
接触过以后,会发现一点也不难的.
从目标进程中读取想要的数据然后解析就是这样的原理.

个人主页 | 引用 | 返回 | 删除 | 回复

Re:呼叫转移获取主叫,被叫和原始被叫号码外挂实现

[ 2006-10-15 17:04:00 | By: bluesen(游客) ]
我前阵子一直在研究ISUP协议,你这个包是TUP数据,今天找了个资料看了一下,基本上搞明白了,你的是IAI消息包,解析如下(当然不是用你那种“黑客”手段,是按协议分析的):
你的原始数据: 84 67 2C 2A 64 2C 2A 37 00 21 0A 00 80 59 01 15 40 24 C3 31 57 43 43 23 F9 70 53 13 51 09

第一个字节0x84表示为TUP协议,如果是0x85则为ISUP协议。
开始:
首字节ISO: 0x84 - 1000(国内网络) 0100(TUP)
紧接着8个字节是:DPC(3): 67 2C 2A
OPC(3): 64 2C 2A
CIC(两个字节的12bits) 37 00
消息类型: MessageType(1): 21 : 21 0010 0001 Initial Address with Additional Information IAI(带有附加信息的初始地址消息)

主叫用户类别(1): 0A(长途,如果是18市话)
消息标识语和地址信令数量(2): 00 80 : 带8位被叫号码
(被叫号码)地址信令(4): 59 01 15 40 (解BCD码为:95105104)

第一表示语: 24 (二进制:0010 0100,表示:有“附加主叫信息”和“原被叫地址”,其它“国内应用”等无)

(附加主叫信息)地址表示语和地址数量:C3 (地址数量:0xC就是十进制12位)
(附加主叫信息)地址: 31 57 43 43 23 F9 (解BCD码为:13573434329)

(原被叫地址)地址表示语和地址数量:70 (地址数量:7位)
(原被叫地址)地址: 53 13 51 09 (解BCD码为:3531159)

你自己按这种方法再去分析第二个数据包吧,但愿对你有所启发。

以下为blog主人的回复:

 大哥讲的我看懂了.因为我只第一次见到这种数据.以前并没有见过类似的数据,所以分不清,局方所送的数据是否正常,只知道我们所买的系统平台不能正常解析出"原被叫地址",才认为他们总有一方是错误的.也曾与他们进行沟通,因为各种原因双方都认为自己没有错误.最后,因为BOSS加压,我才想出那个办法来解决问题.

大哥说我的方法属于"黑客"手段. ^_^.
我也同意我在这C7协议方面是"盲人".
看了你的分析,我又学了一点点.果然是自己的知识不够.
以后,有问题还请大哥多多指教.

 

Re:呼叫转移获取主叫,被叫和原始被叫号码外挂实现

[ 2006-10-12 13:51:00 | By: bluesen(游客) ]

何必瞎摸索呢,看看7号信令的文档就知道了。看看消息、参数是如何编码的,这都有标准文档啊。

我前几天也做了类似的工作,当然我是按照标准来,可以解析出任何一个参数。http://blog.csdn.net/bluesen


以下为blog主人的回复:

 应该叫你大哥吧或者叫叔叔.还是叫大哥吧.^_^
谢谢你的点化.
下面我附上一些我用东进收到的信令数据吧.
我不是为了证明什么,我只是想找到这个问题更好的解决办法.
如果按照标准方法可以解决,那么我也同意用标准的方法更快更安全.

请大哥对下面的数据解析一下吧.
里面包含了.被叫,主叫,原始被叫
因为我用东进厂家带的工具查看不到,可能是 送出方的数据有问题吧.我是这么想的.

3735017: 09:40:38   recv buf   84 67 2C 2A 64 2C 2A 37 00 21 0A 00 80 59 01 15 40 24 C3 31 57 43 43 23 F9 70 53 13 51 09
3735018: 09:40:39   recv buf   84 67 2C 2A 64 2C 2A 21 00 21 0A 00 80 59 01 15 40 24 C2 31 57 43 93 15 F5 70 53 13 16 05

第一条的结果是:95105104 13753434329F 3531159
第二条的结果是:95105104 13753439515F 3531615

 

发表评论:

    大名:
    密码: (游客无须输入密码)
    主页:
    标题:
    正在载入数据,请稍候……