This reverse engineering was performed on a unnamed private server so I'm not sure how the encryption will look on the newer Conquer but it should be relatively same unless it has been changed for this private server.
First thing you need to do is to attach OllyDBG 1.0 or 2.1 version to Conquer.exe. I won't be covering how to bypass possible Anti Cheat methods that I understand are present on the newer Conquer client.
I approached this reversing by applying some previous knowledge of packets and their types. I know that the attack packet type is 0x3FE in hexadecimal so the first thing I did was searching for that constant in Conquer.exe. I then placed breakpoints at the locations where we are using the constant 0x3FE and used the SS-skill in conquer in order to trigger this function. This lead me to the following function
Code:
CPU Disasm Address Hex dump Command Comments 0073F162 /$ 55 PUSH EBP ; Conquer.0073F162(guessed Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7,Arg8) 0073F163 |. 8BEC MOV EBP,ESP 0073F165 |. 56 PUSH ESI 0073F166 |. 57 PUSH EDI 0073F167 |. 8B7D 0C MOV EDI,DWORD PTR SS:[ARG.2] 0073F16A |. 8BF1 MOV ESI,ECX 0073F16C |. 85FF TEST EDI,EDI 0073F16E |. 75 07 JNZ SHORT 0073F177 0073F170 |. 33C0 XOR EAX,EAX 0073F172 |. E9 F3000000 JMP 0073F26A 0073F177 |> 8B86 04040000 MOV EAX,DWORD PTR DS:[ESI+404] 0073F17D |. 53 PUSH EBX 0073F17E |. 6A 2C PUSH 2C 0073F180 |. 59 POP ECX 0073F181 |. 66:8908 MOV WORD PTR DS:[EAX],CX 0073F184 |. 8B86 04040000 MOV EAX,DWORD PTR DS:[ESI+404] 0073F18A |. B9 FE030000 MOV ECX,3FE 0073F18F |. 66:8948 02 MOV WORD PTR DS:[EAX+2],CX 0073F193 |. E8 44FFEFFF CALL <JMP.&WINMM.timeGetTime> ; Jump to WINMM.timeGetTime 0073F198 |. 8B8E 04040000 MOV ECX,DWORD PTR DS:[ESI+404] 0073F19E |. 8941 04 MOV DWORD PTR DS:[ECX+4],EAX 0073F1A1 |. E8 36FFEFFF CALL <JMP.&WINMM.timeGetTime> ; Jump to WINMM.timeGetTime 0073F1A6 |. 8B8E 04040000 MOV ECX,DWORD PTR DS:[ESI+404] 0073F1AC |. 8941 08 MOV DWORD PTR DS:[ECX+8],EAX 0073F1AF |. 8B86 04040000 MOV EAX,DWORD PTR DS:[ESI+404] 0073F1B5 |. 66:8B4D 1C MOV CX,WORD PTR SS:[ARG.6] 0073F1B9 |. 66:8948 1C MOV WORD PTR DS:[EAX+1C],CX 0073F1BD |. 8B86 04040000 MOV EAX,DWORD PTR DS:[ESI+404] 0073F1C3 |. 66:8B50 08 MOV DX,WORD PTR DS:[EAX+8] 0073F1C7 |. BB FF000000 MOV EBX,0FF 0073F1CC |. 66:23D3 AND DX,BX 0073F1CF |. 43 INC EBX 0073F1D0 |. 66:0FAFD3 IMUL DX,BX 0073F1D4 |. 66:0355 20 ADD DX,WORD PTR SS:[ARG.7] 0073F1D8 |. BB 21370000 MOV EBX,3721 0073F1DD |. 66:33D3 XOR DX,BX 0073F1E0 |. 66:8950 1E MOV WORD PTR DS:[EAX+1E],DX 0073F1E4 |. 8B86 04040000 MOV EAX,DWORD PTR DS:[ESI+404] 0073F1EA |. 8B55 10 MOV EDX,DWORD PTR SS:[ARG.3] 0073F1ED |. 8978 0C MOV DWORD PTR DS:[EAX+0C],EDI 0073F1F0 |. 8B86 04040000 MOV EAX,DWORD PTR DS:[ESI+404] 0073F1F6 |. 8950 10 MOV DWORD PTR DS:[EAX+10],EDX 0073F1F9 |. 8B86 04040000 MOV EAX,DWORD PTR DS:[ESI+404] 0073F1FF |. 66:8B55 14 MOV DX,WORD PTR SS:[ARG.4] 0073F203 |. 66:8950 14 MOV WORD PTR DS:[EAX+14],DX 0073F207 |. 8B86 04040000 MOV EAX,DWORD PTR DS:[ESI+404] 0073F20D |. 66:8B55 18 MOV DX,WORD PTR SS:[ARG.5] 0073F211 |. 66:8950 16 MOV WORD PTR DS:[EAX+16],DX 0073F215 |. 8B86 04040000 MOV EAX,DWORD PTR DS:[ESI+404] 0073F21B |. 66:8B55 08 MOV DX,WORD PTR SS:[ARG.1] 0073F21F |. 66:8950 18 MOV WORD PTR DS:[EAX+18],DX 0073F223 |. 0FB7C1 MOVZX EAX,CX 0073F226 |. 3D E8030000 CMP EAX,3E8 0073F22B |. 5B POP EBX 0073F22C |. 7C 39 JL SHORT 0073F267 0073F22E |. 3D EA030000 CMP EAX,3EA 0073F233 |. 7E 23 JLE SHORT 0073F258 0073F235 |. 3D 06040000 CMP EAX,406 0073F23A |. 74 1C JE SHORT 0073F258 0073F23C |. 3D 65040000 CMP EAX,465 0073F241 |. 74 15 JE SHORT 0073F258 0073F243 |. 3D 7E040000 CMP EAX,47E 0073F248 |. 74 0E JE SHORT 0073F258 0073F24A |. 3D 88040000 CMP EAX,488 0073F24F |. 74 07 JE SHORT 0073F258 0073F251 |. 3D 8D040000 CMP EAX,48D 0073F256 |. 75 0F JNE SHORT 0073F267 0073F258 |> 8BB6 04040000 MOV ESI,DWORD PTR DS:[ESI+404] 0073F25E |. B8 79620000 MOV EAX,6279 0073F263 |. 66:3146 1E XOR WORD PTR DS:[ESI+1E],AX 0073F267 |> 33C0 XOR EAX,EAX 0073F269 |. 40 INC EAX 0073F26A |> 5F POP EDI 0073F26B |. 5E POP ESI 0073F26C |. 5D POP EBP 0073F26D \. C2 2000 RETN 20
For example this part
Code:
CPU Disasm Address Hex dump Command Comments 0073F17E |. 6A 2C PUSH 2C 0073F180 |. 59 POP ECX 0073F181 |. 66:8908 MOV WORD PTR DS:[EAX],CX 0073F184 |. 8B86 04040000 MOV EAX,DWORD PTR DS:[ESI+404] 0073F18A |. B9 FE030000 MOV ECX,3FE 0073F18F |. 66:8948 02 MOV WORD PTR DS:[EAX+2],CX 0073F193 |. E8 44FFEFFF CALL <JMP.&WINMM.timeGetTime> ; Jump to WINMM.timeGetTime 0073F198 |. 8B8E 04040000 MOV ECX,DWORD PTR DS:[ESI+404] 0073F19E |. 8941 04 MOV DWORD PTR DS:[ECX+4],EAX 0073F1A1 |. E8 36FFEFFF CALL <JMP.&WINMM.timeGetTime> ; Jump to WINMM.timeGetTime 0073F1A6 |. 8B8E 04040000 MOV ECX,DWORD PTR DS:[ESI+404] 0073F1AC |. 8941 08 MOV DWORD PTR DS:[ECX+8],EAX
Anyways, lets continue on our reversing adventure. For me OllyDBG 2.1 shows that the function first function is called from 4 different addresses which I suspect handle different attack functionality such as melee and magic attack. The next thing I did was breakpointing each of the calls until I found the one that is called when using skill on Conquer. This lead me to the following assembly
Code:
CPU Disasm Address Hex dump Command Comments 0073B4CD |. FF75 10 PUSH DWORD PTR SS:[EBP+10] ; /Arg8 = A4E08569 0073B4D0 |. 8B4D EC MOV ECX,DWORD PTR SS:[EBP-14] ; | 0073B4D3 |. E8 4C1F0000 CALL 0073D424 ; | 0073B4D8 |. 0FB740 1C MOVZX EAX,WORD PTR DS:[EAX+1C] ; | 0073B4DC |. 50 PUSH EAX ; |Arg7 0073B4DD |. FF75 0C PUSH DWORD PTR SS:[EBP+0C] ; |Arg6 => [ARG.EBP+0C] 0073B4E0 |. 8D8D C4FBFFFF LEA ECX,[EBP-43C] ; | 0073B4E6 |. 57 PUSH EDI ; |Arg5 0073B4E7 |. 56 PUSH ESI ; |Arg4 0073B4E8 |. FF75 10 PUSH DWORD PTR SS:[EBP+10] ; |Arg3 => [ARG.EBP+10] 0073B4EB |. 53 PUSH EBX ; |Arg2 0073B4EC |. 6A 18 PUSH 18 ; |Arg1 = 18 0073B4EE |. E8 6F3C0000 CALL 0073F162 ; \Conquer.0073F162
Code:
byte[] ConstructAttackPacket(uint AttackType, uint AttackerUID, uint TargetUID, ushort X, ushort Y, ushort SpellID, ushort SubType, uint TargetUID)
The function from the start until ConstructAttackPacket is the following:
Code:
CPU Disasm Address Hex dump Command Comments 0073B412 /$ 68 30040000 PUSH 430 ; Conquer.0073B412(guessed Arg1,Arg2,Arg3,Arg4,Arg5) 0073B417 |. B8 49C88900 MOV EAX,0089C849 ; Entry point 0073B41C |. E8 12680F00 CALL 00831C33 0073B421 |. 894D E8 MOV DWORD PTR SS:[EBP-18],ECX 0073B424 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; /Arg2 => [ARG.EBP+8] 0073B427 |. 8D45 EC LEA EAX,[EBP-14] ; | 0073B42A |. 50 PUSH EAX ; |Arg1 => ARG.EBP-14 0073B42B |. E8 F3F2FFFF CALL 0073A723 ; \Conquer.0073A723 0073B430 |. 8365 FC 00 AND DWORD PTR SS:[EBP-4],00000000 0073B434 |. 837D EC 00 CMP DWORD PTR SS:[EBP-14],0 0073B438 |. 75 17 JNE SHORT 0073B451 0073B43A |> 834D FC FF OR DWORD PTR SS:[EBP-4],FFFFFFFF 0073B43E |. 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10] 0073B441 |. 85C9 TEST ECX,ECX 0073B443 |. 74 05 JZ SHORT 0073B44A 0073B445 |. E8 CA09CDFF CALL 0040BE14 ; [Conquer.0040BE14 0073B44A |> 32C0 XOR AL,AL 0073B44C |. E9 C6010000 JMP 0073B617 0073B451 |> 0FB745 08 MOVZX EAX,WORD PTR SS:[EBP+8] 0073B455 |. 2D BE140000 SUB EAX,14BE 0073B45A |. 6A 03 PUSH 3 ; /Arg2 = 3 0073B45C |. 50 PUSH EAX ; |Arg1 0073B45D |. E8 9299F2FF CALL 00664DF4 ; \Conquer.00664DF4 0073B462 |. 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+0C] 0073B465 |. 33C3 XOR EAX,EBX 0073B467 |. 35 5D910000 XOR EAX,0000915D 0073B46C |. 0FB7C0 MOVZX EAX,AX 0073B46F |. 8945 0C MOV DWORD PTR SS:[EBP+0C],EAX 0073B472 |. 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10] 0073B475 |. 05 E64A6F74 ADD EAX,746F4AE6 0073B47A |. 33C3 XOR EAX,EBX 0073B47C |. 35 63242D5F XOR EAX,5F2D2463 0073B481 |. C1C0 0D ROL EAX,0D 0073B484 |. 8945 10 MOV DWORD PTR SS:[EBP+10],EAX 0073B487 |. 8B45 14 MOV EAX,DWORD PTR SS:[EBP+14] 0073B48A |. 05 EE22FFFF ADD EAX,FFFF22EE 0073B48F |. 6A 01 PUSH 1 ; /Arg2 = 1 0073B491 |. 50 PUSH EAX ; |Arg1 0073B492 |. E8 5D99F2FF CALL 00664DF4 ; \Conquer.00664DF4 0073B497 |. 8BF0 MOV ESI,EAX 0073B499 |. 8B45 18 MOV EAX,DWORD PTR SS:[EBP+18] 0073B49C |. 05 2289FFFF ADD EAX,FFFF8922 0073B4A1 |. 6A 05 PUSH 5 ; /Arg2 = 5 0073B4A3 |. 33F3 XOR ESI,EBX ; | 0073B4A5 |. 50 PUSH EAX ; |Arg1 0073B4A6 |. 81F6 D62E0000 XOR ESI,00002ED6 ; | 0073B4AC |. E8 4399F2FF CALL 00664DF4 ; \Conquer.00664DF4 0073B4B1 |. 8BF8 MOV EDI,EAX 0073B4B3 |. 33FB XOR EDI,EBX 0073B4B5 |. 83C4 18 ADD ESP,18 0073B4B8 |. 8D8D C4FBFFFF LEA ECX,[EBP-43C] 0073B4BE |. 81F7 9BB90000 XOR EDI,0000B99B 0073B4C4 |. E8 393C0000 CALL 0073F102 ; [Conquer.0073F102 0073B4C9 |. C645 FC 01 MOV BYTE PTR SS:[EBP-4],1
Code:
CPU Disasm Address Hex dump Command Comments 0073B455 |. 2D BE140000 SUB EAX,14BE 0073B45A |. 6A 03 PUSH 3 ; /Arg2 = 3 0073B45C |. 50 PUSH EAX ; |Arg1 0073B45D |. E8 9299F2FF CALL 00664DF4 ; \Conquer.00664DF4 0073B462 |. 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+0C] 0073B465 |. 33C3 XOR EAX,EBX 0073B467 |. 35 5D910000 XOR EAX,0000915D 0073B46C |. 0FB7C0 MOVZX EAX,AX 0073B46F |. 8945 0C MOV DWORD PTR SS:[EBP+0C],EAX 0073B472 |. 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10] 0073B475 |. 05 E64A6F74 ADD EAX,746F4AE6 0073B47A |. 33C3 XOR EAX,EBX 0073B47C |. 35 63242D5F XOR EAX,5F2D2463 0073B481 |. C1C0 0D ROL EAX,0D 0073B484 |. 8945 10 MOV DWORD PTR SS:[EBP+10],EAX 0073B487 |. 8B45 14 MOV EAX,DWORD PTR SS:[EBP+14] 0073B48A |. 05 EE22FFFF ADD EAX,FFFF22EE 0073B48F |. 6A 01 PUSH 1 ; /Arg2 = 1 0073B491 |. 50 PUSH EAX ; |Arg1 0073B492 |. E8 5D99F2FF CALL 00664DF4 ; \Conquer.00664DF4 0073B497 |. 8BF0 MOV ESI,EAX 0073B499 |. 8B45 18 MOV EAX,DWORD PTR SS:[EBP+18] 0073B49C |. 05 2289FFFF ADD EAX,FFFF8922 0073B4A1 |. 6A 05 PUSH 5 ; /Arg2 = 5 0073B4A3 |. 33F3 XOR ESI,EBX ; | 0073B4A5 |. 50 PUSH EAX ; |Arg1 0073B4A6 |. 81F6 D62E0000 XOR ESI,00002ED6 ; | 0073B4AC |. E8 4399F2FF CALL 00664DF4 ; \Conquer.00664DF4 0073B4B1 |. 8BF8 MOV EDI,EAX 0073B4B3 |. 33FB XOR EDI,EBX 0073B4B5 |. 83C4 18 ADD ESP,18 0073B4B8 |. 8D8D C4FBFFFF LEA ECX,[EBP-43C] 0073B4BE |. 81F7 9BB90000 XOR EDI,0000B99B 0073B4C4 |. E8 393C0000 CALL 0073F102 ; [Conquer.0073F102 0073B4C9 |. C645 FC 01 MOV BYTE PTR SS:[EBP-4],1
I started by inserting a breakpoint at the start of the function. I then looked the registers / function calls to find some familiar values. It helped me quite bit that I knew SS skill ID is 1046 so I knew to look for it and I found it at
Code:
CPU Disasm Address Hex dump Command Comments 0073B455 |. 2D BE140000 SUB EAX,14BE 0073B45A |. 6A 03 PUSH 3 ; /Arg2 = 3 0073B45C |. 50 PUSH EAX ; |Arg1 0073B45D |. E8 9299F2FF CALL 00664DF4 ; \Conquer.00664DF4 0073B462 |. 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+0C] 0073B465 |. 33C3 XOR EAX,EBX 0073B467 |. 35 5D910000 XOR EAX,0000915D 0073B46C |. 0FB7C0 MOVZX EAX,AX 0073B46F |. 8945 0C MOV DWORD PTR SS:[EBP+0C],EAX
Code:
CPU Disasm Address Hex dump Command Comments 0073B45A |. 6A 03 PUSH 3 ; /Arg2 = 3 0073B45C |. 50 PUSH EAX ; |Arg1 0073B45D |. E8 9299F2FF CALL 00664DF4 ; \Conquer.00664DF4
Code:
CPU Disasm Address Hex dump Command Comments 0073B48F |. 6A 01 PUSH 1 ; /Arg2 = 1 0073B491 |. 50 PUSH EAX ; |Arg1 0073B492 |. E8 5D99F2FF CALL 00664DF4 ; \Conquer.00664DF4
Code:
CPU Disasm Address Hex dump Command Comments 0073B4A1 |. 6A 05 PUSH 5 ; /Arg2 = 5 0073B4A3 |. 33F3 XOR ESI,EBX ; | 0073B4A5 |. 50 PUSH EAX ; |Arg1 0073B4A6 |. 81F6 D62E0000 XOR ESI,00002ED6 ; | 0073B4AC |. E8 4399F2FF CALL 00664DF4 ; \Conquer.00664DF4
Code:
CPU Disasm Address Hex dump Command Comments 00664DF4 /$ 56 PUSH ESI ; Conquer.00664DF4(guessed Arg1,Arg2) 00664DF5 |. 57 PUSH EDI 00664DF6 |. 8B7C24 10 MOV EDI,DWORD PTR SS:[ARG.2] 00664DFA |. 85FF TEST EDI,EDI 00664DFC |. 7C 05 JL SHORT 00664E03 00664DFE |. 83FF 10 CMP EDI,10 00664E01 |. 7C 21 JL SHORT 00664E24 00664E03 |> 68 13020000 PUSH 213 00664E08 |. 68 14A29000 PUSH OFFSET 0090A214 ; ASCII "e:\cq2client\cq2client-65.3\basecode\basefunc.h" 00664E0D |. 68 F8A19000 PUSH OFFSET 0090A1F8 ; ASCII "nBits >= 0 && nBits < 16" 00664E12 |. 68 E8C38A00 PUSH OFFSET 008AC3E8 ; ASCII "ASSERT" 00664E17 |. 68 60C38A00 PUSH OFFSET 008AC360 ; /Format = "" 00664E1C |. E8 E8A2FDFF CALL 0063F109 ; \Conquer.0063F109 00664E21 |. 83C4 14 ADD ESP,14 00664E24 |> 8B5424 0C MOV EDX,DWORD PTR SS:[ARG.1] 00664E28 |. BE FFFF0000 MOV ESI,0FFFF 00664E2D |. 6A 10 PUSH 10 00664E2F |. 23D6 AND EDX,ESI 00664E31 |. 59 POP ECX 00664E32 |. 2BCF SUB ECX,EDI 00664E34 |. 8BC2 MOV EAX,EDX 00664E36 |. D3E0 SHL EAX,CL 00664E38 |. 8BCF MOV ECX,EDI 00664E3A |. D3EA SHR EDX,CL 00664E3C |. 5F POP EDI 00664E3D |. 0BC2 OR EAX,EDX 00664E3F |. 23C6 AND EAX,ESI 00664E41 |. 5E POP ESI 00664E42 \. C3 RETN
Afterwards at
Code:
CPU Disasm Address Hex dump Command Comments 00664E24 |> \8B5424 0C MOV EDX,DWORD PTR SS:[ARG.1] 00664E28 |. BE FFFF0000 MOV ESI,0FFFF 00664E2D |. 6A 10 PUSH 10 00664E2F |. 23D6 AND EDX,ESI 00664E31 |. 59 POP ECX 00664E32 |. 2BCF SUB ECX,EDI 00664E34 |. 8BC2 MOV EAX,EDX 00664E36 |. D3E0 SHL EAX,CL 00664E38 |. 8BCF MOV ECX,EDI 00664E3A |. D3EA SHR EDX,CL 00664E3C |. 5F POP EDI 00664E3D |. 0BC2 OR EAX,EDX 00664E3F |. 23C6 AND EAX,ESI
We move the first parameter to EDX-register and constant 0xFFFF to ESI register. Then couple lines lower we assign ECX value 0x10 (PUSH 10 && POP ECX) and subtract the second parameter from it and assign it to ECX. One of the above functions used constant 0x03 as the second parameter so at this point ecx would be 0x10 - 0x03 = 0x0D.
We then move the first parameter (EDX) to EAX and shift it left by the value of ECX. We then move ECX value of the second parameter (EDI) and shift the first parameter right by the amount assigned to second parameter. After this we OR these two calculations together and AND it by the constant 0xFFFF (ESI)
The above might be a bit confusing but in the end you can translate this function to C# equivalent of:
Code:
static uint Shift(uint Value, int Amount)
{
int LeftShift = 16 - Amount;
Value = Value & 0xFFFF;
Value = (Value << LeftShift) | (Value >> Amount);
return Value & 0xFFFF;
}
Now we can return back to this part of the code
Code:
CPU Disasm Address Hex dump Command Comments 0073B455 |. 2D BE140000 SUB EAX,14BE 0073B45A |. 6A 03 PUSH 3 ; /Arg2 = 3 0073B45C |. 50 PUSH EAX ; |Arg1 0073B45D |. E8 9299F2FF CALL 00664DF4 ; \Conquer.00664DF4 0073B462 |. 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+0C] 0073B465 |. 33C3 XOR EAX,EBX 0073B467 |. 35 5D910000 XOR EAX,0000915D 0073B46C |. 0FB7C0 MOVZX EAX,AX
Code:
MOV EBX,DWORD PTR SS:[EBP+0C]
At this point we can begin to construct our C# code to Encrypt the information.
Code:
static void Encrypt(ushort SpellID, ushort X, ushort Y, uint UID, uint TargetUID)
{
uint ID = (uint)(SpellID - 0x14BE);
ID = Shift(ID, 3) ^ UID;
ID = ID ^ 0x915D;
ID = ID & 0xFFFF;
}
Code:
CPU Disasm Address Hex dump Command Comments 0073B472 |. 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10] 0073B475 |. 05 E64A6F74 ADD EAX,746F4AE6 0073B47A |. 33C3 XOR EAX,EBX 0073B47C |. 35 63242D5F XOR EAX,5F2D2463 0073B481 |. C1C0 0D ROL EAX,0D
This translates to the following in C#:
Code:
uint eax = TargetUID + 0x746F4AE6;
eax = eax ^ UID;
eax = eax ^ 0x5F2D2463;
eax = rol(eax, 0x0D);
static uint rol(uint value, int amount)
{
return (value << amount) | (value >> (32 - amount));
}
Next up we have the X/Y encryption
Code:
CPU Disasm Address Hex dump Command Comments 0073B487 |. 8B45 14 MOV EAX,DWORD PTR SS:[EBP+14] 0073B48A |. 05 EE22FFFF ADD EAX,FFFF22EE 0073B48F |. 6A 01 PUSH 1 ; /Arg2 = 1 0073B491 |. 50 PUSH EAX ; |Arg1 0073B492 |. E8 5D99F2FF CALL 00664DF4 ; \Conquer.00664DF4 0073B497 |. 8BF0 MOV ESI,EAX 0073B499 |. 8B45 18 MOV EAX,DWORD PTR SS:[EBP+18] 0073B49C |. 05 2289FFFF ADD EAX,FFFF8922 0073B4A1 |. 6A 05 PUSH 5 ; /Arg2 = 5 0073B4A3 |. 33F3 XOR ESI,EBX ; | 0073B4A5 |. 50 PUSH EAX ; |Arg1 0073B4A6 |. 81F6 D62E0000 XOR ESI,00002ED6 ; | 0073B4AC |. E8 4399F2FF CALL 00664DF4 ; \Conquer.00664DF4 0073B4B1 |. 8BF8 MOV EDI,EAX 0073B4B3 |. 33FB XOR EDI,EBX 0073B4B5 |. 83C4 18 ADD ESP,18 0073B4B8 |. 8D8D C4FBFFFF LEA ECX,[EBP-43C] 0073B4BE |. 81F7 9BB90000 XOR EDI,0000B99B
Next we have the Y coordinate encryption which is retrieved from memory to EAX register (MOV EAX,DWORD PTR SS:[EBP+18]). We then add 0xFFFF8922 to it and call Shift(Y, 0x05). This result is XORed by player UID and then by 0x0000B99B.
All in all the Encryption function looks like this.
Code:
static void Encrypt(ushort SpellID, ushort X, ushort Y, uint UID, uint TargetUID)
{
uint ID = (uint)(SpellID - 0x14BE);
ID = Shift(ID, 3) ^ UID;
ID = ID ^ 0x915D;
ID = ID & 0xFFFF;
Console.WriteLine("ID: " + ID.ToString("X8"));
uint eax = TargetUID + 0x746F4AE6;
eax = eax ^ UID;
eax = eax ^ 0x5F2D2463;
eax = rol(eax, 0x0D);
Console.WriteLine("Target UID: " + eax.ToString("X8"));
uint encX = X + 0xFFFF22EE;
encX = Shift(encX, 1);
encX = encX ^ UID ^ 0x2ED6;
Console.WriteLine("X: " + encX.ToString("X8"));
uint encY = Y + 0xFFFF8922;
encY = Shift(encY, 5);
encY = encY ^ UID ^ 0xB99B;
Console.WriteLine("Y: " + encY.ToString("X8"));
}
Code:
static uint ror(uint value, int amount)
{
return (value >> amount) | (value << (32 - amount));
}
static uint RightShift(uint Value, int Amount)
{
int RightShift = 16 - Amount;
Value = Value & 0xFFFF;
Value = (Value >> RightShift) | (Value << Amount);
return Value & 0xFFFF;
}
static void Decrypt(ushort SpellID, uint X, uint Y, uint UID, uint TargetUID)
{
uint ID = (uint)(SpellID ^ 0x915D);
ID = ID ^ UID;
ID = RightShift(ID, 3);
ID += 0x14BE;
ID = ID & 0xFFFF;
uint Target = ror(TargetUID, 0x0D);
Target = Target ^ 0x5F2D2463;
Target = Target ^ UID;
Target -= 0x746F4AE6;
uint decX = X ^ 0x2ED6 ^ UID;
decX = RightShift(decX, 1);
decX -= 0xFFFF22EE;
decX = decX & 0xFFFF;
uint decY = Y ^ 0xB99B ^ UID;
decY = RightShift(decY, 5);
decY -= 0xFFFF8922;
decY = decY & 0xFFFF;
}






