Skip to content

Instantly share code, notes, and snippets.

@abhisek
Created August 8, 2012 18:09
Show Gist options
  • Save abhisek/3297158 to your computer and use it in GitHub Desktop.
Save abhisek/3297158 to your computer and use it in GitHub Desktop.
DLL Injector
$:.unshift("E:\\Tools\\metasm")
require 'metasm'
require 'optparse'
$ASMCODE =
# Win32 PEB based API Resolver
# Metasm seems to fail on jecxz so we compile using nasm and use the binary
"\xe8\x56\x00\x00\x00\x53\x55\x56\x57\x8b\x6c\x24\x18\x8b\x45\x3c" +
"\x8b\x54\x05\x78\x01\xea\x8b\x4a\x18\x8b\x5a\x20\x01\xeb\xe3\x32" +
"\x49\x8b\x34\x8b\x01\xee\x31\xff\xfc\x31\xc0\xac\x38\xe0\x74\x07" +
"\xc1\xcf\x0d\x01\xc7\xeb\xf2\x3b\x7c\x24\x14\x75\xe1\x8b\x5a\x24" +
"\x01\xeb\x66\x8b\x0c\x4b\x8b\x5a\x1c\x01\xeb\x8b\x04\x8b\x01\xe8" +
"\xeb\x02\x31\xc0\x5f\x5e\x5d\x5b\xc2\x08\x00\x31\xc9\x64\x8b\x71" +
"\x30\x8b\x76\x0c\x8b\x76\x1c\x8b\x5e\x08\x8b\x7e\x20\x8b\x36\x66" +
"\x39\x4f\x18\x75\xf2\x5e\x53\x68\x8e\x4e\x0e\xec\xff\xd6\x89\xc7" +
"\x57\x56\x53\x89\xe5" +
# %define LoadLibraryA [ebp + 8]
# %define LGetProcAddress [ebp + 4]
# %define KERNEL32 BASE [ebp + 0]
Metasm::Shellcode.assemble(Metasm::Ia32.new, %Q{
jmp _end
_start:
pop ecx ; DLL Path in ECX
; LoadLibraryA(DLL)
push ecx
call [ebp + 8]
test eax, eax
jz _exit
; GetProcessAddress() and find Init()
push eax ; DLL Base
push 0x95481bf4 ; Hash of Init
call [ebp + 4]
test eax, eax
jz _exit
call eax ; Init()
_exit:
; Resolve Exit Thread
push [ebp]
push 0x60e0ceef ; Hash of Exit Thread
call [ebp + 4]
; Call ExitThread
push 0x00
call eax
int 3
_end:
call _start
; Path (ASCII) for DLL goes here
}).encode_string()
def process_inject_dll(process, path)
puts "[+] Attempting to inject \"#{path}\" to pid: #{process.pid}"
Metasm::WinOS.inject_run_shellcode(process, $ASMCODE + path.to_s + "\x00")
end
if __FILE__ == $0
options = {}
opts = OptionParser.new do |opts|
opts.banner = "Usage: Injector.rb [options]"
opts.on("-p", "--pid [PID]", "Inject to process identified by PID") do |pid|
options[:pid] = pid.to_i
end
opts.on("-n", "--name [NAME]", "Inject to all processes matching name (eg. chrome.exe)") do |name|
options[:name] = name.to_s
end
opts.on("-D", "--dll-path [PATH]", "Path of DLL to inject") do |dll|
options[:dll] = dll.to_s
end
opts.on("-l", "--list", "List processes") do |v|
options[:list_processes] = true
end
end
opts.parse!
if options[:list_processes]
Metasm::WinOS.list_processes.each do |proc|
puts "%d: %s" % [proc.pid, proc.modules.size > 0 ? proc.modules[0].path : "N/A"]
end
exit
end
if (options[:dll].nil?) or (options[:pid].nil? and options[:name].nil?)
puts opts
exit(1)
end
Metasm::WinOS.list_processes.each do |process|
process_inject_dll(process, options[:dll]) if ((options[:pid]) and (process.pid == options[:pid].to_i)) or
((options[:name]) and (!process.modules.empty?) and
(File.basename(process.modules[0].path).downcase == options[:name].downcase))
end
end
C:\Injector>ruby Injector.rb
Usage: Injector.rb [options]
-p, --pid [PID] Inject to process identified by PID
-n, --name [NAME] Inject to all processes matching name (eg. chrome.exe)
-D, --dll-path [PATH] Path of DLL to inject
-l, --list List processes
@abhisek
Copy link
Author

abhisek commented Sep 3, 2014

The injected DLL does not export an Init function?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment