ITPub博客

首页 > IT基础架构 > 网络安全 > 联众升级协议分析 续篇(四) (转)

联众升级协议分析 续篇(四) (转)

原创 网络安全 作者:themoney 时间:2007-10-05 14:41:51 0 删除 编辑
联众升级协议分析 续篇(四) (转)[@more@]

联众升级协议分析 续篇(四)

云网(Mailto:jimzj@21cn.com">jimzj@21cn.com)

接上篇

 

 XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:office" />

二、发牌命令

原来我分析牌时,因为是先从出牌入手的,所以得到的牌的代号只有13个,还有牌的颜色,所以在分析这个命令时一度陷入不能得到结果的地步,不过经过一天的苦想,终于明白过来了,呵呵,在这里先为自己能想到这个干杯一下。J

 

0x0050  17 20 00 00 04 00 00 00-01 00 00 00 16 20 00 00  . ........... ..

0x0060  29 00 00 00 19 00 00 00-FF FF FF FF F4 01 00 00  ).......?????..

0x0070  00 00 00 00 38 4A 27 29-13 17 3B 5D 44 32 0F 12  ....8J')..;]D2..

0x0080  5A 58 6A 2E 45 0B 64 24-56 16 3A 3E 05  ZXj.E.d$V.:>.

 

从上面的数据看命令字是0x00002016,再上面一个命令字0x00002017是开始一局游戏标志,这个用来标志一些状态用的;再看一下0x19(也就是十进制的25)呵呵,想一下我们四个人打两付牌时8个底牌,总共是(54*2 – 8 )/ 4 = 25 刚好,这个位置就是发给我们的牌数(因为还有一付牌,三付牌)我们再看一下数据从38 4A 27 29-13 17 3B 5D 44 32 0F 12 5A 58 6A 2E 45 0B 64 24-56 16 3A 3E 05是不是刚好也就25个,这个就是服务器发给每一个玩家的牌了,在玩这个游戏时,我们在客户端看到的是一个一个牌得到的,但实际上,一开始我们就全部得到了,如果你解开了这个协议,一开始我们就知道了所有自己的牌,不就可以知道了能叫什么颜色,是否能反别人的牌,还有每一种花色的牌的多少,岂不是很好……

  我们定义的数据结构如下:

typedef struct _tagSHJIFaDePaiInfo

{

  int  nCount ;  //牌数

  char  cUser  ; 

  char  cFlag1 ;

  char  cFlag2 ;

  char  cFlag3 ;

 

  int  nFlag1 ;

  int  nFlag2 ;

}SHJIFaDePaiInfo, *lpSHJIFaDePaiInfo ;

结构中不包牌的信息,因为移动指针后,就可以读到牌的信息了(每一个位Byte表示一个牌),如下所示:

 

void __fastcall TFrmMain::RevFaDePaiInfo( char * pPackContent )

{

  SHJIFaDePaiInfo * pInfo = ( SHJIFaDePaiInfo * )pPackContent ;

 

  for( int i = 0 ; i < pInfo->nCount ; i ++ )

  {

  byte btCard = * ((byte *)(( byte * )( pInfo + 1 ) + i * sizeof( byte ))) ; 

    ………………

}

}

三、叫牌命令

每一轮出牌前总会有一个人先叫牌的信息,所以在这里这个命令会在出牌前,可能有多个这样的命令,但最后一个命令就是用户最终叫主了。

 

0x0000  11 20 00 00 18 00 00 00-01 00 E0 00 01 00 00 00  . ........?....

0x0010  01 00 00 00 01 00 00 00-DE 05 00 00 02 00 00 00  ........?......

 

叫牌的内容应该包括,那一个用户叫的牌,牌的颜色(黑桃,红桃,草花,方块),叫牌的数量(一个或一双),从上面的我添加的颜色的数据看到,正好就是这三个位置的信息了,这个可能你的多接收几次数据,对比后才会得到,我也是接收了几次叫牌的信息后才分析出来的:

所以我们定义的叫牌的数据结构如下所示:

typedef struct _tagSHJIJiaoPaiInfo

{

  char  cUser ;  //叫牌用户编号

  char  cFlag0 ;

  char  cFlag1 ;

  char  cFlag2 ;

  char  cColor ;  //颜色(大王=0x35,小王=0x34)

  char  cFlag3 ;

  char  cFlag4 ;

  char  cFlag5 ;

 

  char  cCount ;  //叫的张数

  char  cFlag6 ;

  char  cFlag7 ;

  char  cFlag8 ;

  char  cFlag14 ;

  char  cFlag9 ;

  char  cFlag10 ;

  char  cFlag11 ;

 

  int  nFlag12 ;

  int  nFlag13 ;

}SHJIJiaoPaiInfo, *lpSHJIJiaoPaiInfo ;

 

数据结构中的其它的数据标志位是暂时我还不清楚有什么用途,不过只要知道我们想要的足够的信息就可以了。

下面是取得叫牌的信息:

 

void __fastcall TFrmMain::RevJiaoPaiInfo( char * pPackContent )

{

  SHJIJiaoPaiInfo * pInfo = ( SHJIJiaoPaiInfo * )pPackContent ;

 

  if( m_eZhuColor != ( GAMECARDCOLOR )pInfo->cColor )

  {

  m_eZhuColor = ( GAMECARDCOLOR )pInfo->cColor ;

  ShowInitImagePic( m_cDaJi, m_eZhuColor ) ; //显示在界面上

  }

  SetJiaoPaiPic( pInfo->cUser, m_eZhuColor, pInfo->cCount ) ; //显示那一个用户叫牌

}

 

取得叫牌的信息,你就可以显示在自己的外挂界面上,同时也可以区分用户出牌时主还是付牌了J

 

四、扣底命令

如果你是庄家,会的扣底牌的信息,否则,服务器发送的这个指令中是不包含这个底牌的信息的。

 

0x0000  03 20 00 00 E4 00 00 00-03 00 00 00 1E 00 00 00  . ..?..........

0x0010  03 00 00 00 05 00 00 00-00 00 00 00 01 00 00 00  ................

0x0020  00 00 00 00 01 00 00 00-1D 00 00 00 03 00 00 00  ................

 

在这个指令中,并没有包括底牌的个数据,不知联众在做这个命令字是为会缺了这个?所以你必需自己去计算一下底牌的个数了,不过只有两种,一付牌和三付牌时是6个底,二付牌时是8个底,这样就可以把底牌的信息取得了,在扣底的信息中还包含了是那一个用户扣底的,也就是第一个出牌的户了,这个信息用来指示那一个用户最先出牌,不过如果知道庄家是谁也同样可以知道第一个出牌人的编号。定义的数据结构如下所示:

 

 

typedef struct _tagSHJICaoDiFlag

{

  char  cUser ;  //第一个出牌用户(庄家)

  char  cFlag0 ;

  char  cFlag1 ;

  char  cFlag2 ;

}SHJICaoDiFlag, *lpSHJICaoDiFlag ;

 

typedef struct _tagSHJICaoDiInfo

{

  int  nPosition ; //位置信息

 

  char  cColor ;  //牌颜色

  char  cFlag0 ;

  char  cFlag1 ;

  char  cFlag2 ;

 

  char  cCard  ;  //底牌

  char  cFlag3 ;

  char  cFlag4 ;

  char  cFlag5 ;

 

  int  nFlag6 ;

  int  nFlag7 ;

  int  nFlag8 ;

  int  nFlag9 ;

}SHJICaoDiInfo, *lpSHJICaoDiInfo ;

 

因为前段的信息只有一个,后段的每一个牌的信息是循环出现的,所以从扣底的个数就可以得到每一个底牌的信息了。

 

void __fastcall TFrmMain::RevCaoDiInfo( char * pPackContent, int nLen )

{

  SHJICaoDiFlag * pInfo = ( SHJICaoDiFlag * )pPackContent ;

 

  m_bCanCaculate = true ;  //开始计算标志

 

  m_ZhangJia = (( pInfo->cUser < POS_LEFT || pInfo->cUser > POS_BOT ) ? 0 : pInfo->cUser ) ; 

 

if( nLen == 4 ) return ;  //如果不包括底牌信息返回

 

  //底牌信息

  for( int i = 0 ; i < m_DiPaiCount ; i ++ )  // DiPaiCount是底牌的个数

  {

  SHJICaoDiInfo * pCard = ( SHJICaoDiInfo * )( ( char * )( pInfo + 1 ) + i * sizeof( SHJICaoDiInfo )) ;

 

  //显示在外挂界面上底牌的信息

  UnShowImagePicInfo(( GAMECARDCOLOR )pCard->cColor, pCard->cCard ) ;

  ShowPicOnImage(( GAMECARDCOLOR )pCard->cColor, pCard->cCard, PanelDIPAI ) ;

  }

}

 

取得和底牌信息可以显示在界面上,不必每次看是要自己去点击客户端的查看底牌信息按键,同时如果你是看别人打牌,他设置了不让旁观者看时,你也可以直接看到他的底牌信息,呵呵J


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10794571/viewspace-974813/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    119
  • 访问量
    337807