淺談貝貝遊戲資料加密解密方式

李鬼vs李逵發表於2015-10-20
  貝貝遊戲 網址www.game499.com 這個遊戲和其他的網狐的客服端不同,介面不同其次主要的不同是他們資料加密方法不同,傳統的資料加密方式如下,因為手上有網狐的原始碼所以直接上原始碼
//加密資料
WORD CTCPSocket::EncryptBuffer(BYTE pcbDataBuffer[], WORD wDataSize, WORD wBufferSize)
{
	//效驗引數
	ASSERT(wDataSize>=sizeof(TCP_Head));
	ASSERT(wBufferSize>=(wDataSize+2*sizeof(DWORD)));
	ASSERT(wDataSize<=(sizeof(TCP_Head)+SOCKET_TCP_PACKET));

	//調整長度
	WORD wEncryptSize=wDataSize-sizeof(TCP_Command),wSnapCount=0;
	if ((wEncryptSize%sizeof(DWORD))!=0)
	{
		wSnapCount=sizeof(DWORD)-wEncryptSize%sizeof(DWORD);
		memset(pcbDataBuffer+sizeof(TCP_Info)+wEncryptSize,0,wSnapCount);
	}

	//效驗碼與位元組對映
	BYTE cbCheckCode=0;
	for (WORD i=sizeof(TCP_Info);i<wDataSize;i++)
	{
		cbCheckCode+=pcbDataBuffer[i];
		pcbDataBuffer[i]=MapSendByte(pcbDataBuffer[i]);
	}

	//填寫資訊頭
	TCP_Head * pHead=(TCP_Head *)pcbDataBuffer;
	pHead->TCPInfo.cbCheckCode=~cbCheckCode+1;
	pHead->TCPInfo.wPacketSize=wDataSize;
	pHead->TCPInfo.cbDataKind=SOCKET_VER;

	//建立金鑰
	DWORD dwXorKey=m_dwSendXorKey;
	if (m_dwSendPacketCount==0)
	{
		//生成第一次隨機種子
		GUID Guid;
		CoCreateGuid(&Guid);
		dwXorKey=GetTickCount()*GetTickCount();
		dwXorKey^=Guid.Data1;
		dwXorKey^=Guid.Data2;
		dwXorKey^=Guid.Data3;
		dwXorKey^=*((DWORD *)Guid.Data4);
		
		//隨機對映種子
		dwXorKey=SeedRandMap((WORD)dwXorKey);
		dwXorKey|=((DWORD)SeedRandMap((WORD)(dwXorKey>>16)))<<16;
		dwXorKey^=g_dwPacketKey;
		m_dwSendXorKey=dwXorKey;
		m_dwRecvXorKey=dwXorKey;
	}

	//加密資料
	WORD * pwSeed=(WORD *)(pcbDataBuffer+sizeof(TCP_Info));
	DWORD * pdwXor=(DWORD *)(pcbDataBuffer+sizeof(TCP_Info));
	WORD wEncrypCount=(wEncryptSize+wSnapCount)/sizeof(DWORD);
	for (i=0;i<wEncrypCount;i++)
	{
		*pdwXor++^=dwXorKey;
		dwXorKey=SeedRandMap(*pwSeed++);
		dwXorKey|=((DWORD)SeedRandMap(*pwSeed++))<<16;
		dwXorKey^=g_dwPacketKey;
	}

	//插入金鑰
	if (m_dwSendPacketCount==0)
	{
		MoveMemory(pcbDataBuffer+sizeof(TCP_Head)+sizeof(DWORD),pcbDataBuffer+sizeof(TCP_Head),wDataSize);
		*((DWORD *)(pcbDataBuffer+sizeof(TCP_Head)))=m_dwSendXorKey;
		pHead->TCPInfo.wPacketSize+=sizeof(DWORD);
		wDataSize+=sizeof(DWORD);
	}

	//設定變數
	m_dwSendPacketCount++;
	m_dwSendXorKey=dwXorKey;

	return wDataSize;
}
<pre name="code" class="cpp">//解密資料
WORD CTCPSocket::CrevasseBuffer(BYTE pcbDataBuffer[], WORD wDataSize)
{
	//效驗引數
	ASSERT(m_dwSendPacketCount>0);
	ASSERT(wDataSize>=sizeof(TCP_Head));
	ASSERT(((TCP_Head *)pcbDataBuffer)->TCPInfo.wPacketSize==wDataSize);


	//調整長度
	WORD wSnapCount=0;
	if ((wDataSize%sizeof(DWORD))!=0)
	{
		wSnapCount=sizeof(DWORD)-wDataSize%sizeof(DWORD);
		memset(pcbDataBuffer+wDataSize,0,wSnapCount);
	}


	//解密資料
	DWORD dwXorKey=m_dwRecvXorKey;
	DWORD * pdwXor=(DWORD *)(pcbDataBuffer+sizeof(TCP_Info));
	WORD  * pwSeed=(WORD *)(pcbDataBuffer+sizeof(TCP_Info));
	WORD wEncrypCount=(wDataSize+wSnapCount-sizeof(TCP_Info))/4;
	for (WORD i=0;i<wEncrypCount;i++)
	{
		if ((i==(wEncrypCount-1))&&(wSnapCount>0))
		{
			BYTE * pcbKey=((BYTE *)&m_dwRecvXorKey)+sizeof(DWORD)-wSnapCount;
			CopyMemory(pcbDataBuffer+wDataSize,pcbKey,wSnapCount);
		}
		dwXorKey=SeedRandMap(*pwSeed++);
		dwXorKey|=((DWORD)SeedRandMap(*pwSeed++))<<16;
		dwXorKey^=g_dwPacketKey;
		*pdwXor++^=m_dwRecvXorKey;
		m_dwRecvXorKey=dwXorKey;
	}


	//效驗碼與位元組對映
	TCP_Head * pHead=(TCP_Head *)pcbDataBuffer;
	BYTE cbCheckCode=pHead->TCPInfo.cbCheckCode;
	for (int i=sizeof(TCP_Info);i<wDataSize;i++)
	{
		pcbDataBuffer[i]=MapRecvByte(pcbDataBuffer[i]);
		cbCheckCode+=pcbDataBuffer[i];
	}
	if (cbCheckCode!=0) throw TEXT("資料包效驗碼錯誤");


	return wDataSize;
}


