loop_in_codes

低调做技术__欢迎移步我的独立博客 codemaro.com 微博 kevinlynx

逆向思路:破解飞秋群聊协议

题外

飞秋是一款局域网内的IM软件,界面类似QQ,实现上与飞鸽(IP message)有点渊源,免费,不开源。

公司大概两年前开始使用这款软件作为员工之间办公吹牛的工具。最近游戏玩得少,就想彻底换到linux下,

组内也有其他两人是llinux-er,不过悲剧的是换到linux下就无法收取飞秋群里的聊天信息了,不免寂寞。

所以,就想写个协议兼容的程序(或者说改个东西)来收取群信息。

 

准备

我本身并不擅长逆向工程,破解什么的纯碎业余。在GOOGLE/BAIDU之后发现并没有前人留下的成果。

使用抓包程序,以及综合网络上的信息,还是可以得出不少有用的信息:

# 飞秋兼容了飞鸽的协议,其协议格式基本上基于文本形式,各个内容之间使用冒号作为分隔,例如:

1:100:user:pcname:32:message_body

# 飞秋在私聊情况下的消息内容是没有加密的,但群聊信息加密了,解密这个内容也是我的目标所在

# 在抓包软件下根据消息的目标IP地址可以推断飞秋发送群信息是基于UDP组播的,即就算你不是这个群

   的成员,也会收到群消息

有用的文章: 《局域网内实现飞鸽欺骗》《飞鸽传书数据加密分析》(个人感觉没有任何实质内容,而

且飞鸽传书并不是飞秋,属于误导性文章,但是依然有用)。最重要的,稍微浏览IP message的代码,

以及linux下的iptux(另一个兼容飞鸽的局域网IM)代码,都是对接下来的破解有益的。

 

破解

我希望我提供更多的,是一种crack的思路,虽然我不是一个cracker。破解和写程序不太一样,它需要

更多的耐心、运气、程序之外的思考。如前所做的准备,尤其重要。

工具及环境:飞秋2.4版本、OllyDbg,为了方便接收群信息,最好有两台电脑。

 

STEP 1 找入手点

在开始面对一大推汇编代码时,我们需要一个最接近目标的点。获取这个点根据目标的不同而不同。例如,

这里主要是针对网络数据的解密。所以,最直接的就是去找这些网络数据。当然,根据具体程序的表现,也

可以从其他点入手,例如飞秋收到群消息后会在任务栏闪烁图标,也可以从这个功能逆向过去。

 

因为飞秋使用UDP协议,所以我们可以在recvfrom函数下断点(bp recvfrom)。因为接收UDP包的接口

可能还有WSARecvFrom,甚至winsock1.0中的recvfrom,所以最好都下断点。另一台机器发送群消息,

程序在winsock1.0里的recvfrom断下来:

71A43001 >  8BFF            mov     edi, edi
71A43003    55              push    ebp
71A43004    8BEC            mov     ebp, esp
71A43006    51              push    ecx

这个不是我们需要的,我们需要根据这个点获得用户层代码,这将是整个破解过程的起点。所以,OD中

ALT+K查看调用堆栈,然后跳到调用recvfrom的函数处:

00490890  /$  56            push    esi                              ;  接收数据的函数入口
00490891  |.  8B7424 08     mov     esi, dword ptr [esp+8]
00490895  |.  8D46 10       lea     eax, dword ptr [esi+10]
00490898  |.  50            push    eax                              ; /pFromLen
00490899  |.  56            push    esi                              ; |pFrom
0049089A  |.  C700 10000000 mov     dword ptr [eax], 10              ; |
004908A0  |.  8B09          mov     ecx, dword ptr [ecx]             ; |
004908A2  |.  6A 00         push    0                                ; |Flags = 0
004908A4  |.  8D46 18       lea     eax, dword ptr [esi+18]          ; |
004908A7  |.  68 FF3F0000   push    3FFF                             ; |BufSize = 3FFF (16383.)
004908AC  |.  50            push    eax                              ; |Buffer
004908AD  |.  51            push    ecx                              ; |Socket
004908AE  |.  E8 C7F30C00   call    <jmp.&WSOCK32.#17>               ; \recvfrom

邪恶的OD已经将调用recvfrom时传入参数的指令标记出来了。中文注释是我分析时加的。recvfrom里传入

