Skip to main content

0404 | Extending Python

The Python package managers

  • a package contains a bundle of files which are required for a module to work
  • modules are libraries of existing code which we can use and call in our program
  • pip | package manager for python
  • install pwntools
    • newest release
      • pip install pwntools
    • specific version
      • pip install pwntools==4.13.0
  • test pwntools install
    • launch interactive python
      from pwn import *
      exit()
  • uninstall package
    • pip uninstall pwntools
  • list installed libraries
    • pip list
    • pip freeze
  • use "requirements.txt" for multiple packages
    • example | "requirements.txt"
      pwntools==4.13.0
      py-cpuinfo==9.0.0
      py-sneakers==1.0.1
    • install it with pip
      • pip install -r requirements.txt

Python virtual environments

  • great for solving dependency conflicts
  • a virtual environment enables you to create an isolated python environment which is not dependent on other virtual environments or packages installed on the host system
  • by default | the new virtual environment does not include ANY packages | clean slate
  • installing
    • pip install virtualenv
    • or in my experience on kali
      • sudo apt install python3.11-venv
  • using it
    • create working dir
      • mkdir virtual-demo; cd virtual-demo
    • create virtual environment
      • python3 -m venv env
    • activate the environment
      • source env/bin/activate
    • install pwntools
      • pip install pwntools
    • deactivate the environment
      • deactivate

Introduction to sys

  • provides functions and variables related to the python runtime environment
    • example | gives access to data sent as part of the command line arguments when executing a python script
  • standard library --> comes packaged with python
  • gives access to some low level functions | like flush
  • example | "sys-demo.py" | (play around with commenting/uncommenting as you see fit)
    import sys

    # version information of the python interpreter
    print(sys.version)
    # current executable binary
    print(sys.executable)
    # current platform
    print(sys.platform)

    # read from standard input -- stdin -- (filehandle)
    #for line in sys.stdin:
    # if line.strip() == "exit":
    # break
    # sys.stdout.write(">> {}".format(line))

    # flush the buffer
    for i in range(1,5):
    sys.stdout.write(str(i))
    sys.stdout.flush()

    # flush the buffer
    for i in range(1,5):
    print(i)

    # cool status bar denoting the progress of cracking
    import time
    for i in range(0, 51):
    # time.sleep(0.1)
    time.sleep(0) # to speed up execution for testing
    # use carrige return \r to jump to the start of the line each time
    sys.stdout.write("{} [{}{}]\r".format(i, '#'*i, "."*(50-i)))
    sys.stdout.flush()
    sys.stdout.write("\n")

    # ACCESSING COMMAND LINE ARGUMENTS
    # list of the command line arguments
    print(sys.argv)

    # check number of args
    if len(sys.argv) != 3:
    print("[X] To run {} enter a username and password".format(sys.argv[0]))
    sys.exit(5)

    # assigning the cmd arguments
    username = sys.argv[1]
    password = sys.argv[2]

    print("{} {}".format(username, password))

    # access the path where python will search for modules
    print(sys.path)
    print("-"*50)
    # access the modules we have access to
    print(sys.modules)

    # exit code
    # return value after script is executed
    # indicating running success or failure
    # if everything went fine --> 0
    # verify it with `echo $?`
    sys.exit(0)

