watobo 0.9.8.677
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/watobo_gui.rb +39 -0
- data/certificates/cert.pem +19 -0
- data/certificates/privkey.pem +15 -0
- data/certificates/watobo_dh.key +5 -0
- data/config/datastore.yml +5 -0
- data/config/forwarding_proxy.yml +12 -0
- data/config/general.yml +4 -0
- data/config/gui.yml +23 -0
- data/config/interceptor.yml +16 -0
- data/config/scan_policy.yml +13 -0
- data/config/scanner.yml +34 -0
- data/icons/Add.ico +0 -0
- data/icons/Add_24x24.ico +0 -0
- data/icons/Bandwidth.ico +0 -0
- data/icons/Bandwidth_24x24.ico +0 -0
- data/icons/Mr. Bomb.ico +0 -0
- data/icons/Mr. Bomb_16x16.ico +0 -0
- data/icons/Mr. Bomb_24x24.ico +0 -0
- data/icons/Orange Ball.ico +0 -0
- data/icons/Orange Ball_16x16.ico +0 -0
- data/icons/Orange Ball_24x24.ico +0 -0
- data/icons/Pause.ico +0 -0
- data/icons/Play.ico +0 -0
- data/icons/Play_24x24.ico +0 -0
- data/icons/Red Ball.ico +0 -0
- data/icons/Red Ball_16x16.ico +0 -0
- data/icons/Red Ball_24x24.ico +0 -0
- data/icons/Run.ico +0 -0
- data/icons/Stop.ico +0 -0
- data/icons/Stop_24x24.ico +0 -0
- data/icons/Terminal.ico +0 -0
- data/icons/Transfer.ico +0 -0
- data/icons/Transfer_16x16.ico +0 -0
- data/icons/User.ico +0 -0
- data/icons/User_16x16.ico +0 -0
- data/icons/User_24x24.ico +0 -0
- data/icons/Web Browser.ico +0 -0
- data/icons/Web Browser_16x16.ico +0 -0
- data/icons/Write Document.ico +0 -0
- data/icons/Yellow Ball.ico +0 -0
- data/icons/Yellow Ball_16x16.ico +0 -0
- data/icons/Yellow Ball_24x24.ico +0 -0
- data/icons/advanced.ico +0 -0
- data/icons/advanced_16x16.ico +0 -0
- data/icons/advanced_24x24.ico +0 -0
- data/icons/applications.ico +0 -0
- data/icons/applications_16x16.ico +0 -0
- data/icons/applications_24x24.ico +0 -0
- data/icons/browser_16x16.ico +0 -0
- data/icons/browser_24x24.ico +0 -0
- data/icons/burn.ico +0 -0
- data/icons/burn_16x16.ico +0 -0
- data/icons/burn_24x24.ico +0 -0
- data/icons/calculator.ico +0 -0
- data/icons/calculator_24x24.ico +0 -0
- data/icons/cb_checked.ico +0 -0
- data/icons/cb_checked_orange.ico +0 -0
- data/icons/cb_unchecked.ico +0 -0
- data/icons/coin_24x24.ico +0 -0
- data/icons/conversation.ico +0 -0
- data/icons/conversation_24x24.ico +0 -0
- data/icons/engine.ico +0 -0
- data/icons/filter.ico +0 -0
- data/icons/folder.ico +0 -0
- data/icons/folder_16x16.ico +0 -0
- data/icons/fuzzer_16x16.ico +0 -0
- data/icons/fuzzer_24x24.ico +0 -0
- data/icons/go-down_16x16.png +0 -0
- data/icons/go-up_16x16.png +0 -0
- data/icons/help.ico +0 -0
- data/icons/help_16x16.ico +0 -0
- data/icons/help_24x24.ico +0 -0
- data/icons/iChat.ico +0 -0
- data/icons/iChat_16x16.ico +0 -0
- data/icons/iChat_24x24.ico +0 -0
- data/icons/icons.txt +3 -0
- data/icons/info.ico +0 -0
- data/icons/info_16x16.ico +0 -0
- data/icons/info_24x24.ico +0 -0
- data/icons/interceptor_24x24.ico +0 -0
- data/icons/lock.ico +0 -0
- data/icons/lock_12x12.ico +0 -0
- data/icons/lock_16x16.ico +0 -0
- data/icons/monitor.ico +0 -0
- data/icons/plugin.ico +0 -0
- data/icons/plugin_24x24.ico +0 -0
- data/icons/scan_16x16.png +0 -0
- data/icons/send.ico +0 -0
- data/icons/server.ico +0 -0
- data/icons/server_16x16.ico +0 -0
- data/icons/siberas_logo_x24.gif +0 -0
- data/icons/tag_blue_32x32.ico +0 -0
- data/icons/watobo-48x48.png +0 -0
- data/icons/watobo-logo.png +0 -0
- data/icons/watobo.ico +0 -0
- data/lib/watobo/adapters/data_store.rb +38 -0
- data/lib/watobo/adapters/file/file_store.rb +211 -0
- data/lib/watobo/adapters/session_store.rb +27 -0
- data/lib/watobo/adapters.rb +26 -0
- data/lib/watobo/config.rb +143 -0
- data/lib/watobo/constants.rb +92 -0
- data/lib/watobo/core/active_check.rb +404 -0
- data/lib/watobo/core/cookie.rb +69 -0
- data/lib/watobo/core/fuzz_gen.rb +160 -0
- data/lib/watobo/core/http_socket.rb +142 -0
- data/lib/watobo/core/interceptor.rb +729 -0
- data/lib/watobo/core/passive_check.rb +141 -0
- data/lib/watobo/core/project.rb +1058 -0
- data/lib/watobo/core/scanner.rb +396 -0
- data/lib/watobo/core/session.rb +1320 -0
- data/lib/watobo/core/simple_ca.rb +393 -0
- data/lib/watobo/core.rb +34 -0
- data/lib/watobo/defaults.rb +40 -0
- data/lib/watobo/external/diff/lcs/array.rb +42 -0
- data/lib/watobo/external/diff/lcs/block.rb +72 -0
- data/lib/watobo/external/diff/lcs/callbacks.rb +343 -0
- data/lib/watobo/external/diff/lcs/change.rb +190 -0
- data/lib/watobo/external/diff/lcs/hunk.rb +279 -0
- data/lib/watobo/external/diff/lcs/ldiff.rb +247 -0
- data/lib/watobo/external/diff/lcs/string.rb +40 -0
- data/lib/watobo/external/diff/lcs.rb +1124 -0
- data/lib/watobo/external/ntlm/ntlm.rb +797 -0
- data/lib/watobo/externals.rb +28 -0
- data/lib/watobo/framework/create_project.rb +55 -0
- data/lib/watobo/framework/init.rb +149 -0
- data/lib/watobo/framework/init_modules.rb +116 -0
- data/lib/watobo/framework/license_text.rb +50 -0
- data/lib/watobo/framework.rb +26 -0
- data/lib/watobo/gui/about_watobo.rb +68 -0
- data/lib/watobo/gui/browser_preview.rb +460 -0
- data/lib/watobo/gui/certificate_dialog.rb +132 -0
- data/lib/watobo/gui/chat_diff.rb +415 -0
- data/lib/watobo/gui/chatviewer_frame.rb +427 -0
- data/lib/watobo/gui/checkboxtree.rb +221 -0
- data/lib/watobo/gui/checks_policy_frame.rb +123 -0
- data/lib/watobo/gui/client_cert_dialog.rb +227 -0
- data/lib/watobo/gui/confirm_scan_dialog.rb +67 -0
- data/lib/watobo/gui/conversation_table.rb +386 -0
- data/lib/watobo/gui/conversation_table_ctrl.rb +175 -0
- data/lib/watobo/gui/csrf_token_dialog.rb +446 -0
- data/lib/watobo/gui/dashboard.rb +341 -0
- data/lib/watobo/gui/define_scope_frame.rb +380 -0
- data/lib/watobo/gui/edit_comment.rb +70 -0
- data/lib/watobo/gui/edit_scope_dialog.rb +69 -0
- data/lib/watobo/gui/finding_info.rb +212 -0
- data/lib/watobo/gui/findings_tree.rb +459 -0
- data/lib/watobo/gui/full_scan_dialog.rb +269 -0
- data/lib/watobo/gui/fuzzer_gui.rb +1522 -0
- data/lib/watobo/gui/hex_viewer.rb +106 -0
- data/lib/watobo/gui/interceptor_gui.rb +994 -0
- data/lib/watobo/gui/interceptor_settings_dialog.rb +201 -0
- data/lib/watobo/gui/log_viewer.rb +97 -0
- data/lib/watobo/gui/login_wizzard.rb +301 -0
- data/lib/watobo/gui/main_window.rb +1815 -0
- data/lib/watobo/gui/manual_request_editor.rb +1105 -0
- data/lib/watobo/gui/master_pw_dialog.rb +142 -0
- data/lib/watobo/gui/password_policy_dialog.rb +98 -0
- data/lib/watobo/gui/plugin/base.rb +82 -0
- data/lib/watobo/gui/plugin_board.rb +95 -0
- data/lib/watobo/gui/preferences_dialog.rb +116 -0
- data/lib/watobo/gui/progress_window.rb +102 -0
- data/lib/watobo/gui/project_wizzard.rb +369 -0
- data/lib/watobo/gui/proxy_dialog.rb +550 -0
- data/lib/watobo/gui/quick_scan_dialog.rb +242 -0
- data/lib/watobo/gui/request_editor.rb +480 -0
- data/lib/watobo/gui/save_chat_dialog.rb +158 -0
- data/lib/watobo/gui/scanner_settings_dialog.rb +360 -0
- data/lib/watobo/gui/select_chat_dialog.rb +169 -0
- data/lib/watobo/gui/session_management_dialog.rb +688 -0
- data/lib/watobo/gui/sites_tree.rb +347 -0
- data/lib/watobo/gui/status_bar.rb +88 -0
- data/lib/watobo/gui/table_editor.rb +445 -0
- data/lib/watobo/gui/tagless_viewer.rb +62 -0
- data/lib/watobo/gui/templates/plugin.rb +80 -0
- data/lib/watobo/gui/templates/plugin2.rb +103 -0
- data/lib/watobo/gui/text_viewer.rb +247 -0
- data/lib/watobo/gui/transcoder_window.rb +215 -0
- data/lib/watobo/gui/utils/gui_utils.rb +129 -0
- data/lib/watobo/gui/utils/init_icons.rb +106 -0
- data/lib/watobo/gui/utils/load_icons.rb +54 -0
- data/lib/watobo/gui/utils/load_plugins.rb +94 -0
- data/lib/watobo/gui/utils/master_password.rb +90 -0
- data/lib/watobo/gui/utils/save_default_settings.rb +99 -0
- data/lib/watobo/gui/utils/save_project_settings.rb +21 -0
- data/lib/watobo/gui/utils/save_proxy_settings.rb +45 -0
- data/lib/watobo/gui/utils/save_session_settings.rb +21 -0
- data/lib/watobo/gui/utils/session_history.rb +134 -0
- data/lib/watobo/gui/workspace_dialog.rb +89 -0
- data/lib/watobo/gui/www_auth_dialog.rb +348 -0
- data/lib/watobo/gui/xml_viewer_frame.rb +114 -0
- data/lib/watobo/gui.rb +139 -0
- data/lib/watobo/mixins/httpparser.rb +664 -0
- data/lib/watobo/mixins/request_parser.rb +210 -0
- data/lib/watobo/mixins/shapers.rb +345 -0
- data/lib/watobo/mixins/transcoders.rb +88 -0
- data/lib/watobo/mixins.rb +32 -0
- data/lib/watobo/utils/check_regex.rb +36 -0
- data/lib/watobo/utils/copy_object.rb +29 -0
- data/lib/watobo/utils/crypto.rb +74 -0
- data/lib/watobo/utils/expand_range.rb +45 -0
- data/lib/watobo/utils/file_management.rb +73 -0
- data/lib/watobo/utils/load_chat.rb +219 -0
- data/lib/watobo/utils/load_icon.rb +47 -0
- data/lib/watobo/utils/print_debug.rb +34 -0
- data/lib/watobo/utils/response_hash.rb +143 -0
- data/lib/watobo/utils/secure_eval.rb +57 -0
- data/lib/watobo/utils/text2request.rb +96 -0
- data/lib/watobo/utils.rb +32 -0
- data/lib/watobo.rb +76 -0
- data/modules/active/Apache/mod_status.rb +123 -0
- data/modules/active/Flash/crossdomain.rb +102 -0
- data/modules/active/directories/dirwalker.rb +89 -0
- data/modules/active/discovery/fileextensions.rb +151 -0
- data/modules/active/discovery/http_methods.rb +135 -0
- data/modules/active/domino/domino_db.lst +164 -0
- data/modules/active/domino/domino_db.rb +128 -0
- data/modules/active/fileinclusion/lfi_simple.rb +134 -0
- data/modules/active/jboss/jboss_basic.rb +119 -0
- data/modules/active/sap/business_objects.rb +73 -0
- data/modules/active/sap/its_commands.rb +101 -0
- data/modules/active/sap/its_service_parameter.rb +105 -0
- data/modules/active/sap/its_services.rb +103 -0
- data/modules/active/sap/its_xss.rb +98 -0
- data/modules/active/sqlinjection/sql_boolean.rb +262 -0
- data/modules/active/sqlinjection/sqli_simple.rb +205 -0
- data/modules/active/xss/xss_simple.rb +179 -0
- data/modules/passive/cookie_options.rb +97 -0
- data/modules/passive/cookie_xss.rb +85 -0
- data/modules/passive/detect_code.rb +89 -0
- data/modules/passive/detect_fileupload.rb +80 -0
- data/modules/passive/detect_infrastructure.rb +98 -0
- data/modules/passive/detect_one_time_tokens.rb +86 -0
- data/modules/passive/dirindexing.rb +81 -0
- data/modules/passive/disclosure_emails.rb +82 -0
- data/modules/passive/disclosure_ipaddr.rb +87 -0
- data/modules/passive/filename_as_parameter.rb +85 -0
- data/modules/passive/form_spotter.rb +75 -0
- data/modules/passive/hotspots.rb +86 -0
- data/modules/passive/in_script_parameter.rb +92 -0
- data/modules/passive/multiple_server_headers.rb +98 -0
- data/modules/passive/possible_login.rb +134 -0
- data/modules/passive/redirect_url.rb +88 -0
- data/modules/passive/redirectionz.rb +96 -0
- data/modules/passive/xss_dom.rb +91 -0
- data/plugins/catalog/catalog.ico +0 -0
- data/plugins/catalog/catalog.rb +726 -0
- data/plugins/catalog/db_tests +6483 -0
- data/plugins/catalog/db_variables +29 -0
- data/plugins/filefinder/dbs/hbci.db +12 -0
- data/plugins/filefinder/filefinder.rb +602 -0
- data/plugins/sslchecker/cli/sslchecker_cli.rb +21 -0
- data/plugins/sslchecker/gui/cipher_table.rb +260 -0
- data/plugins/sslchecker/gui/gui.rb +245 -0
- data/plugins/sslchecker/gui/sslchecker.rb +26 -0
- data/plugins/sslchecker/icons/green_16x16.ico +0 -0
- data/plugins/sslchecker/icons/grey_16x16.ico +0 -0
- data/plugins/sslchecker/icons/red_16x16.ico +0 -0
- data/plugins/sslchecker/icons/sslchecker.ico +0 -0
- data/plugins/sslchecker/lib/check.rb +117 -0
- metadata +317 -0
|
@@ -0,0 +1,797 @@
|
|
|
1
|
+
# .
|
|
2
|
+
# ntlm.rb
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2012 by siberas, http://www.siberas.de
|
|
5
|
+
#
|
|
6
|
+
# This file is part of WATOBO (Web Application Tool Box)
|
|
7
|
+
# http://watobo.sourceforge.com
|
|
8
|
+
#
|
|
9
|
+
# WATOBO is free software; you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation version 2 of the License.
|
|
12
|
+
#
|
|
13
|
+
# WATOBO is distributed in the hope that it will be useful,
|
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
# GNU General Public License for more details.
|
|
17
|
+
#
|
|
18
|
+
# You should have received a copy of the GNU General Public License
|
|
19
|
+
# along with WATOBO; if not, write to the Free Software
|
|
20
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
21
|
+
# .
|
|
22
|
+
#
|
|
23
|
+
# = net/ntlm.rb
|
|
24
|
+
#
|
|
25
|
+
# An NTLM Authentication Library for Ruby
|
|
26
|
+
#
|
|
27
|
+
# This code is a derivative of "dbf2.rb" written by yrock
|
|
28
|
+
# and Minero Aoki. You can find original code here:
|
|
29
|
+
# http://jp.rubyist.net/magazine/?0013-CodeReview
|
|
30
|
+
# -------------------------------------------------------------
|
|
31
|
+
# Copyright (c) 2005,2006 yrock
|
|
32
|
+
#
|
|
33
|
+
# This program is free software.
|
|
34
|
+
# You can distribute/modify this program under the terms of the
|
|
35
|
+
# Ruby License.
|
|
36
|
+
#
|
|
37
|
+
# 2006-02-11 refactored by Minero Aoki
|
|
38
|
+
# -------------------------------------------------------------
|
|
39
|
+
#
|
|
40
|
+
# All protocol information used to write this code stems from
|
|
41
|
+
# "The NTLM Authentication Protocol" by Eric Glass. The author
|
|
42
|
+
# would thank to him for this tremendous work and making it
|
|
43
|
+
# available on the net.
|
|
44
|
+
# http://davenport.sourceforge.net/ntlm.html
|
|
45
|
+
# -------------------------------------------------------------
|
|
46
|
+
# Copyright (c) 2003 Eric Glass
|
|
47
|
+
#
|
|
48
|
+
# Permission to use, copy, modify, and distribute this document
|
|
49
|
+
# for any purpose and without any fee is hereby granted,
|
|
50
|
+
# provided that the above copyright notice and this list of
|
|
51
|
+
# conditions appear in all copies.
|
|
52
|
+
# -------------------------------------------------------------
|
|
53
|
+
#
|
|
54
|
+
# The author also looked Mozilla-Firefox-1.0.7 source code,
|
|
55
|
+
# namely, security/manager/ssl/src/nsNTLMAuthModule.cpp and
|
|
56
|
+
# Jonathan Bastien-Filiatrault's libntlm-ruby.
|
|
57
|
+
# "http://x2a.org/websvn/filedetails.php?
|
|
58
|
+
# repname=libntlm-ruby&path=%2Ftrunk%2Fntlm.rb&sc=1"
|
|
59
|
+
# The latter has a minor bug in its separate_keys function.
|
|
60
|
+
# The third key has to begin from the 14th character of the
|
|
61
|
+
# input string instead of 13th:)
|
|
62
|
+
#--
|
|
63
|
+
# $Id: ntlm.rb,v 1.1 2006/10/05 01:36:52 koheik Exp $
|
|
64
|
+
#++
|
|
65
|
+
|
|
66
|
+
require 'base64'
|
|
67
|
+
require 'openssl'
|
|
68
|
+
require 'openssl/digest'
|
|
69
|
+
|
|
70
|
+
require 'kconv'
|
|
71
|
+
|
|
72
|
+
module Net #:nodoc:
|
|
73
|
+
module NTLM
|
|
74
|
+
|
|
75
|
+
module VERSION #:nodoc:
|
|
76
|
+
MAJOR = 0
|
|
77
|
+
MINOR = 1
|
|
78
|
+
TINY = 1
|
|
79
|
+
STRING = [MAJOR, MINOR, TINY].join('.')
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
SSP_SIGN = "NTLMSSP\0"
|
|
83
|
+
BLOB_SIGN = 0x00000101
|
|
84
|
+
LM_MAGIC = "KGS!@\#$%"
|
|
85
|
+
TIME_OFFSET = 11644473600
|
|
86
|
+
MAX64 = 0xffffffffffffffff
|
|
87
|
+
|
|
88
|
+
FLAGS = {
|
|
89
|
+
:UNICODE => 0x00000001,
|
|
90
|
+
:OEM => 0x00000002,
|
|
91
|
+
:REQUEST_TARGET => 0x00000004,
|
|
92
|
+
# :UNKNOWN => 0x00000008,
|
|
93
|
+
:SIGN => 0x00000010,
|
|
94
|
+
:SEAL => 0x00000020,
|
|
95
|
+
# :UNKNOWN => 0x00000040,
|
|
96
|
+
:NETWARE => 0x00000100,
|
|
97
|
+
:NTLM => 0x00000200,
|
|
98
|
+
# :UNKNOWN => 0x00000400,
|
|
99
|
+
# :UNKNOWN => 0x00000800,
|
|
100
|
+
:DOMAIN_SUPPLIED => 0x00001000,
|
|
101
|
+
:WORKSTATION_SUPPLIED => 0x00002000,
|
|
102
|
+
:LOCAL_CALL => 0x00004000,
|
|
103
|
+
:ALWAYS_SIGN => 0x00008000,
|
|
104
|
+
:TARGET_TYPE_DOMAIN => 0x00010000,
|
|
105
|
+
:TARGET_INFO => 0x00800000,
|
|
106
|
+
:NTLM2_KEY => 0x00080000,
|
|
107
|
+
:KEY128 => 0x20000000,
|
|
108
|
+
:KEY56 => 0x80000000
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
FLAG_KEYS = FLAGS.keys.sort{|a, b| FLAGS[a] <=> FLAGS[b] }
|
|
112
|
+
|
|
113
|
+
DEFAULT_FLAGS = {
|
|
114
|
+
:TYPE1 => FLAGS[:UNICODE] | FLAGS[:OEM] | FLAGS[:REQUEST_TARGET] | FLAGS[:NTLM] | FLAGS[:ALWAYS_SIGN] | FLAGS[:NTLM2_KEY],
|
|
115
|
+
:TYPE2 => FLAGS[:UNICODE],
|
|
116
|
+
:TYPE3 => FLAGS[:UNICODE] | FLAGS[:REQUEST_TARGET] | FLAGS[:NTLM] | FLAGS[:ALWAYS_SIGN] | FLAGS[:NTLM2_KEY]
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# module functions
|
|
120
|
+
class << self
|
|
121
|
+
def decode_utf16le(str)
|
|
122
|
+
Kconv.kconv(swap16(str), Kconv::ASCII, Kconv::UTF16)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def encode_utf16le(str)
|
|
126
|
+
swap16(Kconv.kconv(str, Kconv::UTF16, Kconv::ASCII))
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def pack_int64le(val)
|
|
130
|
+
[val & 0x00000000ffffffff, val >> 32].pack("V2")
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def swap16(str)
|
|
134
|
+
str.unpack("v*").pack("n*")
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def split7(str)
|
|
138
|
+
s = str.dup
|
|
139
|
+
until s.empty?
|
|
140
|
+
(ret ||= []).push s.slice!(0, 7)
|
|
141
|
+
end
|
|
142
|
+
ret
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def gen_keys(str)
|
|
146
|
+
split7(str).map{ |str7|
|
|
147
|
+
bits = split7(str7.unpack("B*")[0]).inject('')\
|
|
148
|
+
{|ret, tkn| ret += tkn + (tkn.gsub('1', '').size % 2).to_s }
|
|
149
|
+
[bits].pack("B*")
|
|
150
|
+
}
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def apply_des(plain, keys)
|
|
154
|
+
dec = OpenSSL::Cipher::DES.new
|
|
155
|
+
keys.map {|k|
|
|
156
|
+
dec.key = k
|
|
157
|
+
dec.encrypt.update(plain)
|
|
158
|
+
}
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def lm_hash(password)
|
|
162
|
+
keys = gen_keys password.upcase.ljust(14, "\0")
|
|
163
|
+
apply_des(LM_MAGIC, keys).join
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def ntlm_hash(password, opt = {})
|
|
167
|
+
pwd = password.dup
|
|
168
|
+
unless opt[:unicode]
|
|
169
|
+
pwd = encode_utf16le(pwd)
|
|
170
|
+
end
|
|
171
|
+
OpenSSL::Digest::MD4.digest pwd
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def ntlmv2_hash(user, password, target, opt={})
|
|
175
|
+
ntlmhash = ntlm_hash(password, opt)
|
|
176
|
+
userdomain = (user + target).upcase
|
|
177
|
+
unless opt[:unicode]
|
|
178
|
+
userdomain = encode_utf16le(userdomain)
|
|
179
|
+
end
|
|
180
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, ntlmhash, userdomain)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# responses
|
|
184
|
+
def lm_response(arg)
|
|
185
|
+
begin
|
|
186
|
+
hash = arg[:lm_hash]
|
|
187
|
+
chal = arg[:challenge]
|
|
188
|
+
rescue
|
|
189
|
+
raise ArgumentError
|
|
190
|
+
end
|
|
191
|
+
chal = NTL::pack_int64le(chal) if chal.is_a?(Integer)
|
|
192
|
+
keys = gen_keys hash.ljust(21, "\0")
|
|
193
|
+
apply_des(chal, keys).join
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def ntlm_response(arg)
|
|
197
|
+
hash = arg[:ntlm_hash]
|
|
198
|
+
chal = arg[:challenge]
|
|
199
|
+
chal = NTL::pack_int64le(chal) if chal.is_a?(Integer)
|
|
200
|
+
keys = gen_keys hash.ljust(21, "\0")
|
|
201
|
+
apply_des(chal, keys).join
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def ntlmv2_response(arg, opt = {})
|
|
205
|
+
begin
|
|
206
|
+
key = arg[:ntlmv2_hash]
|
|
207
|
+
chal = arg[:challenge]
|
|
208
|
+
ti = arg[:target_info]
|
|
209
|
+
rescue
|
|
210
|
+
raise ArgumentError
|
|
211
|
+
end
|
|
212
|
+
chal = NTL::pack_int64le(chal) if chal.is_a?(Integer)
|
|
213
|
+
|
|
214
|
+
if opt[:client_challenge]
|
|
215
|
+
cc = opt[:client_challenge]
|
|
216
|
+
else
|
|
217
|
+
cc = rand(MAX64)
|
|
218
|
+
end
|
|
219
|
+
cc = NTLM::pack_int64le(cc) if cc.is_a?(Integer)
|
|
220
|
+
|
|
221
|
+
if opt[:timestamp]
|
|
222
|
+
ts = opt[:timestamp]
|
|
223
|
+
else
|
|
224
|
+
ts = Time.now.to_i
|
|
225
|
+
end
|
|
226
|
+
# epoch -> milsec from Jan 1, 1601
|
|
227
|
+
ts = 10000000 * (ts + TIME_OFFSET)
|
|
228
|
+
|
|
229
|
+
blob = Blob.new
|
|
230
|
+
blob.timestamp = ts
|
|
231
|
+
blob.challenge = cc
|
|
232
|
+
blob.target_info = ti
|
|
233
|
+
|
|
234
|
+
bb = blob.serialize
|
|
235
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, key, chal + bb) + bb
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def lmv2_response(arg, opt = {})
|
|
239
|
+
key = arg[:ntlmv2_hash]
|
|
240
|
+
chal = arg[:challenge]
|
|
241
|
+
|
|
242
|
+
chal = NTLM::pack_int64le(chal) if chal.is_a?(Integer)
|
|
243
|
+
|
|
244
|
+
if opt[:client_challenge]
|
|
245
|
+
cc = opt[:client_challenge]
|
|
246
|
+
else
|
|
247
|
+
cc = rand(MAX64)
|
|
248
|
+
end
|
|
249
|
+
cc = NTLM::pack_int64le(cc) if cc.is_a?(Integer)
|
|
250
|
+
|
|
251
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest::MD5.new, key, chal + cc) + cc
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def ntlm2_session(arg, opt = {})
|
|
255
|
+
begin
|
|
256
|
+
passwd_hash = arg[:ntlm_hash]
|
|
257
|
+
chal = arg[:challenge]
|
|
258
|
+
rescue
|
|
259
|
+
raise ArgumentError
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
if opt[:client_challenge]
|
|
263
|
+
cc = opt[:client_challenge]
|
|
264
|
+
else
|
|
265
|
+
cc = rand(MAX64)
|
|
266
|
+
end
|
|
267
|
+
cc = NTLM::pack_int64le(cc) if cc.is_a?(Integer)
|
|
268
|
+
|
|
269
|
+
keys = gen_keys passwd_hash.ljust(21, "\0")
|
|
270
|
+
session_hash = OpenSSL::Digest::MD5.digest(chal + cc).slice(0, 8)
|
|
271
|
+
response = apply_des(session_hash, keys).join
|
|
272
|
+
[cc.ljust(24, "\0"), response]
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
# base classes for primitives
|
|
278
|
+
class Field
|
|
279
|
+
attr_accessor :active, :value
|
|
280
|
+
|
|
281
|
+
def initialize(opts)
|
|
282
|
+
@value = opts[:value]
|
|
283
|
+
@active = opts[:active].nil? ? true : opts[:active]
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def size
|
|
287
|
+
@active ? @size : 0
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
class String < Field
|
|
292
|
+
def initialize(opts)
|
|
293
|
+
super(opts)
|
|
294
|
+
@size = opts[:size]
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def parse(str, offset=0)
|
|
298
|
+
if @active and str.size >= offset + @size
|
|
299
|
+
@value = str[offset, @size]
|
|
300
|
+
@size
|
|
301
|
+
else
|
|
302
|
+
0
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def serialize
|
|
307
|
+
if @active
|
|
308
|
+
@value
|
|
309
|
+
else
|
|
310
|
+
""
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def value=(val)
|
|
315
|
+
@value = val
|
|
316
|
+
@size = @value.nil? ? 0 : @value.size
|
|
317
|
+
@active = (@size > 0)
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
class Int16LE < Field
|
|
323
|
+
def initialize(opt)
|
|
324
|
+
super(opt)
|
|
325
|
+
@size = 2
|
|
326
|
+
end
|
|
327
|
+
def parse(str, offset=0)
|
|
328
|
+
if @active and str.size >= offset + @size
|
|
329
|
+
@value = str[offset, @size].unpack("v")[0]
|
|
330
|
+
@size
|
|
331
|
+
else
|
|
332
|
+
0
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def serialize
|
|
337
|
+
[@value].pack("v")
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
class Int32LE < Field
|
|
342
|
+
def initialize(opt)
|
|
343
|
+
super(opt)
|
|
344
|
+
@size = 4
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def parse(str, offset=0)
|
|
348
|
+
if @active and str.size >= offset + @size
|
|
349
|
+
@value = str.slice(offset, @size).unpack("V")[0]
|
|
350
|
+
@size
|
|
351
|
+
else
|
|
352
|
+
0
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def serialize
|
|
357
|
+
[@value].pack("V") if @active
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
class Int64LE < Field
|
|
362
|
+
def initialize(opt)
|
|
363
|
+
super(opt)
|
|
364
|
+
@size = 8
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def parse(str, offset=0)
|
|
368
|
+
if @active and str.size >= offset + @size
|
|
369
|
+
d, u = str.slice(offset, @size).unpack("V2")
|
|
370
|
+
@value = (u * 0x100000000 + d)
|
|
371
|
+
@size
|
|
372
|
+
else
|
|
373
|
+
0
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def serialize
|
|
378
|
+
[@value & 0x00000000ffffffff, @value >> 32].pack("V2") if @active
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# base class of data structure
|
|
383
|
+
class FieldSet
|
|
384
|
+
class << FieldSet
|
|
385
|
+
def define(&block)
|
|
386
|
+
c = Class.new(self)
|
|
387
|
+
def c.inherited(subclass)
|
|
388
|
+
proto = @proto
|
|
389
|
+
subclass.instance_eval {
|
|
390
|
+
@proto = proto
|
|
391
|
+
}
|
|
392
|
+
end
|
|
393
|
+
c.module_eval(&block)
|
|
394
|
+
c
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def string(name, opts)
|
|
398
|
+
add_field(name, String, opts)
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def int16LE(name, opts)
|
|
402
|
+
add_field(name, Int16LE, opts)
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
def int32LE(name, opts)
|
|
406
|
+
add_field(name, Int32LE, opts)
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def int64LE(name, opts)
|
|
410
|
+
add_field(name, Int64LE, opts)
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
def security_buffer(name, opts)
|
|
414
|
+
add_field(name, SecurityBuffer, opts)
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
def prototypes
|
|
418
|
+
@proto
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
def names
|
|
422
|
+
@proto.map{|n, t, o| n}
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
def types
|
|
426
|
+
@proto.map{|n, t, o| t}
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
def opts
|
|
430
|
+
@proto.map{|n, t, o| o}
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
private
|
|
434
|
+
|
|
435
|
+
def add_field(name, type, opts)
|
|
436
|
+
(@proto ||= []).push [name, type, opts]
|
|
437
|
+
define_accessor name
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
def define_accessor(name)
|
|
441
|
+
module_eval(<<-End, __FILE__, __LINE__ + 1)
|
|
442
|
+
def #{name}
|
|
443
|
+
self['#{name}'].value
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def #{name}=(val)
|
|
447
|
+
self['#{name}'].value = val
|
|
448
|
+
end
|
|
449
|
+
End
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
def initialize
|
|
454
|
+
@alist = self.class.prototypes.map{ |n, t, o| [n, t.new(o)] }
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
def serialize
|
|
458
|
+
@alist.map{|n, f| f.serialize }.join
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
def parse(str, offset=0)
|
|
462
|
+
@alist.inject(offset){|cur, a| cur += a[1].parse(str, cur)}
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def size
|
|
466
|
+
@alist.inject(0){|sum, a| sum += a[1].size}
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def [](name)
|
|
470
|
+
a = @alist.assoc(name.to_s.intern)
|
|
471
|
+
raise ArgumentError, "no such field: #{name}" unless a
|
|
472
|
+
a[1]
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
def []=(name, val)
|
|
476
|
+
a = @alist.assoc(name.to_s.intern)
|
|
477
|
+
raise ArgumentError, "no such field: #{name}" unless a
|
|
478
|
+
a[1] = val
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
def enable(name)
|
|
482
|
+
self[name].active = true
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
def disable(name)
|
|
486
|
+
self[name].active = false
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
Blob = FieldSet.define {
|
|
492
|
+
int32LE :blob_signature, {:value => BLOB_SIGN}
|
|
493
|
+
int32LE :reserved, {:value => 0}
|
|
494
|
+
int64LE :timestamp, {:value => 0}
|
|
495
|
+
string :challenge, {:value => "", :size => 8}
|
|
496
|
+
int32LE :unknown1, {:value => 0}
|
|
497
|
+
string :target_info, {:value => "", :size => 0}
|
|
498
|
+
int32LE :unknown2, {:value => 0}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
SecurityBuffer = FieldSet.define {
|
|
502
|
+
int16LE :length, {:value => 0}
|
|
503
|
+
int16LE :allocated, {:value => 0}
|
|
504
|
+
int32LE :offset, {:value => 0}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
class SecurityBuffer
|
|
508
|
+
attr_accessor :active
|
|
509
|
+
def initialize(opts)
|
|
510
|
+
super()
|
|
511
|
+
@value = opts[:value]
|
|
512
|
+
@active = opts[:active].nil? ? true : opts[:active]
|
|
513
|
+
@size = 8
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
def parse(str, offset=0)
|
|
517
|
+
if @active and str.size >= offset + @size
|
|
518
|
+
super(str, offset)
|
|
519
|
+
@value = str[self.offset, self.length]
|
|
520
|
+
@size
|
|
521
|
+
else
|
|
522
|
+
0
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
def serialize
|
|
527
|
+
super if @active
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
def value
|
|
531
|
+
@value
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
def value=(val)
|
|
535
|
+
@value = val
|
|
536
|
+
self.length = self.allocated = val.size
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
def data_size
|
|
540
|
+
@active ? @value.size : 0
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
class Message < FieldSet
|
|
545
|
+
class << Message
|
|
546
|
+
def parse(str)
|
|
547
|
+
m = Type0.new
|
|
548
|
+
m.parse(str)
|
|
549
|
+
case m.type
|
|
550
|
+
when 1
|
|
551
|
+
t = Type1.parse(str)
|
|
552
|
+
when 2
|
|
553
|
+
t = Type2.parse(str)
|
|
554
|
+
when 3
|
|
555
|
+
t = Type3.parse(str)
|
|
556
|
+
else
|
|
557
|
+
raise ArgumentError, "unknown type: #{m.type}"
|
|
558
|
+
end
|
|
559
|
+
t
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
def decode64(str)
|
|
563
|
+
parse(Base64.decode64(str))
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
def has_flag?(flag)
|
|
568
|
+
(self[:flag].value & FLAGS[flag]) == FLAGS[flag]
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
def set_flag(flag)
|
|
572
|
+
self[:flag].value |= FLAGS[flag]
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
def dump_flags
|
|
576
|
+
FLAG_KEYS.each{ |k| print(k, "=", flag?(k), "\n") }
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
def serialize
|
|
580
|
+
deflag
|
|
581
|
+
super + security_buffers.map{|n, f| f.value}.join
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
def encode64
|
|
585
|
+
Base64.encode64(serialize).gsub(/\n/, '')
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
def decode64(str)
|
|
589
|
+
parse(Base64.decode64(str))
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
alias head_size size
|
|
593
|
+
|
|
594
|
+
def data_size
|
|
595
|
+
security_buffers.inject(0){|sum, a| sum += a[1].data_size}
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
def size
|
|
599
|
+
head_size + data_size
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
private
|
|
604
|
+
|
|
605
|
+
def security_buffers
|
|
606
|
+
@alist.find_all{|n, f| f.instance_of?(SecurityBuffer)}
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
def deflag
|
|
610
|
+
security_buffers.inject(head_size){|cur, a|
|
|
611
|
+
a[1].offset = cur
|
|
612
|
+
cur += a[1].data_size
|
|
613
|
+
}
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
def data_edge
|
|
617
|
+
security_buffers.map{ |n, f| f.active ? f.offset : size}.min
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
# sub class definitions
|
|
621
|
+
|
|
622
|
+
Type0 = Message.define {
|
|
623
|
+
string :sign, {:size => 8, :value => SSP_SIGN}
|
|
624
|
+
int32LE :type, {:value => 0}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
Type1 = Message.define {
|
|
628
|
+
string :sign, {:size => 8, :value => SSP_SIGN}
|
|
629
|
+
int32LE :type, {:value => 1}
|
|
630
|
+
int32LE :flag, {:value => DEFAULT_FLAGS[:TYPE1] }
|
|
631
|
+
security_buffer :domain, {:value => "", :active => false}
|
|
632
|
+
security_buffer :workstation, {:value => "", :active => false}
|
|
633
|
+
string :padding, {:size => 0, :value => "", :active => false }
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
class Type1
|
|
637
|
+
class << Type1
|
|
638
|
+
def parse(str)
|
|
639
|
+
t = new
|
|
640
|
+
t.parse(str)
|
|
641
|
+
t
|
|
642
|
+
end
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
def parse(str)
|
|
646
|
+
super(str)
|
|
647
|
+
enable(:domain) if has_flag?(:DOMAIN_SUPPLIED)
|
|
648
|
+
enable(:workstation) if has_flag?(:WORKSTATION_SUPPLIED)
|
|
649
|
+
super(str)
|
|
650
|
+
if ( (len = data_edge - head_size) > 0)
|
|
651
|
+
self.padding = "\0" * len
|
|
652
|
+
super(str)
|
|
653
|
+
end
|
|
654
|
+
end
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
Type2 = Message.define{
|
|
658
|
+
string :sign, {:size => 8, :value => SSP_SIGN}
|
|
659
|
+
int32LE :type, {:value => 2}
|
|
660
|
+
security_buffer :target_name, {:size => 0, :value => ""}
|
|
661
|
+
int32LE :flag, {:value => DEFAULT_FLAGS[:TYPE2]}
|
|
662
|
+
int64LE :challenge, {:value => 0}
|
|
663
|
+
int64LE :context, {:value => 0, :active => false}
|
|
664
|
+
security_buffer :target_info, {:value => "", :active => false}
|
|
665
|
+
string :padding, {:size => 0, :value => "", :active => false }
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
class Type2
|
|
669
|
+
class << Type2
|
|
670
|
+
def parse(str)
|
|
671
|
+
t = new
|
|
672
|
+
t.parse(str)
|
|
673
|
+
t
|
|
674
|
+
end
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
def parse(str)
|
|
678
|
+
super(str)
|
|
679
|
+
if has_flag?(:TARGET_INFO)
|
|
680
|
+
enable(:context)
|
|
681
|
+
enable(:target_info)
|
|
682
|
+
super(str)
|
|
683
|
+
end
|
|
684
|
+
if ( (len = data_edge - head_size) > 0)
|
|
685
|
+
self.padding = "\0" * len
|
|
686
|
+
super(str)
|
|
687
|
+
end
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
def response(arg, opt = {})
|
|
691
|
+
usr = arg[:user]
|
|
692
|
+
pwd = arg[:password]
|
|
693
|
+
if usr.nil? or pwd.nil?
|
|
694
|
+
raise ArgumentError, "user and password have to be supplied"
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
if opt[:workstation]
|
|
698
|
+
ws = opt[:workstation]
|
|
699
|
+
else
|
|
700
|
+
ws = ""
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
if opt[:client_challenge]
|
|
704
|
+
cc = opt[:client_challenge]
|
|
705
|
+
else
|
|
706
|
+
cc = rand(MAX64)
|
|
707
|
+
end
|
|
708
|
+
cc = NTLM::pack_int64le(cc) if cc.is_a?(Integer)
|
|
709
|
+
opt[:client_challenge] = cc
|
|
710
|
+
|
|
711
|
+
if has_flag?(:OEM) and opt[:unicode]
|
|
712
|
+
usr = NTLM::decode_utf16le(usr)
|
|
713
|
+
pwd = NTLM::decode_utf16le(pwd)
|
|
714
|
+
ws = NTLM::decode_utf16le(ws)
|
|
715
|
+
opt[:unicode] = false
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
if has_flag?(:UNICODE) and !opt[:unicode]
|
|
719
|
+
usr = NTLM::encode_utf16le(usr)
|
|
720
|
+
pwd = NTLM::encode_utf16le(pwd)
|
|
721
|
+
ws = NTLM::encode_utf16le(ws)
|
|
722
|
+
opt[:unicode] = true
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
tgt = self.target_name
|
|
726
|
+
ti = self.target_info
|
|
727
|
+
|
|
728
|
+
chal = self[:challenge].serialize
|
|
729
|
+
|
|
730
|
+
if opt[:ntlmv2]
|
|
731
|
+
ar = {:ntlmv2_hash => NTLM::ntlmv2_hash(usr, pwd, tgt, opt), :challenge => chal, :target_info => ti}
|
|
732
|
+
lm_res = NTLM::lmv2_response(ar, opt)
|
|
733
|
+
ntlm_res = NTLM::ntlmv2_response(ar, opt)
|
|
734
|
+
elsif has_flag?(:NTLM2_KEY)
|
|
735
|
+
ar = {:ntlm_hash => NTLM::ntlm_hash(pwd, opt), :challenge => chal}
|
|
736
|
+
lm_res, ntlm_res = NTLM::ntlm2_session(ar, opt)
|
|
737
|
+
else
|
|
738
|
+
lm_res = NTLM::lm_response(pwd, chal)
|
|
739
|
+
ntlm_res = NTLM::ntlm_response(pwd, chal)
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
Type3.create({
|
|
743
|
+
:lm_response => lm_res,
|
|
744
|
+
:ntlm_response => ntlm_res,
|
|
745
|
+
:domain => tgt,
|
|
746
|
+
:user => usr,
|
|
747
|
+
:workstation => ws,
|
|
748
|
+
:flag => self.flag
|
|
749
|
+
})
|
|
750
|
+
end
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
Type3 = Message.define{
|
|
755
|
+
string :sign, {:size => 8, :value => SSP_SIGN}
|
|
756
|
+
int32LE :type, {:value => 3}
|
|
757
|
+
security_buffer :lm_response, {:value => ""}
|
|
758
|
+
security_buffer :ntlm_response, {:value => ""}
|
|
759
|
+
security_buffer :domain, {:value => ""}
|
|
760
|
+
security_buffer :user, {:value => ""}
|
|
761
|
+
security_buffer :workstation, {:value => ""}
|
|
762
|
+
security_buffer :session_key, {:value => "", :active => false }
|
|
763
|
+
int64LE :flag, {:value => 0, :active => false }
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
class Type3
|
|
767
|
+
class << Type3
|
|
768
|
+
def parse(str)
|
|
769
|
+
t = new
|
|
770
|
+
t.parse(str)
|
|
771
|
+
t
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
def create(arg, opt ={})
|
|
775
|
+
t = new
|
|
776
|
+
t.lm_response = arg[:lm_response]
|
|
777
|
+
t.ntlm_response = arg[:ntlm_response]
|
|
778
|
+
t.domain = arg[:domain]
|
|
779
|
+
t.user = arg[:user]
|
|
780
|
+
t.workstation = arg[:workstation]
|
|
781
|
+
|
|
782
|
+
if arg[:session_key]
|
|
783
|
+
t.enable(:session_key)
|
|
784
|
+
t.session_key = arg[session_key]
|
|
785
|
+
end
|
|
786
|
+
if arg[:flag]
|
|
787
|
+
t.enable(:session_key)
|
|
788
|
+
t.enable(:flag)
|
|
789
|
+
t.flag = arg[:flag]
|
|
790
|
+
end
|
|
791
|
+
t
|
|
792
|
+
end
|
|
793
|
+
end
|
|
794
|
+
end
|
|
795
|
+
end
|
|
796
|
+
end
|
|
797
|
+
end
|