It is really useful for a pentester to know about python and be able to script something. Being able to automate things can definitely help us go quicker in our daily practice. Of course we do not need to be a developer but it is very helpful to be able to read code.
notes from my practice, TCM Academy and DeepLearning.AI
shebang
For python our script need to have this shebang in the first line #!/bin/python3 this will allow us to launch the script using ./ myscript.py instead of python3 myscript.py
Strings
Print a string
#!/bin/python3print("Hello world!")# double quotesprint('Hello world!')# single quotesprint("""This string runsmultiple lines""")# triple quotes for multiple linesprint("This string is "+"awesome")# concatenation
Using f-Strings
f-Strings is useful to mix strings with computations or data
# Will print The temperature 75F in degrees celsius is 23.88888888888889Cprint(f"The temperature 75F in degrees celsius is {(75-32) *5/9}C")# It works also with multiligne stringsprint(f""" Most countries use the metric system for recipe measurement, but American bakers use a different system. For example, they use fluid ounces to measure liquids instead of milliliters (ml). So you need to convert recipe units to your local measuring system! For example, 8 fluid ounces of milk is {8*29.5735} ml. And 100ml of water is {100/29.5735} fluid ounces.""")# This will print''' Most countries use the metric system for recipe measurement, but American bakers use a different system. For example, they use fluid ounces to measure liquids instead of milliliters (ml). So you need to convert recipe units to your local measuring system! For example, 8 fluid ounces of milk is 236.588 ml. And 100ml of water is 3.381405650328842 fluid ounces.'''# It also works on variablesmy_name ="gabrielle"print(f"Hello {my_name}!")# this will print Hello gabrielle!# And we can mix var and computation as followfav_num =8print(f"Your favorite number plus 10 is {fav_num+10}")# this will print Your favorite number plus 10 is 18
type()
In Python, you can check the type of any data that you are using. To check the data type, you can use the type() function.
The order of operations in Python is the same as in arithmetic. First, you compute parentheses, then exponents, then you multiply and divide (from left to right), and finally, you add and subtract (from left to right).
#!/bin/python3print(50+50)# will add and print the resultprint(50-50)# will substract and print the resultprint(50+50)# will multiply and print the resultprint(50/50)# will divide and print the resultprint(50+50-50*50/50)# will calculate the equation and print the resultprint(50**2)# exponentsprint(50%6)# moduloprint(50//6)# no leftovers# convert from from Fahrenheit to Celsiusprint((75-32) *5/9)
Variables and Methods
#!/bin/python3mystring ="this is a string stored in a variable called mystring"print(mystring)# will print the content of the varprint(mystring.upper())# the upper() method will put the text in all capsprint(mystring.lower())# the lower() method will put the text in all lowerprint(mystring.title())# the title() method will capitalize the first letter of each wordprint(len(mystring))# the len method will print the number of chars in the var mystringname ="name"# stringage =7# intsize =2.4# floatprint(int(30.9))# will cast a float in an int and not round so the it will print 30age +=1# will add 1 to the initial ar so the valur will become 8
Functions
#!/bin/python3defwho_am_i(): name ="name" age =7print("my name is "+ name +"I am "+str(age) +" years old")who_am_i()#will call the function # function with a parameterdefadd_one_hundred(num):print(num +100)add_one_hundred(100)# will call the function and use the 100 as the parameter# Function with multiple parametersdefadd(x,y):print(x + y)add(7,7)# will call the function so it will add 7+7defmultiply(x,y):return x * yprint(multiply(7,7))# will print 49defsquare_root(x):print(x**.5)square_root(64)# will print 8.0defnl():print('\n')nl()# will save us time because we can just call the function instead of writing the print statement everytime we want a new line
Boolean Expressions
#!/bin/python3bool1 =Truebool2 =3*3==9bool3 =Falsebool4 =3*3!=9print(bool1,bool2,bool3,bool4)# will print True True False Falseprint(type(bool1))# will print <class 'bool'>
Relational and Boolean operators
#!/bin/python3greater_than =7>5# Trueless_than =5<7# Truegreater_than_equal_to =7>=7# Trueless_than_equal_to =7<=7# Truetest_and = (7>5) and (5<7) # Truetest_and2 = (7>5) and (5>7) # Falsetest_or = (7>5) or (5<7) # Truetest_or2 = (7>5) or (5>7) # Truetest_not =notTrue# False
Conditional Statements
#!/bin/python3defdrink(money):if money >=2:return"You got a drink"else:return"no drink for you"print(drink(3))print(drink(1))defalcohol(age,money):if (age >=21) and (money >=5):return"We're getting a drink"elif (age >=21) and (money <5):return"Come back with more money"elif (age <21) and (money >=5):return"Nice try kid!"else:return"You're too poor and too young"print(alcohol(21,5))print(alcohol(21,4))print(alcohol(20,4))
Lists (mutable)
Declare a list
friends_list = ["Tommy","Isabel","Daniel"]print(friends_list)# will print ['Tommy', 'Isabel', 'Daniel']len(friends_list)# will print 3print(friends_list[1])# Output: Isabel# add single element to listfriends_list.append("Otto")#using removefriends_list.remove("Tommy")
#!/bin/python3movies=["When Harry met Sally","movie2","movie 3","movi 4"] # this is a listprint(movies[0])# return first itemprint(movies[1:4])# will print from 2nd item to 3rdprint(movies[1:])# will print from 2nd item to last itemprint(movies[:2])# will print from begining of the list until the 1st item (so here only the first item)print(movies[-1])# will print the very last item of the listmovies.append("another movie")# add an item to the end of the listmovies.pop()# will remove the last item of the listmovies.pop(0)# will remove the first item of the listprint(len(movies) # print length of list
Tuples (immutable)
It is immutable meaning we can not use pop or append on them once it is declared it can not be modified.
#!/bin/python3grades=(""a,"b","c","d","e","f")print(grades[1])# will print b
Looping
For loops
Start to finish of an iterate
#!/bin/python3vegetables=["cucumber","spinach","cabbage"]for x in vegetables:print(x)
While loops
Execute as long as true
#!/bin/python3i=1while1<10:print(i) i++
Importing modules
#!/bin/python3import sys # systems functions and parametersfrom datetime import datetime as dt # import with alias + plus using from makes it to import only part of the moduleprint(sys.version)print(dt.now())
Advanced strings
#!/bin/python3my_name="myname"print(my_name[0])print(my_name[-1])sentence ="This is a sentence"print(sentence.split())# will split using space as a delimiter so it will take each word separatelysentence_split = sentence.split()sentence_join =' '.join(sentence_split)quote ="he said 'give me all your money'"# we can use single quotes in double quotes to keep the double quote from being escaped (would also work the other way around)quote ="he said \"give me all your money\""# we can also escape characters with \too_much_space =" hello "print(too_much_space.strip())print("A"in"Apple")# will print Trueprint("A"in"apple")# will print Falseletter ="A"word ="Apple"print(letter.lower() in word.lower())# improvedmovie ="movie"print("my favorite movie is {}.".format(movie))
Dictionaries
Key value pairs A Dictionnary is a data structure that helps you store key-value pairs. The main difference with list, is that dictionaries assign a key to each values instead of an index.
#!/bin/python3drinks ={"Drink1":7,"Drink2":10,"Drink3":8}# drink is the key, price is the valueprint(drinks)ice_cream_flavors ={"Mint Chocolate Chip":"Refreshing mint ice cream studded with decadent chocolate chips.","Cookie Dough":"Vanilla ice cream loaded with chunks of chocolate chip cookie dough.","Salted Caramel":"Sweet and salty with a smooth caramel swirl and a hint of sea salt."}employees ={"Finance": ["Bob","Linda","Tina"],"IT": ["Gene","Louise","Nicole"],"HR": ["Jimmy","Marty"]print(employees)employees['Legal'] = ["Mr. Frond"] # Add new key:value pairprint(employees)employees.update({"Sales": ["Adie", "Ollie"]})# Add new key:value pairprint(employees)drinks["Drink1"] = 8print(drinks)print(drinks.get("drink1"))
Sys
import sysimport time# get info on systemdefget_info():print(sys.version)print(sys.executable)print(sys.platform)# we can use sys for user input# Here it is going to wait for user input until user types exitdefuser_input():for line in sys.stdin:if line.strip()=="exit":break sys.stdout.write(">> {}".format(line))# writes on the same linedefoneline():for i inrange(1,5): sys.stdout.write(str(i)) sys.stdout.flush()# writes on different linesdefmultiplelines():for i inrange(1,5):print(i)# makes a progress bardefprogress_bar():for i inrange(0, 51): time.sleep(0.1) sys.stdout.write("{} [{}{}]\r".format(i, '#'*i, "."*(50-i))) sys.stdout.flush() sys.stdout.write("\n")# will print all args when the script is launcheddefprint_args():print(sys.argv)iflen(sys.argv)!=3:print("[X] To run {} enter a username and password".format(sys.argv[0])) username = sys.argv[1] password = sys.argv[2]print("{}:{}".format(username, password))# sys allows to access the path where python will search for modulesdefget_modulespath():print(sys.path)defget_all_modules():print(sys.modules)get_info()user_input()oneline()progress_bar()print_args()get_modulespath()get_all_modules()# Exit with an exit code mentionning everything was oksys.exit(0)# Note: to check exit code in terminal we can use echo $?
Reading and writing files
# file has to exist here we put a file in the same dirf =open("top-10.txt")print(f)f =open("top-10.txt", 'rt')print(f)print("-----")print("read")print(f.read())print("-----")f =open("top-10.txt", 'rt')print("readlines")print(f.readlines())# will not print content another timeprint(f.readlines())# will print content again if we ask for it with seekf.seek(0)print(f.readlines())# iterate over eachline and strip off charsf.seek(0)for line in f:print(line.strip())f.close()# write to a filef =open("test.txt", "w")f.write("test line!")f.close()# read it to see if it exists:f =open("test.txt")print(f.read())# append an existing filef =open("test.txt", "a")f.write("test line! again")# check resultsf =open("test.txt")print(f.read())# get info on the fileprint(f.name)print(f.closed)print(f.mode)# for larger file we can use the file objectwithopen('rockyou.txt', encoding='latin-1')as f:for line in f:pass
Sockets
We use socket to connect to an open port and an IP addess
#!/bin/python3import socketHOST='127.0.0.1'PORT='7777's = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# AF_INET is IPV4 SOCK_STREAM is the ports.connect((HOST,PORT))
To test our script we can launch netcat
nc -nlvp 7777
Building a port scanner
We can use socket to build a port scanner
#!/bin/python3import sysimport socketfrom datetime import datetime# usage: python3 scanner.py <IP-ADR># Define our targetiflen(sys.argv)==2: target = socket.gethostbyname(sys.argv[1])# Translate host name to IPV4else:print("Invalid amount of arguments")print("Syntax python3 scanner.py <IP-ADR>")# Add a bannerprint("-"*50)print("Scanning target "+target)print("Time started: "+str(datetime.now()))print("-"*50)try:for port inrange(1,65535): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) socket.setdefaultitmeout(1) result = s.connect_ex((target,port))# returns an error indicator if connection successful will return 0 otherwise will return 1if result ==0:print("Port {} is open".format(port)) s.close()# Make a clean exit if there is a keyboard interruption like ctrl+cexceptKeyboardInterrupt:print("\nExiting program. ") sys.exit()except socket.gaierror:print("Hostname could not be resolved.") sys.exit()except socket.error:print("Could not connect to server.") sys.exit()
This script is just and exercise (done in the PEH TCM course) so it definitely could be improved:
Handle other type of errors
...
Virtual Environments
We might sometimes need to use a version for a script and another version for another Create and isolate python virtual environments not dependant With virtualenv we can have multiple version of a package installed and usable in a system at the same time pip install virtualenv We can then create a folder and launch our virtual env in it:
mkdirvirtualdemocdvirtual-demopython3-mvenvenv
We then have to activate it:
sourceenv/bin/activate
And in our virtual environment we can install anything we need We can have multiple virtual environments running at the same time. One we finished with the virtualenv we can type deactivate
Using functions from a local file
We can create a file called helper_functions.py
We can then import our file in our other python script by using import.
# Imports a specific functionfrom helper_functions import myfunction# Imports every functionimport helper_functions# Imports every function using this we do not have to call the function using helper_functions.myfunctionfrom helper_functions import*
Built-in packages
The math package
# Import from the math package the cos, sin and pi functionsfrom math import cos, sin, piprint(pi)
The statistics package
from statistics import mean, stdevmy_friends_heights = [160,172,155,180,165,170,158,182,175,168]# calculate the mean valuemean(my_friends_heights)# calculate the standard deviationstdev(my_friends_heights)
The random package
from random import samplespices = ["cumin","turmeric","oregano","paprika"]vegetables = ["lettuce","tomato","carrot","broccoli"]proteins = ["chicken","tofu","beef","fish","tempeh"]# The sample function takes two parameters: the list you want to select from, and the number of items you want to selectrandom_spices =sample(spices, 2)random_vegetables =sample(vegetables, 2)random_protein =sample(proteins, 1)print(random_protein)
The pandas package
import pandas as pd creates a shortcut that you can use to avoid typing pandas.
# Dataset adapted from here https://www.kaggle.com/datasets/nehalbirla/vehicle-dataset-from-cardekhodata = pd.read_csv('car_data.csv')print(data)# Code to show only the cars with a price >= 10000print(data[data["Price"]>=10000])# Show all the cars from the 2015 print(data[data["Year"]==2015])filtered_data = data[data["Year"]==2015]print(filtered_data["Price"].median())
Package matplotlib
# Note the .pyplotimport matplotlib.pyplot as pltplt.scatter(data["Kilometer"], data["Price"])plt.title('Car Price vs. Kilometers Driven')plt.xlabel('Kilometers Driven')plt.ylabel('Price (in USD)')plt.show()# create a pie chart of the data showing how many cars were sold each year.import matplotlib.pyplot as plt# Assuming 'data' is your DataFrame and it has a 'Year' column# that indicates the year each car was sold# Step 1: Aggregate the data to count cars sold per yearcar_sales_per_year = data['Year'].value_counts()# Step 2: Create the pie chartplt.pie(car_sales_per_year, labels=car_sales_per_year.index, autopct='%1.1f%%')# Add a titleplt.title('Cars Sold Per Year')# Show the plotplt.show()
Package Beautiful soup
Beautiful soup is a python package to interpret HTML webpages inside python programs
Use APIs
Example with a weather API
import osimport requestsfrom dotenv import load_dotenv# Get the Weather API key from the .env file# https://openweathermap.org/price you need to set an env variable for the API keyload_dotenv('.env', override=True)api_key = os.getenv('WEATHER_API_KEY')# Store the latitude value in the 'lat' variablelat =37.4419# Palo Alto, CA# Store the longitude value in the 'long' variablelon =-122.1430url =f"https://api.openweathermap.org/data/2.5/forecast?units=metric&cnt=1&lat={lat}&lon={lon}&appid={api_key}"# Use the get function from the requests library to store the response from the APIresponse = requests.get(url)# Take the response from the API (in JSON) and assign it to a Python dictionarydata = response.json()# Print (will print all in json)print(data)# Get better looking resultstemperature = data['list'][0]['main']['temp']description = data['list'][0]['weather'][0]['description']wind_speed = data['list'][0]['wind']['speed']print(f"Temperature: {temperature}")print(f"Weather Description: {description}")print(f"Wind Speed: {wind_speed}")# Write a weather reportweather_string =f"""The temperature is {temperature}°C. It is currently {description},with a wind speed of {wind_speed}m/s."""print(weather_string)
By default our virtual env does not contains our previously installed python packages or any modules We can check which virtualenv is being called with which python3:
On our host (outside of our virtualenv) the same command gives this: