- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshellcode_utils.py
More file actions
Latest commit
141 lines (109 loc) · 5 KB
/
Copy pathshellcode_utils.py
File metadata and controls
141 lines (109 loc) · 5 KB
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
#! /usr/bin/python
# ALL the credits to WJDigby --> https://gist.github.com/WJDigby/acd41da3dc68a14a2ea3e2d5be871b60
# Requries at least Python 3.6
# Reads from stdin or file ( -i / --input-file), writes to stdout or file ( -o / --output-file)
# Supports XORing with provided key (-x / --xor)
# Supports output formats of C, C#, Java, VB, and B64 string ( -f / --format)
# Change shellcode output variable name with -n / --name
# Examples:
# Read shellcode from stdin, XOR with key 'secret!', format in C byte array, and write to file "sc.txt":
# python shellcode_utils.py -i - -x 'secret!' -f c -o sc.txt < shellcode.bin
# Read shellcode from file, format in Base64 string, change shellcode variable name to "not_shellcode":
# python shellcode_utils.py -i shellcode.bin -f b64 -n not_shellcode
importargparse
fromcollectionsimportnamedtuple
importcodecs
importsys
defxor_sc(sc, key):
"""XOR shellcode with provided key of arbitrary length.
Takes shellcode characters as bytes, returns XORed bytes.
"""
xored_sc= []
i=0
forsc_byteinsc:
ifi<len(key):
xored_byte=sc_byte^key[i]
xored_sc.append(xored_byte)
i+=1
else:
xored_byte=sc_byte^key[0]
xored_sc.append(xored_byte)
i=1
returnbytes(xored_sc)
defformat_sc(sc, output_format):
"""Format the shellcode for pasting in C/C++, C#, Java, or Visual Basic projects.
Takes shellcode as bytes, returns formatted bytes.
"""
ifoutput_format=='b64':
sc=split_sc(sc)
returnsc
sc= ["{0:#0{1}x}".format(int(x),4) forxinsc]
CodeFormat=namedtuple('CodeFormat', 'open close heading items_per_line func')
ifoutput_format=='c':
cf=CodeFormat(open='{\n', close='\n};', heading=f'unsigned char shellcode[{len(sc)}] = ', items_per_line=12, func=None)
elifoutput_format=='c#':
cf=CodeFormat(open='{\n', close='\n};', heading='byte[] shellcode = ', items_per_line=12, func=None)
elifoutput_format=='java':
cf=CodeFormat(open='{\n', close='\n};', heading='byte shellcode[] = ', items_per_line=5, func=['(byte)'+xforxinsc])
elifoutput_format=='vb':
cf=CodeFormat(open='{\n', close='\n}', heading='Dim shellcode As Byte() = ', items_per_line=12,
func=[x.replace('0x', '&H').upper() forxinsc])
ifcf.func:
sc=cf.func
iterations= (len(sc) //cf.items_per_line) iflen(sc) %cf.items_per_line==0else (len(sc) //cf.items_per_line+1)
iteration=0
index= [0, cf.items_per_line]
lines= []
whileiteration<iterations:
line=', '.join(sc[index[0]:index[1]])
lines.append(line)
index[0] =index[1]
index[1] =index[1] +cf.items_per_line
iteration+=1
sc=',\n'.join(lines)
sc=cf.heading+cf.open+sc+cf.close
returnsc.encode()
defsplit_sc(sc, row_length=80):
"""Format shellcode for pasting into projects as series of concatenated Base64 strings.
Takes shellcode as bytes, returns formatted base64 encoded bytes.
"""
sc=codecs.encode(sc, 'base64').decode().replace('\n', '')
base64_sc=''
index= [0, row_length-1]
foriinrange((len(sc) //row_length) +1):
base64_sc+=f'shellcode {"="ifindex[0] ==0else"+="} "{sc[index[0]:index[1]]}";\n'
index[0] =index[1]
index[1] =index[1] +row_length
returnbase64_sc.encode()
defmain():
"""XOR and format shellcode."""
parser=argparse.ArgumentParser()
parser.add_argument('-i', '--input-file', type=argparse.FileType('rb'),
help='File containing shellcode or read from <stdin>')
parser.add_argument('-o', '--output-file', type=argparse.FileType('wb'), default=sys.stdout,
help='Output file to write. Defaults to <stdout>.')
parser.add_argument('-x', '--xor', type=str, help='XOR shellcode with key.')
parser.add_argument('-f', '--format', type=str.lower, choices=['c', 'c#', 'vb', 'java', 'b64'],
help='Format the shellcode for including in C/C++ or C# projects.')
parser.add_argument('-n', '--name', type=str, help='Name for the shellcode variable. Default "shellcode".')
args=parser.parse_args()
infile=args.input_file
outfile=args.output_file
key=args.xor
output_format=args.format
var_name=args.name
ifnotinfile:
print('[-] Provide shellcode via -i/--input-file or stdin')
exit()
# Read shellcode from file or stdin into bytes
sc=infile.buffer.read() ifinfile.fileno() ==0elseinfile.read()
ifkey:
sc=xor_sc(sc, key.encode())
ifoutput_format:
sc=format_sc(sc, output_format)
ifoutput_formatandvar_name:
sc=sc.replace(b'shellcode', var_name.encode())
# Select write method for writing to stdout or file
sys.stdout.buffer.write(sc) ifoutfile.fileno() ==1elseoutfile.write(sc)
if__name__=='__main__':
main()