OregonCore  revision 3611e8a-git
Your Favourite TBC server
WardenMac.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
19 #include "Common.h"
20 #include "WorldPacket.h"
21 #include "WorldSession.h"
22 #include "Log.h"
23 #include "Opcodes.h"
24 #include "ByteBuffer.h"
25 #include <openssl/md5.h>
26 #include "World.h"
27 #include "Player.h"
28 #include "Util.h"
29 #include "WardenMac.h"
30 #include "WardenModuleMac.h"
31 
33 {
34 }
35 
37 {
38 }
39 
41 {
42  Client = pClient;
43  // Generate Warden Key
44  SHA1Randx WK(K->AsByteArray(), K->GetNumBytes());
45  WK.generate(InputKey, 16);
46  WK.generate(OutputKey, 16);
47  /*
48  Seed: 4D808D2C77D905C41A6380EC08586AFE (0x05 packet)
49  Hash: <?> (0x04 packet)
50  Module MD5: 0DBBF209A27B1E279A9FEC5C168A15F7
51  New Client Key: <?>
52  New Server Key: <?>
53  */
54  uint8 mod_seed[16] = { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE };
55 
56  memcpy(Seed, mod_seed, 16);
57 
60  sLog.outDebug("Server side warden for client %u initializing...", pClient->GetAccountId());
61  sLog.outDebug(" C->S Key: %s", ByteArrayToHexStr(InputKey, 16).c_str());
62  sLog.outDebug(" S->C Key: %s", ByteArrayToHexStr(OutputKey, 16).c_str());
63  sLog.outDebug(" Seed: %s", ByteArrayToHexStr(Seed, 16).c_str());
64  sLog.outDebug("Loading Module...");
65 
67 
68  sLog.outDebug(" Module Key: %s", ByteArrayToHexStr(Module->Key, 16).c_str());
69  sLog.outDebug(" Module ID: %s", ByteArrayToHexStr(Module->ID, 16).c_str());
70  RequestModule();
71 }
72 
74 {
76 
78 
79  // data assign
80  mod->CompressedSize = len;
81  mod->CompressedData = new uint8[len];
84 
85  // md5 hash
86  MD5_CTX ctx;
87  MD5_Init(&ctx);
88  MD5_Update(&ctx, mod->CompressedData, len);
89  MD5_Final((uint8*)&mod->ID, &ctx);
90 
91  return mod;
92 }
93 
95 {
96  sLog.outDebug("Initialize module");
97 }
98 
100 {
101  sLog.outDebug("Request hash");
102 
103  // Create packet structure
104  WardenHashRequest Request;
106  memcpy(Request.Seed, Seed, 16);
107 
108  // Encrypt with warden RC4 key.
109  EncryptData((uint8*)&Request, sizeof(WardenHashRequest));
110 
112  pkt.append((uint8*)&Request, sizeof(WardenHashRequest));
113  Client->SendPacket(&pkt);
114 }
115 
117 {
118 
119  // test
120  int keyIn[4];
121 
122  uint8 mod_seed[16] = { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE };
123 
124  for (int i = 0; i < 4; ++i)
125  keyIn[i] = *(int*)(&mod_seed[0] + i * 4);
126 
127  int keyOut[4];
128  int keyIn1, keyIn2;
129  keyOut[0] = keyIn[0];
130  keyIn[0] ^= 0xDEADBEEFu;
131  keyIn1 = keyIn[1];
132  keyIn[1] -= 0x35014542u;
133  keyIn2 = keyIn[2];
134  keyIn[2] += 0x5313F22u;
135  keyIn[3] *= 0x1337F00Du;
136  keyOut[1] = keyIn1 - 0x6A028A84;
137  keyOut[2] = keyIn2 + 0xA627E44;
138  keyOut[3] = 0x1337F00D * keyIn[3];
139  // end test
140 
141  buff.rpos(buff.wpos());
142 
143  Sha1Hash sha1;
144  sha1.UpdateData((uint8*)keyIn, 16);
145  sha1.Finalize();
146 
147  //const uint8 validHash[20] = { 0x56, 0x8C, 0x05, 0x4C, 0x78, 0x1A, 0x97, 0x2A, 0x60, 0x37, 0xA2, 0x29, 0x0C, 0x22, 0xB5, 0x25, 0x71, 0xA0, 0x6F, 0x4E };
148 
149  // verify key not equal kick player
150  if (memcmp(buff.contents() + 1, sha1.GetDigest(), 20) != 0)
151  {
152  sLog.outWarden("Request hash reply: failed");
153  if (sWorld.getConfig(CONFIG_WARDEN_KICK))
154  Client->KickPlayer();
155  return;
156  }
157 
158  sLog.outDebug("Request hash reply: succeed");
159 
160  // client 7F96EEFDA5B63D20A4DF8E00CBF48304
161  //const uint8 client_key[16] = { 0x7F, 0x96, 0xEE, 0xFD, 0xA5, 0xB6, 0x3D, 0x20, 0xA4, 0xDF, 0x8E, 0x00, 0xCB, 0xF4, 0x83, 0x04 };
162 
163  // server C2B7ADEDFCCCA9C2BFB3F85602BA809B
164  //const uint8 server_key[16] = { 0xC2, 0xB7, 0xAD, 0xED, 0xFC, 0xCC, 0xA9, 0xC2, 0xBF, 0xB3, 0xF8, 0x56, 0x02, 0xBA, 0x80, 0x9B };
165 
166  // change keys here
167  memcpy(InputKey, keyIn, 16);
168  memcpy(OutputKey, keyOut, 16);
169 
172 
173  m_initialized = true;
174 
176 }
177 
179 {
180  sLog.outDebug("Request data");
181 
182  ByteBuffer buff;
184 
185  std::string str = "Test string!";
186 
187  buff << uint8(str.size());
188  buff.append(str.c_str(), str.size());
189 
190  buff.hexlike();
191 
192  // Encrypt with warden RC4 key.
193  EncryptData(const_cast<uint8*>(buff.contents()), buff.size());
194 
195  WorldPacket pkt(SMSG_WARDEN_DATA, buff.size());
196  pkt.append(buff);
197  Client->SendPacket(&pkt);
198 
199  m_WardenDataSent = true;
200 }
201 
203 {
204  sLog.outDebug("Handle data");
205 
206  m_WardenDataSent = false;
207  m_WardenKickTimer = 0;
208 
209  //uint16 Length;
210  //buff >> Length;
211  //uint32 Checksum;
212  //buff >> Checksum;
213 
214  //if (!IsValidCheckSum(Checksum, buff.contents() + buff.rpos(), Length))
215  //{
216  // buff.rpos(buff.wpos());
217  // if (sWorld.getConfig(CONFIG_BOOL_WARDEN_KICK))
218  // Client->KickPlayer();
219  // return;
220  //}
221 
222  bool found = false;
223 
224  std::string str = "Test string!";
225 
226  Sha1Hash sha1;
227  sha1.UpdateData(str);
228  uint32 magic = 0xFEEDFACE; // unsure
229  sha1.UpdateData((uint8*)&magic, 4);
230  sha1.Finalize();
231 
232  uint8 sha1Hash[20];
233  buff.read(sha1Hash, 20);
234 
235  if (memcmp(sha1Hash, sha1.GetDigest(), 20))
236  {
237  sLog.outWarden("Handle data failed: SHA1 hash is wrong!");
238  found = true;
239  }
240 
241  MD5_CTX ctx;
242  MD5_Init(&ctx);
243  MD5_Update(&ctx, str.c_str(), str.size());
244  uint8 ourMD5Hash[16];
245  MD5_Final(ourMD5Hash, &ctx);
246 
247  uint8 theirsMD5Hash[16];
248  buff.read(theirsMD5Hash, 16);
249 
250  if (memcmp(ourMD5Hash, theirsMD5Hash, 16))
251  {
252  sLog.outWarden("Handle data failed: MD5 hash is wrong!");
253  found = true;
254  }
255 
256  if (found && sWorld.getConfig(CONFIG_WARDEN_KICK))
257  Client->KickPlayer();
258 }
ClientWardenModule * Module
Definition: WardenBase.h:126
const uint8 * contents() const
Definition: ByteBuffer.h:331
bool m_WardenDataSent
Definition: WardenBase.h:124
uint8 * AsByteArray(int minSize=0, bool reverse=true)
Definition: BigNumber.cpp:166
void Init(WorldSession *pClient, BigNumber *K)
Definition: WardenMac.cpp:40
int GetNumBytes(void)
Definition: BigNumber.cpp:151
uint32 CompressedSize
Definition: WardenBase.h:82
uint32 getMSTime()
Definition: Timer.h:32
void Init(uint8 *seed)
Definition: SARC4.cpp:41
#define sLog
Log class singleton.
Definition: Log.h:187
uint8 Seed[16]
Definition: WardenBase.h:69
uint32 m_WardenKickTimer
Definition: WardenBase.h:123
SARC4 oCrypto
Definition: WardenBase.h:121
uint32 GetAccountId() const
Definition: WorldSession.h:100
void SendPacket(WorldPacket const *packet)
void RequestData()
Definition: WardenMac.cpp:178
uint8 * GetDigest(void)
Definition: Sha1.h:41
uint32 m_WardenTimer
Definition: WardenBase.h:125
uint8 * CompressedData
Definition: WardenBase.h:83
void generate(uint8 *buf, uint32 sz)
size_t wpos() const
Definition: ByteBuffer.h:264
ACE_UINT8 uint8
Definition: Define.h:73
void Finalize()
Definition: Sha1.cpp:61
size_t size() const
Definition: ByteBuffer.h:336
void RequestModule()
Definition: WardenBase.cpp:103
std::string ByteArrayToHexStr(uint8 *bytes, uint32 length)
Definition: Util.cpp:493
void InitializeModule()
Definition: WardenMac.cpp:94
SARC4 iCrypto
Definition: WardenBase.h:120
void HandleData(ByteBuffer &buff)
Definition: WardenMac.cpp:202
void hexlike() const
Definition: ByteBuffer.h:451
WorldSession * Client
Definition: WardenBase.h:116
void append(const std::string &str)
Definition: ByteBuffer.h:358
uint8 Module_0DBBF209A27B1E279A9FEC5C168A15F7_Key[16]
void UpdateData(const uint8 *dta, int len)
Definition: Sha1.cpp:31
ClientWardenModule * GetModuleForClient(WorldSession *session)
Definition: WardenMac.cpp:73
uint8 Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data[9318]
#define sWorld
Definition: World.h:860
void EncryptData(uint8 *Buffer, uint32 Len)
Definition: WardenBase.cpp:158
size_t rpos() const
Definition: ByteBuffer.h:253
ACE_UINT32 uint32
Definition: Define.h:71
uint8 InputKey[16]
Definition: WardenBase.h:117
void HandleHashResult(ByteBuffer &buff)
Definition: WardenMac.cpp:116
bool m_initialized
Definition: WardenBase.h:127
uint8 OutputKey[16]
Definition: WardenBase.h:118
void RequestHash()
Definition: WardenMac.cpp:99
Definition: Sha1.h:26
uint8 Seed[16]
Definition: WardenBase.h:119