private void LoadMessages() { ABCFile abc = ABCFiles.Last(); ASClass habboMessagesClass = abc.GetClass("HabboMessages"); if (habboMessagesClass == null) { IsPostShuffle = false; foreach (ASClass @class in abc.Classes) { if (@class.Traits.Count != 2 || @class.Traits[0].Type?.Name != "Map" || @class.Traits[1].Type?.Name != "Map") { continue; } if (@class.Instance.Traits.Count != 2) { continue; } habboMessagesClass = @class; break; } if (habboMessagesClass == null) { return; } } ASCode code = habboMessagesClass.Constructor.Body.ParseCode(); int outMapTypeIndex = habboMessagesClass.Traits[1].QNameIndex; ASInstruction[] instructions = code .Where(i => i.OP == OPCode.GetLex || i.OP == OPCode.PushShort || i.OP == OPCode.PushByte).ToArray(); for (int i = 0; i < instructions.Length; i += 3) { GetLexIns getLexInst = instructions[i + 0] as GetLexIns; bool isOutgoing = getLexInst?.TypeNameIndex == outMapTypeIndex; Primitive primitive = instructions[i + 1] as Primitive; ushort id = Convert.ToUInt16(primitive?.Value); getLexInst = instructions[i + 2] as GetLexIns; ASClass messageClass = abc.GetClass(getLexInst?.TypeName.Name); HMessage message = new HMessage(id, isOutgoing, messageClass); (isOutgoing ? OutMessages : InMessages).Add(id, message); if (!_messages.ContainsKey(messageClass)) { _messages.Add(messageClass, message); } } }
private PacketValue[] GetIncomingStructure(ASInstance instance, ASMethod method) { if (method.Body.Exceptions.Count > 0) { return(null); } ASCode code = method.Body.ParseCode(); if (code.JumpExits.Count > 0 || code.SwitchExits.Count > 0) { return(null); } List <PacketValue> structure = new List <PacketValue>(); ABCFile abc = method.GetABC(); for (int i = 0; i < code.Count; i++) { ASInstruction instruction = code[i]; if (instruction.OP != OPCode.GetLocal_1) { continue; } ASInstruction next = code[++i]; switch (next.OP) { case OPCode.CallProperty: { CallPropertyIns callProperty = (CallPropertyIns)next; if (callProperty.ArgCount > 0) { ASMultiname propertyName = null; ASInstruction previous = code[i - 2]; switch (previous.OP) { case OPCode.GetLex: { GetLexIns getLex = (GetLexIns)previous; propertyName = getLex.TypeName; break; } case OPCode.ConstructProp: { ConstructPropIns constructProp = (ConstructPropIns)previous; propertyName = constructProp.PropertyName; break; } case OPCode.GetLocal_0: { propertyName = instance.QName; break; } } ASInstance innerInstance = abc.GetInstance(propertyName); ASMethod innerMethod = innerInstance.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount); if (innerMethod == null) { ASClass innerClass = abc.GetClass(propertyName); innerMethod = innerClass.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount); } PacketValue[] innerStructure = GetIncomingStructure(innerInstance, innerMethod); if (innerStructure == null) { return(null); } structure.AddRange(innerStructure); } else { if (!TryGetPacketValue(callProperty.PropertyName, null, out PacketValue piece)) { return(null); } structure.Add(piece); } break; } case OPCode.ConstructProp: { ConstructPropIns constructProp = (ConstructPropIns)next; ASInstance innerInstance = abc.GetInstance(constructProp.PropertyName); PacketValue[] innerStructure = GetIncomingStructure(innerInstance, innerInstance.Constructor); if (innerStructure == null) { return(null); } structure.AddRange(innerStructure); break; } case OPCode.ConstructSuper: { ASInstance superInstance = abc.GetInstance(instance.Super); PacketValue[] innerStructure = GetIncomingStructure(superInstance, superInstance.Constructor); if (innerStructure == null) { return(null); } structure.AddRange(innerStructure); break; } case OPCode.CallSuper: { CallSuperIns callSuper = (CallSuperIns)next; ASInstance superInstance = abc.GetInstance(instance.Super); ASMethod superMethod = superInstance.GetMethod(callSuper.MethodName.Name, null, callSuper.ArgCount); PacketValue[] innerStructure = GetIncomingStructure(superInstance, superMethod); if (innerStructure == null) { return(null); } structure.AddRange(innerStructure); break; } case OPCode.CallPropVoid: { CallPropVoidIns callPropVoid = (CallPropVoidIns)next; if (callPropVoid.ArgCount != 0) { return(null); } if (!TryGetPacketValue(callPropVoid.PropertyName, null, out PacketValue piece)) { return(null); } structure.Add(piece); break; } default: return(null); } } return(structure.Count == 0 ? null : structure.ToArray()); }
private List <HReference> FindMessageReferences(ASClass fromClass, ASContainer fromContainer, ASMethod fromMethod) { int instructionRank = 0; ABCFile abc = fromMethod.GetABC(); Stack <ASMultiname> nameStack = new Stack <ASMultiname>(); List <HReference> references = new List <HReference>(); ASContainer container = null; ASCode code = fromMethod.Body.ParseCode(); for (int i = 0; i < code.Count; i++) { ASInstruction instruction = code[i]; switch (instruction.OP) { default: continue; case OPCode.NewFunction: { NewFunctionIns newFunction = (NewFunctionIns)instruction; references.AddRange(FindMessageReferences(fromClass, fromContainer, newFunction.Method)); continue; } case OPCode.GetProperty: { GetPropertyIns getProperty = (GetPropertyIns)instruction; nameStack.Push(getProperty.PropertyName); continue; } case OPCode.GetLex: { GetLexIns getLex = (GetLexIns)instruction; container = abc.GetClass(getLex.TypeName.Name); continue; } case OPCode.GetLocal_0: { container = fromContainer; continue; } case OPCode.ConstructProp: { ConstructPropIns constructProp = (ConstructPropIns)instruction; nameStack.Push(constructProp.PropertyName); break; } } ASMultiname messageQName = nameStack.Pop(); if (string.IsNullOrWhiteSpace(messageQName.Name)) { continue; } ASClass messageClass = abc.GetClass(messageQName.Name); if (messageClass == null) { continue; } if (!_messages.TryGetValue(messageClass, out HMessage message)) { continue; } if (message.References.Any(r => r.FromMethod == fromMethod)) { continue; } HReference reference = new HReference(); message.References.Add(reference); if (message.IsOutgoing) { reference.FromClass = fromClass; reference.FromMethod = fromMethod; reference.InstructionRank = ++instructionRank; reference.IsAnonymous = (!fromMethod.IsConstructor && fromMethod.Trait == null); references.Add(reference); } else { ASMultiname methodName = nameStack.Pop(); ASMethod callbackMethod = fromContainer.GetMethod(methodName.Name); if (callbackMethod == null) { callbackMethod = container.GetMethod(methodName.Name); if (callbackMethod == null) { ASMultiname slotName = nameStack.Pop(); ASTrait hostTrait = container.GetTraits(TraitKind.Slot) .FirstOrDefault(st => st.QName == slotName); container = abc.GetInstance(hostTrait.Type.Name); callbackMethod = container.GetMethod(methodName.Name); } } reference.FromMethod = callbackMethod; } } return(references); }
private string GetIncomingStructure(ASInstance instance, ASMethod method) { if (method.Body.Exceptions.Count > 0) { return(null); } ASCode code = method.Body.ParseCode(); if (code.JumpExits.Count > 0 || code.SwitchExits.Count > 0) { return(null); } string structure = null; ABCFile abc = method.GetABC(); for (int i = 0; i < code.Count; i++) { ASInstruction instruction = code[i]; if (instruction.OP != OPCode.GetLocal_1) { continue; } ASInstruction next = code[++i]; switch (next.OP) { case OPCode.CallProperty: { var callProperty = (CallPropertyIns)next; if (callProperty.ArgCount > 0) { ASMultiname propertyName = null; ASInstruction previous = code[i - 2]; switch (previous.OP) { case OPCode.GetLex: { var getLex = (GetLexIns)previous; propertyName = getLex.TypeName; break; } case OPCode.ConstructProp: { var constructProp = (ConstructPropIns)previous; propertyName = constructProp.PropertyName; break; } case OPCode.GetLocal_0: { propertyName = instance.QName; break; } } ASInstance innerInstance = abc.GetInstance(propertyName); ASMethod innerMethod = innerInstance.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount); if (innerMethod == null) { ASClass innerClass = abc.GetClass(propertyName); innerMethod = innerClass.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount); } string innerStructure = GetIncomingStructure(innerInstance, innerMethod); if (string.IsNullOrWhiteSpace(innerStructure)) { return(null); } structure += innerStructure; } else { if (!TryGetStructurePiece(callProperty.PropertyName, null, out char piece)) { return(null); } structure += piece; } break; } case OPCode.ConstructProp: { var constructProp = (ConstructPropIns)next; ASInstance innerInstance = abc.GetInstance(constructProp.PropertyName); string innerStructure = GetIncomingStructure(innerInstance, innerInstance.Constructor); if (string.IsNullOrWhiteSpace(innerStructure)) { return(null); } structure += innerStructure; break; } case OPCode.ConstructSuper: { ASInstance superInstance = abc.GetInstance(instance.Super); string innerStructure = GetIncomingStructure(superInstance, superInstance.Constructor); if (string.IsNullOrWhiteSpace(innerStructure)) { return(null); } structure += innerStructure; break; } case OPCode.CallSuper: { var callSuper = (CallSuperIns)next; ASInstance superInstance = abc.GetInstance(instance.Super); ASMethod superMethod = superInstance.GetMethod(callSuper.MethodName.Name, null, callSuper.ArgCount); string innerStructure = GetIncomingStructure(superInstance, superMethod); if (string.IsNullOrWhiteSpace(innerStructure)) { return(null); } structure += innerStructure; break; } case OPCode.CallPropVoid: { var callPropVoid = (CallPropVoidIns)next; if (callPropVoid.ArgCount != 0) { return(null); } if (!TryGetStructurePiece(callPropVoid.PropertyName, null, out char piece)) { return(null); } structure += piece; break; } default: return(null); } } return(structure); }