| 105 | | |
|---|
| 106 | | |
|---|
| 107 | | =pod |
|---|
| 108 | | |
|---|
| 109 | | =head1 DEFAULT PARAMETER LIST |
|---|
| 110 | | |
|---|
| 111 | | When a Driver B<$object> is instantiated using the B<new()> function, |
|---|
| 112 | | the following parameters are supplied default values. Each value |
|---|
| 113 | | can be overridden by specifying the new (key => value) pair into the |
|---|
| 114 | | B<new()> function, as arguments. |
|---|
| 115 | | |
|---|
| 116 | | Furthermore, as each parameter is initialized, each can be individually |
|---|
| 117 | | retrieved and set at any time, using the following syntax: |
|---|
| 118 | | |
|---|
| 119 | | my $value = $object->{key}; # Gets key's value. |
|---|
| 120 | | $object->{key} = $value; # Sets key's value. |
|---|
| 121 | | |
|---|
| 122 | | =head2 timeout |
|---|
| | 117 | # This variable holds the base URL reference for the SWF movie |
|---|
| | 118 | # we are currently processing. |
|---|
| | 119 | our $base_url; |
|---|
| | 120 | |
|---|
| | 121 | # Put all the relative URLs that were retrieved into a hash as |
|---|
| | 122 | # keys, but first turn them into full URLs. Set the value for |
|---|
| | 123 | # each URL key to 1 (this is its score). |
|---|
| | 124 | our %urls; |
|---|
| | 125 | |
|---|
| | 126 | |
|---|
| | 127 | ####################################################################### |
|---|
| | 128 | # Private Methods Implemented # |
|---|
| | 129 | ####################################################################### |
|---|
| | 130 | |
|---|
| | 131 | =pod |
|---|
| | 132 | |
|---|
| | 133 | =head1 PRIVATE METHODS |
|---|
| | 134 | |
|---|
| | 135 | =head2 HoneyClient::Agent::Driver::ActiveContent::Flash->_addURL($url) |
|---|
| 126 | | This parameter indicates how long (in seconds) the Driver should wait |
|---|
| 127 | | for an application response, once driven for one iteration. |
|---|
| 128 | | The default value is any valid "timeout" setting located within the |
|---|
| 129 | | global configuration file that matches any portion of this package's |
|---|
| 130 | | namespace. See L<HoneyClient::Util::Config> for more information. |
|---|
| | 139 | Adds the specified URL to the hash of URLs to be returned. Checks |
|---|
| | 140 | to see if the URL is relative or absolute, and in the former case |
|---|
| | 141 | appends the base URL appropriately. |
|---|
| 183 | | foreach (@urls) { |
|---|
| 184 | | print "$_\n"; |
|---|
| 185 | | } |
|---|
| 186 | | |
|---|
| 187 | | # If there are any getURL2 calls, mark this file |
|---|
| 188 | | # for additional analysis |
|---|
| 189 | | if (grep(/getURL2/, @bytecode)) { |
|---|
| 190 | | print "Detected getURL2, need to process with Flare\n"; |
|---|
| 191 | | } |
|---|
| 192 | | |
|---|
| 193 | | # We can certainly do better processing of these getURL2 |
|---|
| 194 | | # calls. What we need to do is read up to the preceeding |
|---|
| 195 | | # lines in the assembly to where the getVariable call is |
|---|
| 196 | | # made. The push call immediately before it has the name |
|---|
| 197 | | # of the variable that is used in the getURL2 call. To |
|---|
| 198 | | # get the value of that variable, one needs to look for |
|---|
| 199 | | # where the variable is set. If it is a simple String |
|---|
| 200 | | # assignment, then there will be another push call |
|---|
| 201 | | # somewhere that has the variable name as the first |
|---|
| 202 | | # parameter and the value as the second parameter. Note |
|---|
| 203 | | # that this process could very quickly become complicated, |
|---|
| 204 | | # so let's just try to handle the basic cases for now and |
|---|
| 205 | | # we can mark the file for human analysis as a fallback. |
|---|
| | 200 | # Chop any trailing slash off the base URL |
|---|
| | 201 | $base_url = $args{'base_url'}; |
|---|
| | 202 | $base_url =~ s/\/$//; |
|---|
| | 203 | |
|---|
| | 204 | # Call flasm in OS-dependent way and capture the output in an array. |
|---|
| | 205 | if ($^O =~ m/linux/i) { |
|---|
| | 206 | $filename = $args{'file'}->filename; |
|---|
| | 207 | } |
|---|
| | 208 | # Must encode all backslashes with double backslashes, since |
|---|
| | 209 | # backtick commands don't like single backslashes. |
|---|
| | 210 | elsif ($^O =~ m/win/i || $ENV{'OS'} =~ m/win/i) { |
|---|
| | 211 | my $filename = (fullwin32path($args{'file'}->filename) =~ s/\\/\\\\/g); |
|---|
| | 212 | } |
|---|
| | 213 | |
|---|
| | 214 | # Call flasm and store the output bytecode string in an array |
|---|
| | 215 | my @bytecode = `$flasm_exec -d $filename`; |
|---|
| | 216 | |
|---|
| | 217 | # Check the return value on the flasm call that just happened. |
|---|
| | 218 | # We care if the return code was anything other than 0. |
|---|
| | 219 | if ($? >> 8) { |
|---|
| | 220 | my $signal = ($? & 127); |
|---|
| | 221 | $LOG->fatal("Call to flasm exited on signal $signal"); |
|---|
| | 222 | Carp::croak "Error: Call to flasm exited on signal $signal"; |
|---|
| | 223 | } |
|---|
| | 224 | |
|---|
| | 225 | # Parse out lines that contain the getURL method (exclude any |
|---|
| | 226 | # getURL2 calls from this, as they need to be handled differently) |
|---|
| | 227 | my @geturl_calls = grep(/getURL /, @bytecode); |
|---|
| | 228 | |
|---|
| | 229 | # Each getURL line has getURL followed by the URL in single |
|---|
| | 230 | # quotes. Extract the URL, remove the single quotes, and store |
|---|
| | 231 | # the URL in a new array. |
|---|
| | 232 | my @found_urls; |
|---|
| | 233 | |
|---|
| | 234 | foreach (@geturl_calls) { |
|---|
| | 235 | $_ =~ s/^\s+//; |
|---|
| | 236 | my ($fun, $url) = split(/\s+/); |
|---|
| | 237 | $url =~ s/'//g; |
|---|
| | 238 | push @found_urls, $url; |
|---|
| | 239 | } |
|---|
| | 240 | |
|---|
| | 241 | foreach (@found_urls) { |
|---|
| | 242 | _addURL $_; |
|---|
| | 243 | } |
|---|
| | 244 | |
|---|
| | 245 | # Sanity check on the URLs |
|---|
| | 246 | foreach (sort keys %urls) { |
|---|
| | 247 | $LOG->debug("$_"); |
|---|
| | 248 | } |
|---|
| 207 | | # TODO: Eventually, return something useful. |
|---|
| 208 | | my %urls = ( |
|---|
| 209 | | 'http://www.google.com' => 1, |
|---|
| 210 | | ); |
|---|
| | 250 | # We can exit here if there are no getURL2 calls |
|---|
| | 251 | unless (grep(/getURL2/, @bytecode)) { |
|---|
| | 252 | return %urls; |
|---|
| | 253 | } |
|---|
| | 254 | |
|---|
| | 255 | # If we made it here, then at least one getURL2 call was |
|---|
| | 256 | # detected. Proceed with additional processing. |
|---|
| | 257 | $LOG->warn("Detected getURL2\n"); |
|---|
| | 258 | |
|---|
| | 259 | # Before we forget, turn off unlink on destroy for our |
|---|
| | 260 | # temporary file handle, so the file is kept around for |
|---|
| | 261 | # analysts to look at later. |
|---|
| | 262 | $args{'file'}->unlink_on_destroy(0); |
|---|
| | 263 | |
|---|
| | 264 | # What we do next is some parsing on the flasm decompilation. |
|---|
| | 265 | # We are looking for getURL2 calls, and will then try to piece |
|---|
| | 266 | # together the URLs that go into them. |
|---|
| | 267 | my $i = 0; |
|---|
| | 268 | |
|---|
| | 269 | foreach (@bytecode) { |
|---|
| | 270 | # First, find a line containing a getURL2 call |
|---|
| | 271 | if ($_ =~ /getURL2/) { |
|---|
| | 272 | $LOG->debug("Got a getURL2 on line " . ($i+1)); |
|---|
| | 273 | |
|---|
| | 274 | my ($fun, $var, $val); |
|---|
| | 275 | my $instr; |
|---|
| | 276 | my $haveVar = 0; |
|---|
| | 277 | |
|---|
| | 278 | # Next, work backwards from the call. We start from $i - 2 |
|---|
| | 279 | # here because the $i - 1 line always contains the URL's target |
|---|
| | 280 | # (e.g., '', '_parent', '_blank'). |
|---|
| | 281 | for (my $j = $i - 2; $bytecode[$j] !~ /^\s+constants/; $j--) { |
|---|
| | 282 | # The first time through, look for a getVariable call, which |
|---|
| | 283 | # tells us what variable has the value of the URL. |
|---|
| | 284 | if (!$haveVar and $bytecode[$j] =~ /getVariable/) { |
|---|
| | 285 | $LOG->debug("Found getVariable on line " . ($j+1)); |
|---|
| | 286 | # The line before this one has the name of the |
|---|
| | 287 | # variable that contains the URL |
|---|
| | 288 | $instr = $bytecode[--$j]; |
|---|
| | 289 | $instr =~ s/^\s+//; |
|---|
| | 290 | ($fun, $var) = split(/\s+/, $instr); |
|---|
| | 291 | $LOG->debug("Name of the URL variable is $var"); |
|---|
| | 292 | $haveVar = 1; |
|---|
| | 293 | } |
|---|
| | 294 | # Once we have the URL variable, we can look back further |
|---|
| | 295 | # for the push call that sets its value. |
|---|
| | 296 | elsif ($haveVar and $bytecode[$j] =~ /^\s+push $var/) { |
|---|
| | 297 | $instr = $bytecode[$j]; |
|---|
| | 298 | $instr =~ s/^\s+//; |
|---|
| | 299 | ($var, $val) = split(/, /, $instr); |
|---|
| | 300 | $LOG->info("Value of the URL is $val"); |
|---|
| | 301 | $val =~ s/'//g; |
|---|
| | 302 | _addURL $val; |
|---|
| | 303 | last; |
|---|
| | 304 | } |
|---|
| | 305 | } |
|---|
| | 306 | } |
|---|
| | 307 | |
|---|
| | 308 | $i++; |
|---|
| | 309 | } |
|---|
| | 310 | |
|---|