-
Notifications
You must be signed in to change notification settings - Fork 0
/
telegen.py
276 lines (219 loc) · 9.35 KB
/
telegen.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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
### telegen.py
### 9/21/2021
### Created by: Noah Hansen
import argparse
import os
import datetime
import sys
import getpass
import socket
from csv import writer
from subprocess import Popen, PIPE
#-------------------------------------------------------------------------------
# logData()
# takes data from array and writes it to the given path of a csv file
#
# :param log_path: a string denoting the path of a CSV file in which we wish to
# write log info to
# :param elements: array of elements that will coordinate to rows in csv
#-------------------------------------------------------------------------------
def logData(log_path, elements):
try:
with open(log_path, 'a+', newline='') as fileObj:
csvWriter = writer(fileObj)
csvWriter.writerow(elements)
except Exception as a:
print("ERROR: There was an error attempting to write to log " + log_path)
print("Exception: ")
print(a)
#-------------------------------------------------------------------------------
# aggregateFileData()
# Aggregates all log data regarding file mods, creation, and deletion
#
# :param activity_arg: A string denoting whether were deleting, modding,
# or creating a file
# :param filePath: A string denoting the path of the file we are acting on
#-------------------------------------------------------------------------------
def aggregrateFileData(activity_arg, filePath):
dateTime = datetime.datetime.now()
path = os.path.abspath(filePath)
activity = activity_arg
user = getpass.getuser()
processName = "telegen.py"
commandLine = "python "
tmpString = " ".join(sys.argv)
commandLine = commandLine + tmpString
pid = os.getpid()
elements = [dateTime, path, activity, user, processName, commandLine, pid]
logData("./logs/file_log.csv", elements)
#-------------------------------------------------------------------------------
# startProcess()
# starts the given process with specified commandline args
#
# :param command: A string denoting the command in which we would like to run
# :return None: Only return if an error is thrown
#-------------------------------------------------------------------------------
def startProcess(command):
print("Starting Process: " + str(command))
commandArr = command.split(" ")
try:
process = Popen(commandArr, stdout=PIPE, stdin=PIPE, shell=True)
except Exception as a:
print("ERROR: There was an error attempting to call command " + command)
print("Exception: ")
print(a)
return None
### this has to be done so the command doesn't throw a write error
output = process.stdout.read()
### Aggregate logging info
user = getpass.getuser()
dateTime = datetime.datetime.now()
pid = os.getpid()
processName = "telegen.py"
commandLine = "python "
tmpString = " ".join(sys.argv)
commandLine = commandLine + tmpString
elements = [dateTime, user, processName, commandLine, pid]
logData("./logs/process_log.csv", elements)
print("Data from the process has been logged at <telegen.py_directory>/logs/process_log.csv")
#-------------------------------------------------------------------------------
# createFile()
# Creates a file at a specified path
#
# :param filePath: A string denoting the path in which the file will be created
# :return None: Only return if an error is thrown
#-------------------------------------------------------------------------------
def createFile(filePath):
### Checks if file exists
if os.path.exists(filePath):
print("ERROR: This file already exists")
print("Cancelling file creation...")
return None
### Error handles any other problems
try:
f=open(filePath, "w+")
except Exception as a:
print("ERROR: There was an error attempting to create the file at " + filePath)
print("Cancelling file creation...")
print("Exception: ")
print(a)
return None
print("File has been created at " + filePath)
### Aggregate logging info
aggregrateFileData("create", filePath)
print("Data from the process has been logged at <telegen.py_directory>/logs/file_log.csv")
#-------------------------------------------------------------------------------
# modifyFile()
# Modifies file at a specified path
#
# :param filePath: A string denoting the path in which the file will be created
# :return None: Only return if an error is thrown
#-------------------------------------------------------------------------------
def modifyFile(filePath):
### Checks if file doesn't exist
if not os.path.exists(filePath):
print("ERROR: This file doesn't exist exists")
print("Cancelling file modification...")
return None
### Error handles any other problems
try:
f=open(filePath, "a+")
except Exception as a:
print("ERROR: There was an error attempting to modify the file at " + filePath)
print("Cancelling file modification...")
print("Exception: ")
print(a)
return None
f.write("THIS IS A FILE MODIFICATION")
print("File has been modified at " + filePath)
### Aggregate logging info
aggregrateFileData("modify", filePath)
print("Data from the process has been logged at <telegen.py_directory>/logs/file_log.csv")
#-------------------------------------------------------------------------------
# deleteFile()
# Deletes a file at the specified path
#
# :param filePath: A string denoting the path in which the file will be created
# :return None: Only return if an error is thrown
#-------------------------------------------------------------------------------
def deleteFile(filePath):
try:
os.remove(filePath)
except Exception as a:
print("ERROR: There was an error trying to remove the file at " + filePath)
print("Cancelling file deletion...")
print("Exception: ")
print(a)
return None
print("File has been removed at " + filePath)
### Aggregate logging info
aggregrateFileData("delete", filePath)
print("Data from the process has been logged at <telegen.py_directory>/logs/file_log.csv")
#-------------------------------------------------------------------------------
# establishConnection()
# Establishes a connection to google.com and transmits data
#
# :return None: Only return if an error is thrown
#-------------------------------------------------------------------------------
def establishConnection():
print("Establish a connection at google.com:80")
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('google.com', 80))
request = b'GET google.com HTTP/1.1\n\n'
s.send(request)
print("Request has been sent")
except Exception as a:
print("ERROR: there was an error while connecting")
print("Cancelling connection...")
print("Exception: ")
print(a)
return None
### Aggregate logging info
dateTime = datetime.datetime.now()
user = getpass.getuser()
destination = "google.com:80"
source = str(socket.gethostbyname(socket.gethostname())) + ":" + str(s.getsockname()[1])
### No calc needed here since request is already a byte object
dataSize = len(request)
protocol = "HTTP"
processName = "telegen.py"
commandLine = "python "
tmpString = " ".join(sys.argv)
commandLine = commandLine + tmpString
pid = os.getpid()
elements = [dateTime, user, destination, source, dataSize, protocol, processName, commandLine, pid]
logData("./logs/connection_log.csv", elements)
print("Data from the connection has been logged at <telegen.py_directory>/logs/connection_log.csv")
if __name__ == "__main__":
### Change to file directory
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
### argparse is used to create command line arguments for the framework
parser = argparse.ArgumentParser(description='Red Canary Telemetry Generation')
parser.add_argument('--startprocess', metavar='\"<process>\"', type=str,
help="start a process/shell command (i.e. ls -l)", required=False)
parser.add_argument('--createfile', metavar='<file_path>', type=str,
help="create a file at the specified location", required=False)
parser.add_argument('--modfile', metavar='<file_path>', type=str,
help="modify a file at the specified location", required=False)
parser.add_argument('--deletefile', metavar='<file_path>', type=str,
help="delete a file at the specified location", required=False)
parser.add_argument('--startconnection',
help="start a connection with google.com and transmit data",
required=False, action='store_true')
args = parser.parse_args()
### Would prefer to use a switch statement here.. but python doesn't support that ###
if args.startprocess:
startProcess(args.startprocess)
if args.createfile:
createFile(args.createfile)
if args.modfile:
modifyFile(args.modfile)
if args.deletefile:
deleteFile(args.deletefile)
if args.startconnection:
establishConnection()
if not (args.startprocess or args.createfile or args.modfile or args.deletefile or args.startconnection):
print(args)