Class: Rex::Proto::RFB::Cipher
- Inherits:
-
Object
- Object
- Rex::Proto::RFB::Cipher
- Defined in:
- lib/rex/proto/rfb/cipher.rb
Overview
A bit of information about the DES algorithm was found here: www.vidarholen.net/contents/junk/vnc.html
In addition, VNC uses two individual 8 byte block encryptions rather than using any block mode (like cbc, ecb, etc).
Class Method Summary collapse
-
.decrypt(cipher, password = "\x17\x52\x6b\x06\x23\x4e\x58\x07") ⇒ Object
NOTE: The default password is that of winvnc/etc which is used for encrypting the password(s) on disk/in registry.
- .encrypt(plain, password) ⇒ Object
- .encrypt_ard(username, password, generator, key_length, prime_modulus, peer_public_key) ⇒ Object
- .mangle_password(password) ⇒ Object
Class Method Details
.decrypt(cipher, password = "\x17\x52\x6b\x06\x23\x4e\x58\x07") ⇒ Object
NOTE: The default password is that of winvnc/etc which is used for encrypting the password(s) on disk/in registry.
64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/rex/proto/rfb/cipher.rb', line 64 def self.decrypt(cipher, password = "\x17\x52\x6b\x06\x23\x4e\x58\x07") key = self.mangle_password(password) # pad the cipher text to 9 bytes cipher << ("\x00" * (9 - cipher.length)) if cipher.length < 9 # NOTE: This only does one 8 byte block plain = '' c = OpenSSL::Cipher.new('des') c.decrypt c.key = key c.update(cipher) end |
.encrypt(plain, password) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/rex/proto/rfb/cipher.rb', line 42 def self.encrypt(plain, password) key = self.mangle_password(password) # pad the plain to 16 chars plain << ("\x00" * (16 - plain.length)) if plain.length < 16 # VNC auth does two 8-byte blocks individually instead supporting some block mode cipher = '' 2.times { |x| c = OpenSSL::Cipher.new('des') c.encrypt c.key = key cipher << c.update(plain[x*8, 8]) } cipher end |
.encrypt_ard(username, password, generator, key_length, prime_modulus, peer_public_key) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/rex/proto/rfb/cipher.rb', line 79 def self.encrypt_ard(username, password, generator, key_length, prime_modulus, peer_public_key) generator = OpenSSL::BN.new(generator, 2) prime_modulus = OpenSSL::BN.new(prime_modulus, 2) peer_public_key = OpenSSL::BN.new(peer_public_key, 2) user_struct = username + ("\0" * (64 - username.length)) + password + ("\0" * (64 - password.length)) dh_peer = OpenSSL::PKey::DH.new(key_length * 8, generator) dh_peer.set_key(peer_public_key, nil) dh = OpenSSL::PKey::DH.new(dh_peer) dh.set_pqg(prime_modulus, nil, generator) dh.generate_key! shared_key = dh.compute_key(dh_peer.pub_key) md5 = OpenSSL::Digest::MD5.new key_digest = md5.digest(shared_key) cipher = OpenSSL::Cipher.new("aes-128-ecb") cipher.encrypt cipher.key = key_digest cipher.padding = 0 ciphertext = cipher.update(user_struct) + cipher.final response = ciphertext + dh.pub_key.to_s(2) return response end |
.mangle_password(password) ⇒ Object
32 33 34 35 36 37 38 39 40 |
# File 'lib/rex/proto/rfb/cipher.rb', line 32 def self.mangle_password(password) key = '' key = password.dup if password key.slice!(8,key.length) if key.length > 8 key << "\x00" * (8 - key.length) if key.length < 8 # We have to mangle the key so the LSB are kept vs the MSB [key.unpack('B*').first.scan(/.{8}/).map! { |e| e.reverse }.join].pack('B*') end |