Multi-conditional search and replace (clearing a ftp trojan script example)

This is a simple Ruby script example which covers a multi-conditional find and replace mechanism. In this script, I'll tried to clear files which are infected by todays popular ftp trojans (Trojan runs on windows clients, grabs ftp login informations, send it to a central server and afterwards it connects to your ftp server from thousands of different IP addresses to inject malicious javascript and iframe codes)

 

We want to remove <iframe ...></iframe> codes which goes to a unwanted address. We also want to remove infected javascript codes. But, they're different kinds of this trojan, and it's changing itself. A simple search/replace operation is not enough, sometimes infected code can be like this:

<ScRipT language="Javascript">.....</Script
>

or like that. So I want to use a HTML/XML parser to be sure that script tag and contents cleared properly.

I used Nokogiri Ruby gem for XML parsing, it is a fast library and required libxml2-dev. You have to use libxml2 version >= 2.7.3 otherwise you may be encounter some encoding problems. If you already have ruby and gem package, here instructions:

apt-get install libxslt1-dev libxml2-dev
gem install nokogiri

After that, you can use thefollowing script: It takes an optional target directory argument, otherwise starts with current directory and scans specific types of files recursively, finds script and iframe nodes on XML tree and check the values according to defined regular expressions and write backs to files. You can customize it for different types of this trojan.

 

It is not a production ready code, use at your own risk!

 

#!/usr/bin/ruby
## Requires libxml2 (>= 2.7.3), otherwise you may encounter
## encoding problems with nokogiri
## Nokogiri gem must be compiled with libxml2-dev (>= 2.7.3)

require "rubygems"
require "nokogiri"
require "find"

## To improve overall performance, only scan for specific filenames
FILENAME_SUFFIXES = [".html", ".htm", ".HTM", ".HTML", ".php"]

INFECTED_SCRIPTS = INFECTED_IFRAMES = []

INFECTED_SCRIPTS << /document.write\(unescape/i
INFECTED_SCRIPTS << /kV60kV105kV102/i
INFECTED_SCRIPTS << /v4a911/i

## Create regular expression array for infected iframe tags
INFECTED_IFRAMES << /.*\:8080\//i

## Please send improvements to mdemirten at yh.com.tr
ENV['LANG'] = "en_US.UTF-8"

if ARGV[0]
  BASEDIR = ARGV[0]
else
  BASEDIR = ENV['PWD']
end

raise "No such directory" unless File.exists?BASEDIR

count = 0

Find.find(BASEDIR) do |path|
  if FileTest.file?path
    # check the suffix
    if FILENAME_SUFFIXES.include?File.extname(path)
      changed = false
      tmp = Nokogiri::HTML(open(path))
      # get the encoding properly, its a workaround
      encoding = tmp.encoding
      doc = Nokogiri::HTML.parse(open(path), nil, encoding)
      doc.search('script').each do |node|
        INFECTED_SCRIPTS.each do |regexp|
          if node.text.match regexp
            puts "Found script: #{regexp} : #{path}"
            node.remove
            changed = true
          end
        end
      end
      doc.search('iframe').each do |node|
        INFECTED_IFRAMES.each do |regexp|
          if node["src"] and node["src"].match regexp
            puts "Found iframe: #{node["src"]} : #{path}"
            node.remove
            changed = true
          end
        end
      end
      if changed
        File.open(path, "w+") do |f|
          f.puts doc.to_s
        end
        count += 1
      end
    end
  end
end

puts "Total of #{count.to_s} file cleared"






Hi, I'm trying to run the script, but it ends with this error: cleanup.rb:53: undefined method `match' for nil:NilClass (NoMethodError) from cleanup.rb:52:in `each' from cleanup.rb:52 from /var/lib/gems/1.8/gems/nokogiri-1.3.1/lib/nokogiri/xml/node_set.rb:153:in `each' from /var/lib/gems/1.8/gems/nokogiri-1.3.1/lib/nokogiri/xml/node_set.rb:152:in `upto' from /var/lib/gems/1.8/gems/nokogiri-1.3.1/lib/nokogiri/xml/node_set.rb:152:in `each' from cleanup.rb:51 from /usr/lib/ruby/1.8/find.rb:39:in `find' from /usr/lib/ruby/1.8/find.rb:38:in `catch' from /usr/lib/ruby/1.8/find.rb:38:in `find' from cleanup.rb:36
Last by Murat Demirten over 3 years ago Reply this comment
Added nil control on line 51, please check it again. Further analysis may be required with your files, we used it to correct thousands of files but I'm sure there are more scenarios like yours.
You must be login first or sign-up for an account to post comments.

Maybe you should look at these also: