public override void AddTransitionsToSimulation(Simulation simulation) { simulation.AddRootTransition( this, new WriteToReadPrimitive( MemoryAccessParameter.Content, MemoryAddress.AddressOfStackFramePointer, name: "corrupt stack frame pointer leading to function return", constraints: (context) => ( (context.Target.IsX86Application() == true) ), onSuccess: (SimulationContext context, ref Violation v) => { v.Address = MemoryAddress.AddressOfStackFramePointer; v.Name = "read frame pointer from stack"; } ) ); simulation.AddTransition( this, new ReadToReadPrimitive( MemoryAccessParameter.Base, MemoryAddress.AddressOfStackFramePointer, name: "restore corrupted frame pointer and return from child function", constraints: (context) => ( // // The attacker must be able to trigger a return from the function. // (context.AttackerFavorsAssumeTrue(AssumptionName.CanTriggerFunctionReturn) == true) && // // If the violation does not corrupt the stack protection cookie or it is possible // to bypass the stack protection check, then the transition is possible. // ( (context.CanCorruptMemoryAtAddress(MemoryAddress.AddressOfStackProtectionCookie) == false) || (context.CanDetermineStackProtectionCookie() == true) ) ), onSuccess: (SimulationContext context, ref Violation v) => { v.Name = "restore stack pointer"; v.Address = MemoryAddress.AddressOfStackReturnAddress; v.ControlTransferMethod = ControlTransferMethod.FunctionReturn; v.AddressingMode = MemoryAddressingMode.Absolute; } ) ); }
public override void AddTransitionsToSimulation(Simulation simulation) { var dataTypes = new MemoryContentDataType[] { MemoryContentDataType.WriteBasePointer, MemoryContentDataType.WriteDisplacement, MemoryContentDataType.WriteContent, MemoryContentDataType.WriteExtent, MemoryContentDataType.ReadBasePointer, MemoryContentDataType.ReadContent, MemoryContentDataType.ReadDisplacement, MemoryContentDataType.ReadExtent, MemoryContentDataType.FunctionPointer, MemoryContentDataType.CppVirtualTablePointer }; foreach (MemoryContentDataType dataType in dataTypes) { MemoryAddress address = new MemoryAddress(dataType, MemoryRegionType.Stack); simulation.AddRootTransition( this, new InitializeDestinationContentPrimitive( String.Format("Initialize content at destination address ({0}) of write via stack local var initialization", address), destinationAddress: address, constraints: (context) => ( (context.AttackerFavorsAssumeTrue(AssumptionName.CanInitializeContentViaStackOverlappingLocal) == true) ) ) ); simulation.AddRootTransition( this, new InitializeSourceContentPrimitive( String.Format("Initialize content at source address ({0}) of read via stack local var initialization", address), sourceAddress: address, constraints: (context) => ( (context.AttackerFavorsAssumeTrue(AssumptionName.CanInitializeContentViaStackOverlappingLocal) == true) ) ) ); } }
public override void AddTransitionsToSimulation(Simulation simulation) { foreach (MemoryRegionType region in Enum.GetValues(typeof(MemoryRegionType))) { if (!MemoryAddress.WritableRegionTypes.Contains(region)) { continue; } MemoryAddress functionPointerAddress = new MemoryAddress(MemoryContentDataType.FunctionPointer, region); simulation.AddRootTransition( this, new WriteToReadPrimitive( MemoryAccessParameter.Content, functionPointerAddress, name: String.Format("corrupt function pointer stored in {0}", region), onSuccess: (SimulationContext context, ref Violation v) => { v.Name = "call through function pointer"; v.ControlTransferMethod = ControlTransferMethod.IndirectFunctionCall; v.ContentDataType = MemoryContentDataType.FunctionPointer; v.AddressingMode = MemoryAddressingMode.Absolute; } ) ); } MemoryAddress anyFunctionPointerAddress = new MemoryAddress(MemoryContentDataType.FunctionPointer); simulation.AddRootTransition( this, new ReadToExecutePrimitive( anyFunctionPointerAddress, ControlTransferMethod.IndirectFunctionCall, name: String.Format("call through function pointer"), constraints: (context) => ( (context.AttackerFavorsAssumeTrue(AssumptionName.CanTriggerFunctionPointerCall)) ) ) ); }
public override void AddTransitionsToSimulation(Simulation simulation, MemoryAddress codeAddress) { simulation.AddRootTransition( this, new CodeExecutionPrimitive( "execute ROP (stage to VirtualProtect/VirtualAlloc)", codeExecutionAddress: codeAddress, constraints: (context) => ( (context.IsAssumedTrue(AssumptionName.CanExecuteControlledCode) == false) && (context.CanExecuteData() == false) && (context.IsAssumedTrue(AssumptionName.CanBypassNX) == false) && (this.GetBaseROPConstraints(codeAddress)(context) == true) && (context.AttackerFavorsAssumeTrue(AssumptionName.CanProtectDataAsCode) == true) ), nextViolation: (context) => { Violation v = context.CurrentViolation.NewTransitiveViolation( MemoryAccessMethod.Execute, name: "execute arbitrary code", baseState: MemoryAccessParameterState.Controlled, contentSrcState: MemoryAccessParameterState.Controlled ); return(v); }, onSuccess: (SimulationContext context, ref Violation v) => { context.Assume(AssumptionName.CanExecuteCode); context.Assume(AssumptionName.CanExecuteControlledCode); context.Assume(new Assumption.CanFindAddress(MemoryAddress.AddressOfAttackerControlledData)); context.Assume(new Assumption.CanFindAddress(MemoryAddress.AddressOfAttackerControlledCode)); context.Assume(AssumptionName.CanBypassNX); context.Assume(AssumptionName.CanExecuteDesiredCode); } ) ); }
public override void AddTransitionsToSimulation(Simulation simulation) { simulation.AddRootTransition( this, new WriteToReadPrimitive( MemoryAccessParameter.Content, MemoryAddress.AddressOfStackStructuredExceptionHandler, name: "corrupt SEH handler", constraints: (context) => ( (context.Target.OperatingSystem.IsWindows() == true) && (context.Target.IsX86Application() == true) && (context.CanTriggerException() == true) ), onSuccess: (SimulationContext context, ref Violation v) => { v.Name = "read exception handler"; v.AddressingMode = MemoryAddressingMode.Absolute; v.Address = MemoryAddress.AddressOfStackStructuredExceptionHandler; } ) ); simulation.AddTransition( this, new ReadToExecutePrimitive( MemoryAddress.AddressOfStackStructuredExceptionHandler, ControlTransferMethod.IndirectFunctionCall, name: "call corrupted handler via exception", constraints: (context) => ( (context.CanBypassSAFESEH() == true) && (context.CanBypassSEHOP() == true) ), onSuccess: (SimulationContext context, ref Violation v) => { v.Name = "transfer control to exception handler"; // Assume that we can find an image code segment if we can find the address of NTDLL if (context.HasAssumption(new Assumption.CanFindAddress(MemoryAddress.AddressOfNtdllImageBase))) { context.Assume(new Assumption.CanFindAddress(new MemoryAddress(MemoryContentDataType.Code, MemoryRegionType.ImageCodeSegment))); } } ) ); }
public override void AddTransitionsToSimulation(Simulation simulation) { simulation.AddRootTransition( this, new CodeExecutionPrimitive( "execute payload in JIT code region", codeExecutionAddress: new MemoryAddress(MemoryContentDataType.Code, MemoryRegionType.JITCode), constraints: (context) => ( (context.IsAssumedTrue(AssumptionName.CanExecuteControlledCode) == false) && (context.IsAssumedTrue(AssumptionName.CanBypassNX) == false) && (context.AttackerFavorsAssumeTrue(AssumptionName.IsJITEngineVersionKnown) == true) && (context.CanInitializeCodeViaJIT() == true) ), nextViolation: (context) => { Violation v = context.CurrentViolation.NewTransitiveViolation( MemoryAccessMethod.Execute, name: "execute arbitrary code", baseState: MemoryAccessParameterState.Controlled, contentSrcState: MemoryAccessParameterState.Controlled ); return(v); }, onSuccess: (SimulationContext context, ref Violation v) => { context.Assume(AssumptionName.CanInitializeCodeViaJIT); context.Assume(new Assumption.CanFindAddress(MemoryAddress.AddressOfAttackerControlledCode)); context.Assume(AssumptionName.CanExecuteCode); context.Assume(AssumptionName.CanExecuteControlledCode); context.Assume(AssumptionName.CanBypassNX); context.Assume(AssumptionName.CanExecuteDesiredCode); } ) ); }
public override void AddTransitionsToSimulation(Simulation simulation) { simulation.AddRootTransition( this, new InitializeExecutableContentPrimitive( name: "load non-ASLR image", codeAddress: new MemoryAddress(MemoryContentDataType.Code, MemoryRegionType.ImageCodeSegment), newContentState: MemoryAccessParameterState.Fixed, constraints: (context) => ( (context.CanLoadNonASLRImage() == true) ), onSuccess: (SimulationContext context, ref Violation v) => { context.Assume(AssumptionName.CanLoadNonASLRImage); } ) ); }
public override void AddTransitionsToSimulation(Simulation simulation) { simulation.AddRootTransition( this, new CodeExecutionPrimitive( name: "execute attacker controlled data as code", codeExecutionAddress: new MemoryAddress(MemoryContentDataType.AttackerControlledData), constraints: (context) => ( (context.IsAssumedTrue(AssumptionName.CanExecuteControlledCode) == false) && (context.CanExecuteData() == true) && (context.CanFindAddress(MemoryAddress.AddressOfAttackerControlledCode) == true) ), nextViolation: (context) => { Violation v = context.CurrentViolation.NewTransitiveViolation( MemoryAccessMethod.Execute, name: "execute arbitrary code", baseState: MemoryAccessParameterState.Controlled, contentSrcState: MemoryAccessParameterState.Controlled ); return(v); }, onSuccess: (SimulationContext context, ref Violation v) => { context.Assume(AssumptionName.CanExecuteCode); context.Assume(AssumptionName.CanExecuteControlledCode); context.Assume(AssumptionName.CanExecuteDesiredCode); } ) ); // add another transition to represent hopping through a jmp esp to controlled data. }
public override void AddTransitionsToSimulation(Simulation simulation, MemoryAddress codeAddress) { simulation.AddRootTransition( this, new CodeExecutionPrimitive( "execute ROP (pure)", codeExecutionAddress: codeAddress, constraints: (context) => ( (context.IsAssumedTrue(AssumptionName.CanExecuteCode) == false) && (context.IsAssumedTrue(AssumptionName.CanBypassNX) == false) && (this.GetBaseROPConstraints(codeAddress)(context) == true) ), nextViolation: (context) => { Violation v = context.CurrentViolation.NewTransitiveViolation( MemoryAccessMethod.Execute, name: "execute existing code", baseState: MemoryAccessParameterState.Controlled, contentSrcState: MemoryAccessParameterState.Fixed ); return(v); }, onSuccess: (SimulationContext context, ref Violation v) => { context.Assume(AssumptionName.CanExecuteCode); context.Assume(AssumptionName.CanBypassNX); context.Assume(AssumptionName.CanExecuteDesiredCode); } ) ); }
public override void AddTransitionsToSimulation(Simulation simulation) { var dataTypes = new MemoryContentDataType[] { MemoryContentDataType.AttackerControlledData, MemoryContentDataType.WriteBasePointer, MemoryContentDataType.WriteDisplacement, MemoryContentDataType.WriteContent, MemoryContentDataType.WriteExtent, MemoryContentDataType.ReadBasePointer, MemoryContentDataType.ReadContent, MemoryContentDataType.ReadDisplacement, MemoryContentDataType.ReadExtent, MemoryContentDataType.FunctionPointer, MemoryContentDataType.CppVirtualTablePointer, MemoryContentDataType.CppVirtualTable, }; var regionTypes = new MemoryRegionType[] { MemoryRegionType.Heap, MemoryRegionType.Any }; foreach (MemoryRegionType regionType in regionTypes) { foreach (MemoryContentDataType dataType in dataTypes) { MemoryAddress address = new MemoryAddress(dataType, regionType); simulation.AddRootTransition( this, new InitializeDestinationContentPrimitive( String.Format("heap spray content to init dest {0}", address), destinationAddress: address, constraints: (context) => ( (context.CanInitializeContentViaHeapSpray() == true) ), onSuccess: (SimulationContext context, ref Violation v) => { context.Assume(AssumptionName.CanInitializeContentViaHeapSpray); context.Assume(new Assumption.CanFindAddress(MemoryAddress.AddressOfAttackerControlledData)); } ) ); simulation.AddRootTransition( this, new InitializeSourceContentPrimitive( String.Format("heap spray content to init src {0}", address), sourceAddress: address, constraints: (context) => ( (context.CanInitializeContentViaHeapSpray() == true) ), onSuccess: (SimulationContext context, ref Violation v) => { context.Assume(AssumptionName.CanInitializeContentViaHeapSpray); context.Assume(new Assumption.CanFindAddress(MemoryAddress.AddressOfAttackerControlledData)); } ) ); } } // // Heap spraying can also be used to spray code (on systems that don't support or enable // NX). // MemoryAddress codeAddress = new MemoryAddress(MemoryContentDataType.AttackerControlledData); simulation.AddRootTransition( this, new InitializeExecutableContentPrimitive( String.Format("initialize content with code via heap spray"), codeAddress, constraints: (context) => ( // no need for this technique if we can already accomplish this via spraying data. (context.CanExecuteMemoryAtAddress(new MemoryAddress(MemoryContentDataType.AttackerControlledData, null)) == false) && (context.CanInitializeContentViaHeapSpray() == true) ), onSuccess: (SimulationContext context, ref Violation v) => { context.Assume(AssumptionName.CanInitializeContentViaHeapSpray); context.Assume(new Assumption.CanFindAddress(MemoryAddress.AddressOfAttackerControlledData)); context.Assume(new Assumption.CanFindAddress(MemoryAddress.AddressOfAttackerControlledCode)); } ) ); }
public override void AddTransitionsToSimulation(Simulation simulation) { simulation.AddRootTransition( this, new WriteToReadPrimitive( MemoryAccessParameter.Content, name: "corrupt return address on stack", writeAddress: MemoryAddress.AddressOfStackReturnAddress, onSuccess: (SimulationContext context, ref Violation v) => { v.Name = "read return address from stack"; v.Address = MemoryAddress.AddressOfStackReturnAddress; v.ControlTransferMethod = ControlTransferMethod.FunctionReturn; v.AddressingMode = MemoryAddressingMode.Absolute; //context.AssumeIsStackProtectionCookieCorrupted(); } ) ); simulation.AddTransition( this, new ReadToExecutePrimitive( MemoryAddress.AddressOfStackReturnAddress, controlTransferMethod: ControlTransferMethod.FunctionReturn, name: "return from function with corrupted return address", constraints: (context) => ( // // Base verifies that this is an indirect control transfer via a return through a stack return address. // // // The attacker must be able to trigger a return from the function. // (context.AttackerFavorsAssumeTrue(AssumptionName.CanTriggerFunctionReturn) == true) && // // If the violation does not corrupt the stack protection cookie or it is possible // to bypass the stack protection check, then the transition is possible. // ( (context.AttackerFavorsEqual(context.CurrentViolation.FunctionStackProtectionEnabled, false) == true) || (context.CanCorruptMemoryAtAddress(MemoryAddress.AddressOfStackProtectionCookie) == false) || (context.CanDetermineStackProtectionCookie() == true) ) ), onSuccess: (SimulationContext context, ref Violation v) => { v.Name = "execute from return address"; } ) ); }
public override void AddTransitionsToSimulation(Simulation simulation, MemoryAddress codeAddress) { simulation.AddRootTransition( this, new CodeExecutionPrimitive( "execute ROP (stage to disable NX for process)", codeExecutionAddress: codeAddress, constraints: (context) => ( (context.IsAssumedTrue(AssumptionName.CanExecuteControlledCode) == false) && (context.CanExecuteData() == false) && (context.IsAssumedTrue(AssumptionName.CanBypassNX) == false) && (this.GetBaseROPConstraints(codeAddress)(context) == true) && (context.Target.OperatingSystem.IsWindows() == true) && (context.Target.IsX86Application() == true) && (context.AttackerFavorsEqual(context.Target.Application.MemoryRegionNXPolicy[MemoryRegion.UserProcessHeap], MitigationPolicy.On) == true) && (context.AttackerFavorsEqual(context.Target.Application.NXPermanent, false)) ), nextViolation: (context) => { Violation v = context.CurrentViolation.NewTransitiveViolation( MemoryAccessMethod.Execute, name: "execute arbitrary code", baseState: MemoryAccessParameterState.Controlled, contentSrcState: MemoryAccessParameterState.Unknown ); return(v); }, onSuccess: (SimulationContext context, ref Violation v) => { context.Assume(AssumptionName.CanExecuteCode); // // Assume that it is now possible to execute data as code since we have disabled NX. // context.ForgetAssumption(AssumptionName.CanExecuteData); context.AssumeIsTrue(AssumptionName.CanExecuteData); context.Assume(new Assumption.CanFindAddress(MemoryAddress.AddressOfAttackerControlledData)); context.Assume(new Assumption.CanFindAddress(MemoryAddress.AddressOfAttackerControlledCode)); context.Assume(AssumptionName.CanBypassNX); } ) ); }
public override void AddTransitionsToSimulation(Simulation simulation) { foreach (MemoryRegionType region in Enum.GetValues(typeof(MemoryRegionType))) { if (!MemoryAddress.WritableRegionTypes.Contains(region)) { continue; } MemoryAddress virtualTablePointerAddress = new MemoryAddress(MemoryContentDataType.CppVirtualTablePointer, region); simulation.AddRootTransition( this, new WriteToReadPrimitive( MemoryAccessParameter.Content, virtualTablePointerAddress, name: String.Format("corrupt C++ object virtual table pointer stored in {0}", region), constraints: (context) => ( (context.AttackerFavorsEqual(context.CurrentViolation.ContentContainerDataType, MemoryContentDataType.CppObject) == true) ), onSuccess: (SimulationContext context, ref Violation v) => { v.Name = "read corrupted virtual table pointer"; v.ContentDataType = MemoryContentDataType.CppVirtualTablePointer; v.AddressingMode = MemoryAddressingMode.Absolute; } ) ); simulation.AddRootTransition( this, new ReadToReadPrimitive( MemoryAccessParameter.Base, virtualTablePointerAddress, name: String.Format("read virtual table pointer from C++ object stored in {0}", region), constraints: (context) => ( (context.AttackerFavorsEqual(context.CurrentViolation.ContentContainerDataType, MemoryContentDataType.CppObject) == true) && (context.AttackerFavorsAssumeTrue(AssumptionName.CanTriggerVirtualMethodCall)) ), onSuccess: (SimulationContext context, ref Violation v) => { v.Name = "read virtual method address from virtual table"; v.ContentDataType = MemoryContentDataType.CppVirtualTable; v.ControlTransferMethod = ControlTransferMethod.VirtualMethodCall; v.AddressingMode = MemoryAddressingMode.Absolute; } ) ); } MemoryAddress virtualTableAddress = new MemoryAddress(MemoryContentDataType.CppVirtualTable); simulation.AddTransition( this, new ReadToExecutePrimitive( virtualTableAddress, ControlTransferMethod.VirtualMethodCall, name: "call virtual method via virtual table", constraints: (context) => ( (context.AttackerFavorsAssumeTrue(AssumptionName.CanTriggerVirtualMethodCall) == true) ), onSuccess: (SimulationContext context, ref Violation v) => { v.Name = "execute virtual method"; } ) ); }