的接收缓存,是我们应该关注的。如果能跟进这个缓存,假设程序的流程比较简单:接收了数据,然后在某个

地方直接解密,不管它的加密方式是什么,只要能找到这个缓存数据从加密变为解密的地方,对于整个破解而言,

都算是迈进了一大步。

于是,在00490890(上面找到的函数入口)下断点,准备跟进接收缓存。注意:在OD里调试跟在vc里不一样,

跳到调用堆栈里的某个函数,寄存器依然是当前的值。所以需要重新跟。

 

STEP 2 内存断点

F9让程序继续运行,再次在另一台机器上发送群消息。这回程序在00490890处断下,然后跟接收缓存:

004908AC  |.  50            push    eax                              ; |Buffer = 0011F4CC
004908AD  |.  51            push    ecx                              ; |Socket
004908AE  |.  E8 C7F30C00   call    <jmp.&WSOCK32.#17>               ; \recvfrom

接收缓存Buffer的值为0011F4CC,如前所述,我们要跟进这个地址指向的内存的变化情况。F8单步运行到

recvfrom后,也就是接收了网络数据后,查看内存内容

(d 0011F4CC):

0011F4CC  31 5F 6C 62 74 34 5F 30 23 31 32 38 23 38 38 41  1_lbt4_0#128#88A
0011F4DC  45 31 44 44 34 36 36 46 44 23 30 23 30 23 37 32  E1DD466FD#0#0#72
0011F4EC  3A 31 32 39 35 37 32 31 32 31 33 3A 41 64 6D 69  :1295721213:Admi
0011F4FC  6E 69 73 74 72 61 74 6F 72 3A 50 43 2D 32 30 31  nistrator:PC-201
0011F50C  30 31 31 30 34 32 30 30 35 3A 34 31 39 34 33 33  011042005:419433
0011F51C  39 3A 5E 3B 83 A1 14 6D A4 D2 E3 D8 E8 AB B1 3A  9:^;儭mひ阖璜?
0011F52C  5B BC C2 FE E9 DA CB DD 00 BC 59 FC 9D A7 D7 91  [悸谒?糦鼭ё

内容开头正是飞秋的协议头,未加密,不过没多大用。根据之前获取的飞秋协议,可知,在0011F51E

处就是聊天内容的密文。

很自然地,为了监视这段内存的变化情况,在该位置下内存访问断点(右击数据区即可看到下断点的选项)。

F9继续走,然后马上断下来:

0049010F  |.  F3:A5         rep     movs dword ptr es:[edi], dword ptr [>
00490111  |.  8B4A 04       mov     ecx, dword ptr [edx+4]
00490114  |.  C74424 24 000>mov     dword ptr [esp+24], 0
0049011C  |.  894D 64       mov     dword ptr [ebp+64], ecx
0049011F  |.  33C9          xor     ecx, ecx

程序到了一个陌生的环境(在这种满世界都是汇编代码的情况下,几乎一不小心就会迷失其中),看了下

附近的代码,没什么可疑。通过下内存访问断点的思路,似乎显得荆棘丛生。

 

STEP 3 靠近目标

不妨冷静下来思考,如果没有直接的路,我们可能需要悲惨地大海捞针。在写一个网络程序时,网络底层

收到数据包,无非要么直接进行逻辑处理,要么缓存到一个逻辑处理队列里稍后处理。后者虽然对于程序员

而言是个好方法,但是因为跨了线程,又涉及到队列缓存,对于逆向而言,绝对是悲剧。

 

但是如果使用了前者呢?对于一个网络客户端程序而言,也许直接进行逻辑处理才是最KISS的方法。(这种猜测

的破解方式,绝对需要运气。)所以,如果是直接进行处理,那么在接收到网络数据附近,必然就有解密函数。

所以,不妨顺着收包函数附近随意浏览一番。(但不要走进太深的call,不然又迷失了。)

0048FE10  /$  B8 18400000   mov     eax, 4018                          
0048FE15  |.  E8 560A0C00   call    00550870
0048FE1A  |.  8D4424 00     lea     eax, dword ptr [esp]
0048FE1E  |.  56            push    esi
0048FE1F  |.  8BF1          mov     esi, ecx
0048FE21  |.  50            push    eax
0048FE22  |.  E8 690A0000   call    00490890                             ;  接收网络数据

0048FE10函数调用了刚才发现的收包函数。这个函数在收完数据后,不久就调用了另一个函数:

0048FE3F  |.  51            push    ecx
0048FE40  |.  52            push    edx
0048FE41  |.  8BCE          mov     ecx, esi
0048FE43  |.  E8 88020000   call    004900D0                             ;  似乎很可疑?

进到004900D0函数,发现这个函数真TMD巨大。随意浏览之,发现OD有这种提示:

00490178  |.  68 34FD5E00   push    005EFD34                             ;  ASCII "_lbt"
0049017D  |.  8D4C24 14     lea     ecx, dword ptr [esp+14]
00490181  |.  89BC24 544000>mov     dword ptr [esp+4054], edi

_lbt,恩,消息头里有这个字符串标识。估计是在做些消息头的逻辑操作。这个函数太长,里面还有若干call,

可谓头大。所以说,代码写得丑,可读性差,对于防破解还是颇有益处的。跳回到0048FE43,发现当前

函数基本完了。

 

于是往上看,来到调用这个函数的地方:

0050F647  |.  E8 C407F8FF   call    0048FE10
0050F64C  |.  BF 01000000   mov     edi, 1

回顾下,我们有函数A接收网络数据,有函数B调用A,现在回到了C,来到了调用B的地方0050F647。C函数

也很巨大,直接往下浏览,会发现一些switch语句:

0050F71A  |.  81E6 FF000000 and     esi, 0FF
0050F720  |.  8D46 FF       lea     eax, dword ptr [esi-1]               ;  Switch (cases 1..D3)
0050F723  |.  3D D2000000   cmp     eax, 0D2
0050F728  |.  0F87 8C000000 ja      0050F7BA
0050F72E  |.  33C9          xor     ecx, ecx
0050F730  |.  8A88 60315100 mov     cl, byte ptr [eax+513160]
0050F736  |.  FF248D 403051>jmp     dword ptr [ecx*4+513040]
0050F73D  |>  8D9424 F40000>lea     edx, dword ptr [esp+F4]              ;  Case 1 of switch 0050F720

往后浏览下这个switch…case,发现非常之大,这个函数也因此非常巨大。不妨猜测这个是根据不同消息做不同

逻辑处理的地方。这个想法正是给予我们灵感的关键。

 

群聊消息必然也有个类型,通过之前OD获取到的网络数据(或者截取网络封包所得),群聊消息的类型为:4194339

(16进制400023H),去掉高位,也就是23H。仔细地对比每一个case,果然发现了一段处理代码:

00512787  |> \39AC24 640100>cmp     dword ptr [esp+164], ebp             ;  Case 23 of switch 0050F720
0051278E  |.  75 07         jnz     short 00512797                       ;  群聊天处理
00512790  |.  8BC7          mov     eax, edi
00512792  |.  E9 8C080000   jmp     00513023

这个代码之下的处理也有不少代码。在不涉及到更多细节之前,我们可以大胆地将注意力放在接下来的call上。从这个case

往下,第一个call为:

005127E6  |.  50            push    eax
005127E7  |.  E8 A4A20000   call    0051CA90                             ;  非常可疑
005127EC  |.  B8 01000000   mov     eax, 1
005127F1  |.  E9 2D080000   jmp     00513023

 

STEP 4 多尝试

有怀疑,就用事实来证明。果断地在005127E6处下断点。然后发群消息,程序断下来。因为这个函数压入了

eax作为参数,且对ecx做了赋值:

005127E4  |.  8BCB          mov     ecx, ebx
005127E6  |.  50            push    eax
005127E7  |.  E8 A4A20000   call    0051CA90                             ;  非常可疑

在调用一个函数前对ecx做赋值,一般都是C++成员函数调用。eax作为一个参数,非常值得关注,果断查看eax

指向的内存值:

001235C8  41 64 6D 69 6E 69 73 74 72 61 74 6F 72 00 6D 00  Administrator.m.
001235D8  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
001235E8  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
001235F8  00 00 50 43 2D 32 30 31 30 31 31 30 34 32 30 30  ..PC-20101104200
00123608  35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  5...............
00123618  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00123628  8A 7B 00 00 C0 A8 00 03 09 79 00 00 01 00 00 00  妠..括..y.....
00123638  04 00 00 00 00 00 00 00 80 00 00 00 38 38 41 45  .......€...88AE
00123648  31 44 44 34 36 36 46 44 00 00 00 00 00 00 00 00  1DD466FD........
00123658  00 00 00 00 F4 C7 23 00 FD 22 3B 4D 23 00 40 00  ....羟#.?;M#.@.
00123668  49 00 00 00 36 00 00 00 5E 3B 83 A1 14 6D A4 D2  I...6...^;儭mひ

有用户名、机器名、发送者MAC地址,这么多可疑信息。完全可以猜测,eax传入的是一个结构体地址,

当然对象地址也可以,反正是个复杂数据结构。更重要的,在这块内存往下不远处,果断地发现了从

网络接收到的加密的聊天内容:

00123670  5E 3B 83 A1 14 6D A4 D2 E3 D8 E8 AB B1 3A 5B BC  ^;儭mひ阖璜?[
00123680  C2 FE E9 DA CB DD 00 BC 59 FC 9D A7 D7 91 CF 5A  漫橼溯.糦鼭ё懴Z

F8直接步过0051CA90函数。任务栏开始出现闪烁的图标(虽然没有闪),上面的内存数据变了:

00123670  74 65 73 74 7B 2F 66 6F 6E 74 3B 2D 31 34 20 30  test{/font;-14 0
00123680  20 30 20 30 20 34 30 30 20 30 20 30 20 30 20 31   0 0 400 0 0 0 1
00123690  33 34 20 33 20 32 20 31 20 32 20 CB CE CC E5 20  34 3 2 1 2 宋体

test正是我发的内容。

 

STEP 5 缩小范围

实际上走到这里,凭借运气和程序编写的常识,已经找到关键点。不过看来0051CA90这个函数做的事情

有点多,除了解密内容似乎还有UI上的一些处理(例如那个闪烁的任务栏图标)。所以,我们要做的是,进一步

跟进,找到关键点。

 

现在缩小范围要容易得多,因为我们得到了一个会变化的内存地址:00123670。只需要F8一步一步地

运行代码,一旦发现内存内容改变,则可以进一步进如,从而找到关键call。具体过程我就不给了,大概为:

0051CB02  |.  52            push    edx
0051CB03  |.  68 00400000   push    4000
0051CB08  |.  56            push    esi
0051CB09  |.  50            push    eax
0051CB0A  |.  56            push    esi
0051CB0B  |.  E8 F041F7FF   call    00490D00                             ; 跟进

 

00490DB0  |.  6A 00         push    0
00490DB2  |.  83E1 03       and     ecx, 3
00490DB5  |.  6A 22         push    22
00490DB7  |.  F3:A4         rep     movs byte ptr es:[edi], byte ptr [es>
00490DB9  |.  8BBC24 344000>mov     edi, dword ptr [esp+4034]
00490DC0  |.  50            push    eax                                  ;  数据长度
00490DC1  |.  8D4424 20     lea     eax, dword ptr [esp+20]
00490DC5  |.  57            push    edi                                  ;  输出缓存
00490DC6  |.  50            push    eax                                  ;  输入缓存(加密内容)
00490DC7  |.  8D4C24 20     lea     ecx, dword ptr [esp+20]
00490DCB  |.  E8 5049F7FF   call    00405720                             ;  最终解密函数

 

00405720函数内的实现基本上全是数据操作指令。加解密算法无非就是捣鼓这些数据,所以当我进到

00405720函数时,基本上可以断定它就是最终的解密函数。

 

STEP 6 解密

事实上我们并不需要去弄懂它的具体解密算法,就算是直接的C++代码,没有算法论文的话也很难看懂,更何况

是这里的汇编。最直接的方式,就是查看这个解密函数对外界的依赖情况,例如需要的参数,this里是否有依赖

的数据。在了解了这些情况后,大可以将这段汇编复制出来直接作为C++内嵌汇编代码使用。

 

不过,这里我想到了更简单的方式。因为我注意到飞秋和飞鸽在实现上有着不解之缘,而且我琢磨着作者也不会

为了一个加解密不太重要的应用场合而去整些高深的算法。我想到,飞秋也许会直接使用飞鸽里的加解密代码!

 

在IP message的源码里,有blowfish加密算法的实现,我们来看接口:

class CBlowFish
{
private:
    DWORD    *PArray;
    DWORD    (*SBoxes)[256];
    void    Blowfish_encipher(DWORD *xl, DWORD *xr);
    void    Blowfish_decipher(DWORD *xl, DWORD *xr);

public:
            CBlowFish(const BYTE *key=NULL, int keybytes=0);
            ~CBlowFish();
    void    Initialize(const BYTE *key, int keybytes);
    DWORD    GetOutputLength(DWORD lInputLong, int mode);
    DWORD    Encrypt(const BYTE *pInput, BYTE *pOutput, DWORD lSize, int mode=BF_CBC|BF_PKCS5, _int64 IV=0);
    DWORD    Decrypt(const BYTE *pInput, BYTE *pOutput, DWORD lSize, int mode=BF_CBC|BF_PKCS5, _int64 IV=0);
};

从接口实现来说算是简洁漂亮友好和谐。我也用Decrypt这个函数的参数比对了上面没找到的那个call(00405720),

因为这里只是怀疑这个call就是这里的Decrypt,但并没有确切的证据。不过,对比下他们的参数就可以非常肯定了:

00490DB0  |.  6A 00         push    0           ;参数IV
00490DB2  |.  83E1 03       and     ecx, 3
00490DB5  |.  6A 22         push    22        ;参数mode
00490DB7  |.  F3:A4         rep     movs byte ptr es:[edi], byte ptr [es>
00490DB9  |.  8BBC24 344000>mov     edi, dword ptr [esp+4034]
00490DC0  |.  50            push    eax                                  ; 参数 数据长度
00490DC1  |.  8D4424 20     lea     eax, dword ptr [esp+20]
00490DC5  |.  57            push    edi                                  ;  参数输出缓存
00490DC6  |.  50            push    eax                                  ; 参数输入缓存(加密内容)
00490DC7  |.  8D4C24 20     lea     ecx, dword ptr [esp+20]
00490DCB  |.  E8 5049F7FF   call    00405720                             ;  最终解密函数

最重要的,是参数mode。Decrypt默认参数mode是BF_CBC|BF_PKCS5的位组合,结果,恰好为22!

所以,基本上可以断定:飞秋的加解密实现,就是使用了IP message的blowfish算法:blowfish.cpp/h/h2。

 

STEP 7 密钥

查看CBlowFish的使用,在解密前需要初始化,大概就是传入密钥之类。如果我们上面的猜测没有错,那么我们

从网络上取得的数据,然后取得密钥,直接使用blowfish的源码,就可以解密出消息内容。

 

接下来的关键就是,找到这个密钥。关于这个密钥,之前在飞秋的配置文件FeiqCfg.xml里绕了很久的圈子,因为

发现加入一个群的时候,这个文件里就会多出一项很长的16进制字符串。也一度猜测密钥就是保存在这个字符串的

某个偏移里。接下来会让人大跌眼镜。

 

因为CBlowFish这个类确实简单,使用它的最简单方式就是直接创建局部对象,然后传入key和keysize,即可完成

初始化。在之前展示的思路里,我也一度先去尝试最简单的方法。对于C++局部对象的创建,有个显著特征就是

mov ecx, dword ptr [esp+xxx],也就是往ecx里写入一个栈地址。而且可以肯定的是,这个构造代码,必然发生

于call 00405720前面不远处,往上跟进:

00490D3F  |> \8B8C24 304000>mov     ecx, dword ptr [esp+4030]
00490D46  |>  51            push    ecx                                  
00490D47  |.  52            push    edx                                  
00490D48  |.  8D4C24 0C     lea     ecx, dword ptr [esp+C]
00490D4C  |.  E8 3F3DF7FF   call    00404A90                             

一个压入两个参数的函数调用,对比CBlowFish的构造函数,刚好是2个参数。跟进00404A90:

 

00404A90  /$  56            push    esi
00404A91  |.  8BF1          mov     esi, ecx
00404A93  |.  6A 48         push    48
00404A95  |.  E8 69301600   call    00567B03
00404A9A  |.  68 00100000   push    1000
00404A9F  |.  8906          mov     dword ptr [esi], eax
00404AA1  |.  E8 5D301600   call    00567B03

 

又是可爱的立即数!48H、1000H,这种特别的立即数总能让人安心,对比CBlowFish构造函数实现:

CBlowFish::CBlowFish (const BYTE *key, int keybytes)
{
    PArray = new DWORD [NPASS + 2];//NPASS=16
    SBoxes = new DWORD [4][256];

    if (key)
        Initialize(key, keybytes);
}

sizeof(DWORD)*18=48H,sizeof(DWORD)*4*256=1000H!这么极具喜剧意义的汇编C++代码映射,

基本可以肯定,00404AA1处,正是构造CBlowFish对象的地方,而构造的参数,正是我们魂牵梦萦的解密密钥:

 

00490D46  |> \51            push    ecx                                  ;  key长度
00490D47  |.  52            push    edx                                  ;  密钥key
00490D48  |.  8D4C24 0C     lea     ecx, dword ptr [esp+C]
00490D4C  |.  E8 3F3DF7FF   call    00404A90                             ;  构造blowfish对象

 

在此处下断点,发送群消息,程序断下来,看看密钥究竟是什么。如果它确实是FeiqCfg.xml里的某个值,

那么我们还要进一步跟这个值具体在哪个配置项里。看看吧,密钥edx:

 

edx=00123644, (ASCII "88AE1DD466FD")

 

 

TM的密钥居然是发送者的MAC地址!当我看到这个的时候我几乎快摔倒地上。如果飞秋使用一个MAC地址

作为密钥,那么这意味着:通过自己写的程序,可以取得局域网内其他群里的聊天内容!这个实在太邪恶了。

上回抓包的时候,虽然看不到内容,但可以看到美术、策划在群里聊的无比欢乐。这回有喜感了。

 

STEP END 可略

看看时间,悲剧地发现整篇文章花了接近3个小时才写完。此刻我正踌躇要不要把代码发上来,但转念一想

最后那个STEP的发现实在让人蛋疼,所以还是算了。打算稍微封装下,然后使用这份代码在iptux 上改改包装

个界面,目的就算达成了。相信浏览完整篇文章,写出自己的代码不是什么大问题。

 

其实我大可以直接给结论,但是我依然乐于分享过程和思路。一来算是自我总结记录(每次拿起OD,总是快捷

键一路忘);二来也给有心人一个指引。

 

最后,对这种东西还是有必要出个免责声明:根据本文章所造成的一切后果与文章作者无关。为了不糟蹋我这3个

小时的时间,转载麻烦注明出处。

PS,最后回顾下结论,其实发现这个解密非常非常简单。你说如果直接给卢本陶(飞秋作者)发封邮件,他会不

会直接告诉我?

posted on 2011-01-23 21:01 Kevin Lynx 阅读(25575) 评论(9)  编辑 收藏 引用 所属分类: c/c++通用编程

评论

# re: 逆向思路:破解飞秋群聊协议[未登录] 2011-01-24 14:43 dophi

已阅  回复  更多评论   

# re: 逆向思路:破解飞秋群聊协议 2011-01-24 22:03 lin_style

我觉得会,哈哈哈  回复  更多评论   

# re: 逆向思路:破解飞秋群聊协议 2011-01-25 23:28 欲三更

呵呵,我看到文章的开头就猜飞秋加密用的应该是飞鸽传书源码里的某种加密算法,果不其然哈哈^_^  回复  更多评论   

# re: 逆向思路:破解飞秋群聊协议 2011-01-26 18:23 YcdoiT

一个菜鸟大开眼界  回复  更多评论   

# re: 逆向思路:破解飞秋群聊协议[未登录] 2011-01-27 23:31 微妙的平衡

kl又在做坏事了。  回复  更多评论   

# re: 逆向思路:破解飞秋群聊协议 2011-01-28 16:04 tunpishuang

"代码写得丑,可读性差,对于防破解还是颇有益处的。" 哈哈。太有喜感了。  回复  更多评论   

# re: 逆向思路:破解飞秋群聊协议 2012-09-26 10:54 super5er

看完之后,兴奋不已!  回复  更多评论   

# re: 逆向思路:破解飞秋群聊协议 2014-11-18 14:10 FatBean

你好:
请问飞秋群聊消息的发送应该调用什么接口?  回复  更多评论   

# re: 逆向思路:破解飞秋群聊协议 2015-06-30 16:07 primeking

你好,我和你一样,我用iptux接受不到飞秋群的信息。可是我是个硬件工程师,你可以把你改好的iptux给我一个吗?277787468@qq.com  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理