上面程式碼是從網狐的原始碼裡面摘選出來的 他們預設的加密和解密祕鑰是:0X12345678 這種加密方式和解密方式很簡單安全性呢說呢如果資料被攔截 比如通過裝置攔截資料是可以再中間加密解密出來的,就是說如果有人想從資料方面 至少是可以把資料給攔截下面並且知道里面具體是什麼資料,在安全性方面並不能夠達到特別安全‘

  然而對於貝貝遊戲,貝貝遊戲原始碼應該是從之前998遊戲手上購買的,他們的加密形式比較複雜,因為我手上並沒有貝貝遊戲的原始碼 我只能通過逆向簡單說一下他們的加密方式

加密方式主要有AES加密 

我找了一個AES 加密解密的DEMO 截圖


<pre name="code" class="cpp">"

還有一種是RSA加密 

(RSA是目前最有影響力的公鑰加密演算法,它能夠抵抗到目前為止已知的絕大多數密碼攻擊,已被ISO推薦為公鑰資料加密標準)


可見他們加密的嚴密程度是非常嚴的,可以斷定的說即使你在中途把資料攔截下來你如果沒有私鑰你也沒法破解出祕鑰的,因為對於RSA私鑰只會儲存到遊戲伺服器端,其他地方均不會出現。

下面是百度RSA加密解密處理流程

  大概理論知識說得差不多了,接下來我們主要給大家理清一下這個棋牌遊戲他是如何和伺服器通訊的

  大概步驟是這樣的 

1:第一步 客服端和伺服器建立起TCP 連結,3次握手後傳送資料給伺服器端,第一個傳送的資料是AES的加密金鑰,這個金鑰是隨機生成的,以後在這個SOCK連線中一直是用這個祕鑰進行通訊的,客服端先隨機生成一個祕鑰然後通過用RSA的方法+RSA公鑰加密 把加密資料傳送到伺服器端

   伺服器端通過RSA私鑰把傳送過來的資料解密出來,解密出來的即是AES的金鑰,這個金鑰是既作為在這個SOCK斷開之前一直用的。到目前為止RSA加密就到此為止了,之後RSA即派不上用場了,所以RSA演算法只是作為一個加密金鑰的作用,那有人會問這樣安全嗎?說實話正是因為用RSA演算法才讓整個接下來的資料變得安全,因為一般的加密演算法都是一個金鑰,客服端要加密這個金鑰肯定會在客服端出現,然後RSA機制是公鑰在客服端,然後私鑰只在服務端,即保證了在傳送祕鑰的過程中即使資料被攔截人家要解密不出來金鑰,還有人會問既然這麼安全為什麼不一致都用RSA呢,其實很簡單RSA加密演算法安全其實是建立在他複雜上面,既然複雜他的處理流程是很慢的,加密解密速度是很慢的,尤其是作為遊戲如果光一個資料加密解密就需要很長時間,那麼遊戲之前通訊如此頻繁遊戲肯定會感覺很卡,因為資料不能及時被處理。所以他只是在建立SOCK的時候呼叫一下這個演算法

2:第二步 既然客服端隨機生成的祕鑰已經通知到伺服器端了,那麼他們之後的資料都是用AES 這種演算法速度很快,而且在不知道金鑰的情況下也是很安全的,而這個金鑰是

隨機的,所以你說安全嗎

 貝貝遊戲AES加密演算法呼叫處


貝貝遊戲AES解密演算法呼叫處


   上面截圖是在貝貝遊戲中AES加密解密的地方。

   大概貝貝的資料加密解密就是通過上面2個步驟,所以說貝貝遊戲在資料安全性方面還是很不錯的,至少個人感覺很嚴密。

上面大致闡述了一下貝貝遊戲的在通訊方面的方式方法,裡面可能有很多因為自己能力有限有錯誤的地方或者有限的地方請自動忽略,個人微信feilongqp  歡迎加我


   


相關文章