public static void Dump(uint specificOpcode = 0xBADD) { if (specificOpcode != 0xBADD) { Pattern[11] = (byte)((specificOpcode & 0xFF00) >> 8); Pattern[10] = (byte)(specificOpcode & 0x00FF); Console.WriteLine(BitConverter.ToString(Pattern).Replace('-', ' ')); } var patternOffsets = Program.ClientBytes.FindPattern(Pattern, 0xFF); var callIndex = (uint)(Array.IndexOf <byte>(Pattern, 0xE8) + 0x400C00); Logger.WriteLine(); Logger.WriteLine("Dumping CMSG opcodes..."); Logger.WriteLine("Found {0} CMSGs candidates. Dumping, this may take a while...", patternOffsets.Count); Logger.WriteLine("+---------------+------------+------------+------------+"); Logger.WriteLine("| Opcode | vTable | CliPut | CONFIDENCE |"); Logger.WriteLine("+---------------+------------+------------+------------+"); foreach (var currPatternOffset in patternOffsets) { Program.BaseStream.Seek(currPatternOffset, SeekOrigin.Begin); var bytes = Program.ClientStream.ReadBytes(Pattern.Length); var callOffset = BitConverter.ToInt32(bytes, 15); // False positive check int PutUInt32 = 0; switch (Program.ClientBuild.BuildNumber) { case 19324: PutUInt32 = 0x0040FD64; break; case 19702: PutUInt32 = 0x004110E6; break; case 19802: PutUInt32 = 0x004111B6; break; case 19865: PutUInt32 = 0x004111B6; break; default: PutUInt32 = 0x0; break; } var subCall = (uint)(currPatternOffset + callIndex) + callOffset + 5; if (subCall != PutUInt32 && PutUInt32 != 0) // CDataStore::PutInt32 { continue; } var opcodeValue = specificOpcode == 0xBADD ? BitConverter.ToUInt16(bytes, 10) : specificOpcode; var ptBytes = BitConverter.GetBytes(currPatternOffset + 0x400C00); var vtablePattern = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, // Ctor 0xFF, 0xFF, 0xFF, 0xFF, // CliPut ptBytes[0], ptBytes[1], ptBytes[2], ptBytes[3], // CliPutWithMsgId (where we are at) 0xFF, 0xFF, 0xFF, 0xFF // Dtor }; var vtOffsets = Program.ClientBytes.FindPattern(vtablePattern, 0xFF).Where(t => (t - 0x400C00) < Program.ClientBytes.Length); foreach (var vtOffset in vtOffsets) { Program.BaseStream.Seek(vtOffset + 4, SeekOrigin.Begin); var cliPut = Program.ClientStream.ReadUInt32(); var cliPutWithMsg = Program.ClientStream.ReadUInt32(); if (cliPutWithMsg != (currPatternOffset + 0x400C00)) { continue; } List <uint> callerOffset; if (Config.BinDiff != string.Empty) { var offBytes = BitConverter.GetBytes(vtOffset + 0x400C00); var ctorPattern = new byte[] { 0x8B, 0xC1, // mov eax, ecx 0x83, 0x60, 0x0C, 0x00, // and dword ptr [eax+0Ch], 0 0xC7, 0x00, offBytes[0], offBytes[1], offBytes[2], offBytes[3] // mov dword ptr [eax], <vtable> }; callerOffset = Program.ClientBytes.FindPattern(ctorPattern, 0xFF); } else { callerOffset = new List <uint>() { 0 } }; cmsgInfo.Add(new CMSGInfo(Opcodes.GetOpcodeNameForClient(opcodeValue, callerOffset.FirstOrDefault() + 0x400C00), opcodeValue, vtOffset + 0x400C00, cliPut, cliPutWithMsg, Program.FuncDiff != null ? Program.FuncDiff.getCertianty(callerOffset.FirstOrDefault() + 0x400C00) : 0)); Console.WriteLine(cmsgInfo.Last().getPrintString()); ++opcodeCount; break; } } cmsgInfo = cmsgInfo.OrderBy(x => x.Name).ToList(); foreach (CMSGInfo cmsg in cmsgInfo) { if (cmsg.Opcode != 0x0105) //OTHER UGLY HACK { cmsg.FormatName(); Logger.WriteLine(cmsg.getPrintString()); } } Logger.WriteLine("+---------------+------------+------------+------------+"); Logger.WriteLine("Dumped {0} CMSG JAM opcodes.", opcodeCount); }