Manage Windows Advanced Firewall ports with PHP trough COM class

March 15, 2012 – 11:38 am

One day you want to be able to quickly open and close a port for a certain service running on your windows server.
I agree most security preachers would be amazed what you can do with a default installation of Apache and PHP and would simply disable COM objects in php or simply rule out such a functionalities by editing process rights on the Apache or PHP instances, but my machine  isn't the one where the whole world hangs on to so I have the liberty to do some fun proto POC stuff.

As such I wrote a simple script that allows you to load the Microsoft Advanced Firewall as a COM object and edit it's rules.
With 'editing' I mean allowing or blocking a certain port / process rule or enabling / disabling a rule completely.
Simply said this script allows you to alter existing rules but not to edit or add ports.

You can give the script a set of ports that it has to list, or you can switch a config boolean and list all configurable ports.
If it is a remote server I advice you not to list port 80 :)
You can leave out the the authentication block if you like, because most of the time people have setup htaccess themselves.

Code preview below image

or DOWNLOAD here: source code firewall demo

demo: windows firewall controller in php with COM

*****
PHP:
*****

session_start();
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Content-Type: text/html; charset=ansi");

/**
* Windows Firewall with Advanced Security browser editor: enable / disable or block / allow existing rules.
* @license Use, modify, destroy, improve and glue any license on this as long as I can keep using it myself ;)
* @author Stijn De Ryck
*/

/******* ************* ********/
/******* USER SETTINGS ********/
/******* ************* ********/

//WWW-Auth
const USERNAME = 'admin';
const PASSWORD = 'password';
//CHANGE this to ANY STRING of choice!
const HASH_SECRET = "VPS_LATCHO_SECRET";
//if MANAGE_ALL_PORTS is set to TRUE then the application wil ignore the compacted lists:
// ( MANAGE_EXISTING_INBOUND_PORTS and MANAGE_EXISTING_OUTBOUND_PORTS ) and manage all ports that are found in existing rules
const MANAGE_ALL_PORTS = FALSE;
//The in the firewall existing predefined rules whereof you want to display the following INBOUND ports, "*" is also a valid option
static $MANAGE_EXISTING_INBOUND_PORTS = array(80,21,23,3306,110,25,443,465,993,3389,6900,6800,8080,4389,81,9696);
//The in the firewall existing predefined rules whereof you want to display the following OUTBOUND ports, "*" is also a valid option
static $MANAGE_EXISTING_OUTBOUND_PORTS = array(110,25,443,465,993,3389,6900,8080,23,80,"*");

/******* **** ********/
/******* AUTH ********/
/******* **** ********/
//improvable.... TODO post ?logout ?login with href

$authorized = false;
if(isset($_GET['logout']) && ($_SESSION['auth'])) {
$_SESSION['auth'] = null;
session_destroy();
}
if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
$authuser = strtolower($_SERVER['PHP_AUTH_USER']);
if ( (strtolower(USERNAME) == $authuser)
&& (strtolower(PASSWORD) == strtolower($_SERVER['PHP_AUTH_PW']))
&& (!empty($_SESSION['auth']))
){ $authorized = true; }
}
if ( ! $authorized ) {
if (!isset($_GET['logout']))
{
header('WWW-Authenticate: Basic Realm="Login please"');
header('HTTP/1.0 401 Unauthorized');
$_SESSION['auth'] = true;
}
exit;
return;
}

/******* ********* ********/
/******* FW CONSTS ********/
/******* ********* ********/

//Domain
const NET_FW_PROFILE2_DOMAIN = 1;
const NET_FW_PROFILE2_PRIVATE = 2;
const NET_FW_PROFILE2_PUBLIC = 4;
//Enabled rule
const NET_FW_RULE_ENABLED = TRUE;
const NET_FW_RULE_DISABLED = FALSE;
//Direction
const NET_FW_RULE_DIR_IN = 1;
const NET_FW_RULE_DIR_OUT = 2;
//Action
const NET_FW_ACTION_ALLOW = 1;
const NET_FW_ACTION_BLOCK = 0;
//Protocol
const NET_FW_IP_PROTOCOL_TCP = 6;
const NET_FW_IP_PROTOCOL_UDP = 17;
const NET_FW_IP_PROTOCOL_ICMPv4 = 1;
const NET_FW_IP_PROTOCOL_ICMPv6 = 58;
//human readable protocols
$protoLabels = array(NET_FW_IP_PROTOCOL_TCP => 'TCP', NET_FW_IP_PROTOCOL_UDP => 'UDP', NET_FW_IP_PROTOCOL_ICMPv4=>'ICMPv4',NET_FW_IP_PROTOCOL_ICMPv6=>'ICMPv6' );
//human readable profiles ( public, private,...)
$profileLabels = array(1=> 'Domain',2=>'Private',4=>'Public',3=>'Dom+Priv',5=>'Dom+Pub',6=>'Priv+Pub',7=>'Dom+Priv+Pub',2147483647=>'All Profiles');

/******* ******************* ********/
/******* RULES ENUM & EDITOR ********/
/******* ******************* ********/

$objFirewall = new COM("HNetCfg.FwPolicy2");
$inboundForm="";
$outboundForm="";

foreach($objFirewall->Rules as $key => $rule) {

//NOTE: http://msdn.microsoft.com/en-us/library/windows/desktop/aa364724%28v=vs.85%29.aspx
//rule's current settings:
$name = $rule->Name;
$appname = $rule->ApplicationName ;
$svcname = $rule->ServiceName ;
$desc = $rule->Description;
$direction = $rule->Direction;
$proto = $rule->Protocol;
$action = $rule->Action;
$profile = $rule->Profiles;
$enabled = $rule->Enabled;

$localPorts = $rule->LocalPorts;
$remotePorts = $rule->RemotePorts;
//the local ports that are managed by this rule as array
$aRuleLocalPorts = explode(',',$localPorts);
$aRuleRemotePorts = explode(',',$remotePorts);
//the md5 identifier that enables us to filter a rule.
$identifier = md5(HASH_SECRET.$name.$appname.$svcname.$desc.$direction.$proto.$profile.$localPorts.$remotePorts);

if( ! in_array( $proto , array( NET_FW_IP_PROTOCOL_TCP
, NET_FW_IP_PROTOCOL_UDP
, NET_FW_IP_PROTOCOL_ICMPv4
, NET_FW_IP_PROTOCOL_ICMPv6
)
)
||
( ! (MANAGE_ALL_PORTS)
&&
count(array_intersect($MANAGE_EXISTING_INBOUND_PORTS, $aRuleLocalPorts)) == 0
&&
count(array_intersect($MANAGE_EXISTING_OUTBOUND_PORTS, $aRuleRemotePorts)) == 0
)
) { continue; };

//if we received the md5 rule identifier as variable 'ToggleBlockAllow', toggle block/allow state
if( isset($_POST['ToggleBlockAllow']) && $_POST['ToggleBlockAllow'] === $identifier ) {
$action = ($rule->Action == NET_FW_ACTION_ALLOW) ? NET_FW_ACTION_BLOCK : NET_FW_ACTION_ALLOW;
$rule->Action = $action ;
};
//if we received the md5 rule identifier as variable 'ToggleEnabled', toggle enabled/disabled state
if( isset($_POST['ToggleEnabled']) && $_POST['ToggleEnabled'] === $identifier ) {
$enabled = ($rule->Enabled == NET_FW_RULE_ENABLED) ? NET_FW_RULE_DISABLED : NET_FW_RULE_ENABLED;
$rule->Enabled = $enabled ;
};

//rule allowed/blocked state settings
$allowChecked = ($action == NET_FW_ACTION_ALLOW) ? "checked=\"checked\"" : "";
$allowLabel = ($action == NET_FW_ACTION_ALLOW) ? "<b>Allowed </b>" : "<u>Blocked </u>";
//rule enabled state settings
$enableChecked = ($enabled == NET_FW_RULE_ENABLED) ? "checked=\"checked\"" : "";
$enableLabel = ($enabled == NET_FW_RULE_ENABLED) ? "<b>Rule enabled</b>" : "<u>Rule disabled</u>";
$portListByDirection = ($direction == NET_FW_RULE_DIR_IN) ? $localPorts : $remotePorts ;
$portListByDirection = str_replace(',',', ',$portListByDirection) ;
//form color based on enabled/disabled rule, allowed/blocked state
$col = ($enabled == NET_FW_RULE_ENABLED) ? (($action == NET_FW_ACTION_ALLOW) ? "#009922" : "#992200") : "#aaaaaF";
//human readable protocol
$protoLabel = $protoLabels[$proto];
//human readable profile ( public, private,...)
$profileLabel = $profileLabels[$profile];
//messy form-item html for this rule
$formItem ="<tr>";
$formItem .="<td valign='top'>".$protoLabel."</td>";
$formItem .="<td width='100' valign='top'> <font color='".$col."'>[<b> $portListByDirection </b>]</font></td>";
$formItem .="<td width='100' valign='top'>  $profileLabel</td>";
$formItem .="<td width='100' valign='top'><font color='".$col."'>  ".$allowLabel."</font><input type=\"checkbox\" id=\"".$identifier."\" name=\"allowcheck\" onChange=\"toggle(this.id,'ToggleBlockAllow')\" ".$allowChecked." /></td>";
$formItem .="<td width='120' valign='top'>  ".$enableLabel."<input type=\"checkbox\" id=\"".$identifier."\" name=\"enablecheck\" onChange=\"toggle(this.id,'ToggleEnabled')\" ".$enableChecked." /></td>";
$formItem .="<td valign='top'><font color='".$col."'>   ".$name."</font>";
$formItem .="<i>  <font size=2>".( strpos(strtoupper($appname),"SVCHOST") ? "SVCHOST: ":strtoupper($appname) ) .' '.strtoupper($svcname)."</font></i></label></td>\n";
$formItem ."</tr>\n";

if( $direction == NET_FW_RULE_DIR_IN && ( count(array_intersect($MANAGE_EXISTING_INBOUND_PORTS, $aRuleLocalPorts)) > 0 || MANAGE_ALL_PORTS == TRUE ) ) {
//attach inbound form item if we manage this port (MANAGE_INBOUND_PORTS)
$inboundForm .= $formItem;
}else if( $direction == NET_FW_RULE_DIR_OUT && count(array_intersect($MANAGE_EXISTING_OUTBOUND_PORTS, $aRuleRemotePorts)) > 0 || MANAGE_ALL_PORTS == TRUE) {
//attach outbound form item if we manage this port (MANAGE_OUTBOUND_PORTS)
$outboundForm .= $formItem;
}
}

$html = "<html>\n<head>\n";
$toggleRuleScript = "<script>\n";
$toggleRuleScript .= "function toggle(identifier,switchOption){\n";
$toggleRuleScript .= "document.body.innerHTML += '<form id=\"dynForm\" action=\"\" method=\"post\"><input type=\"hidden\" name=\"'+switchOption+'\" value=\"'+identifier+'\"/></form>'; \n";
$toggleRuleScript .= "document.getElementById(\"dynForm\").submit(); \n}\n";
$toggleRuleScript .= "</script>\n";
$html .=$toggleRuleScript;
$html .="</head>\n<body>\n";
$html .="<h3>Inbound Rules</h3>";
$html .= "<table border=1 bordercolor=#aaaaaa>".$inboundForm."</table>";
$html .="<h3>Outbound Rules</h3>";
$html .= "<table border=1 bordercolor=#aaaaaa>".$outboundForm."</table>";
$html .="</body></html>";
echo $html;

Enjoy!

getting the xpath of a domNode element in javascript (within Air’s htmlComponent)

March 8, 2011 – 9:22 pm

I wanted to store references to certain html nodes and there info in a html document that was loaded in air's htmlcomponent.

It's reaonably easy to inject javascript into any loaded document.

The function I came up with is adapted from another example that I found online, but it is improved so that it takes care of duplicate id's if any are found.

So here al little piece of JavaScript that will get you the xpath of a node in an html doument and a little helder function to check the validity of the generated xpath.

function createXPathFromElement(elm) {
    var allNodes = document.getElementsByTagName('*');
    for (segs = []; elm && elm.nodeType == 1; elm = elm.parentNode)
    {
        if (elm.hasAttribute('id')) {
                var uniqueIdCount = 0;
                for (var n=0;n < allNodes.length;n++) {
                    if (allNodes[n].hasAttribute('id') && allNodes[n].id == elm.id) uniqueIdCount++;
                    if (uniqueIdCount > 1) break;
                };
                if ( uniqueIdCount == 1) {
                    segs.unshift('id("' + elm.getAttribute('id') + '")');
                    return segs.join('/');
                } else {
                    segs.unshift(elm.localName.toLowerCase() + '[@id="' + elm.getAttribute('id') + '"]');
                }
        } else if (elm.hasAttribute('class')) {
            segs.unshift(elm.localName.toLowerCase() + '[@class="' + elm.getAttribute('class') + '"]');
        } else {
            for (i = 1, sib = elm.previousSibling; sib; sib = sib.previousSibling) {
                if (sib.localName == elm.localName)  i++; };
                segs.unshift(elm.localName.toLowerCase() + '[' + i + ']');
        };
    };
    return segs.length ? '/' + segs.join('/') : null;
}; 

function lookupElementByXPath(path) {
    var evaluator = new XPathEvaluator();
    var result = evaluator.evaluate(path, document.documentElement, null,XPathResult.FIRST_ORDERED_NODE_TYPE, null);
    return  result.singleNodeValue;
} 

in Air's htmlcomponent I wnated to have the javascript in the code without having to load an exteral js file (not tested) and maybe risking security sandbox errors.
So In the onComplete handler of the htmlComponent I did this to inject the extra javascript in the document: (Make sure to carefully escape double quotes \" and \>\< signs !)
Again the same code, but now inline:
handling the htmlComponent listener: this.addEventListener(Event.COMPLETE, onComplete);


private function onComplete(e:Event):void
{
	var container:Object = this.window.document.createElement('div');
	this.window.onunload = cleanup;
	container.id = 'scriptContainer';
	this.window.document.body.appendChild(container);
	var script:Object = this.window.document.createElement("script");
	script.type = 'text/javascript';

	script.innerHTML = 	" function createXPathFromElement(elm) { \n"
		+"		var allNodes = document.getElementsByTagName('\*'); \n"
		+"		for (segs = []; elm && elm.nodeType == 1; elm = elm.parentNode) \n"
		+"		{ \n"
		+"			if (elm.hasAttribute('id')) { \n"
		+"					var uniqueIdCount = 0; \n"
		+"					for (var n=0;n \< allNodes.length;n++) { \n"
		+"						if (allNodes[n].hasAttribute('id') && allNodes[n].id == elm.id) uniqueIdCount++; \n"
		+"						if (uniqueIdCount \> 1) break; \n"
		+"					}; \n"
		+"					if ( uniqueIdCount == 1) { \n"
		+"						segs.unshift('id(\"' + elm.getAttribute('id') + '\")'); \n"
		+"						return segs.join('/'); \n"
		+"					} else { \n"
		+"						segs.unshift(elm.localName.toLowerCase() + '[@id=\"' + elm.getAttribute('id') + '\"]'); \n"
		+"					} \n"
		+"			} else if (elm.hasAttribute('class')) { \n"
		+"				segs.unshift(elm.localName.toLowerCase() + '[@class=\"' + elm.getAttribute('class') + '\"]'); \n"
		+"			} else { \n"
		+"				for (i = 1, sib = elm.previousSibling; sib; sib = sib.previousSibling) { \n"
		+"					if (sib.localName == elm.localName)  i++; }; \n"
		+"					segs.unshift(elm.localName.toLowerCase() + '[' + i + ']'); \n"
		+"			}; \n"
		+"		}; \n"
		+"		return segs.length ? '/' + segs.join('/') : null; \n"
		+"	}; \n"
		+"	\n"
		+"	function lookupElementByXPath(path) { \n"
		+"		var evaluator = new XPathEvaluator(); \n"
		+"		var result = evaluator.evaluate(path, document.documentElement, null,XPathResult.FIRST_ORDERED_NODE_TYPE, null); \n"
		+"		return  result.singleNodeValue; \n"
						+"	} \n";

	container.appendChild(script);
}

Within the htmlComponent (AS3) you can add code to listen for javascript mouse events and trace / store the xpath like this:


public function onClick(el:Object):String
{
    var targ:Object = el.srcElement || el.target;
    return this.window.createXPathFromElement(targ);
}

Adobe Air HtmlComponent full content to (png) Image: Problems and solutions

February 10, 2011 – 5:10 pm

I try to make this a comprehendable compact story post.
Html to image transformation in air has three difficulties:

1) BitmapData has size limitations
2) the HtmlComponent's horizontal or vertical size can't be larger then 2880 or 4096 px depending on the Air version so we can't grab the content in one time, and even if we could we still had problem 1)
3) if we scroll the content of the html component to capture the content in multiple blocks then we hit upon a display invalidate / update problem; The scrolled display isn't updated yet when we draw it to BitmapData. If we would succeed in the capturing of multiple blocks, still we would have a problem tocombine them into 1)

My workaround is to scroll the content and grab it in multiple blocks.
Every scroll I implemented a little timeout.
To tackle the maximum BitmapData size problem of 1) without going into special compiler / expanded memory / C++ tricks, was to write the BitmapData of all blocks at once into a PNG. This way we prevent  that we have to combine them first into a (possible too) large BitmapData object.
Therefore I took the adobe PngEncoder class and altered it so that instead of providing it with 1 BitmapData object, you can feed it a Vector-array of multiple BitmapData blocks and tell it how to write them away ( stacked vertically or horizontally). And so PngStackEncoder was born next to HtmlToPng.
I chose to go with PNG, because it encodes faster then jpg.

Source files for grab here:  htmlToPng Source and Demo zip

HtmlToPng result in an easy workable interface:

html 2 png demo

The HtmlToPng class uses the altered PngEncoder: PngStackEncoder, used like this:

PngStackEncoder usage

Above Demo html to png example will produce this images: (scalled down to 20% for this post).

html2png_1.png

html2png_2.png

html2png_3.png

html2png_4.png

where the black blocks are actually transparent or any other color you can provide with th the PngStackEncoder.encode fuction.

FlashDevelop Dark Theme As3 Syntax Colors (updated FD4)

February 10, 2011 – 3:40 pm

UPDATE 26 October 2011:

New download for Flashdevelop 4 because the color scheme installer of FD3 didn't seemd to do the trick.

Download here for >FD4:

Flashdevelop4_Dark_Theme_Latcho_v2.fdz

I updated my dark theme a bit to be even lighter on the eyes. Minor changes.

The method description block's green color has now less contrast with the background.

The brown color for class / function names is now a bit altered.

Download the modified theme here (<=FD3): Flashdevelop_Dark_Theme_Latcho_v2.fdz

updated Style:

Flashdevelop-Dark-As3-Syntax-Theme-v2-Latcho

The font used before was inconsolata, but that doesn't renders nice in FD3 anymore so I now advice to use Consolas from M$.

You can download the Consolas font pack here for free: Consolas Download

Cheers,

Latcho

(Obsfucate data) embed an swf as a hexadecimal string in your …swf

September 26, 2009 – 2:47 am

You can embed an swf, or any other binary octet stream, containing -harder to get to- data as a hexadecimal string into your project.

Note: This is not true data security. Nothing is securable in actionscript, but you CAN make it hard(er) to get to.

So to describe my last attempt to hide some game xml data that I embedded in an second swf i went ahead like this to embed that swf as a hex string in my main project like this:

  • 1) Create a seperate empty project along your main project and create a simple swf containing the protectable data.
  • 2) I'm not a smoker but let's say you want secure the class "SensimillaPlantagesXml.as" containing your sensitive sensimilla location xml data. Compile that class into "sensitive.swf" (uhum). Make sure that that class is embedded into the swf by including a reference to it in your document's main class new SensimillaPlantagesXml() or just put 'SensimillaPlantagesXml' as a word in your documentclass's constructor
  • 3)Create a second project along your main project that will serve as a hexadecimal tracer: Embed the swf in it with the Embed tag. We will now convert the binary application octet stream from 'sensitive.swf' to a hexadecimal string:
  • 4) This will leave us with a long hexadecimal string in the trace output window, representing your swf as hexadecimal data.
    The class to do the Binary to Hexadecimal conversion I will include later, below in this post.
  • Trace Output: 4357530a2a60000078dad55c4d6cdbd87626f547cbffae6399444f9274a3d4a642b4e9cc4719eedb.........

  • 5)Copy that string without additional spaces and paste it in a 'Data' class under a variable, called var _hexData here.
  • 6)So let me show you now how you load this hexadcimal string, and parse it as an accessible swf within you main project:


  • The only easy way to get to ALL the data of the embedded-hex-swf is (including bitmaps) is
    making an swf file from it; Now be my guest and write me a short (AIR?) tutorial please :).

    This procedure is not super secure but discourages our fast'n easy decompiler friends.
    Still better then posting the data over http.
    If the process is not clear by now, please let me know, so I can improve above instructions.

    Here you can see the transformation class that contains the two static functions binToHex() and hexToBin();

    And here you can see BinHex.as:

    Download BinHex.as

    Ciao !

    See this post as raw text

    FlashDevelop: duplicate a text selection block with a shortcut

    August 18, 2009 – 8:14 pm

    Want to duplicate multiple lines of code with a keyboard shortcut in flashdevelop ?
    FlashDevelop->Tools->Macros->Add-> Entries->... :

    
    
    ScintillaCommand|SelectionDuplicate

    Label: &BlockDupe
    Shortcut: Alt+DOWN (my own choice)

    
    

    text block duplication trough flashdevelop macro

    Dupe'm :)
    Cheers to Joel Stransky ;)

    FlashDevelop Syntax Coloring: Dark Theme

    August 15, 2009 – 1:47 am

    ----

    See for UPDATE (oktober 2011) and flashdevelop 4 compatible installert his post:

    http://greencollective.nl/blog/?p=31
    ----

    Back in time I used Sepy as a texteditor as an alternative to the Flash IDE Non-Code-Editor.
    Now my snappy editor of choice is FlashDevelop, totally tailored towards Flex SDK publishing.

    In Sepy I had a nice dark background theme, but since the switch to FD I never took the time to configure colors in FD.
    It really can make a difference for your eyes, a darker background; Less radiation or flickerHz effects I 'd say.

    For everybody who wants to get AS3 coding  'darker', here is my theme for you to grab. It's a flash develop zip file, and should install by just running it after download and answer the dialog with..YES! . (  A restart of FD might be necessary ? )
    If you're not sure yet, backup your current brightwhite scheme first.
    Grab here: SyntaxColorAS3_FD_Latcho.fdz

    [[ UPDATE: there is a minor update on this the with minimal changes available here: http://greencollective.nl/blog/?p=31  ]]

    You can alter and save your settings by opening the menu Tools>Syntax Coloring:AS3.

    The font I just started using is named 'Inconsolata'  (as seen in the screenshot);
    Seems to be  a 1st choice of a bunch-a-folks. Looks peacefull to me on first sight.
    The original Inconsolata Open Type font wasn't received by FD's font enumerator, but I found a ported TTF that does well.
    Grab here:  Inconsolata.ttf

    Enjoy.

    preview SyntaxColorAS3_FD_Latcho

    Why wouldn't I be a

    sponsor

    setting breakpoints, debug swf via console / terminal /prompt with fdb

    August 13, 2009 – 12:00 am

    Finally found a nice article that explains how flex sdk's fdb command line debug tool works :)

    Reminder for myself:

    http://installingcats.com/2007/12/07/how-to-use-command-line-debugger-fdb-to-debug-flex-flash-on-mac-os-x/

    Got into it for a moment ----> this will be a messy post :)

    found some extra info / commands within fdb now:

    New to fdb? Do 'tutorial' for basic info.
    List of fdb commands:
    bt (bt)             Print backtrace of all stack frames
    break (b)           Set breakpoint at specified line or function
    cf (cf)             Display the name and number of the current file
    clear (cl)          Clear breakpoint at specified line or function
    condition (cond)    Apply/remove conditional expression to a breakpoint
    continue (c)        Continue execution after stopping at breakpoint
    commands (com)      Sets commands to execute when breakpoint hit
    delete (d)          Delete breakpoints or auto-display expressions
    directory (dir)     Add a directory to the search path for source files
    disable (disab)     Disable breakpoints or auto-display expressions
    disassemble (disas) Disassemble source lines or functions
    display (disp)      Add an auto-display expressions
    enable (e)          Enable breakpoints or auto-display expressions
    file (fil)          Specify application to be debugged.
    finish (f)          Execute until current function returns
    handle (han)        Specify how to handle a fault
    help (h)            Display help on fdb commands
    home (ho)           Set listing location to where execution is halted
    info (i)            Display information about the program being debugged
    kill (k)            Kill execution of program being debugged
    list (l)            List specified function or line
    next (n)            Step program
    print (p)           Print value of variable EXP
    pwd (pw)            Print working directory
    quit (q)            Exit fdb
    run (r)             Start debugged program
    set (se)            Set the value of a variable
    source (so)         Read fdb commands from a file
    step (s)            Step program until it reaches a different source line
    tutorial (t)        Display a tutorial on how to use fdb
    undisplay (u)       Remove an auto-display expression
    viewswf (v)         Set or clear filter for file listing based on swf
    what (wh)           Displays the context of a variable
    where (w)           Same as bt
    Type 'help' followed by command name for full documentation.
    (fdb)

    Start an application with 'run'.
    View file names with 'info sources'.
    List a file with 'list'.
    Set breakpoints with 'break'.
    Execute program with 'continue' until a breakpoint is hit.
    Examine state of program with 'where', 'print', 'info locals'.
    Execute individual statements with 'next', 'step', and 'finish'.
    Resume execution with 'continue'.
    Quit fdb with 'quit'.

    It boils down to launching FDB.EXE in your flexsdk's 'bin' dir.
    - Typing run:
    (fdb) run

    - Open a debug-enabled swf (preferably on http in your browser since that ads-in network access if you don't have security configured for that local swf path)
    - set a breakpoint via a functionname (even if it is in another file, the name will match when fdb hits it), so for example type:
    (fdb) b registerModule<enter>
    You have now set a breakpoint for that function name that will be resolved later, linenumbers / filenames must be possible too.
    And then type continue + <enter> ( add more breakpoints if you like) and again continue + <enter>
    The swf will now run until it hits the breakpoint marked functionname 'registerModule':
    Resolved breakpoint 1 to registerModule() at ModuleManager.as:23
    (fdb) continue + <enter>
    Breakpoint 1, registerModule() at ModuleManager.as:23   (yeahaa!)
    23             public function registerModule(modRegName:String,instance:IModule):void {
    now by command p we want to know what the variable  'instance' holds
    ( note (!) if you end the variable name with  a dot (.) you get more info) !:
    (fdb) p instance.

    outputs:
    $7 = instance = [Object 758409729, class='nl.greenberry.gogeo.app::App']
    _appController = [Object 757300145, class='nl.greenberry.gogeo.app::AppController']
    _appDisplayModel = null
    _appEventModel = null
    _appModuleManager = null
    _appSoundModel = null
    _eventModel = [Object 758625729, class='nl.greenberry.gogeo.app::EventModel']
    _modelLocator = [Object 758703937, class='nl.greenberry.gogeo.app::ModelLocator']
    _moduleManager = [Object 760443361, class='nl.greenberry.gogeo.app::ModuleManager']
    _moduleName = null
    _stage = [Object 756722513, class='flash.display::Stage']
    displayModel = [Object 757301009, class='nl.greenberry.gogeo.app::DisplayModel']
    eventModel = [Object 758625729, class='nl.greenberry.gogeo.app::EventModel']
    moduleManager = [Object 760443361, class='nl.greenberry.gogeo.app::ModuleManager']
    moduleName = null
    NAME = "Go-Geo"
    soundModel = [Object 758409793, class='nl.greenberry.gogeo.app::SoundModel']
    stage = [Object 756722513, class='flash.display::Stage']
    VERSION = "0.0.1"

    and the rest you will find out !

    by the way you can alter variables realtime, and it displays your traces too:
    [trace] sayHello

    cheers !
    Flashdevelop now complete for me :)

    flex sdk compile time variables, switches and resources Hacks

    December 9, 2008 – 2:51 am

    Super nice article on how to create a compiletime conditional switch for for ex. calling an alternate version of the same function or adding compiletime var-values at  with the flex sdk command line
    http://code.awenmedia.com/node/34

    Code examples from his site:

    ADDING COMPILETIME VARS:
    
    
    mxmlc MyConfigClass.as -define+=CONFIG::someSetting,true
    or
    ...-define+=CONFIG::myString,"'Hello!'" -define+=CONFIG::myNumber,"7"

    for someSetting the AS3 class would be:

    package {
    public class MyConfigClass
    {
       public static const SOME_SETTING:Boolean=CONFIG::someSetting;  // Actual AS3 this time
    
       public function doSomething():void
       {
          if (SOME_SETTING)
          {
              // Do it!
          }
       }
    }
    }
    
    
    CONDITIONAL FUNCTION SWITCH:
    
    mxmlc MyClass.as -define+=CONFIG::isDebug,true  -define+=CONFIG::isRelease,false
    
    //AS3
    package
    {
    public class MyClass
    {
        CONFIG::isDebug
        public function doSomething():void
        {
            trace("This is a debug build!");
        }
    
        CONFIG::isRelease
        public function doSomething():void
        {
            trace("This is a release build!");
        }
    }
    }
    
    
    
    

    Another from usefull tip-set from awen on adding resources and css files at compiletime by abusing some flex buildin hacks:

    http://code.awenmedia.com/node/33

    
    

    AS3 textfield blinking caret after textfield focus / tabbing ? Solved!

    July 19, 2008 – 2:21 am

    2011 note: This is only tested and works with normal textfields and not with the new extended TLF textfield.

    To obtain focus on a textfield with a custom textformat on it can give you headaches:
    From wrong caret color to disapaering textcontent when you use tab button to unselectable text content.
    You just keep fumbling around with _Textfield.stage.focus = _Textfield without joy.
    I lost several hours to get the caret blinking where I wanted it.

    It is so simple if you just had known that you NEED TO SET THE
    Textfield.defaultTextFormat = myFormat wright before you had the line textfield.setTextformat(myFormat).

    It seems that focussing or unfocussing or tabbbing resets your textformat with the default textformat,
    and since that didn't exist... flash defaults to a STATIC textfield. YipiYoYO....
    Figure that, especially after the tab first killed your textcontent and then makes your field unselectable.

    But hey when you apply the defaulTextformat wright before you start playing,
    suddenly the focussing and caret'ing works like a charm.
    Hope you are happy to find this post ! I would have been ;)
    Here a little helper boyie class :

    use it like this after import CaretFocus;
    CaretFocus.atBegin(TField)
    CaretFocus.atEnd(TField)
    CaretFocus.atIndex(TField,5)
    CaretFocus.unfocus(TField)
    CaretFocus.focus(TField)