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>
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");
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>
[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>
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>
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>
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>
//var nUnitGui= "".applicationWinForms()[0];
//nUnitGui.set_Text("NUnit (O2 version)");
//var tabControl = nUnitGui.controls<TabControl>(true)[0];
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


[...] (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 [...]