<?xml version="1.0" encoding="utf-8"?>
<s:Window xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:ParamHandlers="ParamHandlers.*"
width="751" height="687" title="AMF Fuzzer" close="closePopUp()" backgroundColor="#60f3ea" showStatusBar="false">
<fx:Script>
<![CDATA[
/****************************************************************************
* ADOBE SYSTEMS INCORPORATED
* Copyright 2012 Adobe Systems Incorporated and it’s licensors
* All Rights Reserved.
*
* NOTICE: Adobe permits you to use, modify, and distribute this file
* in accordance with the terms of the license agreement accompanying it.
* ****************************************************************************/
import osUtils.FileActionEvent;
import osUtils.FileActions;
import ParamHandlers.ObjectParser;
import ParamHandlers.ParamCollection;
import flash.net.registerClassAlias;
import mx.controls.Alert;
import mx.rpc.AbstractOperation;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.remoting.mxml.RemoteObject;
import Fuzzer.FuzzerDB;
import Fuzzer.FuzzerLogger;
[Bindable]
[Embed(source="assets/fuzzer/ErrorImage.jpg")]
public var errorIcon:Class;
private var fActions:FileActions;
private var fuzzLog:FuzzerLogger;
private var fuzzDB:FuzzerDB = new FuzzerDB();
private var currentSlot:int = 0;
private var currentName:String;
private var currentType:String;
private var currentFuzzValue:String;
private var defaultParams:Array;
private var rawParams:Array;
private var lastNavPos:int;
/**
* @private
* This function parses the response from the AMF call and displays it in the text field.
*
* @param e The ResultEvent from the AMF call.
*/
private function parseResponse(e:ResultEvent):void {
var resStr:String;
if (typeof(e.result) == "boolean") {
if (e.result) {
resStr = "The call returned true!";
} else {
resStr = "The call returned false."
}
} else if (typeof(e.result) == "number") {
resStr = "The call returned the number: " + e.result;
} else if (typeof(e.result) == "string") {
resStr = "The call returned the string: " + e.result;
} else if (typeof(e.result) == "xml") {
resStr = e.result.toString();
} else {
var outputData:String = "";
var responseData:* = e.result.source;
var OParser:ObjectParser = new ObjectParser()
outputData += OParser.arrayToString(responseData);
resStr = outputData;
}
this.fuzzLog.addResult(this.currentName, this.currentFuzzValue,resStr);
if (this.currentName == "baseline") {
while (this.currentSlot < this.defaultParams.length && this.rawParams[this.currentSlot].fuzz == "n") {
this.currentSlot++;
}
if (this.currentSlot == this.defaultParams.length) {
this.fuzzLog.createCollection();
mx.controls.Alert.show("Fuzzing Complete!","Success",4,this);
this.winTN.selectedIndex = 1;
return;
}
this.currentType = this.rawParams[this.currentSlot].type;
this.currentName = this.currentSlot.toString() + " - " + this.currentType;
this.fuzzLog.addSlotEntry(this.currentName, this.currentType);
}
fuzzNext();
}
/**
* @private
* This function is called when the AMF call issues a FaultEvent.
*
* @param e The FaultEvent from the AMF call
*/
private function showFault(e:FaultEvent):void {
var resStr:String = e.messageId.toString() + ": " + e.message;
this.fuzzLog.addResult(this.currentName, this.currentFuzzValue,resStr,"errorIcon");
if (this.currentName == "baseline") {
while (this.currentSlot < this.defaultParams.length && this.rawParams[this.currentSlot].fuzz == "n") {
this.currentSlot++;
}
if (this.currentSlot == this.defaultParams.length) {
this.fuzzLog.createCollection();
mx.controls.Alert.show("Fuzzing Complete!","Success",4,this);
this.winTN.selectedIndex = 1;
return;
}
this.currentType = this.rawParams[this.currentSlot].type;
this.currentName = this.currentSlot.toString() + " - " + this.currentType;
this.fuzzLog.addSlotEntry(this.currentName, this.currentType);
}
fuzzNext();
//this.statusOutput.text = "Failed!";
}
/**
* @private
* This function drives the fuzzing effort
*/
private function fuzzNext():void {
var tempParams:Array = this.fuzzDB.getNextAttackArgs(this.currentType,this.currentSlot,this.defaultParams);
if (tempParams == null) {
this.currentSlot++;
while (this.currentSlot < this.defaultParams.length && this.rawParams[this.currentSlot].fuzz == "n") {
this.currentSlot++;
}
if (this.currentSlot == this.defaultParams.length) {
this.fuzzLog.createCollection();
mx.controls.Alert.show("Fuzzing Complete!","Success",4,this);
this.winTN.selectedIndex = 1;
return;
} else {
this.currentType = this.rawParams[this.currentSlot].type;
tempParams = this.fuzzDB.getNextAttackArgs(this.currentType,this.currentSlot,this.defaultParams);
this.currentName = this.currentSlot.toString() + " - " + this.currentType;
this.fuzzLog.addSlotEntry(this.currentName, this.currentType);
}
}
if (tempParams[this.currentSlot] != null) {
this.currentFuzzValue = tempParams[this.currentSlot].toString();
} else {
this.currentFuzzValue = "null"
}
sendRequest(tempParams);
}
/**
* @private
* This function will send the AMF request to the remote server based on the entered information.
*/
private function sendRequest(params:Array = null):void {
var ro:RemoteObject = new RemoteObject(this.roDestination.text);
ro.endpoint = this.roEndpoint.text;
if (params == null) {
params = this.sendDG.getFuncParams();
this.defaultParams = params;
this.rawParams = this.sendDG.getRawParams();
this.fuzzLog = new FuzzerLogger();
this.currentName = "baseline";
this.currentSlot = 0;
this.currentFuzzValue = "baseline";
if (this.rawParams.length > 0 ) {
this.currentType = this.rawParams[0].type;
}
}
if (params.length == 0) {
mx.controls.Alert.show("You can't fuzz something that doesn't take arguments","Error",4,this);
return;
}
ro.addEventListener(ResultEvent.RESULT,parseResponse);
ro.addEventListener(FaultEvent.FAULT,showFault);
if (this.roUsername && this.roUsername.text.length > 0) {
if (this.remoteCreds.selected) {
ro.setRemoteCredentials(this.roUsername.text,this.roPassword.text);
} else {
ro.setCredentials(this.roUsername.text, this.roPassword.text);
}
}
var roOp:AbstractOperation = ro.getOperation(this.roFunction.text);
roOp.send(params[0]);
}
/**
* @private
* Loads custom fuzz values
*/
private function loadFuzzValues():void {
if (this.fActions == null) {
this.fActions = new FileActions();
this.fActions.currentFile = File.documentsDirectory.resolvePath("/");
fActions.addEventListener(FileActionEvent.GENERAL_ERROR, displayError);
fActions.addEventListener(FileActionEvent.IO_ERROR, displayError);
fActions.addEventListener(FileActionEvent.OPEN_RO_COMPLETE, openFile);
} else {
fActions.removeEventListener(FileActionEvent.CREATE_COMPLETE, saveFile);
fActions.removeEventListener(FileActionEvent.OPEN_RO_COMPLETE, openFile);
fActions.addEventListener(FileActionEvent.OPEN_RO_COMPLETE, openFile);
}
var fFilter:FileFilter = new FileFilter("XML","*.xml");
fActions.openFile(fFilter,FileActions.READ);
}
/**
* @private
* Results the fuzzer to the default values
*/
private function resetToDefaults():void {
this.fuzzDB.setDefaults();
}
/**
* @private
* Clears default values
*/
private function clearDefaults():void {
this.fuzzDB.clearDefaults();
}
/**
* @private
* Display error from File Action Event
*/
private function displayError(e:FileActionEvent):void {
mx.controls.Alert.show(e.message,"Error",4,this);
}
/**
* @private
* Prompt where to save the data
*/
private function saveResponse():void {
if (this.fActions == null) {
this.fActions = new FileActions();
this.fActions.currentFile = File.documentsDirectory.resolvePath("/");
fActions.addEventListener(FileActionEvent.GENERAL_ERROR, displayError);
fActions.addEventListener(FileActionEvent.IO_ERROR, displayError);
fActions.addEventListener(FileActionEvent.CREATE_COMPLETE, saveFile);
} else {
fActions.removeEventListener(FileActionEvent.CREATE_COMPLETE, saveFile);
fActions.removeEventListener(FileActionEvent.OPEN_RO_COMPLETE, openFile);
fActions.addEventListener(FileActionEvent.CREATE_COMPLETE, saveFile);
}
this.fActions.openFile(null,FileActions.CREATE,"foo.xml");
}
/**
* @private
* Write data to the file
*/
private function saveFile(e:Event):void {
this.fActions.writeString(this.fuzzLog.logXML.toXMLString());
this.fActions.closeFile();
}
/**
* @private
* Open fuzzer file
*/
private function openFile(e:Event):void {
var myFA:FileActions = e.target as FileActions;
var ba:ByteArray = new ByteArray();
myFA.readAllBytes(ba);
var xml:String = ba.toString();
myFA.closeFile();
try {
this.fuzzDB = new FuzzerDB(new XML(xml));
} catch (err:Error) {
mx.controls.Alert.show(err.message,"Error Parsing XML",4,this);
}
}
/**
* @private
* On Window Close, ensure ObjectCollection PopUp is shut down.
*/
private function closePopUp():void {
this.sendDG.closePopUp();
}
/**
* @private
* Called by the results panel when someone selects an item in the tree, it decides what to put in the resultOutput box based on the selection.
*
* @param evt The tree selection event.
*/
private function treeSelect(evt:Event):void {
var node:XML = Tree(evt.target).selectedItem as XML;
this.resultOutput.setStyle("font-weight","normal");
if (node.@type.indexOf("slot") == 0) {
this.resultOutput.text = "";
} else if (node.@type.indexOf("result") == 0) {
this.resultOutput.text = node.@data.toString();
}
}
/**
* @private
* Initializes the Navigator tab on view.
*/
private function initNavigator():void {
if (this.fuzzLog != null) {
this.resultTree.dataProvider = this.fuzzLog.logData;
this.resultTree.labelFunction = this.fuzzLog.logTreeLabel;
this.resultOutput.text = "";
this.resultOutput.setStyle("font-weight","normal");
} else {
this.resultTree.dataProvider = null;
this.resultOutput.text = "No data from a fuzzing run available";
this.resultOutput.setStyle("font-weight","bold");
}
}
/**
* @private
* Searches the selected output for the selected string.
*/
private function resultSearch():void {
if (this.resultOutput == null || this.resultOutput.text == "") {
return;
}
if (this.resultSearchText.text.length == 0) {
mx.controls.Alert.show("Please enter a value into the search field","Error",4,this);
}
var str:String = this.resultOutput.text;
var index:int;
if (this.resultSearchButton.label == "Find") {
this.resultSearchButton.label = "Find Next";
index = str.indexOf(this.resultSearchText.text);
} else {
index = str.indexOf(this.resultSearchText.text,this.lastNavPos + 1);
}
this.lastNavPos = index;
if (index > -1) {
this.searchOutput.text = "";
this.resultOutput.focusManager.setFocus(this.resultOutput);
this.resultOutput.selectRange(index,index + this.resultSearchText.text.length);
} else {
this.searchOutput.text = "Not found."
}
}
]]>
</fx:Script>
<mx:TabNavigator id="winTN" visible="true" x="8" y="21" width="733" height="656">
<s:NavigatorContent label="Setup" width="100%" height="100%" tabIndex="0">
<s:Group>
<s:Label x="10" y="15" text="Fuzzer Configuration:" width="193"/>
<s:Button x="10" y="41" label="Add Custom Fuzz Values" click="loadFuzzValues()"/>
<s:Button x="172" y="41" label="Clear Defaults" width="132" click="clearDefaults()"/>
<s:Button x="312" y="41" label="Reset To Defaults" width="144" click="resetToDefaults()"/>
<mx:HRule x="11" y="76" width="673"/>
<s:Label x="10" y="113" width="101" text="RO Endpoint:"/>
<s:TextInput x="119" y="107" width="565" id="roEndpoint" maxChars="4096"
toolTip="Example: http://www.example.com:8400/blazeds/messagebroker/amf"/>
<s:Label x="10" y="139" text="RO Destination:" width="101"/>
<s:TextInput x="119" y="133" width="565" id="roDestination"
toolTip="Example: This would be id in the destination tag of your remoting-config.xml or proxy-config.xml"/>
<s:Label x="10" y="166" text="RO Function:" width="101"/>
<s:TextInput x="119" y="160" width="565" id="roFunction"
toolTip="This would be the name of an exposed funtion within the above destination"/>
<s:Label x="539" y="228" text="Auth Username:" width="101"/>
<s:TextInput x="537" y="246" width="147" id="roUsername"/>
<s:Label x="538" y="291" text="Auth Password:" width="101"/>
<s:TextInput x="537" y="308" width="147" id="roPassword"/>
<s:CheckBox x="537" y="348" label="Remote Credentials" width="147" id="remoteCreds"/>
<s:Label x="10" y="199" text="Function Parameters/New Value" width="223"/>
<ParamHandlers:ParamCollection x="10" y="216" width="508" id="sendDG" showFuzz="true" includeClass="true" includeObject="true"/>
<s:Button x="10" y="471" label="Start Fuzzing" width="125" click="sendRequest()"/>
</s:Group>
</s:NavigatorContent>
<s:NavigatorContent id="outputTab" label="Output" width="100%" height="100%" tabIndex="0" show="initNavigator()">
<s:Group>
<s:HGroup x="16" y="0" width="687" height="592" verticalAlign="middle">
<mx:Tree id="resultTree" y="7" height="575" width="207" change="this.treeSelect(event)" iconField="@icon"
folderClosedIcon="@Embed(source='/assets/fuzzer/ResultImage.jpg')"
folderOpenIcon="@Embed(source='/assets/fuzzer/ResultImage.jpg')"
defaultLeafIcon="@Embed(source='/assets/fuzzer/SuccessImage.jpg')"/>
<s:VGroup width="436" height="582" verticalCenter="middle">
<s:HGroup width="415" height="31" horizontalAlign="right" verticalCenter="middle">
<s:Label width="109" x="6" id="searchOutput"/>
<s:TextInput id="resultSearchText" width="214" click="this.resultSearchButton.label='Find'"/>
<s:Button id="resultSearchButton" label="Find" click="resultSearch()"/>
</s:HGroup>
<s:TextArea id="resultOutput" width="416" height="539" color="#FFFFFF" contentBackgroundColor="#000000"/>
</s:VGroup>
</s:HGroup>
<s:Button label="Save Response" click="saveResponse()" x="540" y="592"/>
</s:Group>
</s:NavigatorContent>
</mx:TabNavigator>
</s:Window>