Introduction to requests

  • to make and process http requests in python
  • test-site | http-bin.org | just an http request/response service
    • it will reflect our data back to us
  • install
    • pip install requests
    • comes preinstalled on kali
  • by default | request will perform redirects for all verbs, except for head
  • example | "requests-demo.py" | (play around with commenting/uncommenting as you see fit)
    import requests

    # x = requests.get('http://httpbin.org/get')
    # # test the service -- `curl -I http://httpbin.org/get`
    # # -- (-I:fetch the headers only)

    # # check the headers
    # print(x.headers)
    # # check a specific header
    # print(x.headers['Server'])
    # # check status code
    # print(x.status_code)

    # if x.status_code == 200:
    # print("Success!")
    # elif x.status_code == 404:
    # # like for x = requests.get('http://httpbin.org/get123123')
    # print("Not found!")

    # # check how much time has elapsed from sending the request
    # # to receiving the response
    # print(x.elapsed)

    # # check the cookies -- cookiejar object containing all the cookies
    # print(x.cookies)

    # # check the returned contents -- in bytes -- the FULL response
    # print(x.content)
    # # check the response -- in UNICODE
    # print(x.text)

    # # create a requests with parameters
    # x = requests.get('http://httpbin.org/get', params={'id':'1'})
    # print(x.url)
    # # specify the parameters in the requesting url
    # x = requests.get('http://httpbin.org/get?id=2')
    # print(x.url)

    # # specify additional information -- headers -- it is reflected in the response
    # x = requests.get('http://httpbin.org/get', params={'id':'3'}, headers={'Accept':'application/json'})
    # print(x.text)
    # # specify additional information -- headers -- it is reflected in the response
    # x = requests.get('http://httpbin.org/get', params={'id':'3'}, headers={'Accept':'application/json', 'test_header':'test'})
    # print(x.text)

    # ##### DELETE request
    # x = requests.delete('http://httpbin.org/delete')
    # print(x.text)

    # ##### POST request -- data included as form
    # x = requests.post('http://httpbin.org/post', data={'a':'b'})
    # print(x.text)
    # x = requests.post('http://httpbin.org/post', data={'a':'b', 'c':'d', 'e':'f'})
    # print(x.text)

    # # upload multipart encoded files
    # # picture downloaded from google.com -- the logo
    # # file is sent as in base64 encoded format
    # files = {'file': open('google.png', 'rb')}
    # x = requests.post('http://httpbin.org/post', files=files)
    # print(x.text)

    # ###### HANDLING BASIC AUTHENTICATION
    # x = requests.get('http://httpbin.org/get', auth=('username','password'))
    # print(x.text)
    # # this is sent: "Authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQ=",
    # # checking it -- `echo -ne dXNlcm5hbWU6cGFzc3dvcmQ= | base64 -d`
    # translates to username:password

    ###### WORKING WITH SSL CERTS
    # verify bad ssl cert --> certificate has expired error
    # x = requests.get('https://expired.badssl.com')
    # force it -- no error but a warning
    # x = requests.get('https://expired.badssl.com', verify=False)


    ###### REDIRECTS
    # # not really readable
    # x = requests.get('http://github.com')
    # print(x.headers)
    # # check it with curl -- `curl -I http://github.com`
    # # -- 301 redirect to https://github.com

    # # specify disallowing redirects
    # x = requests.get('http://github.com', allow_redirects=False)
    # print(x.headers)

    # ##### TIMEOUTS -- waiting for the response
    # # will throw an error -- will time out
    # x = requests.get('http://httpbin.org/get', timeout=0.01)
    # print(x.content)

    ###### STATEFUL request -- persising data across sessions -- SESSIONS
    # x = requests.get('http://httpbin.org/cookies', cookies={'a':'b'})
    # print(x.content)

    # # better with sessions
    # x = requests.Session()
    # x.cookies.update({'a':'b'})
    # print(x.get('http://httpbin.org/cookies').text)
    # # will do with every subfrequent request -- no need to specify again
    # print(x.get('http://httpbin.org/cookies').text)

    # ##### PARSING THE JSON RESPONSE AS JSON
    # x = requests.get('https://api.github.com/events')
    # print(x.json())

    ##### Working with other data -- not just text
    # download and save a picture
    x = requests.get('https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png')
    with open('google2.png', 'wb') as f:
    f.write(x.content)

Introduction to pwntools

  • a capture the flag framework and exploit development library
  • includes features to interact with processes locally and remotely
  • encode/pack/unpack data
  • works with different architectures/contexts
  • install pwntools
    • pip install pwntools
  • example | "pwntools-demo.py" | (play around with commenting/uncommenting as you see fit)
    from pwn import *
    # imports the functionality into the global namespace
    # we can call the functions directly

    # # create a cyclic pattern for buffer overflows
    # # for identifying the offset
    # print(cyclic(50))
    # # identify a position -- offset
    # print(cyclic_find("laaa"))

    # ##### shellcode and assembly
    # print(shellcraft.sh())
    # # assembly for execve -- /bin///sh

    # # print it in assembly
    # print(hexdump(asm(shellcraft.sh())))

    # ##### processes -- LOCAL
    # # start a local process -- sh
    # p = process("/bin/sh")
    # # send a command
    # p.sendline("echo hello;")
    # # start an interactive terminal
    # p.interactive()

    # ##### processes -- REMOTE -- start netcat listener before running
    # # netcat listener -- `nc -lp 1234`
    # # start a remote process -- sh
    # # establish connection and start process
    # r = remote("127.0.0.1", 1234)
    # # send a hello
    # r.sendline("hello!")
    # # start interactive session
    # r.interactive()
    # # close connection
    # r.close()

    # ##### PACKING/UNPACKING NUMBERS
    # # packing
    # print(p32(0x13371337))
    # # unpacking
    # print(hex(u32(p32(0x13371337))))

    # ##### LOADING FILES
    # # load the file
    # l = ELF('/bin/bash')
    # # check base address -- information about how it was compiled
    # print(hex(l.address))
    # # check entrypoint
    # print(hex(l.entry))

    # # check the address of a specific symbol from the global offset table
    # print(hex(l.got['write']))

    # # grab info about a specific symbol from the procedure linkage table
    # print(hex(l.plt['write']))

    # ###### searching in an ELF file

    # # search for the /bin/sh string the the file and grab the addresses
    # # null terminator at the end
    # for address in l.search(b'/bin/sh\x00'):
    # print(hex(address))


    # # search for a specific address in the elf file
    # # look for the jump esp gadget
    # # next() -- the first instance found
    # print(hex(next(l.search(asm('jmp esp')))))

    # ###### ROP -- automatised -- no need to load and search
    # r = ROP(l)
    # print(r.rbx)


    ##################### ENCRYPTION/ENCODING/HASHING FUNCTIONS

    # print(xor("A","B"))
    # # verify
    # print(xor(xor("A","B"), "A"))

    # # base64 encoding
    # print(b64e(b"test"))
    # # base64 decoding
    # print(b64d(b"dGVzdA=="))

    # # md5sum-s
    # print(md5sumhex(b"hello"))

    # # sha1
    # print(sha1sumhex(b"hello"))

    ###### LOWER LEVEL FUNCTIONS
    print(bits(b'a'))
    # verify
    print(unbits([0, 1, 1, 0, 0, 0, 0, 1]))