📄 sock.cpp
字号:
/******************************************************
网络类,用于各个模块在发送和接收数据时调用
作者:颜永华
*******************************************************/
#include "StdAfx.h"
#include ".\sock.h"
#include "BlowFish.h"
#include "MD5.h"
#include "OPCODE.H"
extern CLIENT_STATUS clientStatus;
CSock::CSock(void)
{
::ZeroMemory(Key.SendKey,8);
::ZeroMemory(Key.RecvKey,8);
}
CSock::~CSock(void)
{
}
int CSock::sendPacket(BYTE *packet,int len)
{//发送封包
int packetLen=len+9;
BYTE *pPack=(BYTE*)malloc(sizeof(BYTE)*(packetLen));
//加密封包
EnCodeFlow(Key.SendKey,Key.SendKey,packet,pPack,len,0X11);
int i=send(sock,(char*)pPack,packetLen,0);
free(pPack);
if(i!=packetLen)
return 0;
return 1;
}
int CSock::RetFlag()
{
//拆包
CHAR RetFlagBuff[6];
int len=recv(sock,(char*)RetFlagBuff,sizeof(RETFLAG)+1,0);
LPRETFLAG RetFlag=(LPRETFLAG)RetFlagBuff;
if(len+1==sizeof(RETFLAG))
{//控制 看是那个操作的返回
switch(_OPCODE(RetFlag))
{
case SERVER_FIRST_REG:
return RetFlag->bFlag;
case SERVER_LOGIN://成功显示信息
if(RetFlag->bFlag==FLAG_SUCCEED)
{ //登陆成功 请求显示封包
//打包
REQSHOW reqShow;
memset(&reqShow,0,sizeof(REQSHOW));
reqShow.wCode=CLIENT_SHOW_INFO;
reqShow.wLen=sizeof(REQSHOW);
strcpy(reqShow.customerName,clientStatus.cUserName);
if(sendPacket((BYTE*)&reqShow,sizeof(REQSHOW)))
{//保存接收到的显示数据,维护用户信息结构
char showBuff[sizeof(SHOW_INFO_PACKET)];
len=recv(sock,showBuff,sizeof(SHOW_INFO_PACKET),0);
if(len+1==sizeof(SHOW_INFO_PACKET))
{//保存状态信息
LPSHOW_INFO_PACKET pShow=(LPSHOW_INFO_PACKET)showBuff;
strcpy(clientStatus.Addr,pShow->Addr);
strcpy(clientStatus.Email,pShow->Email);
strcpy(clientStatus.Phone,pShow->Phone);
strcpy(clientStatus.RealName,pShow->RealName);
strcpy(clientStatus.RegBankIP,pShow->RegBankIP);
clientStatus.nGrade=pShow->nGrade;
clientStatus.nScore=pShow->nScore;
}
}
}return RetFlag->bFlag;
case SERVER_INMONEY:
return RetFlag->bFlag;
case SERVER_OUTMONEY:
return RetFlag->bFlag;
case SERVER_TRANSFER:
return RetFlag->bFlag;
case SERVER_NOTIFY_PASSWORD:
return RetFlag->bFlag;
default:
return -1;
}
}else
return -1;
}
int CSock::connectServer()
{
//连接服务器
sock=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED);
//定义地址结构
sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_addr.S_un.S_addr=inet_addr("192.168.0.136");
addr.sin_port=htons(8888);
if(SOCKET_ERROR==(::connect(sock,(sockaddr*)&addr,sizeof(addr))))
{
::MessageBox(NULL,"连接服务器失败!","系统提示",0);
return 0;
}
//接收密钥
recv(sock,(char*)Key.RecvKey,8,0);
recv(sock,(char*)Key.SendKey,8,0);
//解密KEY
DeCodeKey(Key.RecvKey);
///////////
/*CString str;
for(int i=0;i<8;i++)
{str.Format("-%02X",Key.RecvKey[i]);
::OutputDebugString(str);}*/
//////////
DeCodeKey(Key.SendKey);
///////
/*for(int i=0;i<8;i++)
{str.Format("-%02X",Key.SendKey[i]);
::OutputDebugString(str);}*/
//////
return 1;
}
void CSock::disconnectServer()
{ //断开连接
closesocket(sock);
sock=INVALID_SOCKET;
}
int CSock::recvpacket(char *packet,int len)
{
return recv(sock,packet,len,0);//返回接收到的接收字节数
}
void CSock::recvReturnUserInfo(char userName[],char pwd[],char UserClass[],
char UserPoint[],char IPAddr[],char Phone[],char UserId[])
{
//接收返回用户信息
char buff[70];
::recv(sock,buff,70,0);
buff[68]='\0';
//memcpy(realName,&buff[0],10);
memcpy( UserId,buff,18);
memcpy(Phone,&buff[18],15);
memcpy(IPAddr,&buff[33],15);
memcpy(UserPoint,&buff[48],10);
memcpy(UserClass,&buff[58],10);
}
//利用key产生动态vkey
//
void CSock::ProduceNewKey(const BYTE *key, BYTE *vkey)
{
int a, b;
//b = (int)&a; //读取局部变量地址
__asm lea eax, a;
__asm mov ebx, [ebp + 4];
//__asm mov ebx, [ebx + 4]; //读取二级返回地址
__asm mov ecx, vkey;
__asm mov word ptr [ecx], ax;
__asm mov word ptr [ecx + 4], bx;
__asm lea eax, b;
__asm mov ebx, [ebp];
__asm mov ebx, [ebx + 4]; //读取二级返回地址
__asm mov word ptr [ecx + 6], ax;
__asm mov word ptr [ecx + 2], bx;
//*(int *)vkey = b;
//*(int *)(vkey + 4) = (int)&b;
for(int i = 0; i < 8; i++) //key前4个字节和局部变量地址异或产生vkey前4个字节
vkey[i] ^= key[i]; //,key后4个字节和二级返回地址异或产生vkey后四个字节
}
//利用key产生vkey所要插入封包的位置放在pos[8]中
void CSock::position(const BYTE *key, BYTE *pos, int len)
{
for(int i = 0; i < 8; i++) //得到8个插入位置(0-100,100为长度)
pos[i] = key[i] % (len + 9);
for(int i = 0; i < 8; i++) //如果插入位置为0的话改成1
if(0 == pos[i])pos[i] = 1;
}
//按pos位置把vkey插入到封包中再次打包放在outChar中
void CSock::ReWriteBag(const BYTE *pos, const BYTE *vkey, const BYTE *inChar, BYTE * outChar, int len, BYTE flag)
{
outChar[len + 8] = flag; //把标志位插入outChar[len+9]最后一个字节
for(int i = 0; i < len; i++) //首先把数据密文拷贝到outChar[108]中,预留了8个字节存放动态vkey
outChar[i] = inChar[i];
int currentLen = len;
for(int i = 0; i < 8; i++) //8个字节一个一个插入,从左到右插入
{
if(pos[i] > currentLen) outChar[pos[i] - 1] = vkey[i]; //如果插入位置大于当前长度,就不必移动其它字节
else //否则就要移动其它字节空出一个字节以便插入了
{
for(int j = currentLen; j >= pos[i]; j--) //移动其它字节
outChar[j] = outChar[j - 1];
outChar[j] = vkey[i]; //插入
}
currentLen++; //当前长度加1
}
}
//按照pos位置从封包中取出vkey[8],剩下的数据放在inChar中
void CSock::ReduceBag(const BYTE *pos, BYTE *outChar, BYTE *vkey, BYTE *inChar, int len)
{
int currentLen = len + 8;
for(int i = 7; i >= 0; i--) //取出vkey,共8个字节,一个一个取,从右到左取出
{
vkey[i] = outChar[pos[i] - 1]; //首先要取出的放到vkey中去
for(int j = pos[i]; j <= currentLen - 1; j++) //每取出一个字节就要把后面的字节一个一个移上来
outChar[j - 1] = outChar[j];
currentLen--; //当前长度减1
}
for(int i = 0; i < len; i++) //取出vkey后的封包放到inChar[100]中去,此时inChar就是取出了vkey的密文了
inChar[i] = outChar[i];
}
//对数据包进行加密
void CSock::EnCode(const BYTE *key, BYTE *inChar, int len)
{
for(int i = 0; i < len; i++)
inChar[i] ^= key[i % 8];
}
//对数据包进行解密,加密算法的逆序
void CSock::DeCode(const BYTE *key, BYTE *inChar, int len)
{
for(int i = 0; i < len; i++)
inChar[i] ^= key[i % 8];
}
//填充客户端和服务器端交互所用到的key
void CSock::FillinKey(BYTE *key, const BYTE *vkey)
{
for(int i = 0; i < 8; i++)
// key[i] = vkey[i];
{
__asm mov edi, vkey;
__asm mov esi, key;
__asm add edi, i;
__asm add esi, i;
__asm mov al, byte ptr [edi];
__asm mov byte ptr [esi], al;
}
}
//发包时:
//DataPack存放着原数据
//len为DataPack封包长度,HandlePack长度为(len+9),标志位插在最后一个字节里
void CSock::EnCodeFlow(BYTE *key, BYTE *vkey, BYTE *DataPack, BYTE *HandledPack, int len, BYTE flag)
{
BYTE pos[8];
EnCode(key, DataPack, len); //加密数据包
if(0x13 == flag)
{
ProduceNewKey(key, vkey); //产生动态vkey
position(key, pos, len); //利用key产生插入位置放在pos[8]中
ReWriteBag(pos, vkey, DataPack, HandledPack, len, flag); //重新打包放在HandledPack[len+9]中
FillinKey(key, vkey);
}
else
{
for(int i = 0; i < len; i++)
HandledPack[i] = DataPack[i];
HandledPack[len + 8] = flag;
}
//HandledPack中存放着密文
}
//接包时:
//HandledPack存放着密文
//len为DataPack封包长度,HandlePack长度为(len+9)
BYTE CSock::DeCodeFlow(BYTE *key, BYTE *vkey, BYTE *DataPack, BYTE *HandledPack, int len)
{
BYTE flag = HandledPack[len + 8];
if(0x13 == flag) //如果是最后一个包就要从里面取出动态密钥
{
BYTE pos[8];
position(key, pos, len); //利用key产生插入位置放在pos[8]中
ReduceBag(pos, HandledPack, vkey, DataPack, len); //把要交换的动态密钥从HandledPack抽出放到vkey去,抽出后的HandledPack存到DataPack中去
}
else //如果不是最后一个包就不要取密钥
{
for(int i = 0; i < len; i++)
DataPack[i] = HandledPack[i];
}
DeCode(key, DataPack, len); //对DataPack包解密
FillinKey(key, vkey); //用接受到的动态vkey填充key
return flag;
//DataPack中存放着明文
}
//连接时从服务器端接受的key进行解密
void CSock::DeCodeKey(BYTE *key)
{
char var_array[10] = "dengchong";
//for(int i = 0; i < 8; i++)
// scanf("%c", &var_array[i]);
//cin>>var_array[i];
for(int i = 0; i < 8; i++)
key[i] ^= var_array[i];
}
//加密金钱数据
void CSock::EnCodeMoney(BYTE *key, BYTE *vkey, BYTE *DataPack, BYTE *HandledPack)
{
BYTE pos[8];
BlowFish BF;
BF.gBlowFishInit(key);
BF.gBlowFishEnCode(DataPack, DataPack);
ProduceNewKey(key, vkey);
position(key, pos, 8);
ReWriteBag(pos, vkey, DataPack, HandledPack, 8, 0x13);
FillinKey(key, vkey);
}
void CSock::DeCodeMoney(BYTE *key, BYTE *vkey, BYTE *DataPack, BYTE *HandledPack)
{
BYTE pos[8];
position(key, pos, 8);
ReduceBag(pos, HandledPack, vkey, DataPack, 8);
BlowFish BF;
BF.gBlowFishInit(key);
BF.gBlowFishDeCode(DataPack, DataPack);
FillinKey(key, vkey);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -