OWASP O2 Platform Blog

Injecting O2 into another .NET Process (in this case NUnit.exe)

Here is a pretty powerful example of what can be done with O2’s .NET reflection APIs.

The objective is to start NUnit under the control of an O2 script and to add a new feature to NUnit (in this case a new error viewer)

There are multiple scripts at play here

1) Inject O2 into – NUnit.h2:  O2 Gui to edit+compile+launch the O2_1st_Script.cs and O2_Launcher
2) O2_Launcher.cs: generic O2 launcher that will look for the O2_1st_Script.cs file, compile it and execute it
3) O2_1st_Script.cs: starts the NUnit gui (WinForms) and once that is started, loads and runs a couple of extra O2 scripts (that have NUnit specific actions)
4) inject error viewer.h2– O2 script that adds the new feature to NUnit
5) Run NUnit – BusinessLogic Class.h2 – O2 script that does a couple actions on the NUnit Gui (in this case select a node from the treeView and click on the ‘Run’ button)

This is what the ‘patched’ version of NUnit looks like:

Here is what the first script (Inject O2 into – NUnit.h2) looks like:

Here is the Source code for each of the relevant scripts

1)  Inject O2 into – NUnit.h2:  O2 Gui to edit+compile+launch the O2_1st_Script.cs and O2_Launcher

</pre>
&nbsp;

var topPanel = O2Gui.open<Panel>("Inject O2 into other apps",700,400);
//var topPanel = panel.clear().add_Panel();
var actionsPanel = topPanel.insert_Above(40);
var codeEditor = topPanel.add_SourceCodeEditor();
topPanel.insert_LogViewer();

var currentFolder = PublicDI.CurrentScript.directoryName();
var compiledDllsFolder = "";
var compiledDllsFolder_TextBox = actionsPanel.add_TextBox(20,"Target Folder","").onTextChange((text)=> compiledDllsFolder= text);
//return currentFolder;
//currentFolder = @"C:\O2\O2Scripts_Database\O2_Core_APIs";

compiledDllsFolder_TextBox.set_Text(@"C:\O2\_XRules_Local\NUnit_Injection\NUnit-2.5.10.11092\NUnit-2.5.10.11092\bin\net-2.0\lib");

&nbsp;

Action<string,string, string> compileToExtension =
    (file, extension,mainClass) =>{
                "Compiling file: {0} ".debug(file);
                var fileToCompile = currentFolder.pathCombine(file + ".cs");
                var compiledDll = compiledDllsFolder.pathCombine(file + extension);
                if (fileToCompile.fileExists().isFalse())
                    "could not find file to compile: {0}".error(fileToCompile); 
                else
                {
                    var assembly = (mainClass.valid())
                                        ? new CompileEngine().compileSourceFiles(new List<string> {fileToCompile}, mainClass)
                                        : new CompileEngine().compileSourceFiles(new List<string> {fileToCompile}, mainClass, System.IO.Path.GetFileNameWithoutExtension(compiledDll));
                    if (assembly.isNull())
                        "no compiled assembly object created for: {0}".error(fileToCompile);
                    else
                    {
                        Files.Copy(assembly.Location, compiledDll);
                        "Copied: {0} to {1}".info(assembly.Location, compiledDll);
                        if (compiledDll.fileExists().isFalse())
                            "compiled file not created in: {0}".error(compiledDll);
                       
                    }
                } 
            };
 
Action<string> compile =
    (file)=> compileToExtension(file,".dll", ""); 
 
 
Action runCompilationProcess =
    ()=>{
            Files.Copy("O2_Kernel.dll".assembly().Location, compiledDllsFolder);
            Files.Copy("O2_Interfaces.dll".assembly().Location, compiledDllsFolder);
            Files.Copy("O2_DotNetWrappers.dll".assembly().Location, compiledDllsFolder);
            Files.Copy("O2_Views_ASCX.dll".assembly().Location, compiledDllsFolder);
            //required for script execution
            Files.Copy("O2_External_SharpDevelop.dll".assembly().Location, compiledDllsFolder);
            Files.Copy("O2SharpDevelop.dll".assembly().Location, compiledDllsFolder);
            Files.Copy("O2_API_AST.dll".assembly().Location, compiledDllsFolder);
            Files.Copy("log4net.dll".assembly().Location, compiledDllsFolder);                       
            Files.Copy("White.Core.dll".assembly().Location, compiledDllsFolder);            //Files.Copy(".dll".assembly().Location, compiledDllsFolder);
            Files.Copy("O2_XRules_Database.exe".assembly().Location, compiledDllsFolder);
           
            compileToExtension("O2_Launcher", ".exe", "V2.O2.Platform.Launcher"); 
           
            Files.Copy(currentFolder.pathCombine("O2_1st_Script.cs"), compiledDllsFolder);
        };

actionsPanel.add_Link("Run Compilation Process", 0,0,()=> runCompilationProcess() )
            .append_Link("Execute O2_Launcher.cs", ()=> compiledDllsFolder.pathCombine("O2_Launcher.exe").startProcess())
            .append_Link("Edit O2_Launcher.cs", ()=> codeEditor.open(currentFolder.pathCombine("O2_Launcher.cs")))
            .append_Link("Edit O2_1st_Script.cs", ()=> codeEditor.open(currentFolder.pathCombine("O2_1st_Script.cs")));

codeEditor.open(currentFolder.pathCombine("O2_Launcher.cs"));
//runCompilationProcess();
return "done";

 
2) O2_Launcher.cs: generic O2 launcher that will look for the O2_1st_Script.cs file, compile it and execute it

// This file is part of the OWASP O2 Platform (http://www.owasp.org/index.php/OWASP_O2_Platform) and is released under the Apache 2.0 License (<a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)
//O2Tag_OnlyAddReferencedAssemblies
using System;
using System.Windows.Forms;
using O2.Kernel.ExtensionMethods; 
using O2.Kernel.Objects;   
using O2.DotNetWrappers.DotNet;
using O2.DotNetWrappers.ExtensionMethods;
using O2.Views.ASCX.Ascx.MainGUI;
using O2.Views.ASCX.classes.MainGUI;
 
//O2Ref:O2_Interfaces.dll
//O2Ref:O2_Kernel.dll
//O2Ref:O2_DotNetWrappers.dll
//O2Ref:O2_Views_ASCX.dll
  
namespace V2.O2.Platform
{ 
    static class Launcher
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary></pre>
&nbsp;

        [STAThread]
        static void Main(string[] args)
        {
            if (Control.ModifierKeys == Keys.Shift)
                showLogViewer().parentForm().width(1000).height(400); 
            var firstScript = "O2_1st_Script.cs";           
            Console.WriteLine("Welcome to the O2 Platform ...");
           
            "Current AppDomain: {0}".info(AppDomain.CurrentDomain.BaseDirectory);
           
            CompileEngine.lsGACExtraReferencesToAdd.Clear();
            var assembly = new CompileEngine().compileSourceFile(firstScript);
            if (assembly.notNull())           
            {
                Console.WriteLine("Executing script {0} from location {1}".info(firstScript, assembly.Location));
                if (assembly.methods().size()>0)
                {
                    assembly.methods()[0].invoke();
                    Console.WriteLine("Invocation complete");
                }
                else
                    Console.WriteLine("Error: there were no methods in compiled assembly");           
            }
            else
                Console.WriteLine("Error: could not find, compile or execute first script ({0})".format(firstScript));
        }               
       
        public static ascx_LogViewer showLogViewer()
        {
            return O2Gui.open<ascx_LogViewer>();
        }              
    }
}

 
3) O2_1st_Script.cs: loads starts the NUnit gui (WinForms) and once that loads runs a couple of extra O2 scripts (that have NUnit specific actions)

// This file is part of the OWASP O2 Platform (http://www.owasp.org/index.php/OWASP_O2_Platform) and is released under the Apache 2.0 License (<a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)
using System;
using System.Windows.Forms;
using O2.Kernel.ExtensionMethods;
using O2.DotNetWrappers.ExtensionMethods;
using O2.DotNetWrappers.DotNet;
using O2.DotNetWrappers.Windows;
using O2.Views.ASCX.Ascx.MainGUI;
using O2.Views.ASCX.classes.MainGUI;</pre>
&nbsp;

using O2.External.SharpDevelop.ExtensionMethods;
//using O2.DotNetWrappers.H2Scripts;
using O2.XRules.Database.Utils;

//O2Ref:O2_Kernel.dll
//O2Ref:O2_Interfaces.dll
//O2Ref:O2_DotNetWrappers.dll
//O2Ref:O2_Views_ASCX.dll
//O2Ref:O2_XRules_Database.exe
//O2Ref:O2_External_SharpDevelop.dll
//O2Ref:O2SharpDevelop.dll
//O2Ref:O2_API_AST.dll
//O2Ref:log4net.dll

//O2Ref:System.dll
//O2Ref:System.Windows.Forms.dll

//O2Ref:System.Drawing.dll
//O2Ref:System.Xml.dll
//O2Ref:System.Core.dll
//O2Ref:System.Data.dll 
//O2Ref:System.Xml.Linq.dll

//O2Ref:nunit-gui-runner.dll

//O2File:Scripts_ExtensionMethods.cs

namespace V2.O2.Platform
{
    public class Launcher
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
       
        public void Main()
        {
            if (Control.ModifierKeys == Keys.Shift)
                showLogViewer();                        
            "This is O2's first Script!!".info();
            "Current AppDomain: {0}".info(AppDomain.CurrentDomain.BaseDirectory);
            O2Thread.staThread(()=>{NUnit.Gui.AppEntry.Main(new string [] {});});
            O2Thread.staThread(
                ()=>{
                        this.sleep(1000);
                        "Trying to get lastFormLoaded".info();
                        var nUnit ="".lastFormLoaded();
                        if (nUnit.isNull())
                        {
                            "Could not get a reference to the main window".error();
                        }
                        else
                        {
                            "Got reference to the main window".info();
                            //var tab =      nUnit.controls<TabControl>(true)[1];     
                            //var scriptEditor = tab.add_Tab("O2Script").add_Script();
                           
                            var scriptEditor = O2Gui.open<Panel>("NUnit Scripts",600,300).add_Script().parentForm().top(600);                       
                           
                            @"E:\_XRules_Local\NUnit_Injection\Scripts\inject error viewer.h2".compile_H2Script().executeFirstMethod();
                            @"E:\_XRules_Local\NUnit_Injection\Scripts\Run NUnit - BusinessLogic Class.h2".compile_H2Script().executeFirstMethod();
                            
                            
                            
                                           }

                    });
        }   
       
        public static ascx_LogViewer showLogViewer()
        {
            return O2Gui.open<ascx_LogViewer>();                       
        }
    }
}

4) inject error viewer.h2– O2 script that adds the new feature to NUnit

var nUnitGui= "".applicationWinForms()[0];</pre>
&nbsp;

nUnitGui.set_Text( NUnit (O2 version)");

var tabControl = nUnitGui.controls<TabControl>(true)[0];
var tabPage = tabControl.controls()[0];
var error_tabPage =  tabPage.controls()[0];

var textBox = error_tabPage.controls<TextBox>(true)[0];

           
//var popupWindow = "errorPage".popupWindow(800,500);
var popupWindow = tabControl.add_Tab("O2 error viewer").add_Panel();

textBox.onTextChange(
    (text)=>{
                var data = from line in textBox.get_Text().split_onLines()
                            where line.valid()
                            select new { location = line.split(" in ")[0].subString(3),  file = line.split(" in ")[1].split(":line")[0], lineNumber =line.split(" in ")[1].split(":line")[1] };

                var popupTableList = popupWindow.clear().add_TableList();
                popupTableList.show(data);
               
               
                var codeViewer = popupTableList.insert_Below().add_SourceCodeViewer();
                popupTableList.afterSelect_get_Row(
                    (row)=>{
                                row.values();
                                var file = row.values()[1];
                                var lineNumber = row.values()[2].toInt();
                                codeViewer.open(file).gotoLine(lineNumber);
                            });
                popupTableList.selectFirst();       
            });

return "ok";
 
//O2File:API_GuiAutomation.cs
//O2Ref:White.Core.dll

//O2Ref:nunit-gui-runner.dll
//O2Ref:nunit.uikit.dll
//O2Ref:O2_Kernel.dll
//O2Ref:O2_Interfaces.dll
//O2Ref:O2_DotNetWrappers.dll
//O2Ref:O2_Views_ASCX.dll
//O2Ref:O2_XRules_Database.exe
//O2Ref:O2_External_SharpDevelop.dll
//O2Ref:O2SharpDevelop.dll
//O2Ref:O2_API_AST.dll
//O2Ref:log4net.dll
//O2Ref:System.Drawing.dll
//O2Ref:System.Xml.dll
//O2Ref:System.Core.dll
//O2Ref:System.Data.dll 
//O2Ref:System.Xml.Linq.dll
//O2Ref:System.Windows.Forms.dll
//O2Ref:System.dll

5) Run NUnit – BusinessLogic Class.h2 – O2 script that does a couple actions on the NUnit Gui (in this case select a node from the treeView and click on the ‘Run’ button) 

var nUnitGui= "".applicationWinForms()[0];</pre>
&nbsp;

nUnitGui.set_Text("NUnit (O2 version)");
var treeView = nUnitGui.controls<TreeView>(true)[1];
var node = treeView.nodes()[0];
treeView.mouse_MoveTo_WinForm();

var guiAutomation = new API_GuiAutomation();
guiAutomation.mouse_MoveBy(-110,-150)
             .mouse_Click();

nUnitGui.button("&Run")
        .mouse_MoveTo_WinForm()
        .click();

return "ok";
 
//O2File:API_GuiAutomation.cs
//O2Ref:White.Core.dll

//O2Ref:nunit-gui-runner.dll
//O2Ref:nunit.uikit.dll
//O2Ref:O2_Kernel.dll
//O2Ref:O2_Interfaces.dll
//O2Ref:O2_DotNetWrappers.dll
//O2Ref:O2_Views_ASCX.dll
//O2Ref:O2_XRules_Database.exe
//O2Ref:O2_External_SharpDevelop.dll
//O2Ref:O2SharpDevelop.dll
//O2Ref:O2_API_AST.dll
//O2Ref:log4net.dll
//O2Ref:System.Drawing.dll
//O2Ref:System.Xml.dll
//O2Ref:System.Core.dll
//O2Ref:System.Data.dll 
//O2Ref:System.Xml.Linq.dll
//O2Ref:System.Windows.Forms.dll
//O2Ref:System.dll

Simple Script.h2

For reference this is the base script that can be executed inside NMap AppDomain

return "O2 Platform script";</pre>
&nbsp;
//var nUnitGui= "".applicationWinForms()[0];
//nUnitGui.set_Text("NUnit (O2 version)");
//var tabControl = nUnitGui.controls<TabControl>(true)[0];

&nbsp;

return "ok";
 
//O2File:API_GuiAutomation.cs
//O2Ref:White.Core.dll

//O2Ref:nunit-gui-runner.dll
//O2Ref:nunit.uikit.dll
//O2Ref:O2_Kernel.dll
//O2Ref:O2_Interfaces.dll
//O2Ref:O2_DotNetWrappers.dll
//O2Ref:O2_Views_ASCX.dll
//O2Ref:O2_XRules_Database.exe
//O2Ref:O2_External_SharpDevelop.dll
//O2Ref:O2SharpDevelop.dll
//O2Ref:O2_API_AST.dll
//O2Ref:log4net.dll
//O2Ref:System.Drawing.dll
//O2Ref:System.Xml.dll
//O2Ref:System.Core.dll
//O2Ref:System.Data.dll 
//O2Ref:System.Xml.Linq.dll
//O2Ref:System.Windows.Forms.dll
//O2Ref:System.dll

July 7, 2011 - Posted by | .NET, Interoperability

1 Comment »

  1. […] (O2 version).h2  has an editor for all these scripts, but by default this is disabled (see NUnit example for details). The default behaviour of Util – Launch AppScan Standard (O2 version).h2 (when […]

    Pingback by Injecting O2 into IBM Rational AppScan Standard « OWASP O2 Platform Blog | August 6, 2011 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: