protected void ReplaceNextOperation(FlashReader inCode, FlashWriter outCode, ASMethod method, OPCode oldOP, object[] oldValues, OPCode newOP, object[] newValues) { while (inCode.IsDataAvailable) { OPCode op = inCode.ReadOP(); object[] values = inCode.ReadValues(op); if (op != oldOP) { outCode.WriteOP(op, values); continue; } if (oldValues != null && (oldValues.Length == values.Length)) { bool valuesMatch = true; for (int i = 0; i < oldValues.Length; i++) { if (oldValues[i] != null && !oldValues[i].Equals(values[i])) { valuesMatch = false; break; } } if (!valuesMatch) { outCode.WriteOP(op, values); continue; } } outCode.WriteOP(newOP, newValues); WriteLog($"Replaced operation '{oldOP}[{string.Join(", ", oldValues)}]' with '{newOP}[{string.Join(", ", newValues)}]' in method '{method}'."); break; } }
public bool DisableExpirationDateCheck() { ABCFile abc = ABCFiles[2]; ASInstance windowContext = abc.FindInstanceByName("WindowContext"); if (windowContext == null) { return(false); } using (var inCode = new FlashReader(windowContext.Constructor.Body.Bytecode)) using (var outCode = new FlashWriter()) { int setLocal11Itterations = 0; while (inCode.Position != inCode.Length) { OPCode op = inCode.ReadOP(); outCode.WriteOP(op); if (op != OPCode.SetLocal) { continue; } int setLocalIndex = inCode.Read7BitEncodedInt(); outCode.Write7BitEncodedInt(setLocalIndex); if (setLocalIndex != 11 || (++setLocal11Itterations != 2)) { continue; } outCode.WriteOP(OPCode.ReturnVoid); outCode.Write(inCode.ToArray(), inCode.Position, inCode.Length - inCode.Position); windowContext.Constructor.Body.Bytecode = outCode.ToArray(); return(true); } } return(false); }
protected void RemoveHostSuffix(ABCFile abc, ASMethod connectMethod) { using (var inCode = new FlashReader(connectMethod.Body.Bytecode)) using (var outCode = new FlashWriter(inCode.Length)) { int ifNeCount = 0; while (inCode.Position != inCode.Length) { OPCode op = inCode.ReadOP(); outCode.WriteOP(op); if (op == OPCode.IfNe && ++ifNeCount == 2) { var iFNeJumpCount = (int)inCode.ReadS24(); outCode.WriteS24(iFNeJumpCount + 6); continue; } else if (op != OPCode.PushInt) { continue; } int pushIntIndex = inCode.Read7BitEncodedInt(); int integerValue = abc.Constants.Integers[pushIntIndex]; switch (integerValue) { case 65244: case 65185: case 65191: case 65189: case 65188: case 65174: case 65238: case 65184: case 65171: case 65172: { pushIntIndex = abc.Constants.AddInteger(65290); break; } } outCode.Write7BitEncodedInt(pushIntIndex); } connectMethod.Body.Bytecode = outCode.ToArray(); } RemoveDeadFalseConditions(connectMethod.Body); }
protected void RemoveDeadFalseConditions(ASMethodBody body) { using (var inCode = new FlashReader(body.Bytecode)) using (var outCode = new FlashWriter(inCode.Length)) { while (inCode.Position != inCode.Length) { OPCode op = inCode.ReadOP(); if (op != OPCode.PushFalse) { outCode.WriteOP(op); continue; } op = inCode.ReadOP(); if (op != OPCode.PushFalse) { outCode.WriteOP(OPCode.PushFalse); outCode.WriteOP(op); continue; } op = inCode.ReadOP(); if (op != OPCode.IfNe) { outCode.WriteOP(OPCode.PushFalse); outCode.WriteOP(OPCode.PushFalse); outCode.WriteOP(op); continue; } else { inCode.ReadS24(); } } body.Bytecode = outCode.ToArray(); } }
protected void FixLocalRegisters(ASMethod method) { // But, what about nested branches? Does not work with those yet, sadly. if (method.Body == null) { return; } if (method.Body.LocalCount == (1 + method.Parameters.Count)) { return; } ABCFile abc = method.ABC; using (var outCode = new FlashWriter()) using (var inCode = new FlashReader(method.Body.Bytecode)) { uint jumpValue = 0; int jumpValueEnd = 0; int jumpValueStart = 0; int totalDifference = 0; bool isJumpingOver = false; var labelPositions = new Stack <int>(); while (inCode.IsDataAvailable) { if (isJumpingOver && inCode.Position >= jumpValueEnd) { isJumpingOver = false; } OPCode op = inCode.ReadOP(); object[] values = inCode.ReadValues(op); if (op != OPCode.Debug || ((byte)values[0] != 1)) { if (IsJumpInstruction(op)) // If a label position is contained in the stack, the next jump instruction will go backwards. { // Not a backwards jump, also check to make sure the jump value isn't crazy big, otherwise it might be a reverse jump instruction. // If large: (uint.MaxValue - value[0]) == Bytes to jump back to get to the last saved label position in stack. if (labelPositions.Count == 0 || ((uint)values[0] <= inCode.Length)) { isJumpingOver = true; jumpValue = (uint)values[0]; // To later check if we're in the middle of the jumping range. jumpValueStart = (outCode.Position + 1); // To re-write the jump value if the data in-between has sgrown. jumpValueEnd = (int)(inCode.Position + jumpValue); } else { // Find by how many bytes we need to move back from current position. values[0] = (uint)(uint.MaxValue - ((outCode.Position + 4) - labelPositions.Pop())); } } else if (op == OPCode.Label) // Store label positions, to easily determine by how many bytes we need to jump back to this position. { labelPositions.Push(outCode.Position + 1); } outCode.WriteOP(op, values); continue; } var local = (byte)values[2]; if (local > method.Parameters.Count) { values[1] = abc.Constants .AddString("local" + local); } outCode.WriteOP(op, values); int difference = (((inCode.Position - outCode.Length) * -1) - totalDifference); totalDifference += difference; if (isJumpingOver) { int curPos = outCode.Position; outCode.Position = jumpValueStart; outCode.WriteS24(jumpValue += (uint)difference); // PlusEqual the value, in-case we've already modifed within the jumping range. outCode.Position = curPos; } } method.Body.Bytecode = outCode.ToArray(); } }
/// <summary> /// Modifies the bytecode to allow the client to connect to anywhere. /// </summary> public void BypassRemoteHostCheck() { ABCFile abc = ABCFiles[2]; ASInstance habboCommMngr = abc.FindFirstInstanceByName("HabboCommunicationManager"); if (habboCommMngr == null) { return; } int hostValueSlotObjTypeIndex = -1; string hostValueSlotObjName = string.Empty; foreach (ASTrait trait in habboCommMngr.Traits) { if (trait.TraitType != TraitType.Slot) { continue; } if (((SlotConstantTrait)trait.Data).TypeName.Name != "String") { continue; } hostValueSlotObjName = trait.Name.Name; hostValueSlotObjTypeIndex = trait.NameIndex; break; } ASMethod initCompMethod = habboCommMngr .FindFirstMethod("initComponent", "void"); int getPropertyObjTypeIndex = abc.Constants .IndexOfMultiname("getProperty"); ASMethod initConnectionMethod = null; using (var outCode = new FlashWriter()) using (var inCode = new FlashReader(initCompMethod.Body.Bytecode)) { object[] values = inCode.ReadValuesUntil(OPCode.CallPropVoid, null, 0); if (values == null) { return; } CopyBytecode(inCode, outCode, 0, inCode.Position); outCode.WriteOP(OPCode.GetLocal_0); outCode.WriteOP(OPCode.FindPropStrict, getPropertyObjTypeIndex); outCode.WriteOP(OPCode.PushString, abc.Constants.AddString("connection.info.host")); outCode.WriteOP(OPCode.CallProperty, getPropertyObjTypeIndex, 1); outCode.WriteOP(OPCode.InitProperty, hostValueSlotObjTypeIndex); WriteLog($"Method '{initCompMethod}' modified to include '{hostValueSlotObjName} = getProperty(\"connection.info.host\");'."); CopyBytecode(inCode, outCode); initCompMethod.Body.Bytecode = outCode.ToArray(); values = inCode.ReadValuesUntil(OPCode.CallPropVoid); ASMultiname callPropVoidType = abc.Constants.Multinames[(int)values[0]]; initConnectionMethod = habboCommMngr.FindFirstMethod(callPropVoidType.Name, "void"); } using (var outCode = new FlashWriter()) using (var inCode = new FlashReader(initConnectionMethod.Body.Bytecode)) { int ifNeCount = 0; int byteJumpCountPos = 0; int differenceOffset = 0; uint byteJumpCountValue = 0; int magicNumberIndex = abc.Constants.AddInteger(65290); while (inCode.IsDataAvailable) { OPCode op = inCode.ReadOP(); object[] values = null; if (op != OPCode.PushInt) { values = inCode.ReadValues(op); outCode.WriteOP(op, values); if (op == OPCode.IfNe && (++ifNeCount == 2 || ifNeCount == 4)) { byteJumpCountPos = (outCode.Position - 3); byteJumpCountValue = (uint)values[0]; } continue; } bool isFinalPushInt = false; int pushIntIndex = inCode.Read7BitEncodedInt(); int pushIntValue = abc.Constants.Integers[pushIntIndex]; #region Switch: pushIntValue switch (pushIntValue) { case 65244: //97 case 65185: //32 case 65191: //175 case 65189: //123 case 65188: //164 case 65174: //45 case 65238: //297 case 65184: //127 case 65171: //20 case 65172: //58 { pushIntIndex = magicNumberIndex; isFinalPushInt = (pushIntValue == 65172); break; } } #endregion outCode.WriteOP(op, pushIntIndex); int byteDifference = (((inCode.Position - outCode.Length) * -1) - differenceOffset); if (isFinalPushInt) { int curPos = outCode.Position; differenceOffset += byteDifference; outCode.Position = byteJumpCountPos; outCode.WriteS24(byteJumpCountValue + (uint)byteDifference); outCode.Position = curPos; if (ifNeCount == 4) { CopyBytecode(inCode, outCode); initConnectionMethod.Body.Bytecode = outCode.ToArray(); WriteLog($"Method '{initConnectionMethod}' modified to not append suffix to the host value."); return; } } } } }
public bool ReplaceRSA(int exponent, string modulus) { ABCFile abc = ABCFiles[2]; int modulusIndex = abc.Constants.AddString(modulus); int exponentIndex = abc.Constants .AddString(exponent.ToString("x")); int rsaStart = 0; ASInstance commClass = abc.FindInstanceByName("HabboCommunicationDemo"); ASMethod verifier = FindVerifyMethod(commClass, abc, out rsaStart); using (var inCode = new FlashReader(verifier.Body.Bytecode)) using (var outCode = new FlashWriter(inCode.Length)) { bool searchingKeys = true; inCode.Position = rsaStart; outCode.Write(inCode.ToArray(), 0, rsaStart); while (inCode.Position != inCode.Length) { byte codeByte = inCode.ReadByte(); outCode.Write(codeByte); if (!searchingKeys) { outCode.Write(inCode.ToArray(), inCode.Position, inCode.Length - inCode.Position); break; } switch ((OPCode)codeByte) { case OPCode.GetLex: { outCode.Position--; outCode.WriteOP(OPCode.PushString); int typeIndex = inCode.Read7BitEncodedInt(); ASMultiname type = abc.Constants.Multinames[typeIndex]; inCode.ReadOP(); inCode.Read7BitEncodedInt(); inCode.Read7BitEncodedInt(); if (modulusIndex > 0) { outCode.Write7BitEncodedInt(modulusIndex); modulusIndex = -1; } else if (searchingKeys) { outCode.Write7BitEncodedInt(exponentIndex); searchingKeys = false; } break; } case OPCode.PushString: { int stringIndex = inCode.Read7BitEncodedInt(); string value = abc.Constants.Strings[stringIndex]; if (string.IsNullOrWhiteSpace(Modulus)) { Modulus = value; outCode.Write7BitEncodedInt(modulusIndex); } else if (string.IsNullOrWhiteSpace(Exponent)) { Exponent = value; outCode.Write7BitEncodedInt(exponentIndex); searchingKeys = false; } break; } default: continue; } } verifier.Body.Bytecode = outCode.ToArray(); if (!searchingKeys) { return(true); } } return(false); }
public bool BypassRemoteHostCheck() { ABCFile abc = ABCFiles[2]; ASInstance commManager = abc.FindInstanceByName("HabboCommunicationManager"); if (commManager == null) { return(false); } // The "host" value is always the first slot, for now. string hostValueSlotName = commManager.FindTraits <SlotConstantTrait>(TraitType.Slot) .Where(t => t.Type.ObjName == "String").ToArray()[0].ObjName; ASMethod initComponent = commManager.FindMethod("initComponent", "void").Method; if (initComponent == null) { return(false); } using (var inCode = new FlashReader(initComponent.Body.Bytecode)) using (var outCode = new FlashWriter(inCode.Length)) { int hostSlotIndex = abc.Constants.IndexOfMultiname(hostValueSlotName); while (inCode.Position != inCode.Length) { OPCode op = inCode.ReadOP(); outCode.WriteOP(op); if (op != OPCode.GetLocal_0) { continue; } op = inCode.ReadOP(); outCode.WriteOP(op); if (op != OPCode.CallPropVoid) { continue; } int callPropVoidIndex = inCode.Read7BitEncodedInt(); outCode.Write7BitEncodedInt(callPropVoidIndex); int callPropVoidArgCount = inCode.Read7BitEncodedInt(); outCode.Write7BitEncodedInt(callPropVoidArgCount); if (callPropVoidArgCount != 0) { continue; } int getPropertyNameIndex = abc.Constants .IndexOfMultiname("getProperty"); outCode.WriteOP(OPCode.GetLocal_0); outCode.WriteOP(OPCode.FindPropStrict); outCode.Write7BitEncodedInt(getPropertyNameIndex); outCode.WriteOP(OPCode.PushString); outCode.Write7BitEncodedInt(abc.Constants.AddString("connection.info.host")); outCode.WriteOP(OPCode.CallProperty); outCode.Write7BitEncodedInt(getPropertyNameIndex); outCode.Write7BitEncodedInt(1); outCode.WriteOP(OPCode.InitProperty); outCode.Write7BitEncodedInt(hostSlotIndex); outCode.Write(inCode.ToArray(), inCode.Position, inCode.Length - inCode.Position); do { op = inCode.ReadOP(); }while (op != OPCode.CallPropVoid); callPropVoidIndex = inCode.Read7BitEncodedInt(); ASMultiname callPropVoidName = abc.Constants.Multinames[callPropVoidIndex]; ASMethod connectMethod = commManager.FindMethod(callPropVoidName.ObjName, "void").Method; RemoveHostSuffix(abc, connectMethod); initComponent.Body.Bytecode = outCode.ToArray(); return(true); } } return(false); }