/// <summary> /// For arguments passed by reference: it assignes new values, and copies flags form inputValues. /// </summary> /// <param name="flow">FlowController</param> /// <param name="inputValues">Input values into analyzed function</param> /// <param name="nativeFunctions">Info about analyzed function</param> /// <returns>List of assigned values into aliases</returns> public static List <Value> ResolveAliasArguments(FlowController flow, List <Value> inputValues, List <NativeFunction> nativeFunctions) { List <Value> result = new List <Value>(); MemoryEntry argc = flow.InSet.ReadVariable(new VariableIdentifier(".argument_count")).ReadMemory(flow.OutSet.Snapshot); int argumentCount = ((IntegerValue)argc.PossibleValues.ElementAt(0)).Value; foreach (var nativeFunction in nativeFunctions) { if (nativeFunction.MinArgumentCount <= argumentCount && nativeFunction.MaxArgumentCount >= argumentCount) { int functionArgumentNumber = 0; for (int i = 0; i < argumentCount; i++) { MemoryEntry arg = flow.InSet.ReadVariable(Argument(i)).ReadMemory(flow.InSet.Snapshot); NativeFunctionArgument functionArgument = nativeFunction.Arguments.ElementAt(functionArgumentNumber); if (functionArgument.ByReference == true) { MemoryEntry res = NativeAnalyzerUtils.ResolveReturnValue(functionArgument.Type, flow); res = new MemoryEntry(FlagsHandler.CopyFlags(inputValues, res.PossibleValues)); flow.OutSet.GetVariable(Argument(i)).WriteMemory(flow.OutSet.Snapshot, res); result.AddRange(res.PossibleValues); } //incremeneting functionArgumentNumber if (nativeFunction.Arguments.ElementAt(functionArgumentNumber).Dots == false) { functionArgumentNumber++; } } } } return(result); }
/// <summary> /// Creates an object a initialize default with defualt fields. /// </summary> /// <param name="flow">FlowController</param> /// <param name="type">Type to resolve</param> /// <returns>ObjectValue</returns> private static Value CreateObject(FlowController flow, string type) { var objectAnalyzer = NativeObjectAnalyzer.GetInstance(flow.OutSet); QualifiedName typeName = new QualifiedName(new Name(type)); if (objectAnalyzer.ExistClass(typeName)) { ClassDecl decl = objectAnalyzer.GetClass(typeName); var fields = objectAnalyzer.GetClass(typeName).Fields; ObjectValue value = flow.OutSet.CreateObject(flow.OutSet.CreateType(decl)); var newObject = flow.OutSet.GetLocalControlVariable(new VariableName(".tmpObject" + type)); newObject.WriteMemory(flow.OutSet.Snapshot, new MemoryEntry(value)); if (value is ObjectValue) { foreach (FieldInfo field in fields.Values) { if (field.IsStatic == false) { var newField = newObject.ReadField(flow.OutSet.Snapshot, new VariableIdentifier(field.Name.Value)); try { newField.WriteMemory(flow.OutSet.Snapshot, NativeAnalyzerUtils.ResolveReturnValue(field.Type, flow)); } catch (Exception) {} } } } return(value); } else { return(flow.OutSet.AnyObjectValue); } }
/// <summary> /// Models constructor of native object /// </summary> /// <param name="flow">FlowController</param> public void Construct(FlowController flow) { if (NativeAnalyzerUtils.checkArgumentsCount(flow, Method)) { NativeAnalyzerUtils.checkArgumentTypes(flow, Method); } initObject(flow); }
/// <summary> /// Reads all arguments and returns them in List /// </summary> /// <param name="flow">FlowController</param> /// <returns>List of arguments</returns> private List <MemoryEntry> getArguments(FlowController flow) { MemoryEntry argc = flow.InSet.ReadVariable(new VariableIdentifier(".argument_count")).ReadMemory(flow.OutSet.Snapshot); int argumentCount = ((IntegerValue)argc.PossibleValues.ElementAt(0)).Value; var arguments = new List <MemoryEntry>(); for (int i = 0; i < argumentCount; i++) { arguments.Add(flow.OutSet.ReadVariable(NativeAnalyzerUtils.Argument(i)).ReadMemory(flow.OutSet.Snapshot)); } return(arguments); }
/// <summary> /// Models constructor of native object /// </summary> /// <param name="flow">FlowController</param> public void initObject(FlowController flow) { var nativeClass = NativeObjectAnalyzer.GetInstance(flow.OutSet).GetClass(ObjectName); var fields = nativeClass.Fields; var thisVariable = flow.OutSet.GetVariable(new VariableIdentifier("this")); List <Value> inputValues = new List <Value>(); foreach (var argument in getArguments(flow)) { inputValues.AddRange(argument.PossibleValues); } MethodIdentifier methodIdentifier = new MethodIdentifier(ObjectName, Method.Name.Name); if (NativeObjectAnalyzer.ReportingFunctions.ContainsKey(methodIdentifier)) { foreach (var flag in NativeObjectAnalyzer.ReportingFunctions[methodIdentifier]) { if (FlagsHandler.IsDirty(inputValues, flag)) { AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisSecurityWarning(NativeAnalyzerUtils.GetCallerScript(flow.OutSet), flow.CurrentPartial, flow.CurrentProgramPoint, flag, methodIdentifier.Name.ToString())); break; } } } foreach (FieldInfo field in fields.Values) { if (field.IsStatic == false) { MemoryEntry fieldValues = NativeAnalyzerUtils.ResolveReturnValue(field.Type, flow); fieldValues = new MemoryEntry(FlagsHandler.CopyFlags(inputValues, fieldValues.PossibleValues)); var fieldEntry = thisVariable.ReadField(flow.OutSet.Snapshot, new VariableIdentifier(field.Name.Value)); fieldEntry.WriteMemory(flow.OutSet.Snapshot, fieldValues); } } }
/// <summary> /// Checks number of arguments in called function. /// </summary> /// <param name="flow">FlowControllers</param> /// <param name="nativeFunctions">NativeFunctions</param> /// <returns>true if the arguments count matches, false otherwise</returns> static public bool checkArgumentsCount(FlowController flow, List <NativeFunction> nativeFunctions) { //check number of arduments MemoryEntry argc = flow.InSet.ReadVariable(new VariableIdentifier(".argument_count")).ReadMemory(flow.OutSet.Snapshot); int argumentCount = ((IntegerValue)argc.PossibleValues.ElementAt(0)).Value; //argument count hassnt been comupted yet if (nativeFunctions.ElementAt(0).MinArgumentCount == -1) { foreach (var nativeFuntion in nativeFunctions) { nativeFuntion.MinArgumentCount = 0; nativeFuntion.MaxArgumentCount = 0; foreach (var nativeFunctionArgument in nativeFuntion.Arguments) { if (nativeFunctionArgument.Dots) { nativeFuntion.MaxArgumentCount = 1000000000; } else if (nativeFunctionArgument.Optional) { nativeFuntion.MaxArgumentCount++; } else { nativeFuntion.MinArgumentCount++; nativeFuntion.MaxArgumentCount++; } } //Console.WriteLine("Name: {0},Min: {1}, Max: {2}", nativeFuntion.Name,nativeFuntion.MinArgumentCount, nativeFuntion.MaxArgumentCount); } } string numberOfArgumentMessage = ""; bool argumentCountMatches = false; foreach (var nativeFunction in nativeFunctions) { if (nativeFunction.MinArgumentCount <= argumentCount && nativeFunction.MaxArgumentCount >= argumentCount) { argumentCountMatches = true; } if (numberOfArgumentMessage != "") { numberOfArgumentMessage += " or"; } if (nativeFunction.MaxArgumentCount >= 1000000000) { if (nativeFunction.MinArgumentCount == 1) { numberOfArgumentMessage += " at least " + nativeFunction.MinArgumentCount + " parameter"; } else { numberOfArgumentMessage += " at least " + nativeFunction.MinArgumentCount + " parameters"; } } else { if (nativeFunction.MaxArgumentCount == nativeFunction.MinArgumentCount) { if (nativeFunction.MinArgumentCount == 1) { numberOfArgumentMessage += " " + nativeFunction.MinArgumentCount + " parameter"; } else { numberOfArgumentMessage += " " + nativeFunction.MinArgumentCount + " parameters"; } } else { numberOfArgumentMessage += " " + nativeFunction.MinArgumentCount + "-" + nativeFunction.MaxArgumentCount + " parameters"; } } } if (argumentCountMatches == false) { string s = ""; if (argumentCount != 1) { s = "s"; } AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(NativeAnalyzerUtils.GetCallerScript(flow.OutSet), "Function " + nativeFunctions.ElementAt(0).Name.ToString() + " expects" + numberOfArgumentMessage + ", " + argumentCount + " parameter" + s + " given.", flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.WRONG_NUMBER_OF_ARGUMENTS)); return(false); } else { return(true); } }
/// <summary> /// Check type of one argument and reports warnings if they doesn't match. /// </summary> /// <param name="flow">FlowController</param> /// <param name="memoryEntry">Values of argument</param> /// <param name="argument">Information about argument</param> /// <param name="argumentNumber">Number of argument</param> /// <param name="functionName">Name of function</param> /// <param name="warnings">List of warnings, for inserting warnings</param> private static void CheckArgumentTypes(FlowController flow, MemoryEntry memoryEntry, NativeFunctionArgument argument, int argumentNumber, string functionName, List <AnalysisWarning> warnings) { bool argumentMatches = true; foreach (Value value in memoryEntry.PossibleValues) { if (value is AnyValue || value is UndefinedValue) { continue; } switch (argument.Type) { case "mixed": break; case "int": case "integer": //TODO: workaround: type declarations in .xml files specifies the arguments that should be of type number by type int // fix declarations in xml files!! //if (!(ValueTypeResolver.IsInt(value) || ValueTypeResolver.IsLong(value))) if (!(ValueTypeResolver.IsInt(value) || ValueTypeResolver.IsLong(value) || ValueTypeResolver.IsFloat(value))) { argumentMatches = false; } break; case "float": case "number": if (!(ValueTypeResolver.IsInt(value) || ValueTypeResolver.IsLong(value) || ValueTypeResolver.IsFloat(value))) { argumentMatches = false; } break; case "string": case "char": if (!ValueTypeResolver.IsString(value)) { argumentMatches = false; } break; case "array": if (!ValueTypeResolver.IsArray(value)) { argumentMatches = false; } break; case "object": if (!ValueTypeResolver.IsObject(value)) { argumentMatches = false; } break; case "bool": case "boolean": if (!ValueTypeResolver.IsBool(value)) { argumentMatches = false; } break; case "resource": case "resouce": if (!(value is AnyResourceValue)) { argumentMatches = false; } break; case "callable": case "callback": if (!ValueTypeResolver.IsString(value) && !(value is FunctionValue)) { argumentMatches = false; } break; case "void": throw new Exception("Void is not a type of argument"); default: if (!ValueTypeResolver.IsObject(value)) { argumentMatches = false; } break; } } if (argumentMatches == false) { warnings.Add(new AnalysisWarning(NativeAnalyzerUtils.GetCallerScript(flow.OutSet), "Wrong type of argument number " + argumentNumber + " in function " + functionName + ", expecting " + argument.Type, flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.WRONG_ARGUMENTS_TYPE)); } }
/// <summary> /// Models a called method. /// </summary> /// <param name="flow"></param> public void Analyze(FlowController flow) { if (NativeAnalyzerUtils.checkArgumentsCount(flow, Method)) { NativeAnalyzerUtils.checkArgumentTypes(flow, Method); } MethodIdentifier methodIdentifier = new MethodIdentifier(ObjectName, Method.Name.Name); var nativeClass = NativeObjectAnalyzer.GetInstance(flow.OutSet).GetClass(ObjectName); var fields = nativeClass.Fields; var functionResult = NativeAnalyzerUtils.ResolveReturnValue(Method.ReturnType, flow); var arguments = getArguments(flow); var thisVariable = flow.OutSet.GetVariable(new VariableIdentifier("this")); List <Value> inputValues = new List <Value>(); bool isStaticCall = false; if (thisVariable.ReadMemory(flow.OutSet.Snapshot).PossibleValues.Count() == 1 && thisVariable.ReadMemory(flow.OutSet.Snapshot).PossibleValues.First() is UndefinedValue) { isStaticCall = true; var fieldsEntries = new List <MemoryEntry>(); foreach (FieldInfo field in fields.Values) { var fieldEntry = thisVariable.ReadField(flow.OutSet.Snapshot, new VariableIdentifier(field.Name.Value)); fieldsEntries.Add(fieldEntry.ReadMemory(flow.OutSet.Snapshot)); inputValues.AddRange(fieldEntry.ReadMemory(flow.OutSet.Snapshot).PossibleValues); } fieldsEntries.AddRange(arguments); foreach (FieldInfo field in fields.Values) { var fieldEntry = thisVariable.ReadField(flow.OutSet.Snapshot, new VariableIdentifier(field.Name.Value)); MemoryEntry newfieldValues = NativeAnalyzerUtils.ResolveReturnValue(field.Type, flow); newfieldValues = new MemoryEntry(FlagsHandler.CopyFlags(inputValues, newfieldValues.PossibleValues)); HashSet <Value> newValues = new HashSet <Value>((fieldEntry.ReadMemory(flow.OutSet.Snapshot)).PossibleValues); foreach (var newValue in newfieldValues.PossibleValues) { newValues.Add(newValue); } thisVariable.ReadField(flow.OutSet.Snapshot, new VariableIdentifier(field.Name.Value)).WriteMemory(flow.OutSet.Snapshot, new MemoryEntry(newValues)); } } foreach (var argument in arguments) { inputValues.AddRange(argument.PossibleValues); } if (NativeObjectAnalyzer.ReportingFunctions.ContainsKey(methodIdentifier)) { foreach (var flag in NativeObjectAnalyzer.ReportingFunctions[methodIdentifier]) { if (FlagsHandler.IsDirty(inputValues, flag)) { AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisSecurityWarning(NativeAnalyzerUtils.GetCallerScript(flow.OutSet), flow.CurrentPartial, flow.CurrentProgramPoint, flag, methodIdentifier.Name.ToString())); break; } } } if (isStaticCall == true) { thisVariable.WriteMemory(flow.OutSet.Snapshot, new MemoryEntry(FlagsHandler.CopyFlags(inputValues, thisVariable.ReadMemory(flow.OutSet.Snapshot).PossibleValues))); } functionResult = new MemoryEntry(FlagsHandler.CopyFlags(inputValues, functionResult.PossibleValues)); if (NativeObjectAnalyzer.CleaningFunctions.ContainsKey(methodIdentifier)) { foreach (var flag in NativeObjectAnalyzer.CleaningFunctions[methodIdentifier]) { functionResult = new MemoryEntry(FlagsHandler.Clean(functionResult.PossibleValues, flag)); } } flow.OutSet.GetLocalControlVariable(SnapshotBase.ReturnValue).WriteMemory(flow.OutSet.Snapshot, functionResult); var assigned_aliases = NativeAnalyzerUtils.ResolveAliasArguments(flow, inputValues, (new NativeFunction[1] { Method }).ToList()); }