/// <summary> /// /// </summary> /// <param name="code"></param> /// <param name="terminalInstructionIndex"></param> /// <param name="stackIn"></param> /// <param name="blocks"></param> /// <returns></returns> public static AVM1Stack TraceBlock( AVM1Code code, int terminalInstructionIndex, AVM1Stack stackIn, List<uint> blocks ) { AVM1Stack newStack = new AVM1Stack(); //stackIn.CopyTo( newStack ); // *** make me work **** return newStack; }
/// <summary> /// /// </summary> /// <param name="code"></param> /// <param name="instructionIndex"></param> /// <returns></returns> public Modification GetInlineCode( AVM1Code code, int instructionIndex ) { List<string> all = new List<string>(); for ( int i = 0; i < _Check.Count; i++ ) { for ( int j = 0; j < _Check[ i ].InlineSource.Count; j++ ) { all.Add( _Check[ i ].InlineSource[ j ] ); } } Modification m = new Modification( (uint)instructionIndex, code[ instructionIndex ], "OriginalAction" ); m.Load( all, new List<ModVariable>() ); return m; }
/// <summary> /// /// </summary> /// <param name="code"></param> /// <param name="instructionIndex"></param> /// <param name="mStack"></param> /// <returns></returns> public override bool Execute( AVM1Code code, int instructionIndex, CheckMachine.MachineStack mStack ) { AVM1DataElement e = new AVM1DataElement(); // check if we can resolve the argument within the basic block of the instruction if ( AVM1.Stack.Trace.TraceArgument( code, instructionIndex, null, _ArgumentNumber, out e ) ) { if ( e.DataType != AVM1DataTypes.AVM_String ) { return false; } else { CheckMachine.MachineStackEntry se = new CheckMachine.MachineStackEntry(); se.Type = CheckMachine.MachineStackType.String; se.Value = e.Value; mStack.Push( se ); return true; } } return false; }
/// <summary> /// /// </summary> /// <param name="code"></param> /// <param name="instructionIndex"></param> /// <param name="stackIn"></param> /// <param name="argc"></param> /// <param name="entry"></param> /// <returns></returns> public static bool TraceArgument( AVM1Code code, int instructionIndex, AVM1Stack stackIn, uint argc, out AVM1DataElement entry ) { if ( null == stackIn) stackIn = new AVM1Stack(); int indexInBlock; BasicBlock home = code.Flowgraph.BlockOfInstruction( ( uint )instructionIndex, out indexInBlock ); if ( null == home ) { throw new Exception( "FUCKUP: instuction index " + instructionIndex.ToString( "d" ) + " not found in AVM1Code graph" ); } for ( int i = 0; i < indexInBlock; i++ ) { if ( code[ ( int )home.Indices[ i ] ].IsStackPredictable ) { code[ ( int )home.Indices[ i ] ].PerformStackOperations( stackIn ); } else { entry = default( AVM1DataElement ); return false; } } if ( stackIn.Count > argc ) { entry = stackIn[ argc ]; return true; } else { entry = default(AVM1DataElement); return false; } }
// link to the CheckMachine /// <summary> /// /// </summary> /// <param name="code"></param> /// <param name="instructionIndex"></param> /// <param name="mStack"></param> /// <returns></returns> public abstract bool Execute( AVM1Code code, int instructionIndex, MachineStack mStack );
/// <summary> /// /// </summary> /// <param name="code"></param> /// <param name="instructionIndex"></param> /// <returns></returns> protected PatchState NeedsPatching( AVM1Code code, int instructionIndex ) { _Machine.Reset(); if ( _Machine.Run( code, instructionIndex, _Check ) ) { // the run completed, that's good // check the result CheckMachine.MachineStackEntry e = _Machine.MachineResult; if ( e.Type == CheckMachine.MachineStackType.KeepInstruction ) return PatchState.Innocent; else if ( e.Type == CheckMachine.MachineStackType.RemoveInstruction ) return PatchState.Change; else throw new Exception( "FUCKUP! Final CheckMachine State is wongobongo" ); } else { return PatchState.Indeterministic; } }
/// <summary> /// /// </summary> /// <param name="code"></param> /// <param name="modLibrary"></param> /// <returns></returns> public bool PatchPrepare( AVM1Code code, ModLib modLibrary ) { List<int> triggerPositions = new List<int>(); // check if trigger action is found, if not bail for ( int i = 0; i < code.Count; i++ ) { if ( code[ i ].ActionType == _TriggerAction ) { triggerPositions.Add( i ); } } if ( 0 == triggerPositions.Count ) return false; // check if static analysis can show no need to patch List<int> patchPositions = new List<int>(); List<int> modificationPositions = new List<int>(); for ( int i = 0; i < triggerPositions.Count; i++ ) { switch ( NeedsPatching( code, triggerPositions[i] ) ) { case PatchState.Innocent: // ignore break; case PatchState.Indeterministic: patchPositions.Add( triggerPositions[ i ] ); break; case PatchState.Change: modificationPositions.Add( triggerPositions[ i ] ); break; default: throw new Exception( "FUCKUP, cannot even handle an enum correctly" ); } } // now patch the indeterministic ones for ( int i = 0; i < patchPositions.Count; i++ ) { Modification mod = this.GetInlineCode( code, patchPositions[ i ] ); modLibrary.Modifications.Add( mod ); } // now, patch the ones that need to go! // ... this.GetRemovalCode( ... ); return true; }
/// <summary> /// /// </summary> /// <param name="input"></param> /// <returns></returns> public bool Parse( Stream input ) { AVM1InstructionSequence bytecode; _ParsingFailures = false; _ClipEventFlags = new ClipEventFlags( this.Version ); _ClipEventFlags.Parse( input ); BinaryReader br = new BinaryReader( input ); _length = br.ReadUInt32(); _codeSize = _length; if ( _ClipEventFlags.ClipEventKeyPress ) { if ( 1 > _length ) { throw new SwfFormatException( "ClipActionRecord length=0 but KeyCode indicated by ClipEventKeyPress" ); } _KeyCode = br.ReadByte(); _codeSize--; } long before = br.BaseStream.Position; try { bytecode = Helper.SwfCodeReader.GetCode( _codeSize, br, this.Version ); if ( br.BaseStream.Position != ( before + _codeSize ) ) { throw new SwfFormatException( "ClipActionRecord code reader consumed more than length indicated (" + ( ( uint )( br.BaseStream.Position - before ) ).ToString() + " consumed, " + _codeSize + " length)" ); } } catch ( AVM1ExceptionByteCodeFormat ave ) { Log.Error(this, ave ); _ParsingFailures = true; if (SwfFile.Configuration.AVM1DeleteInvalidBytecode) { bytecode = new AVM1InstructionSequence(); } else { SwfFormatException swfe = new SwfFormatException( "ClipActionRecord parsing error", ave ); throw swfe; } } finally { // // make sure that the input stream is at the right position // it would have if code reading would have been successful // long diff = ( before + _codeSize ) - br.BaseStream.Position; if ( 0 != diff ) br.BaseStream.Seek( diff, SeekOrigin.Current ); } _Code = new AVM1Code( bytecode ); return _ParsingFailures; }
/// <summary> /// /// </summary> /// <returns></returns> private bool Load() { bool result; RemoveComments(); result = Populate(); AVM1InstructionSequence bytecode; // // Now fill the _Code list for quick access // if ( result ) { bytecode = new AVM1InstructionSequence(); for ( int i = 0; i < _InnerCode.Count; i++ ) { bytecode.Add( _InnerCode[ i ].Code ); } _Code = new AVM1Code( bytecode ); String s = String.Format("Modification with {0:d} instructions loaded", _Code.Count ); //Log.Debug(this, s); } else { //Log.Debug(this, "Error loading modification" ); } return result; }
/* public bool AddFunction( string filenameOfModification ) { Modification m = new Modification( AVM1Actions.ActionDefineFunction2 ); // the actionCode is not used here bool result = m.Load( filenameOfModification, _Variables ); if ( result ) _Functions.Add( m ); return result; } */ /* public void ApplyAll( AVM1CodeCFG ccfg ) { for ( int modFuncs = 0; modFuncs < _Functions.Count; modFuncs++ ) { AVM1BasicBlock head = ccfg[ 0 ]; for ( int i = 0; i < _Functions[ modFuncs ].Code.Count; i++ ) { head.Instructions.Insert( i, _Functions[ modFuncs ].Code[ i ] ); } } for ( int modi = 0; modi < _Modifications.Count; modi++ ) { foreach ( UInt32 id in ccfg.Keys ) { for ( int i = 0; i < ccfg[ id ].Instructions.Count; i++ ) { if ( ccfg[ id ].Instructions[ i ].ActionType == _Modifications[ modi ].Victim ) { ccfg[ id ].Instructions.RemoveAt( i ); for ( int j = 0; j < _Modifications[ modi ].Code.Count; j++ ) { ccfg[ id ].Instructions.Insert( i + j, _Modifications[ modi ].Code[ j ] ); } i += _Modifications[ modi ].Code.Count; } } } } } */ /// <summary> /// /// </summary> /// <param name="codeToBePatched"></param> public void ApplyAll( AVM1Code codeToBePatched ) { for ( int modFuncs = 0; modFuncs < _Functions.Count; modFuncs++ ) { codeToBePatched.InjectAt( 0, _Functions[ modFuncs ].Code ); } for ( int modIndex = 0; modIndex < _Modifications.Count; modIndex++ ) { codeToBePatched.InjectAt( (int)_Modifications[ modIndex ].IndexOfModification, _Modifications[ modIndex ].Code ); int removalPoint = (int)_Modifications[modIndex].IndexOfModification + _Modifications[ modIndex ].Code.Count; codeToBePatched.RemoveAt( removalPoint ); } }