#------------------------------------------------------------------------------ # internet_explorer_cu.pl # NTUSER.DAT Internet Explorer key parser # Try to get useful information on IE # Note: it's not tested against all IE versions available # WARNING: there exist a huge work to be done, IE settings # are a lot and they are sparse in registries # # Change history # 20120426 [fpi] % created and working on # 20120513 [fpi] % first release # 20120528 [fpi] % released to public # # References # "Geoff Chappell - Internet Explorer Registry API " => # "http://www.geoffchappell.com/studies/windows/ie/iertutil/api/ierapi/index.htm", # "Internet Explorer Maintenance Extension Tools and Settings" # http://technet.microsoft.com/en-us/library/cc736412%28v=ws.10%29.aspx # "Introduction to Web Storage" # http://msdn.microsoft.com/en-us/library/cc197062%28v=vs.85%29.aspx # "How can I configure my Internet Explorer browser settings after I have removed malicious software from my computer?" # http://support.microsoft.com/kb/895339 # "How to Change the Internet Explorer Window Title" # http://support.microsoft.com/kb/176497 # # The plugin will not parse *every* IE subkeys. The list of subkeys I was able # to found inside my NTUSER.DAT registries (a join of XP, Vista, 7) is following. Note that: # (P) means parsed, (*) means not parsed but interesting (a TODO), nothing means not parsed. # # Registries coming from (and tested on): # (A) Windows7 Professional 32bit - IE 9.0.8112.16421 # (B) Windows7 Ultimate 64bit - IE 9.0.8112.16421 # (C) Windows XP Home 32bit - IE 8.0.6001.18702 # (D) Windows Vista 64bit - IE 7.0.6002.18005 # # HKCU\Software\Microsoft\Internet Explorer subkeys list: # # Activities (*) [ A ] # ApprovedExtensions (*) [ B ] # ApproveExtensionsMigration (*) [ A B ] # AutoComplete (P) [ A ] # BrowserEmulation [ A B C ] # CaretBrowsing [ A ] # CommandBar [ A B C D ] # Default HTML Editor [ C D ] # Default MHTML Editor [ D ] # Desktop [ A B C D ] # Document Windows [ A B C D ] # DOMStorage (P) [ A B C ] # Download (*) [ A B C D ] # DxTrans [ A ] # Expiration [ A ] # Explorer Bars [ A ] # Extensions (*) [ A B C D ] # Feed Discovery [ A ] # Feeds [ A D ] # Geolocation (*) [ A ] # GPActivities [ A ] # GPU [ A B ] # Help_Menu_URLs [ A B C D ] # IEDevTools (*) [ A B ] # IETld (P) [ A B C ] # InformationBar [ C D ] # IntelliForms (*) [ A B C D ] # International (*) [ A B C D ] # InternetRegistry [ A B C D ] # LinksBar [ A B C ] # LinksExplorer [ A C D ] # LowRights [ B D ] # LowRegistry [ A B C D ] # Main (P) [ A B C D ] # MAO Settings [ A B C ] # Media [ A C D ] # MenuExt (*) [ A B C D ] # MINIE [ A B ] # New Windows [ A B C D ] # PageSetup [ A B C D ] # PhishingFilter (*) [ A B C D ] # Privacy (P) [ A C ] (user settings ndr) # ProtocolExecute [ A ] # Recovery (P) [ A B C ] # Safety [ A ] # SearchScopes (*) [ A B C D ] # SearchUrl [ A B C D ] # Security (*) [ A B C D ] # Services [ A B C D ] (empty? ndr) # Settings [ A B C D ] # Setup [ A B D ] # SiteMode [ A B C D ] # SQM (*) [ A B C ] # Styles [ A ] # Suggested Sites (P) [ A B C ] # TabbedBrowsing [ A B C D ] # TaskbarPreview [ A ] # Text Scaling [ A ] # Toolbar [ A B C D ] # TypedURLs [ B C ] (hum?! ndr) # UpgradeIEAd [ A ] # URLSearchHooks (*) [ A B C D ] # User Preferences (*) [ A B C ] # View Source Editor [ A ] # Zoom [ A B C D ] # # copyright 2012 F. Picasso francesco.picasso@gmail.com #------------------------------------------------------------------------------ package internet_explorer_cu; use strict; my %config = (hive => "NTUSER\.DAT", osmask => 22, hasShortDescr => 1, hasDescr => 0, hasRefs => 0, version => 20120528); sub getConfig{return %config} sub getShortDescr { return "Get HKCU information on Internet Explorer"; } sub getDescr{} sub getRefs { my %refs = ("Geoff Chappell - Internet Explorer Registry API " => "http://www.geoffchappell.com/studies/windows/ie/iertutil/api/ierapi/index.htm", "Internet Explorer Maintenance Extension Tools and Settings" => "http://technet.microsoft.com/en-us/library/cc736412%28v=ws.10%29.aspx", "Introduction to Web Storage" => "http://msdn.microsoft.com/en-us/library/cc197062%28v=vs.85%29.aspx", "How can I configure my Internet Explorer browser settings after I have removed malicious software from my computer?" => "http://support.microsoft.com/kb/895339", "How to Change the Internet Explorer Window Title" => "http://support.microsoft.com/kb/176497" ); } sub getHive {return $config{hive};} sub getVersion {return $config{version};} my $VERSION = getVersion(); #------------------------------------------------------------------------------ my $tab0 = ""; my $tab2 = " "; my $tab4 = " "; my $tab6 = " "; my $tab8 = " "; my $align10 = "%-10s"; my $align15 = "%-15s"; my $align20 = "%-20s"; my $align25 = "%-25s"; my $align30 = "%-30s"; my $align40 = "%-40s"; #------------------------------------------------------------------------------ my %IE_MAIN_TRANSLATE = ( "AdminTabProcs" => \&trBool, "AllowWindowReuse" => \&trBool, "AlwaysShowMenus" => \&trBool, "AutoSearch" => \&trBool, "Cleanup HTCs" => \&trBool, "CompatibilityFlags" => \&trNumHex, "Display Inline Videos" => \&trBool, "DNSPreresolution" => \&trNumHex, "Do404Search" => \&trDo404Search, "DOMStorage" => \&trBool, "DownloadWindowPlacement" => \&trSkip, "EnableSearchPane" => \&trBool, "ForceGDIPlus" => \&trBool, "FrameMerging" => \&trBool, "FrameShutdownDelay" => \&trBool, "FrameTabWindow" => \&trBool, "GotoIntranetSiteForSingleWordEntry" => \&trBool, "HangRecovery" => \&trBool, "HistoryViewType" => \&trHex, "IE8RunOnceCompletionTime" => \&trFileTime, "IE8RunOnceLastShown" => \&trBool, "IE8RunOnceLastShown_TIMESTAMP" => \&trFileTime, "IE8RunOncePerInstallCompleted" => \&trBool, "IE8TourShown" => \&trBool, "IE8TourShownTime" => \&trFileTime, "IE9RecommendedSettingsNo" => \&trBool, "IE9RunOnceCompletionTime" => \&trFileTime, "IE9RunOnceLastShown" => \&trBool, "IE9RunOncePerInstallCompleted" => \&trBool, "IE9TourNoShow" => \&trBool, "IE9TourShown" => \&trBool, "IE9TourShownTime" => \&trFileTime, "MinIEEnabled" => \&trBool, "NoUpdateCheck" => \&trBool, "NscSingleExpand" => \&trBool, "Q300829" => \&trBool, "SearchControlWidth" => \&trSkip, "SessionMerging" => \&trBool, "Show image placeholders" => \&trBool, "ShutdownWaitForOnUnload" => \&trBool, "SmoothScroll" => \&trSkip, "Start Page Redirect Cache_TIMESTAMP" => \&trFileTime, "StatusBarWeb" => \&trBool, "SuppressScriptDebuggerDialog" => \&trBool, "TabShutdownDelay" => \&trNumHex, "Use Stylesheets" => \&trBool, "UseHR" => \&trBool, "UseThemes" => \&trBool, "Window_Placement" => \&trSkip, "XDomainRequest" => \&trBool, "XMLHTTP" => \&trBool ); my %IE_MAIN_WINSEARCH_TRANSLATE = ( "AutoCompleteGroups" => \&trNumHex, "Cleared" => \&trBool, "Cleared_TIMESTAMP" => \&trFileTime, "ConfiguredScopes" => \&trNumHex, "Disabled" => \&trBool, "EnabledScopes" => \&trNumHex, "LastCrawl" => \&trFileTime, "UpgradeTime" => \&trFileTime ); my %IE_PRIVACY_TRANSLATE = ( "CleanDownloadHistory" => \&trBool, "CleanInPrivateBlocking" => \&trBool, "CleanPassword" => \&trBool, "CleanTrackingProtection" => \&trBool, "ClearBrowsingHistoryOnExit" => \&trBool, "UseAllowList" => \&trBool ); my %IE_RECOVERY_TRANSLATE = ( "AutoRecover" => \&trBool, "NoReopenLastSession" => \&trBool ); my %IE_SUGGSITES_TRANSLATE = ( "MigrationTime" => \&trFileTime, "ObjectsCreated" => \&trBool, "ObjectsCreated_TIMESTAMP" => \&trFileTime ); #------------------------------------------------------------------------------ sub pluginmain { my $class = shift; my $hive = shift; ::logMsg( "Launching internet_explorer_cu v.".$VERSION ); ::rptMsg( "internet_explorer_cu v.".$VERSION ); ::rptMsg( "(".getHive().") ".getShortDescr()."\n" ); my $reg = Parse::Win32Registry->new( $hive ); my $root_key = $reg->get_root_key; my $key_path_ie = "Software\\Microsoft\\Internet Explorer"; my $key_path = $key_path_ie; my $key; my $tab; my $align; my $vdata; my $vname; # 20120426 [fpi] : getting the main key $key = $root_key->get_subkey( $key_path ); if ( not $key ) { ::rptMsg( $key_path." not found." ); ::logMsg( $key_path." not found." ); return; } # 20120426 [fpi] : getting, if available, the DownloadDirectory $tab = $tab2; $align = $align10; $vname = "Download Directory"; ::rptMsg( $key_path ); ::rptMsg( "LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); $vdata = getValueData( $key, $vname, undef ); ::rptMsg( sprintf( $tab."$align = '%s'", $vname, $vdata ) ); ::rptMsg( "" ); # --------------------------------------------------------------- # 20120426 [fpi] : not parsing "ApprovedExtensionsMigration" and # "ApprovedExtensions" subkeys, which could be # useful for malware removal and/or for IE timestamping # Ref: "Internet Explorer Maintenance Extension Tools and Settings" # http://technet.microsoft.com/en-us/library/cc736412%28v=ws.10%29.aspx # --------------------------------------------------------------- # 20120426 [fpi] : parsing, if available, the AutoComplete subkey $key_path = $key_path_ie."\\AutoComplete"; if ( $key = $root_key->get_subkey( $key_path ) ) { ::rptMsg( $key_path ); ::rptMsg( "LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); rptAllKeyValues( $key, $tab2, $align10 ); } else { ::rptMsg( $key_path." not found." ); ::logMsg( $key_path." not found." ); } ::rptMsg( "" ); # --------------------------------------------------------------- # 20120426 [fpi] : parsing "DOMstorage", no informations (apart guessing) on the Total # subkey and values # Ref: "Introduction to Web Storage" # http://msdn.microsoft.com/en-us/library/cc197062%28v=vs.85%29.aspx $key_path = $key_path_ie."\\DOMStorage"; if ( $key = $root_key->get_subkey( $key_path ) ) { ::rptMsg( $key_path ); ::rptMsg( "LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); ::rptMsg( "Subkeys:" ); rptAllSubKeys( $key, $tab2, $align20 ); } else { ::rptMsg( $key_path." not found." ); ::logMsg( $key_path." not found." ); } ::rptMsg( "" ); # --------------------------------------------------------------- # 20120502 [fpi] : parsing "IETld", no informations found, guessing # I sometimes noticed a discrepancy in the last WORD (16bit) # value between SOFTWARE key and NTUSER key (??) $key_path = $key_path_ie."\\IETld"; if ( $key = $root_key->get_subkey( $key_path ) ) { ::rptMsg( $key_path ); ::rptMsg( "LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); $vname = "IETldDllVersionHigh"; $vdata = getValueData( $key, $vname, undef, 1 ); my ($vhi1, $vhi2) = ("????", "????"); if ( defined $vdata ) { $vhi1 = $vdata >> 16; $vhi2 = $vdata & 0x0000FFFF; } $vname = "IETldDllVersionLow"; $vdata = getValueData( $key, $vname, undef, 1 ); my ($vlo1, $vlo2) = ("????", "????"); if ( defined $vdata ) { $vlo1 = $vdata >> 16; $vlo2 = $vdata & 0x0000FFFF; } ::rptMsg( $tab2."Internet Explorer version = $vhi1.$vhi2.$vlo1.$vlo2" ); } else { ::rptMsg( $key_path." not found." ); ::logMsg( $key_path." not found." ); } ::rptMsg( "" ); # --------------------------------------------------------------- # 20120502 [fpi] : parsing "Main" and "WindowsSearch" subkey. # Not parsing subkeys "FeatureControl" (could be relevant for # the security settings) and "Touch". $key_path = $key_path_ie."\\Main"; if ( $key = $root_key->get_subkey( $key_path ) ) { ::rptMsg( $key_path ); ::rptMsg( "LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); rptAllKeyValuesTrans( $key, \%IE_MAIN_TRANSLATE, $tab2, $align40 ); #--- Windows Search subkey $key_path .= "\\WindowsSearch"; if ( $key = $root_key->get_subkey( $key_path ) ) { ::rptMsg( "" ); ::rptMsg( $tab2.$key_path ); ::rptMsg( $tab2."LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); rptAllKeyValuesTrans( $key, \%IE_MAIN_WINSEARCH_TRANSLATE, $tab4, $align25 ); } else { ::rptMsg( $tab.$key_path." not found." ); ::logMsg( $key_path." not found." ); } } else { ::rptMsg( $key_path." not found." ); ::logMsg( $key_path." not found." ); } ::rptMsg( "" ); # --------------------------------------------------------------- # 20120502 [fpi] : parsing "Privacy", no info here apart guessing. Tests were # made on Win7 systems: the presence of this key should attest # that the user changed the Privacy settings; the absence that # IE is using defaults settings. Counterchecks welcome. $key_path = $key_path_ie."\\Privacy"; if ( $key = $root_key->get_subkey( $key_path ) ) { ::rptMsg( $key_path ); ::rptMsg( "LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); rptAllKeyValuesTrans( $key, \%IE_PRIVACY_TRANSLATE, $tab2, $align30 ); } else { ::rptMsg( $key_path." not found (IE should use the default Privacy settings)" ); ::logMsg( $key_path." not found." ); } ::rptMsg( "" ); # --------------------------------------------------------------- # 20120502 [fpi] : parsing "Recovery", no information just parsing $key_path = $key_path_ie."\\Recovery"; if ( $key = $root_key->get_subkey( $key_path ) ) { ::rptMsg( $key_path ); ::rptMsg( "LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); rptAllKeyValuesTrans( $key, \%IE_RECOVERY_TRANSLATE, $tab2, $align25 ); #--- Subkeys $key_path = $key_path_ie."\\Recovery"."\\Active"; if ( $key = $root_key->get_subkey( $key_path ) ) { ::rptMsg( "\n".$tab2.$key_path ); ::rptMsg( $tab2."LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); rptAllKeyValues( $key, $tab4, $align25 ); } else { ::rptMsg( "\n".$tab2.$key_path." not found." ); ::logMsg( $key_path." not found." ); } $key_path = $key_path_ie."\\Recovery"."\\AdminActive"; if ( $key = $root_key->get_subkey( $key_path ) ) { ::rptMsg( "\n".$tab2.$key_path ); ::rptMsg( $tab2."LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); rptAllKeyValues( $key, $tab4, $align25 ); } else { ::rptMsg( "\n".$tab2.$key_path." not found." ); ::logMsg( $key_path." not found." ); } $key_path = $key_path_ie."\\Recovery"."\\PendingDelete"; if ( $key = $root_key->get_subkey( $key_path ) ) { ::rptMsg( "\n".$tab2.$key_path ); ::rptMsg( $tab2."LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); rptAllKeyValues( $key, $tab4, $align25 ); } else { ::rptMsg( "\n".$tab2.$key_path." not found." ); ::logMsg( $key_path." not found." ); } } else { ::rptMsg( $key_path." not found." ); ::logMsg( $key_path." not found." ); } ::rptMsg( "" ); # --------------------------------------------------------------- # 20120502 [fpi] : parsing "Suggested Site", lot of web info regarding # the privacy issue derived from this feature. But almost # every privacy issue is a good source for an analyst ;) $key_path = $key_path_ie."\\Suggested Sites"; if ( $key = $root_key->get_subkey( $key_path ) ) { ::rptMsg( $key_path ); ::rptMsg( "LastWrite Time ".gmtime( $key->get_timestamp() )." (UTC)" ); rptAllKeyValuesTrans( $key, \%IE_SUGGSITES_TRANSLATE, $tab2, $align30 ); } else { ::rptMsg( $key_path." not found." ); ::logMsg( $key_path." not found." ); } ::rptMsg( "" ); } #------------------------------------------------------------------------------ sub trBool { my $data = shift; my $temp = "true "; if ( $data != 0 and $data != 1 ) { $temp = "$data (WARNING: expected a boolean '0|1'!)"; return $temp; } $temp = "false" if ( $data == 0 ); $temp .= " [$data]"; return $temp; } sub trDo404Search { my $data = shift; my $temp; $temp = unpack( "V" , $data ); return $temp." [0x".unpack( "H*", $data )."]"; } sub trFileTime { my $data = shift; my ( $t0, $t1 ) = unpack( "VV",$data ); $data = gmtime( ::getTime( $t0, $t1 ) )." UTC"; return $data; } sub trHex { my $data = shift; $data = unpack( "H*", $data ); return "0x".$data; } sub trNumHex { my $data = shift; return sprintf( "%u [0x%08X]", $data, $data ); } sub trSkip { return ""; } #------------------------------------------------------------------------------ sub getKeyValues { my $key = shift; my %vals; my @vk = $key->get_list_of_values(); if (scalar(@vk) > 0) { foreach my $v (@vk) { next if ($v->get_name() eq "" && $v->get_data() eq ""); $vals{$v->get_name()} = $v->get_data(); } } else { } return %vals; } #------------------------------------------------------------------------------ sub getValueData { # key, value name, translator, use stub my $key = shift; my $vn = shift; my $trans = shift; my $stub = shift; my $vd; my $vo; $vo = $key->get_value( $vn ); if ( not defined $vo ) { return undef unless defined $stub; $vd = ""; } else { $vd = $vo->get_data(); if ( defined $trans ) { $vd = $trans->( $vd ); } } return $vd; } #------------------------------------------------------------------------------ sub rptAllSubKeys { # key, tab, align my @subkeys = $_[0]->get_list_of_subkeys(); foreach my $k (@subkeys) { ::rptMsg( sprintf( $_[1]."$_[2] --- %s", $k->get_name() ) . gmtime( $k->get_timestamp() ) . " UTC" ); } } #------------------------------------------------------------------------------ sub rptAllKeyValues { # key, tab, align my @vals = sort {lc $a->get_name() cmp lc $b->get_name} $_[0]->get_list_of_values(); foreach my $v (@vals) { my $val = $v->get_name(); my $data = $v->get_data(); ::rptMsg( sprintf( $_[1]."$_[2] = %s", $val, $data ) ); } } #------------------------------------------------------------------------------ sub rptAllKeyValuesTrans { # key, ttlb, tab, align, my $key = shift; my $ttlb = shift; my $tab = shift; my $align = shift; my $vname; my $vdata; my $trans; my @vals = sort {lc $a->get_name() cmp lc $b->get_name} $key->get_list_of_values(); foreach my $v (@vals) { $vname = $v->get_name(); $vdata = $v->get_data(); $trans = ${$ttlb}{$vname}; $vdata = $trans->( $vdata ) if ( defined $trans ); ::rptMsg( sprintf( $tab."$align = %s", $vname, $vdata ) ); } } #------------------------------------------------------------------------------ 1;