2012-01-11 00:45:24 +00:00
#!/usr/bin/env ruby
#
# $Id$
#
# This script acts as a small registry reader.
# You may easily automate a lot of registry forensics with a proper method.
# $Revision$
#
msfbase = File . symlink? ( __FILE__ ) ? File . readlink ( __FILE__ ) : __FILE__
$: . unshift ( File . join ( File . dirname ( msfbase ) , '..' , 'lib' ) )
require 'rex'
require 'msf/ui'
require 'rex/registry/hive'
def print_all ( nodekey )
print_all_keys ( nodekey )
print_all_values ( nodekey )
end
def print_all_keys ( nodekey )
2012-01-16 23:54:33 +00:00
return if ! nodekey
return if ! nodekey . lf_record
return if ! nodekey . lf_record . children
return if nodekey . lf_record . children . length == 0
2012-01-11 00:45:24 +00:00
table = Rex :: Ui :: Text :: Table . new (
'Header' = > " Child Keys for #{ nodekey . full_path } " ,
'Indent' = > ' ' . length ,
'Columns' = > [ 'Name' , 'Last Edited' , 'Subkey Count' , 'Value Count' ]
)
2012-01-16 23:54:33 +00:00
if nodekey . lf_record && nodekey . lf_record . children && nodekey . lf_record . children . length > 0
2012-01-11 00:45:24 +00:00
nodekey . lf_record . children . each do | key |
table << [ key . name , key . readable_timestamp , key . subkeys_count , key . value_count ]
end
end
puts table . to_s
end
def print_all_values ( nodekey )
2012-01-16 23:54:33 +00:00
return if ! nodekey
return if ! nodekey . lf_record
return if ! nodekey . lf_record . children
return if nodekey . lf_record . children . length == 0
2012-01-11 00:45:24 +00:00
table = Rex :: Ui :: Text :: Table . new (
'Header' = > " Values in key #{ nodekey . full_path } " ,
'Indent' = > ' ' . length ,
'Columns' = > [ 'Name' , 'Value Type' , 'Value' ]
)
if nodekey . value_list && nodekey . value_list . values . length > 0
nodekey . value_list . values . each do | value |
table << [ value . name , value . readable_value_type , value . value . data ]
end
end
puts table . to_s
end
def get_system_information
if @hive . hive_regf . hive_name =~ / SYSTEM /
mounted_devices_info_key = @hive . relative_query ( " \\ MountedDevices " )
current_control_set_key = @hive . value_query ( '\Select\Default' )
2012-01-16 23:54:33 +00:00
current_control_set = " ControlSet00 " + current_control_set_key . value . data . unpack ( 'c' ) . first . to_s if current_control_set_key
2012-01-11 00:45:24 +00:00
2012-01-16 23:54:33 +00:00
computer_name_key = @hive . value_query ( " \\ " + current_control_set + " \\ Control \\ ComputerName \\ ComputerName " ) if current_control_set
computer_name = computer_name_key . value . data . to_s if computer_name_key
2012-01-11 00:45:24 +00:00
2012-01-16 23:54:33 +00:00
event_log_info_key = @hive . relative_query ( " \\ " + current_control_set + " \\ Services \\ EventLog " ) if current_control_set
2012-01-11 00:45:24 +00:00
2012-01-16 23:54:33 +00:00
puts " Computer Name: " + computer_name if computer_name
2012-01-11 00:45:24 +00:00
2012-01-16 23:54:33 +00:00
print_all_values ( event_log_info_key ) if event_log_info_key
puts " ----------------------------------------- " if event_log_info_key
2012-01-11 00:45:24 +00:00
2012-01-16 23:54:33 +00:00
print_all_values ( mounted_devices_info_key ) if mounted_devices_info_key
puts " ----------------------------------------- " if mounted_devices_info_key
2012-01-11 00:45:24 +00:00
elsif @hive . hive_regf . hive_name =~ / SOFTWARE /
current_version_info_key = @hive . relative_query ( " \\ Microsoft \\ Windows NT \\ CurrentVersion " )
login_info_key = @hive . relative_query ( " \\ Microsoft \\ Windows NT \\ CurrentVersion \\ Winlogon " )
print_all_values ( current_version_info_key )
2012-01-16 23:54:33 +00:00
puts " ----------------------------------------- " if current_version_info_key
2012-01-11 00:45:24 +00:00
print_all_values ( login_info_key )
2012-01-16 23:54:33 +00:00
puts " ----------------------------------------- " if login_info_key
2012-01-11 00:45:24 +00:00
end
end
def get_user_information
2012-01-16 23:54:33 +00:00
2012-01-11 00:45:24 +00:00
local_groups_info_key = @hive . relative_query ( " \\ SAM \\ Domains \\ Builtin \\ Aliases \\ Names " )
local_users_info_key = @hive . relative_query ( " \\ SAM \\ Domains \\ Account \\ Users \\ Names " )
2012-01-16 23:54:33 +00:00
print_all ( local_groups_info_key )
puts " ------------------------------------------------ " if local_groups_info_key && local_groups_info_key . lf_record . children
2012-01-11 00:45:24 +00:00
2012-01-16 23:54:33 +00:00
print_all ( local_users_info_key )
puts " ------------------------------------------------ " if local_users_info_key && local_groups_info_key . lf_record . children
2012-01-11 00:45:24 +00:00
end
def dump_creds
end
def get_boot_key
2012-01-16 23:54:33 +00:00
return if ! @hive . root_key
return if ! @hive . root_key . name
puts " Getting boot key "
puts " Root key: " + @hive . root_key . name
default_control_set = @hive . value_query ( '\Select\Default' ) . value . data . unpack ( " c " ) . first
puts " Default ControlSet: ControlSet00 #{ default_control_set } "
bootkey = " "
basekey = " \\ ControlSet00 #{ default_control_set } \\ Control \\ Lsa "
%W{ JD Skew1 GBG Data } . each do | k |
ok = @hive . relative_query ( basekey + " \\ " + k )
return nil if not ok
tmp = " "
0 . upto ( ok . class_name_length - 1 ) do | i |
next if i % 2 == 1
tmp << ok . class_name_data [ i , 1 ]
end
bootkey << [ tmp . to_i ( 16 ) ] . pack ( 'V' )
end
keybytes = bootkey . unpack ( " C* " )
descrambled = " "
# descrambler = [ 0x08, 0x05, 0x04, 0x02, 0x0b, 0x09, 0x0d, 0x03, 0x00, 0x06, 0x01, 0x0c, 0x0e, 0x0a, 0x0f, 0x07 ]
descrambler = [ 0x0b , 0x06 , 0x07 , 0x01 , 0x08 , 0x0a , 0x0e , 0x00 , 0x03 , 0x05 , 0x02 , 0x0f , 0x0d , 0x09 , 0x0c , 0x04 ]
0 . upto ( keybytes . length - 1 ) do | x |
descrambled << [ keybytes [ descrambler [ x ] ] ] . pack ( " C " )
end
puts descrambled . unpack ( " H* " )
2012-01-11 00:45:24 +00:00
end
def list_applications
end
def list_drivers
end
def get_aol_instant_messenger_information
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name != / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
users_list_key = @hive . relative_query ( '\Software\America Online\AOL Instant Messenger(TM)\CurrentVersion\Users' )
last_logged_in_user_key = @hive . relative_query ( " \\ Software \\ America Online \\ AOL Instant Messenger(TM) \\ CurrentVersion \\ Login - Screen Name " )
print_all_keys ( user_list_key )
user_list_key . lf_record . children . each do | screenname |
away_messages_key = @hive . relative_query ( " \\ Software \\ America Online \\ AOL Instant Messenger(TM) \\ CurrentVersion \\ Users \\ #{ screenname . name } \\ IAmGoneList " )
file_xfer_settings_key = @hive . relative_query ( " \\ Software \\ America Online \\ AOL Instant Messenger(TM) \\ CurrentVersion \\ Users \\ #{ screenname . name } \\ Xfer " )
profile_info_key = @hive . relative_query ( " \\ Software \\ America Online \\ AOL Instant Messenger(TM) \\ CurrentVersion \\ Users \\ #{ screenname . name } \\ DirEntry " )
recent_contacts_key = @hive . relative_query ( " \\ Software \\ America Online \\ AOL Instant Messenger(TM) \\ CurrentVersion \\ Users \\ #{ screenname . name } \\ Recent IM ScreenNames " )
print_all ( away_messages_key )
print_all ( file_xfer_settings_key )
print_all ( profile_info_key )
print_all ( recent_contacts_key )
end
end
end
def get_msn_messenger_information
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name =~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
general_information_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ MessengerService \\ ListCache \\ .NETMessengerService \\ " )
file_sharing_information_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ MSNMessenger \\ FileSharing - Autoshare " )
file_transfers_information_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ MSNMessenger \\ - FTReceiveFolder " )
print_all ( general_information_key )
print_all ( file_sharing_information_key )
print_all ( file_transfers_information_key )
end
end
def get_windows_messenger_information
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name =~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
contact_list_information_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ MessengerService \\ ListCache \\ .NET Messenger Service " )
2012-01-16 23:54:33 +00:00
file_transfers_information_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ Messenger Service - FtReceiveFolder " )
2012-01-11 00:45:24 +00:00
last_user_information_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ MessengerService \\ ListCache \\ .NET Messenger Service - IdentityName " )
print_all ( contact_list_information_key )
print_all ( file_transers_information_key )
print_all ( last_user_information_key )
end
end
def get_icq_information
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name =~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
general_information_key = @hive . relative_query ( " \\ Software \\ Mirabalis \\ ICQ " )
print_all ( general_information_key )
2012-01-16 23:54:33 +00:00
elsif @hive . hive_regf . hive_name =~ / SOFTWARE /
owner_number_key = @hive . relative_query ( " \\ Software \\ Mirabalis \\ ICQ \\ Owner " )
print_all ( owner_number_key )
2012-01-11 00:45:24 +00:00
end
end
def get_ie_information
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name =~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
stored_logon_information_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ Protected Storage System Provider \\ SID \\ Internet Explorer \\ Internet Explorer - URL:StringData " )
stored_search_terms_information_key = @hive . relative_quety ( " \\ Software \\ Microsoft \\ Protected Storage SystemProvider \\ SID \\ Internet Explorer \\ Internet Explorer - q:SearchIndex " )
ie_setting_information_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ Internet Explorer \\ Main " )
history_length_value_key = @hive . value_query ( " \\ Software \\ Microsoft \\ Windows \\ CurrentVersion \\ Internet Settings \\ URL History - DaysToKeep " )
typed_urls_information_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ Internet Explorer \\ Typed URLs " )
intelliforms_information_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ Internet Explorer \\ Intelliforms " )
autocomplete_web_addresses_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ Protected Storage System Provider " )
default_download_dir = @hive . relative_query ( " \\ Software \\ Microsoft \\ Internet Explorer " )
print_all ( stored_logon_information_key )
print_all ( stored_search_terms_information_key )
print_all ( ie_settings_information_key )
print_all ( type_urls_information_key )
print_all ( intelliforms_information_key )
print_all ( autocomplete_web_addresses_key )
print_all ( default_download_dir )
puts " Days saved in history: " + history_length_value_key . value . data . to_s
end
end
def get_outlook_information
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name =~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
account_information_key = @hive . relative_query ( " \\ Software \\ Microsoft \\ Protected Storage System Provider \\ SID \\ Identification \\ INETCOMM Server Passwords " )
print_all ( account_information_key )
end
end
def get_yahoo_messenger_information
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name =~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
profiles_key = @hive . relative_query ( " \\ Software \\ Yahoo \\ Pager \\ profiles " )
print_all ( profiles_key )
profiles_key . lf_record . children . each do | child |
file_transfers_information_key = @hive . relative_query ( " \\ Software \\ Yahoo \\ Pager \\ profiles \\ #{ child . name } \\ FileTransfer " )
message_archiving_information_key = @hive . relative_query ( " \\ Software \\ Yahoo \\ Pager \\ profiles \\ #{ child . name } \\ Archive " )
print_all ( file_transfer_information_key )
print_all ( message_archiving_information_key )
end
end
end
def get_networking_information
end
def get_user_application_information
end
if ARGV . length == 0 || ARGV [ 0 ] == " help "
no_args = %Q{
Usage : reg . rb < command > < opts > < hivepath >
Available commands :
query_key Query for more information about a specific node key
query_value Query for the value of a specific value key
get_boot_key Extract the boot key from the SYSTEM hive
dump_creds Dump the usernames and password hashes of the users from the SAM hive
list_applications List all the applications installed via the SOFTWARE hive
list_drivers List all the devices and their respective drivers and driver versions from SYSTEM hive
get_everything When pointed to a directory with hives , it will run all commands on all available hives
get_aol_instant_messenger_information Get credentials and general information on AOL Instant Messenger users from NTUSER . dat
get_msn_messenger_information Get credentials and general information on MSN Messenger users from NTUSER . dat
get_windows_messenger_information Get credentials and general information on Windows Messenger users from NTUSER . dat
get_icq_information Get credentials and general information on ICQ users from NTUSER . dat
get_ie_information Get stored credentials , typed history , search terms , and general settings from NTUSER . dat
get_outlook_information Gets outlook and outlook express stored credentials and general information from NTUSER . dat
get_yahoo_messenger_information Gets credentials and general information on Yahoo ! Messenger users from NTUSER . dat
get_system_information Gets general system administration from both SOFTWARE and SYSTEM hives
get_networking_information Gets networing information from the SAM , SYSTEM , and NTUSER . dat hives
get_user_information Gets general user information from the SYSTEM , SECURITY , SAM , and NTUSER . dat hives
get_user_application_information Gets user - specific application information from the NTUSER . DAT and SOFTWARE hives
}
puts no_args
elsif ARGV [ 0 ] == " query_key "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
puts " Hive name: #{ @hive . hive_regf . hive_name } "
1 . upto ( ARGV . length - 2 ) do | arg |
selected = @hive . relative_query ( ARGV [ arg ] )
print_all ( selected )
end
elsif ARGV [ 0 ] == " query_value "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
puts " Hive name: #{ @hive . hive_regf . hive_name } "
1 . upto ( ARGV . length - 2 ) do | i |
selected = @hive . value_query ( ARGV [ i ] )
if ! selected
puts " Value not found. "
return
end
puts " Value Name: #{ selected . name } "
puts " Value Data: #{ selected . value . data . inspect } "
end
elsif ARGV [ 0 ] == " get_boot_key "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
if @hive . hive_regf . hive_name !~ / SYSTEM /
puts " I need a SYSTEM hive to grab the boot key, not a #{ @hive . hive_regf . hive_name } . "
else
get_boot_key
end
elsif ARGV [ 0 ] == " dump_creds "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
if @hive . hive_regf . hive_name !~ / SAM /
puts " I need a SAM hive, not a #{ @hive . hive_regf . hive_name } "
else
dump_creds
end
elsif ARGV [ 0 ] == " list_applications "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
if @hive . hive_regf . hive_name !~ / SOFTWARE /
puts " I need a SOFTWARE hive, not a #{ @hive . hive_regf . hive_name } . "
else
list_applications
end
elsif ARGV [ 0 ] == " list_drivers "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
if @hive . hive_regf . hive_name !~ / SYSTEM /
puts " I need a SYSTEM hive, not a #{ @hive . hive_regf . hive_name } . "
else
list_drivers
end
elsif ARGV [ 0 ] == " get_everything "
Dir . foreach ( ARGV [ 1 ] ) do | file |
2012-01-16 23:54:33 +00:00
next if file =~ / ^ \ . /
2012-01-11 00:45:24 +00:00
@hive = Rex :: Registry :: Hive . new ( ARGV [ 1 ] + " / " + file )
2012-01-16 23:54:33 +00:00
next if ! @hive . hive_regf
next if ! @hive . hive_regf . hive_name
2012-01-11 00:45:24 +00:00
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name =~ / SYSTEM /
puts " Found a SYSTEM hive... "
2012-01-11 00:45:24 +00:00
list_drivers
get_boot_key
get_system_information
get_networking_information
get_user_information
2012-01-16 23:54:33 +00:00
elsif @hive . hive_regf . hive_name =~ / SOFTWARE /
puts " Found a SOFTWARE hive... "
2012-01-11 00:45:24 +00:00
list_applications
get_icq_information
get_system_information
get_networking_information
get_user_information
get_user_application_information
2012-01-16 23:54:33 +00:00
elsif @hive . hive_regf . hive_name =~ / SAM /
puts " Found a SAM hive... "
2012-01-11 00:45:24 +00:00
get_networking_information
get_user_information
2012-01-16 23:54:33 +00:00
elsif @hive . hive_regf . hive_name =~ / SECURITY /
puts " Found a SECURITY hive... "
2012-01-11 00:45:24 +00:00
get_user_information
2012-01-16 23:54:33 +00:00
elsif @hive . hive_regf . hive_name =~ / NTUSER \ .dat /i
puts " Found a NTUSER.dat hive... "
2012-01-11 00:45:24 +00:00
get_aol_instant_messenger_information
get_icq_information
get_ie_information
get_msn_messenger_information
get_outlook_information
get_windows_messenger_information
get_yahoo_messenger_information
get_networking_information
get_user_information
get_user_application_information
end
end
elsif ARGV [ 0 ] == " get_aol_instant_messenger_information "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name !~ / NTUSER \ .DAT /i
2012-01-11 00:45:24 +00:00
puts " I need the NTUSER.dat hive, not #{ @hive . hive_regf . hive_name } . "
else
get_aol_instant_messenger_information
end
elsif ARGV [ 0 ] == " get_icq_information "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name !~ / NTUSER \ .dat /i && @hive . hive_regf . hive_name !~ / SOFTWARE /
2012-01-11 00:45:24 +00:00
puts " I need either a SOFTWARE or NTUSER.dat hive, not #{ @hive . hive_regf . hive_name } . "
else
get_icq_information
end
elsif ARGV [ 0 ] == " get_ie_information "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name !~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
puts " I need an NTUSER.dat hive, not #{ @hive . hive_regf . hive_name } . "
else
get_ie_information
end
elsif ARGV [ 0 ] == " get_msn_messenger_information "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name !~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
puts " I need an NTUSER.dat hive, not #{ @hive . hive_regf . hive_name } . "
else
get_msn_messenger_information
end
elsif ARGV [ 0 ] == " get_outlook_information "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name !~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
puts " I need an NTUSER.dat hive, not #{ @hive . hive_regf . hive_name } . "
else
get_outlook_information
end
elsif ARGV [ 0 ] == " get_windows_messenger_information "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name !~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
puts " I need an NTUSER.dat hive, not a #{ @hive . hive_regf . hive_name } . "
else
get_windows_messenger_information
end
elsif ARGV [ 0 ] == " get_yahoo_messenger_information "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name !~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
puts " I need an NTUSER.dat hive, not a #{ @hive . hive_regf . hive_name } . "
else
get_yahoo_messenger_information
end
elsif ARGV [ 0 ] == " get_system_information "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
if @hive . hive_regf . hive_name !~ / SYSTEM / && @hive . hive_regf . hive_name !~ / SOFTWARE /
puts " I need the SYSTEM or SOFTWARE hive, not #{ @hive . hive_regf . hive_name } . "
else
get_system_information
end
elsif ARGV [ 0 ] == " get_networking_information "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name !~ / SAM / && @hive . hive_regf . hive_name !~ / SYSTEM / && @hive . hive_regf . hive_name !~ / NTUSER \ .dat /i
2012-01-11 00:45:24 +00:00
puts " I need either a SAM, SYSTEM, or NTUSER.dat hive, not a #{ @hive . hive_regf . hive_name } . "
else
get_networking_information
end
elsif ARGV [ 0 ] == " get_user_information "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
if @hive . hive_regf . hive_name !~ / SAM /
puts " I need a SAM hive. Not a #{ @hive . hive_regf . hive_name } . "
else
get_user_information
2012-01-16 23:54:33 +00:00
2012-01-11 00:45:24 +00:00
end
elsif ARGV [ 0 ] == " get_user_application_information "
@hive = Rex :: Registry :: Hive . new ( ARGV [ ARGV . length - 1 ] )
2012-01-16 23:54:33 +00:00
if @hive . hive_regf . hive_name !~ / NTUSER \ .dat /i && @hive . hive_regf . hive_name !~ / SOFTWARE /
2012-01-11 00:45:24 +00:00
puts " I need either an NTUSER.dat or SOFTWARE hive, not a #{ @hive . hive_regf . hive_name } . "
else
get_user_application_information
end
end