Skip to content

Commit 2025e86

Browse files
committed
v0.5.0 update for Mythic3.3
1 parent 7097157 commit 2025e86

22 files changed

+2072
-543
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
11

2+
## [v0.5.0] - 2024-07-09
3+
4+
### Changed
5+
6+
- This is updated to work with Mythic 3.3+ and will cause some issues with Mythic 3.2 and below
7+
- New Auth
8+
- New Eventing
9+
- New Build/C2/Command parameter options of ChooseOneCustom and FileMultiple
10+
- New Logging options
11+
- Added MythicRPCAPITokenCreate
12+
- Added MythicRPCCallbackNextCheckinRange
13+
- Added MythicRPCFilebrowserParsePath
14+
215
## [v0.4.19] - 2024-04-29
316

417
### Changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pip install mythic-container
1313

1414
## How to use
1515

16-
Use it with Mythic version 3.0.0.
16+
Use it with Mythic version 3.3.0.
1717

1818
For the main execution of the heartbeat and service functionality, simply import and start the service:
1919
```
@@ -24,4 +24,4 @@ mythic_container.mythic_service.start_and_run_forever()
2424

2525
## Where is the code?
2626

27-
The code for this PyPi package can be found at https://github.com/MythicMeta/Mythic_Container
27+
The code for this PyPi package can be found at https://github.com/MythicMeta/MythicContainerPyPi

mythic_container/AuthBase.py

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
from collections.abc import Callable, Awaitable
2+
from typing import Union
3+
4+
import mythic_container
5+
from .logging import logger
6+
import base64
7+
import json
8+
from .MythicCommandBase import PTTaskMessageTaskData
9+
from .SharedClasses import ContainerOnStartMessage, ContainerOnStartMessageResponse
10+
11+
12+
class GetIDPMetadataMessage:
13+
def __init__(self,
14+
container_name: str = "",
15+
server_name: str = "",
16+
idp_name: str = "",
17+
**kwargs):
18+
self.ContainerName = container_name
19+
self.ServerName = server_name
20+
self.IDPName = idp_name
21+
22+
def to_json(self):
23+
return {
24+
"container_name": self.ContainerName,
25+
"server_name": self.ServerName,
26+
"idp_name": self.IDPName
27+
}
28+
29+
30+
class GetIDPMetadataMessageResponse:
31+
def __init__(self,
32+
Success: bool = True,
33+
Error: str = "",
34+
Metadata: str = "",
35+
**kwargs):
36+
self.Success = Success
37+
self.Error = Error
38+
self.Metadata = Metadata
39+
40+
def to_json(self):
41+
return {
42+
"success": self.Success,
43+
"error": self.Error,
44+
"metadata": self.Metadata
45+
}
46+
47+
48+
class GetIDPRedirectMessage:
49+
def __init__(self,
50+
container_name: str = "",
51+
server_name: str = "",
52+
idp_name: str = "",
53+
request_url: str = "",
54+
request_headers: dict = {},
55+
request_cookies: dict = {},
56+
request_query: dict = {}):
57+
self.ContainerName = container_name
58+
self.ServerName = server_name
59+
self.IDPName = idp_name
60+
self.RequestURL = request_url
61+
self.RequestHeaders = request_headers
62+
self.RequestCookies = request_cookies
63+
self.RequestQuery = request_query
64+
65+
def to_json(self):
66+
return {
67+
"container_name": self.ContainerName,
68+
"server_name": self.ServerName,
69+
"idp_name": self.IDPName,
70+
"request_url": self.RequestURL,
71+
"request_headers": self.RequestHeaders,
72+
"request_cookies": self.RequestCookies,
73+
"request_query": self.RequestQuery
74+
}
75+
76+
77+
class GetIDPRedirectMessageResponse:
78+
def __init__(self,
79+
Success: bool = True,
80+
Error: str = "",
81+
RedirectURL: str = "",
82+
RedirectHeaders: dict = {},
83+
RedirectCookies: dict = {}):
84+
self.Success = Success
85+
self.Error = Error
86+
self.RedirectURL = RedirectURL
87+
self.RedirectHeaders = RedirectHeaders
88+
self.RedirectCookies = RedirectCookies
89+
90+
def to_json(self):
91+
return {
92+
"success": self.Success,
93+
"error": self.Error,
94+
"redirect_url": self.RedirectURL,
95+
"redirect_headers": self.RedirectHeaders,
96+
"redirect_cookies": self.RedirectCookies
97+
}
98+
99+
100+
class GetNonIDPMetadataMessage:
101+
def __init__(self,
102+
container_name: str = "",
103+
server_name: str = "",
104+
nonidp_name: str = "",
105+
**kwargs):
106+
self.ContainerName = container_name
107+
self.ServerName = server_name
108+
self.NonIDPName = nonidp_name
109+
110+
def to_json(self):
111+
return {
112+
"container_name": self.ContainerName,
113+
"server_name": self.ServerName,
114+
"nonidp_name": self.NonIDPName
115+
}
116+
117+
118+
class GetNonIDPMetadataMessageResponse:
119+
def __init__(self,
120+
Success: bool = True,
121+
Error: str = "",
122+
Metadata: str = "",
123+
**kwargs):
124+
self.Success = Success
125+
self.Error = Error
126+
self.Metadata = Metadata
127+
128+
def to_json(self):
129+
return {
130+
"success": self.Success,
131+
"error": self.Error,
132+
"metadata": self.Metadata
133+
}
134+
135+
136+
class GetNonIDPRedirectMessage:
137+
def __init__(self,
138+
container_name: str = "",
139+
server_name: str = "",
140+
nonidp_name: str = ""):
141+
self.ContainerName = container_name
142+
self.ServerName = server_name
143+
self.NonIDPName = nonidp_name
144+
145+
def to_json(self):
146+
return {
147+
"container_name": self.ContainerName,
148+
"server_name": self.ServerName,
149+
"nonidp_name": self.NonIDPName,
150+
}
151+
152+
153+
class GetNonIDPRedirectMessageResponse:
154+
def __init__(self,
155+
Success: bool = True,
156+
Error: str = "",
157+
RequestFields: [str] = []):
158+
self.Success = Success
159+
self.Error = Error
160+
self.RequestFields = RequestFields
161+
162+
def to_json(self):
163+
return {
164+
"success": self.Success,
165+
"error": self.Error,
166+
"request_fields": self.RequestFields,
167+
}
168+
169+
170+
class ProcessIDPResponseMessage:
171+
def __init__(self,
172+
container_name: str = "",
173+
server_name: str = "",
174+
idp_name: str = "",
175+
request_url: str = "",
176+
request_headers: dict = {},
177+
request_cookies: dict = {},
178+
request_query: dict = {},
179+
request_body: str = ""):
180+
self.ContainerName = container_name
181+
self.ServerName = server_name
182+
self.IDPName = idp_name
183+
self.RequestURL = request_url
184+
self.RequestHeaders = request_headers
185+
self.RequestCookies = request_cookies
186+
self.RequestQuery = request_query
187+
self.RequestBody = request_body
188+
189+
def to_json(self):
190+
return {
191+
"container_name": self.ContainerName,
192+
"server_name": self.ServerName,
193+
"idp_name": self.IDPName,
194+
"request_url": self.RequestURL,
195+
"request_headers": self.RequestHeaders,
196+
"request_cookies": self.RequestCookies,
197+
"request_query": self.RequestQuery,
198+
"request_body": self.RequestBody
199+
}
200+
201+
202+
class ProcessIDPResponseMessageResponse:
203+
def __init__(self,
204+
SuccessfulAuthentication: bool = False,
205+
Error: str = "",
206+
Email: str = "", ):
207+
self.SuccessfulAuthentication = SuccessfulAuthentication
208+
self.Error = Error
209+
self.Email = Email
210+
211+
def to_json(self):
212+
return {
213+
"successful_authentication": self.SuccessfulAuthentication,
214+
"error": self.Error,
215+
"email": self.Email,
216+
}
217+
218+
219+
class ProcessNonIDPResponseMessage:
220+
def __init__(self,
221+
container_name: str = "",
222+
server_name: str = "",
223+
idp_name: str = "",
224+
request_values: dict = {}):
225+
self.ContainerName = container_name
226+
self.ServerName = server_name
227+
self.IDPName = idp_name
228+
self.RequestValues = request_values
229+
230+
def to_json(self):
231+
return {
232+
"container_name": self.ContainerName,
233+
"server_name": self.ServerName,
234+
"idp_name": self.IDPName,
235+
"request_values": self.RequestValues
236+
}
237+
238+
239+
class ProcessNonIDPResponseMessageResponse:
240+
def __init__(self,
241+
SuccessfulAuthentication: bool = False,
242+
Error: str = "",
243+
Email: str = "", ):
244+
self.SuccessfulAuthentication = SuccessfulAuthentication
245+
self.Error = Error
246+
self.Email = Email
247+
248+
def to_json(self):
249+
return {
250+
"successful_authentication": self.SuccessfulAuthentication,
251+
"error": self.Error,
252+
"email": self.Email,
253+
}
254+
255+
256+
class Auth:
257+
"""Auth definition class for performing custom auth within Mythic
258+
259+
260+
Attributes:
261+
name:
262+
name for this auth service that appears in the Mythic UI
263+
description:
264+
description about what this auth service provides that appears in the Mythic UI
265+
idp_services:
266+
list of names of IDP services you want to expose into the Mythic UI for users to select
267+
non_idp_services:
268+
list of names of Non-IDP auth options you want to expose into the Mythic UI for users to select
269+
270+
Functions:
271+
272+
"""
273+
name: str = ""
274+
description: str = ""
275+
idp_services: [str] = []
276+
non_idp_services: [str] = []
277+
278+
get_idp_metadata: Callable[[GetIDPMetadataMessage], Awaitable[GetIDPMetadataMessageResponse]] = None
279+
get_idp_redirect: Callable[[GetIDPRedirectMessage], Awaitable[GetIDPRedirectMessageResponse]] = None
280+
process_idp_response: Callable[[ProcessIDPResponseMessage], Awaitable[ProcessIDPResponseMessageResponse]] = None
281+
get_non_idp_metadata: Callable[[GetNonIDPMetadataMessage], Awaitable[GetNonIDPMetadataMessageResponse]] = None
282+
get_non_idp_redirect: Callable[[GetNonIDPRedirectMessage], Awaitable[GetNonIDPRedirectMessageResponse]] = None
283+
process_non_idp_response: Callable[[ProcessNonIDPResponseMessage], Awaitable[ProcessNonIDPResponseMessageResponse]] = None
284+
285+
async def on_container_start(self, message: ContainerOnStartMessage) -> ContainerOnStartMessageResponse:
286+
return ContainerOnStartMessageResponse(ContainerName=self.name)
287+
288+
def get_sync_message(self):
289+
idp_subs = [json.dumps({"name": x, "type": "idp"}) for x in self.idp_services]
290+
non_idp_subs = [json.dumps({"name": x, "type": "nonidp"}) for x in self.non_idp_services]
291+
return {
292+
"name": self.name,
293+
"type": "auth",
294+
"description": self.description,
295+
"subscriptions": idp_subs + non_idp_subs
296+
}
297+
298+
299+
authServices: dict[str, Auth] = {}

0 commit comments

Comments
 (0)