Welcome to TiddlyWiki created by Jeremy Ruston; Copyright © 2004-2007 Jeremy Ruston, Copyright © 2007-2011 UnaMesa Association
<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}
h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}
.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}
.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}
.tabSelected{color:[[ColorPalette::PrimaryDark]];
background:[[ColorPalette::TertiaryPale]];
border-left:1px solid [[ColorPalette::TertiaryLight]];
border-top:1px solid [[ColorPalette::TertiaryLight]];
border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}
#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}
.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}
.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}
#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}
.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}
.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}
.tiddler .defaultCommand {font-weight:bold;}
.shadow .title {color:[[ColorPalette::TertiaryDark]];}
.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}
.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}
.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}
.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}
.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}
.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}
.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}
.imageLink, #displayArea .imageLink {background:transparent;}
.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}
.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}
.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}
.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}
.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}
.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}
.readOnly {background:[[ColorPalette::TertiaryPale]];}
#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity=60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}
body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}
h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}
hr {height:1px;}
a {text-decoration:none;}
dt {font-weight:bold;}
ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}
.txtOptionInput {width:11em;}
#contentWrapper .chkOptionInput {border:0;}
.externalLink {text-decoration:underline;}
.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}
.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}
/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}
#mainMenu .tiddlyLinkExisting,
#mainMenu .tiddlyLinkNonExisting,
#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}
.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0px; top:0px;}
.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}
#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}
#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}
.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}
#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}
.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}
.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}
.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}
#contentWrapper {display:block;}
#splashScreen {display:none;}
#displayArea {margin:1em 17em 0 14em;}
.toolbar {text-align:right; font-size:.9em;}
.tiddler {padding:1em 1em 0;}
.missing .viewer,.missing .title {font-style:italic;}
.title {font-size:1.6em; font-weight:bold;}
.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}
.tiddler .button {padding:0.2em 0.4em;}
.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}
.footer {font-size:.9em;}
.footer li {display:inline;}
.annotation {padding:0.5em; margin:0.5em;}
* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}
.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}
.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}
.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}
.fieldsetFix {border:0; padding:0; margin:1px 0px;}
.sparkline {line-height:1em;}
.sparktick {outline:0;}
.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}
* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}
.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<!--}}}-->
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser
Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])
<<option txtUserName>>
<<option chkSaveBackups>> [[SaveBackups]]
<<option chkAutoSave>> [[AutoSave]]
<<option chkRegExpSearch>> [[RegExpSearch]]
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
<<option chkAnimate>> [[EnableAnimations]]
----
Also see [[AdvancedOptions]]
!chkimg = check the read-only portions of the binary (image) in memory vs. the binary on disk, and report differences
-d = print differences as they are found
-nospec = do not exclude "special" changes which it knows nt and hal will make to themselves
hal = image to check
!dh = display file headers
-f = do not display section information
hal = module to display headers for
This report shows that //something// is hooking the SSDT, but GMER wasn't able to identify the memory which is being pointed at as belonging to any specific kernel module.
[img[images/GMER_Symantec_SSDT_Hooks.png]]
The following shows GMER when ShadowWalker is hiding the FUTo driver, and FUTo is hiding itself and ShadowWalker. Gmer is saying it can't find the module which is being pointed to by Interrupt 0xE. If FUTo wasn't hiding ShadowWalker (mm.sys) we wouldn't see the address range of mm.sys, and therefore the target of INT 0xE would still be ambiguous.
[img[images/GMER_SW_FUTo.png]]
~He4Hook hooking the IRP dispatch tables in a variety of drivers
[img[images/GMER_he4hook_IRPhooks.png]]
These are the standard steps that we went through in Intermediate x86:
You will already need [[windbg installed | http://www.microsoft.com/whdc/devtools/debugging/default.mspx]].
[[Virtualized System, Kernel Debugging]]
However, for production systems, I recommend installing ~WinDbg and then [[LiveKD | http://technet.microsoft.com/en-us/sysinternals/bb897415]], which will enable some measure of debugging the system (but you will not be able to change memory for instance.) Behind the scenes LiveKD actually just takes a memory dump, and debugs that.
[[Userspace Debugging]]
In some cases the best option may be to perform offline analysis of the system memory on a separate system (e.g. when one is concerned about forensic impact to the system). In that case, one should perform a memory dump of the system, and then attach to the crash dump with WinDbg as described below.
[[Offline Analysis]]
Go into Control Panels ->Administrative Tools -> Event Viewer, and for each log, right click and select "Clear all events" and say "no" for whether you want to save it before clearing.
Install [[MRUBlaster | http://www.javacoolsoftware.com/mrublaster.html]] and delete all the most recently used items.
This should also clean up file modified times so that people can't just see what was installed based on it being newer than other things. I used http://www.attributemagic.com/attributemagic-free.html which is included as am_free.zip. I then set the created and modified timestamps of C:\WINDOWS\system32\drivers\{ndishlp.sys, hidusbd.sys} to match my ndis.sys (which was April 14 2008, 7:00:am).
Double click the "keysetup.exe" or equivalent file.
Click Next
Click "I accept the agreement" and Next
Click Next (to accept default location)
Click Next
Click Install
Click Finish
When prompted for a password enter "foobarbarism" twice without the quotes and then click Save
Click Understood
Right click on the white-on-light blue K icon which appears in the system tray. Select Settings (the only option)
Enter the password "foobarbarism" (no quotes) and hit OK
Check the box next to "Hide program tray icon"
Check the box next to "Delete help..." and "Remove icons..." (close the prompt which appears after the latter)
On the left side bar, select Passwords
Check the box next to "Allow calling Log Viewer...", which enables the ctrl-shift-alt-V option
Now confirm it works
Open Notepad
enter "This is for AIOK"
Switch back to the AIOK interface and select "Open Log Viewer" from the left side bar.
Click "Do not show this message again" and then close the prompt.
On the left sidebar under "View Entire Log", select "View Textual Log"
Once selected, click the "Filter empty rows" option which becomes available higher up in the left sidebar"
Click on the entry "Untitled - Notepad"
You should see the text "This is for AIOK" in the bottom middle. If you don't, revert VM and try install again.
Close the log viewer
From the left sidebar of AIOK, select "Hide (Esc)"
Double click on "i_bpk_trial.exe" or the equivalent file.
Type "open" and press OK when prompted.
Click Next
Click Yes and Next
For Keyword, change it from bpk to msd and click Next
Change C:\Program Files\BPK to C:\Program Files\MSD.
Click "Stealth installation..."
Click Next
Click Finish
Click Continue evaluation
Right click on the (double i?) icon which appears in the system tray and select Options.
Check the box next to "Don't show program icon at startup"
Click into the box which says "Ctrl + Alt + L" and while clicked into the box type shift-ctrl-alt-L
Click the box next to "Make the program invisible in the Windows startup list". Then click "OK" when prompted.
Click the box next to "Remove the program from Start Menu and uninstall list"
On the left sidebar, select Screenshots.
Click the box next to "Capture screen on mouse click"
Now we will confirm that it is working:
Open notepad and enter "This is for BPK"
Switch back to BPK's interface
On the left sidebar select Logging, and then click View Log
Confirm that you see "This is for BPK" in the log viewer. If you don't, revert the VM and reinstall again.
If so, you can close the log viewer, and close BPK's UI.
It may say "Unable to remove the program from the uninstall list", and that is fine.
When prompted about the "Run on Windows Startup" option, select Close.
Hit shift-ctrl-alt-L to hide the system tray icon.
Delete the "i_bpk_trial.exe" or the equivalent file.
Double click the "refog_setup_kl_702_.exe" or equivalent setup file.
Click OK (for the language of english)
Click Next
Click "I agree"
Click Next
Click Next (to accept the default install location)
UNCHECK the "Create a desktop icon" box and click Next
Click Install
Click Finish (at least on my system it took a while for it to invoke the application)
Now you will be presented with the logo. Select OK
Click Next (accepting monitoring all users)
Click Next (accepting monitoring all types of records)
Click Next (to accept not sending the logs via email)
Click Next (to accept hiding everywhere)
Click Next (to accept the hot keys)
UNCHECK "Check updates automatically" and click Next.
Click Finish
Now let's confirm it's working
Open Notepad
type in "This is for REFOG"
Switch back to the REFOG UI
Expand the "Student" account
Click on "Keystrokes typed"
Click on Notepad in the middle/right large window, and confirm the middle bottom window has "This is for REFOG" displayed in it. If it doesn't revert the VM and try installing again.
You can now close REFOG (and hit OK to its prompt about closing)
Delete the "refog_setup_kl_702_.exe" or equivalent setup file.
This is a much harder problem than simply detecting and thinking you understand the change. However it is not necessarily related to static analysis, which is why this section is optional.
[[Using hardware breakpoints to detect break-on-write]]
[[Using stepping when breakpoints don't work]]
[[Backtracking to the loading of the module]]
[[Determining where dynamically allocated memory was allocated from]]
TODO:
At least for kernel memory it may be possible to track it by using poolmon (but I need to find an example to use to try this first)
http://support.microsoft.com/kb/177415
http://blogs.technet.com/b/markrussinovich/archive/2009/03/26/3211216.aspx
Answer:
In a //fault// (simpsons picture of hilter pointing a bobo, Mr. Burns' teddy bear), EIP points *at* the instruction which caused the fault.
In a //trap// (standard meme picture of Admiral Ackbar "It's a trap!"), EIP points *after* the instruction which caused the trap. I.e. EIP points to next instruction.
In an //abort// (picture of giant spider attacking space shuttle), it is probably unrecoverable, and EIP is usually meaningless.
For a //fault// (picture from Simpsons of hitler pointing at bobo the teddybear), ''EIP points *at* the faulting instruction'' when the interrupt occurs.
For a //trap// (standard Admiral Ackbar "It's A Trap!" meme picture), ''EIP points *after* the trapping instruction'' when the interrupt occurs.
For an //abort// (picture of giant spider attacking space shuttle), ''EIP is unreliable'' and the interrupt is non-recoverable.
= Intall ~FUTo =
Obtain file {{{RootkitsClass/PoC_Rootkits_And_Detectors/FUTo_page_aligned.zip}}}
This is just the ~FUTo from here: , but is has specifically been compiled to ensure that the sections are on 4KB page-aligned (multiples of 0x1000) boundaries. This is because ~ShadowWalker wants things to be page-aligned.
Extract to C:\~FUTo_page_aligned
From C:\~FUTo_page_aligned\~FUTo\EXE copy fu.exe and msdirectx.sys to C:\WINDOWS\System32\drivers.
Open taskmgr.exe and find the Process ID (PID) of System (you will probably need to go to View->Select Columns and add it). In my case it was 4.
From C:\WINDOWS\System32\drivers do {{{fu.exe -ph 4}}}. This will hide the SYSTEM process, making it so that, for instance, Process Explorer cannot view the SYSTEM process and show the loaded modules (if they happened to know that that was possible from within Process Explorer.)
Then do {{{fu.exe -phd msdirectx.sys}}}. This is a DKOM attack that will unlink the fu module (msdirectx.sys) from the loaded kernel modules lists.
TODO: I should probably modify futo to expect its driver in C:\WINDOWS\system32\drivers instead of local dir.
TODO: I should modify futo to mark the service as a boot-service, so that shadowwalker can always hide it.
= Install ~ShadowWalker =
Obtain file {{{RootkitsClass/PoC_Rootkits_And_Detectors/shadowwalker_corey.zip}}}
(modification of shadowwalker (originally from http://www.rootkit.com/vault/hoglund/Shadow_Walker_1.0.rar) by Corey Kallenberg to allow it to hide multiple pages of memory)
Extract to C:\shadowwalker_corey
From C:\shadowwalker_corey execute {{{InstDriver.exe -install mmpc bin\i386\mmpc.sys}}} and {{{InstDriver.exe -start mmpc}}} The projec
This version of ~ShadowWalker (like the unmodified one) is hardcoded to hide ~FUTo's msdirectx.sys.
----
Xeno's bat file
{{{
cd C:\
xcopy /S /E /I Z:\binaryTransfer\rootkits\___installed\shadowwalker_corey shadowwalker_corey
xcopy /S /E /I Z:\binaryTransfer\rootkits\___installed\FUTo_page_aligned FUTo_page_aligned
copy FUTo_page_aligned\FUTo\EXE\fu.exe C:\WINDOWS\system32\drivers
copy FUTo_page_aligned\FUTo\EXE\msdirectx.sys C:\WINDOWS\system32\drivers
copy shadowwalker_corey\InstDriver.exe C:\WINDOWS\system32\
copy shadowwalker_corey\bin\i386\mmpc.sys C:\WINDOWS\system32\drivers
echo "starting install"
chdir C:\WINDOWS\system32\drivers
fu.exe -ph 4
C:\WINDOWS\system32\InstDriver.exe -install mmpc mmpc.sys
C:\WINDOWS\system32\InstDriver.exe -start mmpc
fu.exe -phd msdirectx.sys
rmdir /s /q C:\shadowwalker_corey
rmdir /s /q C:\FUTo_page_aligned
}}}
Install He4Hook
run "He4HookControl.exe -i:1" to install
run "He4HookControl.exe -hk:1" to hook file system
run "He4HookControl.exe -a:C:\WINDOWS\system32\drivers\fu.exe" to hide FUTo file
{{{
cd C:\
xcopy /S /E /I Z:\binaryTransfer\rootkits\___installed\__he4hook_v21a_20021110 he4
copy C:\he4\usermode\build\He4HookInv\He4HookControl\win32\release\He4HookControl.exe C:\WINDOWS\system32\ctl.exe
copy C:\he4\kernelmode\build\he4hookinv\winxp\release\He4HookInv.sys C:\WINDOWS\system32
cd C:\WINDOWS\system32
ctl.exe -i:1
ctl.exe -hk:1
ctl.exe -a:C:\WINDOWS\system32\drivers\fu.exe
}}}
Install SysEnterHook
From C:\SysEnterHook run "copy objchk_wxp_x86\i386\sysenter.sys C:\WINDOWS\system32\drivers"
Install Basic Callgate
From C:\basic_callgate\callgate_driver run "copy objchk_wxp_x86\i386\BASIC.sys C:\WINDOWS\system32\drivers"
From C:\WINDOWS\system32\drivers
InstDriver.exe -install syse sysenter.sys
InstDriver.exe -start syse
InstDriver.exe -install basic BASIC.sys
InstDriver.exe -start basic
rmdir /S C:\SysEnterHook
rmdir /S C:\basic_callgate
{{{
rmdir /S /Q C:\basic_callgate
cd C:\
xcopy /s /e /i Z:\binaryTransfer\rootkits\___installed\basic_callgate bc
xcopy /s /e /i Z:\binaryTransfer\rootkits\___installed\SysEnterHook sysent
copy sysent\objchk_wxp_x86\i386\syse.sys C:\WINDOWS\system32\drivers
copy bc\callgate_driver\objfre_wxp_x86\i386\BASIC.sys C:\WINDOWS\system32\drivers
cd C:\WINDOWS\system32\drivers
..\InstDriver.exe -install basic BASIC.sys
..\InstDriver.exe -start basic
..\InstDriver.exe -install syse syse.sys
..\InstDriver.exe -start syse
rmdir /S /Q C:\sysent
rmdir /S /Q C:\bc
echo "done"
}}}
Vanquish doesn't play nice with Hacker Defender (~HxDef), but if you install Vanquish first and then ~HxDef, it will work, but not persist across reboots. This is actually desirable. It means if the student reboots the system before they even try analyzing it, they will lose easy detectability of this rootkit.
== Install Vanquish ==
Start with the file from {{{RootkitsClass/PoC_Rootkits_And_Detectors/_rootkit.com_user_vaults/xshadow/vanquish-0.2.1.zip}}}
(which was originally from https://www.rootkit.com/vault/xshadow/vanquish-0.2.1.zip)
Extract folder to C:\vanquish-0.2.1
From C:\vanquish-0.2.1 run "setup.cmd do install"
(installer.cmd was modified to remove some "PAUSE>NUL" statements to make it not wait for user input on install)
The rootkit is now installed
= Install ~HxDef =
Obtain file {{{RootkitsClass/PoC_Rootkits_And_Detectors/_rootkit.com_user_vaults/hf/hxdef100r.zip}}}
(which was originally from https://www.rootkit.com/vault/hf/hxdef100r.zip)
Extract folder to C:\hxdef100r
From C:\hxdef100r run "hxdef100.exe"
The rootkit is now installed
----
Xeno's personal bat file, modify to taste
{{{
cd C:\
xcopy /s /e /i Z:\binaryTransfer\rootkits\___installed\hxdef100r hxdef100r
xcopy /s /e /i Z:\binaryTransfer\rootkits\___installed\vanquish-0.2.1 vanquish-0.2.1
vanquish-0.2.1\setup.cmd do install
cd C:\
hxdef100r\hxdef100.exe
}}}
This version hides files/folders starting with _cool_
{{{
echo "basic_hook_hide_file install"
cd C:\
xcopy /s /e /i Z:\binaryTransfer\rootkits\___installed\basic_hook_hide_file bhhf
copy bhhf\objfre_wxp_x86\i386\Ctr12Cap.sys C:\WINDOWS\system32\drivers
cd C:\WINDOWS\system32\drivers
mkdir _cool_beans
..\InstDriver.exe -install Ctr12Cap Ctr12Cap.sys
..\InstDriver.exe -start Ctr12Cap
rmdir /S /Q C:\bhhf
}}}
Install [[Ctrl2cap | http://technet.microsoft.com/en-us/sysinternals/bb897578]] (for IRP attachment)
{{{
C:\Documents and Settings\user>cd /D Z:\binaryTransfer\rootkits\chaff\Ctrl2Cap\
Z:\binaryTransfer\rootkits\chaff\Ctrl2Cap>ctrl2cap.exe /install
}}}
Install [[DaemonTools Lite w/ SPTD | http://www.daemon-tools.cc/eng/downloads/dtLite]] (SPTD will only be active if a debugger is not attached to the system, SPTD does a lot of changes)
Install Trusteer Rapport - http://www.trusteer.com/node/549 - which will do some ssdt hooking. Make sure you don't let it send events to banks, by unchecking the box, and then hitting cancel (NOT ok) when prompted.
Install ~ZoneAlarm Free - http://www.zonealarm.com/security/en-us/zonealarm-pc-security-free-firewall.htm - attaches to devices and hooks SSDT and does some userspace inline hooking
Set [[DebugView | http://technet.microsoft.com/en-us/sysinternals/bb896647]] to auto-run at startup which will cause an inline hook in the kernel at ~DbgPrint().
You need to go to the location where the changes are reported, and begin analyzing the code there.
You always want to keep your eye on the notion of "Am I in the address space of a module yet?"
Generally speaking, 3rd party security software may make use of dynamically allocated memory for hooks which bridge to eventually landing in their normal kernel module.
Rootkit code on the other hand may eventually end up in an identifiable module address space, or it may not. You may not be able to determine that it's in a module address space due to it hiding it's module information with DKOM, or it may have copied all of its code to dynamically allocated address space and then unloaded its normal module.
[[Investigating ambiguous GMER report 1]]
[[Investigating ambiguous GMER report 2]]
[[Investigating ambiguous GMER report 3]]
The following is memory at the 1st hook listed by GMER, for ~ZwAlertResumeThread
Remember: A Zw* function is the kernel-internal name for a Nt* function. Both have the same definition for inputs/outputs. Some (such as this) are still considered undocumented.
The definition of this function is found [[here | http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Thread/NtAlertResumeThread.html]]
{{{
NtAlertResumeThread(
IN HANDLE ThreadHandle,
OUT PULONG SuspendCount
);
}}}
[img[images/windbg_symantec_hook1.png]]
Pay close attention to the following sequence:
{{{
81eb36ac b82810a4e3 mov eax,0E3A41028h ; Move the immediate for (presumably the address of some data structure) into eax
81eb36b1 8b00 mov eax,dword ptr [eax] ; Dereference the address to get the value stored in the first DWORD
81eb36b3 8b4004 mov eax,dword ptr [eax+4] ; Add 4 to the new value and then get the data stored at that address
...
81eb36bc ffd0 call eax ; Ultimately use the value which was extracted from memory as a function pointer, and call to that address
}}}
The following is memory at the 3rd hook listed by GMER, for ~ZwAllocateVirtualMemory
[img[images/windbg_symantec_hook2.png]]
The definition of this function is found [[here | http://msdn.microsoft.com/en-us/library/ff566416(v=vs.85).aspx]]
{{{
NTSTATUS ZwAllocateVirtualMemory(
in HANDLE ProcessHandle,
inout PVOID *BaseAddress,
in ULONG_PTR ZeroBits,
inout PSIZE_T RegionSize,
in ULONG AllocationType,
in ULONG Protect
);
}}}
We have a more complicated initial sequence, but that's just because of more complicated input parameters. We have a similar sequence as the last hook at the end:
{{{
82327fdc b8480473e2 mov eax,0E2730448h ; Move the immediate for (presumably the address of some data structure) into eax
82327fe1 8b00 mov eax,dword ptr [eax] ; Dereference the address to get the value stored in the first DWORD
82327fe3 8b4004 mov eax,dword ptr [eax+4] ; Add 4 to the new value and then get the data stored at that address
...
82327fec ffd0 call eax ; Ultimately use the value which was extracted from memory as a function pointer, and call to that address
}}}
So, the question is, //where// is this code actually calling to?
In order to find that out, we can simply start at one of these hardcoded addresses and double dereference the same way the above snippet of code does.
{{{
kd> dd 0x0E3A41028 (from "mov eax,0E3A41028h")
e3a41028 *f4ba9fd8* 00000001 00000000 00000002 (from "mov eax,dword ptr [eax]")
e3a41038 e1ab93c0 f4baa058 0000000c 805d4b1e
e3a41048 81eb36a0 e3a41028 805d4b1e 00330043
e3a41058 0002080b 00450038 e1abb438 e1ad8268
e3a41068 0c0b0802 49766553 f4ba9fe0 e18a79c8
e3a41078 f4ba9f7c e1aa43a0 00000001 821c57c8
e3a41088 00000000 00000f81 f4ba9fd8 00000001
e3a41098 00000000 00000001 e1ab93a0 f4baa058
kd> dd f4ba9fd8
f4ba9fd8 f4ba3ff0 *f4ba4370* f4ba4e80 f4ba4010 (from "mov eax,dword ptr [eax+4]")
f4ba9fe8 f4ba4150 f4b95710 f4b95f40 f4ba4180
f4ba9ff8 f4b91b40 f4b91b60 f4b95710 f4b95710
f4baa008 f4b95710 f4b95710 f4b95710 f4b95710
f4baa018 f4b9acc0 f4ba4e00 f4b91b60 f4b95710
f4baa028 f4b95f40 f4b91af0 f4b91b40 f4b91b60
f4baa038 f4b95710 f4b95710 f4b95710 f4b95710
f4baa048 f4b95710 f4b95710 00000080 00000013
kd> u f4ba4370 L10 (from "call eax")
f4ba4370 8bff mov edi,edi
f4ba4372 55 push ebp
f4ba4373 8bec mov ebp,esp
f4ba4375 83ec54 sub esp,54h
f4ba4378 56 push esi
f4ba4379 57 push edi
f4ba437a bf010000c0 mov edi,0C0000001h
f4ba437f ff150480baf4 call dword ptr ds:[0F4BA8004h]
f4ba4385 3c01 cmp al,1
}}}
OK, but now the question you have to ask is, "Am I anywhere I know about yet?"
In order to try and answer that question, we look at the loaded modules list and see if the address f4ba4370 is in any module's address space
{{{
kd> .reload
<snip>
kd> lm
start end module name
804d7000 806e4000 nt (pdb symbols) C:\WINDOWS\Symbols\ntkrpamp.pdb\140D20ABBC1B433EA7BF82B979B6BF9D1\ntkrpamp.pdb
806e4000 80704d00 hal (deferred)
<snip>
f4b7c000 f4b8f380 NAVENG (deferred)
f4b90000 f4bb5000 SYMEVENT (deferred) BINGO!
...
}}}
f4b90000 < f4ba4370 < f4bb5000, so the code at f4ba4370 is in SYMEVENT.SYS's module space, therefore we could conclude that the hook is installed by Symantec.
----
Aside
But then there are other questions you could ask if you were highly suspicious:
* "How do you ''REALLY'' know that's Symantec, and not something impersonating it?"
** You could have to have some collection of "known good" versions of Symantec, and then you would have to check if the code on disk at that location matches the code in memory.
* A related question is: How do you know the code which was called to at f4ba4370 isn't just a big blob of attacker code that overwrote code in the legit SYMEVENT.SYS?
** Again, one technique you could use is to throw a presumed-clean copy of SYMEVENT.SYS into IDA and check if the code at the RVA which corresponds to f4ba4370 is the same code as that found at the same RVA in IDA.
** If for instance you don't have a clean copy of the module in question, you could use System Virginity Verifier or the ~WindDbg !chkimg command as was talked about in the rootkits class. However, remember that they just compare what's in memory to what's on disk. If what's on disk is trojaned on disk, then they won't detect any differences.
* How do you know the function pointer that was extracted from *((*0x0E3A41028)+4) wasn't overwritten by an attacker?
** If this was the first time investigating the hook, on a suspected-compromised system, you really wouldn't have any way of knowing! If it jumped to some new dynamically allocated code before jumping to SYMEVENT.SYS, you would have no way of knowing whether that was or wasn't the expected behavior. Such is the quandary introduced by security products using attacker techniques. Your only recourse in this instance would be to get a presumed-clean system and see if it exhibited the same characteristics.
If you recall from Intermediate x86, interrupts below 0x20 are assigned by Intel, and the others are ~OS-configurable. So you could look up in the manual and find that INT 0xE is the page fault interrupt handler.
[img[images/IntelManualPageFault.png]]
With that context in mind, the code begins as follows:
{{{
f9f55a40 8bff mov edi,edi
f9f55a42 60 pushad
f9f55a43 8b542420 mov edx,dword ptr [esp+20h]
f9f55a47 f7c204000000 test edx,4
f9f55a4d 0f8597000000 jne f9f55aea
f9f55a53 0f20d0 mov eax,cr2
f9f55a56 3d0000ff7f cmp eax,7FFF0000h
f9f55a5b 0f8689000000 jbe f9f55aea
f9f55a61 50 push eax
f9f55a62 e829fdffff call f9f55790
f9f55a67 8be8 mov ebp,eax
f9f55a69 83fdfb cmp ebp,0FFFFFFFBh
f9f55a6c 747c je f9f55aea
}}}
The first thing the code does is save all of the registers onto the stack with a pushad. It then moves [esp+0x20] to edx and does test edx, 4. The format of the pushad instruction is such that it does push eax, ecx, edx, ebx, esp before the pushad was executed, ebp, esi, edi. So, esp+4 = the saved esi, ebx + 0x10 = esp, and esp+0x1c = the saved eax. Therefore it is accessing the thing at the top of the stack at the time of the page fault. So we need to recall this picture from Intermediate x86/Intel Manual:
[img[images/IntelManualInterruptFrame.png]]
And now we know that because the first picture specified that the page fault handler always pushes an error code, therefore the thing being moved to edx is the error code. At this point you would need to go look up the error code format, so you could understand what the error code is saying, and what the assembly is checking. I got the following picture from the Nov 2008 manuals distributed with the x86 classes, in section 5.15 Interrupt 14:
[img[images/IntelManualPageFaultErrorCode.png]]
If you also remember from intro x86, the test instruction is like an AND instruction which sets flags but doesn't store the result. So it is doing ErrorCode AND 4. We can see from the error code definition that a 1 in the 4's bit indicates that the page fault occurred in in userspace. And then the jne is saying "jump if the result of this AND is not equal (not zero flag set)". So if the eax at the time of the pushad had a 1 in its 4's bit, then the code jumps to f9f55aea. And we might speculate that f9f55aea is code for exiting on error, because we see it being used multiple times in conditional jumps. We should take a look to try and confirm that notion:
{{{
f9f55aea 61 popad
f9f55aeb ff25106af5f9 jmp dword ptr ds:[0F9F56A10h]
}}}
The jmp is an indirect jump, saying "take the value in memory at 0F9F56A10h, and treat it like an address, and then jump there". By then looking at the data stored at 0F9F56A10h with the [[dps]] command, we can see it is code within the nt kernel, and therefore probably the original entry which should have been at IDT index 0xE.
{{{
lkd> dps 0F9F56A10h L1
f9f56a10 804e1662 nt!Kei386EoiHelper+0x2606
}}}
So indeed it looks like the code at 0F9F56A10h is exit code, because it does a popad to remove the data added to the stack by the pushad earlier, and then jumps to the original handler.
Returning to the original control flow, we can see that the code is accessing the ~CR2 register.
{{{
f9f55a53 0f20d0 mov eax,cr2
f9f55a56 3d0000ff7f cmp eax,7FFF0000h
f9f55a5b 0f8689000000 jbe f9f55aea
}}}
From Intermediate x86 we know that the ~CR2 register is where the hardware automatically stores the address which it was trying to translate when the page fault occurred. Subsequently, it is doing a cmp (which we remember from Intro x86 is like a SUB which sets bits and throws away the results). The code therefore does (eip of code where fault occurred) - 0x7fff0000. And if the flags are such that the eip of the code running at the time of the fault is below or equal to 0x7fff0000, then it jumps to the early exit code. This 0x7fff0000 looks suspiciously close to 0x80000000 where we know that kernel memory starts by convention, so it looks like it is trying to exit early if the fault occurred from userspace. But of course 0x7fff0000 doesn't quite bump up against the 0x80000000 address range (there's a 0x10000 difference). So we need to investigate where userspace really stops and where kernel begins. [[This page | http://msdn.microsoft.com/en-us/library/ff560042(v=vs.85).aspx]] clarifies that indeed the highest memory address for userspace is 0x7ffeffff. Therefore, once again, this handler seems to be checking for if the page fault came from userspace, it doesn't need to do anything, and it just lets the original handler regain control.
{{{
f9f55a61 50 push eax
f9f55a62 e829fdffff call f9f55790
}}}
Finally, if the handler is satisfied that the fault didn't occur in userspace, it pushes the address to one of its subroutines. For now, since we can see that the end of this code, f9f55aea, is relatively close to the beginning, we're just going to survey what all is taking place in the main execution path, before looking at subroutines if necessary. ''This again is one of the principals of RE outlined in the class of surveying code and finding interesting bits before digging deeper.''
{{{
f9f55a67 8be8 mov ebp,eax
f9f55a69 83fdfb cmp ebp,0FFFFFFFBh
f9f55a6c 747c je f9f55aea
}}}
After the function returns, it moves the return value into ebp, checks it, and if it is equal to 0xFFFFFFFB, it jumps to the early exit. If not, it begins a new chunk of code which has some immediates in it (0xC0300000, and 0xC0000000) which should look familiar to people who look Intermediate x86.
{{{
f9f55a6e 0f20d0 mov eax,cr2
f9f55a71 be000030c0 mov esi,0C0300000h
f9f55a76 8bd8 mov ebx,eax
f9f55a78 c1eb16 shr ebx,16h
f9f55a7b 8d1c9e lea ebx,[esi+ebx*4]
f9f55a7e f60380 test byte ptr [ebx],80h
f9f55a81 750d jne f9f55a90
f9f55a83 be000000c0 mov esi,0C0000000h
f9f55a88 8bd8 mov ebx,eax
f9f55a8a c1eb0c shr ebx,0Ch
f9f55a8d 8d1c9e lea ebx,[esi+ebx*4]
f9f55a90 39442424 cmp dword ptr [esp+24h],eax
f9f55a94 750d jne f9f55aa3
}}}
The code starts by moving ~CR2, the address which was trying to be translated at the time of page fault, into eax, and the constant 0xC0300000 into esi. Recall from Intermediate x86 that the Windows kernel always enforces a convention whereby the base of the page directory, the first stop in translating virtual to physical addresses, is always mapped into every virtual memory space at 0xC0300000. This also lets us know that this code is specific to non-PAE mode, because in PAE, the convention states that the base is stored at 0xC060000 instead. That way, the OS always knows where to look to find Page Directory Entries (~PDEs). The code then copies eax to ebx, and performs a logical right shift by 0x16 (decimal 22) bits. This leaves the top 10 bits of the faulting address in ebx, and we learned that when in non-PAE mode, the hardware uses the top ten bits as an index to find the PDE. This is what the lea instruction is doing. It is taking the top 10 bits in ebx as an index, multiplying by the size of the entries (4 bytes), and then adding to the page directory base in esi, in order to get the address of the PDE specified by the index, and store it into ebx. Finally it does a test of the low byte stored in the PDE against 0x80. From Intermediate x86 we know that bit index 7 (10000000 = 0x80) is the PS or Page Size bit. This bit says whether the PDE points at a page table, or a large 4MB page. The jne specifies that if the result of ANDing the PDE value at 0x80 is not zero (meaning the bit is set in the PDE), then it should jump to f9f55a90. Thus the code at f9f55a90 should be assumed to deal with large pages, whereas the fall-through code should be assumed to be deal with translation to a page table.
{{{
f9f55a83 be000000c0 mov esi,0C0000000h
f9f55a88 8bd8 mov ebx,eax
f9f55a8a c1eb0c shr ebx,0Ch
f9f55a8d 8d1c9e lea ebx,[esi+ebx*4]
}}}
In the fall through code, we now see it using the address 0xC0000000 in esi, which we recall is the base of an array of possible page tables. In order to get the index it takes the upper 10 bits and multiplies them by 0x1000 to get the specific page table, and then uses the middle 10 bits as the index into that page table. However, we can not see that sort of operation here. Instead we see a copy of the faulting address being made, followed by a right shift of 0xC (decimal 12) bits. However, this works out because shifting the top 10 bits by only 12 is like shifting them right by 22, and then left by 10, and the left shift is equivalent to multiplying by 0x200, and as we see in the next instruction, they will also be multiplied by 4, thus being equivalent to being multiplied by a total ox 0x1000. This multiplication by 4 happens at the same time as the index is being multiplied by 4, thus yielding the correct base page table + index into the table, when added to the base of 0xC0000000.
{{{
f9f55a90 39442424 cmp dword ptr [esp+24h],eax
f9f55a94 750d jne f9f55aa3
}}}
At the time the above code is executed, ebx therefore either has the address of a PDE which points at a large 4MB page, or the address of a PTE which points at a small 4KB page. Eax still contains the faulting address, and now we see it being compared against the esp+0x24. Since the stack has not changed from before, esp+0x24 is the address of eip at the time the fault occurred. Therefore this is performing ((eip at time of fault) - (faulting address)), and if the result is not equal/zero (meaning the if((eip at time of fault) != (faulting address))) then the code jumps somewhere else. But therefore if the two addresses are the same, it falls through, and we want to see what that code looks like.
{{{
f9f55a96 fa cli
f9f55a97 830b01 or dword ptr [ebx],1
f9f55a9a ff5514 call dword ptr [ebp+14h]
f9f55a9d 8323fe and dword ptr [ebx],0FFFFFFFEh
f9f55aa0 fb sti
f9f55aa1 eb42 jmp f9f55ae5
}}}
Again, we learned in Intermediate x86 that the cli instruction clears the interrupt flag (IF) in the eflags register, preventing further interrupts from happening. If we inspected the IDT entry for index 0xE we would see that it is an interrupt gate, which always clears IF when it is used, thus making this redundant, but the code is probably just written to be cautious. Next we see the code ~ORing the PDE or PTE entry in ebx with 1. This sets the present flag to 1, so that no page fault should occur on access to this address if code attempts to access it (//assuming// that it was a non-present bit which was the cause of the fault.) The code then calls at function at ebp+0x14. But we don't know what the value at ebp is, because we ignored the call at f9f55a62 before which had code immediately after it which set ebp to the returned eax. However, when the call is done executing, the code immediately uses an and instruction to mark the PDE or PTE back to non-present, and sets the IF back to 0. It then does an unconditional jump to f9f55ae5.
{{{
f9f55ae5 61 popad
f9f55ae6 83c404 add esp,4
f9f55ae9 cf iretd
f9f55aea 61 popad
f9f55aeb ff25106af5f9 jmp dword ptr ds:[0F9F56A10h]
}}}
The code at f9f55ae5 looks like the normal exit condition of the interrupt because it immediately precedes the other code which passes handling to the original interrupt handler. The code does the popad to clean up the stack from its pushad, then the add esp, 4 to remove the error code from the stack, and finally the iretd to return to the code which was running at the time that the interrupt occurred (which in this current control flow path.)
At this point if an analyst were familiar with ~ShadowWalker, he might find that this high level behavior of "if interrupting eip = address that caused fault, mark it present and execute some code" might seem familiar. We leave confirmation of this fact as a further exercise, by analyzing the rest of the control flow paths. And once you have confirmed to your satisfaction that the code is indeed doing something ~ShadowWalker-esque, then you would proceed to [[Backtracking to the loading of the module]] to try and nail down which module seemed to be behind it.
----
"For fun" now go also RE why Tuluka is hooking INT E.
Take one of the memory addresses, and type "!pool <address>
{{{
kd> !pool 0x81704bdc
Pool page 81704bdc region is Nonpaged pool
*816fc000 : large page allocation, Tag is MmCm, size is 0x11000 bytes
Pooltag MmCm : Calls made to MmAllocateContiguousMemory, Binary : nt!mm
}}}
This tells you that the code was copied into dynamically allocated non-paged memory which was allocated with ~MmAllocateContiguousMemory(). Now you can reboot the machine and break on each instance of this function, and print the stack.
----
Interestingly, even though the sxe command does not say anything for the load/unload events, ~He4HookInv.sys is still listed as an unloaded module from the [[lm]] command
{{{
kd> lm
start end module name
<snip>
Unloaded modules:
f05dc000 f05ed000 He4HookInv.sys
f9b1c000 f9b25000 vmdebug.sys
f9d3c000 f9d43000 cfsd.sys
f9b2c000 f9b37000 imapi.sys
f9cf4000 f9cf9000 Cdaudio.SYS
f967d000 f9680000 Sfloppy.SYS
}}}
----
Information about added SSDT
{{{
kd> dd nt!KeServiceDescriptorTableShadow
80552fe0 80501bbc 00000000 0000011c 80502030
80552ff0 bf99b600 00000000 0000029b bf99c310
80553000 e21dcf50 00000000 00000005 e17e1bd0
80553010 00000000 00000000 00000000 00000000
80553020 80501bbc 00000000 0000011c 80502030
80553030 00000000 00000000 00000000 00000000
80553040 e21dcf50 00000000 00000005 e17e1bd0
80553050 00000000 00000000 00000000 00000000
kd> dps e21dcf50 L4
e21dcf50 816fe620
e21dcf54 816fe65e
e21dcf58 816fec1a
e21dcf5c 816ff15a
kd> !pool 816fe620
Pool page 816fe620 region is Nonpaged pool
*816fc000 : large page allocation, Tag is MmCm, size is 0x11000 bytes
Pooltag MmCm : Calls made to MmAllocateContiguousMemory, Binary : nt!mm
}}}
[[GettingStarted]]
[[Setting up lab VM 1]]
[[Setting up "undetectable" keylogger lab]]
[[RE rootkits]]
[[Get WinDD | http://moonsols.com/wp-content/plugins/download-monitor/download.php?id=1]] from www.moonsols.com
To have minimal impact on the system, you generally want to run WinDD from an external device, and save the dump to an external device. However I did this lab on a VM, so in your environment, just replace C:\ with the driver letter of your USB device.
C:\moonsols>win32dd /d /f C:\machineName_memory.dmp
hit yes when prompted
Back at the analysis system, you can open machineName_memory.dmp from within WinDbg with File->Open Crash Dump
TODO: fill in more about volatility analysis now that I've played with malware.py
In your environment replace {{{Z:\binaryTransfer\rootkits\___installed}}} with wherever you have the necessary files saved to.
{{{
echo "FUTo/ShadowWalker installation"
cd C:\
xcopy /S /E /I Z:\binaryTransfer\rootkits\___installed\shadowwalker_corey swc
xcopy /S /E /I Z:\binaryTransfer\rootkits\___installed\FUTo_page_aligned fpa
copy fpa\FUTo\EXE\fu.exe C:\WINDOWS\system32\drivers
copy fpa\FUTo\EXE\msdirectx.sys C:\WINDOWS\system32\drivers
copy swc\InstDriver.exe C:\WINDOWS\system32\
copy swc\bin\i386\mmpc.sys C:\WINDOWS\system32\drivers
chdir C:\WINDOWS\system32\drivers
fu.exe -ph 4
C:\WINDOWS\system32\InstDriver.exe -install mmpc mmpc.sys
C:\WINDOWS\system32\InstDriver.exe -start mmpc
fu.exe -phd msdirectx.sys
rmdir /s /q C:\swc
rmdir /s /q C:\fpa
echo "Vanquish/Hacker Defender install"
cd C:\
xcopy /s /e /i Z:\binaryTransfer\rootkits\___installed\hxdef100r hxdef100r
xcopy /s /e /i Z:\binaryTransfer\rootkits\___installed\vanquish-0.2.1 vanquish-0.2.1
vanquish-0.2.1\setup.cmd do install
cd C:\
hxdef100r\hxdef100.exe
cd C:\
xcopy /S /E /I Z:\binaryTransfer\rootkits\___installed\__he4hook_v21a_20021110 he4
copy C:\he4\usermode\build\He4HookInv\He4HookControl\win32\release\He4HookControl.exe C:\WINDOWS\system32\ctl.exe
copy C:\he4\kernelmode\build\he4hookinv\winxp\release\He4HookInv.sys C:\WINDOWS\system32
cd C:\WINDOWS\system32
ctl.exe -i:1
ctl.exe -hk:1
ctl.exe -a:C:\WINDOWS\system32\drivers\fu.exe
rmdir /s /q C:\he4
echo "sysenter/basic_callgate install"
cd C:\
xcopy /s /e /i Z:\binaryTransfer\rootkits\___installed\basic_callgate bc
xcopy /s /e /i Z:\binaryTransfer\rootkits\___installed\SysEnterHook sysent
copy sysent\objchk_wxp_x86\i386\syse.sys C:\WINDOWS\system32\drivers
copy bc\callgate_driver\objfre_wxp_x86\i386\BASIC.sys C:\WINDOWS\system32\drivers
cd C:\WINDOWS\system32\drivers
..\InstDriver.exe -install basic BASIC.sys
..\InstDriver.exe -start basic
..\InstDriver.exe -install syse syse.sys
..\InstDriver.exe -start syse
rmdir /S /Q C:\sysent
rmdir /S /Q C:\bc
echo "basic_hook_hide_file install"
cd C:\
xcopy /s /e /i Z:\binaryTransfer\rootkits\___installed\basic_hook_hide_file bhhf
copy bhhf\objfre_wxp_x86\i386\Ctr12Cap.sys C:\WINDOWS\system32\drivers
cd C:\WINDOWS\system32\drivers
mkdir _cool_beans
..\InstDriver.exe -install Ctr12Cap Ctr12Cap.sys
..\InstDriver.exe -start Ctr12Cap
rmdir /S /Q C:\bhhf
(preview of RE class)
* Sometimes when using the tools listed in the rootkits class, you will see information reported which is ambiguous - it is not clear if it is a change due to a rootkit, or just some 3rd party software.
* Using your RE skills is necessary to try to determine what caused the change.
* * A key point is that it's always up to you how far down the rabbit hole you want to go to provide "proof" which you believe.
* * But the other key point is that without this description, you wouldn't have been able to give chase at all.
[[Ambiguous GMER report 1]]
[[Ambiguous GMER report 2]]
[[Ambiguous GMER report 3]]
There are 3 steps to investigating such changes:
Step 1: [[Attach a debugger]]
Step 2: [[Investigate the memory location]]
Step 3 (optional): [[Determine the cause of the change]]
In "honor" of the AF's keylogger removal difficulties (http://www.wired.com/dangerroom/2011/10/virus-hits-drone-fleet/) , here is a lab showing how to use the same tools and skills from the rootkits class in order to squash keyloggers.
You need to start from a blank Windows XP SP3 32bit VM made for VMWare Player. It should have an account with the username "Student" and password "Awesome password FTW!". Student should be part of the Administrators group.
Once you have the VM, you should set it to be host-only networking and then you can drag and drop, or paste in the following files:
REFOG - http://www.refog.com/download/keylogger.exe
All in One Keylogger - http://www.relytec.com/download/keysetup.exe
BlazingTools Perfect Keylogger (BPK) - http://www.remote-logger.com/downloads/i_bpk_trial.exe
These keyloggers were picked just because of the demo keyloggers I tried downloading, these weren't flagged by my Symantec anti-virus. YMMV
You will also need the following detection tools placed on the system
GMER - http://www2.gmer.net/gmer.zip
VirusBlokAda Anti-Rootkit - ftp://anti-virus.by/pub/beta/vba32arkit_beta.zip
Autoruns - http://download.sysinternals.com/Files/Autoruns.zip
WinDbg - http://msdl.microsoft.com/download/symbols/debuggers/dbg_x86_6.11.1.404.msi
PEView - http://www.magma.ca/~wjr/PEview.zip
Next you will need to install an configure each of the keyloggers in the VM as directed in the next subsections.
NOTE: Because these are trial versions of the software, the files should not be installed until 3 days before the demo/talk.
[[Configure REFOG]]
[[Configure All in One Keylogger]]
[[Configure BPK]]
If your VM is set up correctly you should be able to enter the following commands to bring up each keylogger's interface:
shift-control-alt-K - REFOG
shift-control-alt-V - All in One Keylogger log viewer interface
shift-control-alt-P - All in One Keylogger configuration interface
shift-control-alt-L (that's a lower case L) -
Close VMWare Player to suspend the VM and distribute the files to all students.
Note: The VM should be started in non-PAE mode because ShadowWalker only supports non-PAE, and non-debugging enabled because SPTD disables its hooks if you boot with kernel debugging enabled. So make sure you also remove any debugging entries from C:\boot.ini and force the one remaining entry to non-PAE.
Users should be given a snapshot of a system where at least one rootkit is NOT persistent and will disappear if they reboot the machine to turn on debugging etc.
''You must install in this order''
[[Install the chaff]]
[[Install FUTo/ShadowWalker]] for TLB desynchronization & DKOM (process and kernel module hiding)
[[Install Vanquish/Hacker Defender]] for userspace rootkits and file/registry hiding
[[Install He4Hook]] for process hiding, SSDT registration, execution from dynamically allocated memory
[[Install SYSENTER hook and basic_callgate]] for sysenter hook and a basic callgate :P
[[Install basic_hook_hide_file]] for SSDT hooks
[[Clean up registry & misc]]
[[Omega.bat]]
Xeno's Rootkits Class wiki notes
Place [[http://technet.microsoft.com/en-us/sysinternals/bb897415 | LiveKD]] on a system that already has WinDbg installed. I'm assuming it's installed at C:\livekd.exe.
First set the environment variable for pulling the symbols from the symbol server (you will need internet access on the machine, if you don't have internet, you will need to [[download the symbols from Microsoft for offline use | http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx]] and place them on the system.
{{{
C:\set _NT_SYMBOL_PATH=SRV*C:\symbols\*http://msdl.microsoft.com/download/symbols/
C:\livekd.exe -w
}}}
The -w indicates to launch WinDbg rather than the command line only debugger kd.exe
You can then debug the system in WinDbg with slightly more capabilities than you could get from WinDbg itself when selecting the "local" tab from the File->Kernel Debug options
!LAB
We know from the rootkits class that the windows kernel modifies itself. But what if we didn't know that? What if we saw a change at nt!~KiSystemCallExitBranch+1, and we wanted to know if it was malicious, and we wanted to know what code was doing it?
We could determine this by using hardware breakpoints to set a break to occur when that location is written to.
Because the change we are investigating happens in the kernel, which is the first module to be loaded, we need to be able to stop early in the boot process and set a break on write breakpoint. Therefore we cannot use ~LiveKD, we must have a debugger capable of attaching at boot time.
When connected with a debugger, issue the following command:
[[sxe -c ".lastevent" ld]]
Then reboot the machine.
You will get a breakpoint like the following:
{{{
Last event: Load module ntkrnlpa.exe at 804d7000
debugger time: Sat Feb 12 09:51:09.748 2011 (GMT-5)
nt!DebugService2+0x10:
80531ee2 cc int 3
}}}
This tells you that the last event was the loading of ntkrnlpa.exe into memory (but its code has not yet begun to execute).
At this breakpoint issue the command:
[[ba w 1 nt!KiSystemCallExitBranch+1]]
to set a breakpoint when ~KiSystemCallExitBranch+1 is written to (this assumes you already have the symbols loaded so the debugger can translate ~KiSystemCallExitBranch+1 to an absolute virtual address)
After that, issue this command to turn off the breakpoints when modules load.
[[sxi ld]]
(for some reason if I instead issue the command which also silences the .lastevent: [[sxi -c "" ld]], it doesn't hit the breakpoint.)
and then [[g]]
Eventually you will hit a breakpoint like this:
{{{
nt!KiEnableFastSyscallReturn+0x35:
804fe87f 880d3dc35580 mov byte ptr [nt!KiSystemCallExitAdjusted (8055c33d)],cl
}}}
But if you recall back to Intermediate x86, some hardware breakpoints are faults, and some are traps. A break on write is a trap.
[[Does anyone remember the differences between a fault, trap, and abort?]] Hint: hitler, ackbar, spider
So because break on write is a trap, we need to look at the instruction previous to the EIP when the the interrupt is caught.
That instruction is:
{{{804fe879 000d4a175480 add byte ptr [nt!KiSystemCallExitBranch+0x1 (8054174a)],cl}}}
and the value in cl = 1
So clearly the code in nt!~KiEnableFastSyscallReturn is responsible for this change to the state of memory for ntkrnlpa.exe, and therefore we don't believe it is due to a rootkit.
!LAB
In the rootkits class we also saw that hal.dll modifies itself. This can be seen on a live system with the !chkimg command:
[[!chkimg -d -nospec hal]]
{{{
kd> !chkimg -d -nospec hal
806e793c-806e7940 5 bytes - hal!HalpRealModeStart+7b2
[ 00 00 00 00 00:46 09 15 62 12 ]
806e7945-806e794a 6 bytes - hal!HalpRealModeStart+7bb (+0x09)
[ 00 00 00 00 00 00:07 4c 09 ec 61 12 ]
806e794c-806e7950 5 bytes - hal!HalpRealModeStart+7c2 (+0x07)
[ 00 00 00 00 00:90 c7 59 49 12 ]
806e7953-806e7955 3 bytes - hal!HalpRealModeStart+7c9 (+0x07)
[ 00 00 00:f0 df ff ]
806e7958-806e795f 8 bytes - hal!HalpRealModeStart+7ce (+0x05)
[ 00 00 00 00 00 00 00 00:04 80 90 c7 c4 f9 72 09 ]
806e7962-806e7972 17 bytes - hal!HalpRealModeStart+7d8 (+0x0a)
[ 00 00 00 00 00 00 00 00:dc 3d 05 44 05 44 d7 43 ]
806e7975-806e797d 9 bytes - hal!HalpRealModeStart+7eb (+0x13)
[ 00 00 00 00 00 00 00 00:f0 8a 01 ac 20 dc 3d 90 ]
806e7983-806e7985 3 bytes - hal!HalpRealModeStart+7f9 (+0x0e)
[ 00 00 00:20 02 0b ]
806e7987-806e798b 5 bytes - hal!HalpRealModeStart+7fd (+0x04)
[ 00 00 00 00 00:c0 16 32 92 01 ]
806e798d-806e798f 3 bytes - hal!HalpRealModeStart+803 (+0x06)
[ 00 00 00:20 16 32 ]
64 errors : hal (806e793c-806e798f)
}}}
In all cases we can see that the memory was zeros on disk, but has changed into unknown data in memory.
However, setting a break on write for these self-modification areas ''does not'' cause the system to break when the memory is changed.
Therefore we will have to investigate where the changes come from with an iterative stepping strategy.
Let's start by reusing the [[sxe -c ".lastevent" ld]] command. We will set this and then reboot in order to
When we hit the hal module loading, we will set the memory window to display "hal!~HalpRealModeStart+7b2" which is where the first change is detected.
When we continue from hal's loading to KDCOM's loading, we see that the memory has not changed yet. So we will continue to step from module to module until we detect the change. When we eventually see "Last event: Load module ntdll.dll at 7c900000", the hal memory has changed at that point.
Therefore we are left wondering how best to proceed. Utilizing the knowledge from the Life of Binaries class, we know that the address of the first instructions to execute (assuming there are not TLS callbacks) is stored in the PE headers in the optional header in the field ~AddressOfEntryPoint. We can quickly find this field by using the command [[!dh -f hal]] which will parse the PE headers for the hal.dll loaded in memory, and print some relevant fields like ~AddressOfEntryPoint.
Since we have went too far, we will reboot the system and issue [[!dh -f hal]] after the hal.dll module has been loaded.
{{{
kd> !dh -f hal
File Type: DLL
FILE HEADER VALUES
14C machine (i386)
B number of sections
4802517F time date stamp Sun Apr 13 14:31:27 2008
<snip>
1D9E8 address of entry point
<snip>
}}}
Recall that ~AddressOfEntryPoint is an RVA, so to get the absolute virtual address we must add this value to the base address.
We then set a breakpoint on the first hal code to execute by issuing [[bp hal+1D9E8]], and then we continue with [[g]].
We then see that before we even proceed on to the next module, we hit the breakpoint at hal's entry point
Remembering what was said before about paying attention to control flow (FIXME: fill in any exact words said), we will speculativly set some breakpoints and try to *approximate* a binary search, so that we can try to isolate between which two breakpoints the change may occur.
''NOTE'' when we are looking at the code without respect to control, there is no reason to believe that code halfway down the page actually executes after the code which is before it linearly. However we are still just trying to get a sense of where the change might occur, so it's ok to make some rough estimates.
I selected "next" in my disassembly window about 19 times before I came to what looked like the end of the function, because it had a leave, ret sequence, followed by int 3 padding. So I set a breakpoint on the ret.
I then selected "previous" 10 times which put me back to about [[hal+1dc15]] which was the instruction "call hal!~HalpRegisterVector".
I called this good enough to start with, and I entered [[g]] and saw the following:
{{{
Breakpoint 2 hit
hal!HalInitSystem+0x22d:
80701c15 e86ee8ffff call hal!HalpRegisterVector (80700488)
}}}
Memory had not changed, but just to be sure, I used "step over" ([[p]]) to see if the changes occurred in ~HalpRegisterVector, but they did not. So //assuming// my breakpoint had been approximately half way through the code, the change did not occur in the first half of the code, so I needed to set a break in the second half. I hit "next" 5 times and saw an appealing target of "call hal!HalpAllocPhysicalMemory" at hal+1dc15 and set a breakpoint on it. Again I entered [[g]] and saw the following:
{{{
Breakpoint 3 hit
hal!HalInitSystem+0x331:
80701d19 e870f9ffff call hal!HalpAllocPhysicalMemory (8070168e)
}}}
Memory had still not changed, even after stepping over this function. So I hit "next" 2 times, and saw the instruction "call dword ptr [eax+40h]" at hal+1dd80, and set a breakpoint and continued.
{{{
Breakpoint 1 hit
hal!HalInitSystem+0x46f:
80701e57 c20800 ret 8
}}}
continuing
Breakpoint 0 hit
hal!HalInitSystem:
807019e8 8bff mov edi,edi
Breakpoint 4 hit
hal!HalInitSystem+0x398:
80701d80 ff5040 call dword ptr [eax+40h]
aaand I can't remember how I figured out where to break :)
----
When dealing with malware, it may be the case that they are overwriting your hardware breakpoints. It may be necessary to use this method to find the origin of a change.
[img[images/Debug1.png]]
[img[images/Debug2.png]]
[img[images/Debug3.png]]
[img[images/Debug4.png]]
[img[images/Debug5.png]]
[img[images/Debug6.png]]
[img[images/Debug7.png]]
[img[images/Debug8.png]]
[img[images/Debug9.png]]
[img[images/Debug10.png]]
ba = hardware breakpoint, break on access
w = access type, write
1 = size of memory to care about writes to
nt!KiSystemCallExitBranch+1 = address in memory to care about writes to
bp = set software breakpoint
hal+1D9E8 = ~WinDbg interprets the module name here to refer to the base address where it is loaded in memory
This command is "display a processor-appropriate-sized pointer as a symbol". Meaning, if running on a 32 bit system, it takes the 32 bits specified and tries to describe how it relates to the nearest symbol (either being the exact start address of a symbol such as a function or global variable, or being some offset from that symbol). On a 64 bit system it would take chunks of 64 bits and treat them as addresses, and show how they relate to symbols.
g = "go" or "continue" to continue program execution until a breakpoint is hit or the user selects break.
This can also be accomplished from the ~WinDbg icon bar, or with F5.
How did I determine it was hal+1dc15, when only an absolute virtual address was specified? I use the following command to find RVAs when I know which module I'm in:
{{{
kd> dd 80701c15-hal
0001dc15 01548d00 f88689f8 89000003 00040086
0001dc25 fc968900 8b000003 02e9c1d1 be89c033
<snip>
}}}
This tells me that the RVA is 0001dc15. A ghetto calculator if ever there was one. :)
sxe = "Set exception break, enable"
ld = event to act on: load module
-c = command to execute on break
.lastevent = print last event that occurred
(see ~WinDbg help on "sxe" and "Controlling Events and Exceptions" for more details)
sxi = "Set exception ignore"
ld = event to act on: load module
-c = command to execute on break
"" = do not issue a command
(see ~WinDbg help on "sxe" and "Controlling Events and Exceptions" for more details)
sxi = "Set exception ignore"
ld = event to act on: load module
(see ~WinDbg help on "sxe" and "Controlling Events and Exceptions" for more details)