1. 程式人生 > >程序注入的學習(下)

程序注入的學習(下)

轉載請宣告出處:http://www.cnblogs.com/predator-wang/p/5076681.html

 

5. 無DLL注入(遠端程式碼注入)

在第三中方法種,我們啟動遠端執行緒時,執行緒函式是我們從Kernel32.dll中取得的LoadLibrary函式的地址為執行緒函式的地址,其實我們可以直接將執行緒函式體和函式引數寫入目標程序的地址空間,然後建立遠端執行緒。

使用這個方法時,需要注意以下幾個問題

(1) 遠端執行緒函式體不得使用kernel32.dll,user32.dll以外的函式。因為這個兩個模組在各個程序的相對地址是一樣的,如果一定要使用其它函式,則必須將函式體寫入目標程序空間。

(2) 不能使用任何字串常量,因為字串常量是存放在PE檔案裡.data這個段裡面的,函式裡儲存的只是相對地址。

 

(3) 去掉編譯器的/GZ編譯選項,這個選項是用來Enable Stack Frame Run-Time Error Checking。當這個選項開啟時,編譯器會在每個函式中加入一些程式碼,用來檢驗ESP在函式體中是否被改變,但是這些檢驗函式的地址在不同PE檔案中 有可能是不一樣的。

 

(4) 不得使用增量連結(incremental linking)。增量連結是編譯器為了減少連結時間做的處理,把函式體用一個JMP指令代替,這樣就可以隨意改變函式的內容,而不用修改CALL指令。

 

(5) 不要在函式體內使用超過4kb的區域性變數。區域性變數是存放在棧中的,例如下面這個函式

 

:00401000   push ebp

 :00401001   mov  ebp, esp

 

 :00401003   sub  esp, 00000100           ; change ESP as storage for

 

                                          ; local variables is needed

 

 :00401006   mov  byte ptr [esp], 00      ; var[0] = 0;

 

 :0040100A   mov  byte ptr [esp+01], 01   ; var[1] = 1;

 

 :0040100F   mov  byte ptr [esp+FF], FF   ; var[255] = 255;

 

 :00401017   mov  esp, ebp                ; restore stack pointer

 

 :00401019   pop  ebp

 

 :0040101A   ret

 

 但是當局部變數的大小超過4kb時,棧指標並不直接改版,而是呼叫另一個函式來分配記憶體,這個函式有可能在不同程序中的地址不一樣。

 

(6) 函式體內switch語句中的case不要超過3個,否則編譯器會在PE檔案中使用跳轉表,而這個跳轉表有可能在目標程序中並不存在。

   下面是一個無DLL注入(程式碼注入)的例子:

例如我們要把程式碼注入到HW.exe中,HW.exe的原始碼很簡單,如下:

 

複製程式碼
#include <iostream>
#include <windows.h>
using namespace std;

int main()//指標陣列
{
    cout << "HelloWorld" << endl;
    MessageBoxW(NULL, L"hello", L"hello", MB_OK);
    system("pause");
    return 0;
}
複製程式碼

 

檢視程序ID:

實現注入程式碼的程式NoDLLInject.exe:

複製程式碼
#include <iostream>
#include <Windows.h>
#include <string.h>
#include <tchar.h>

using namespace std;

typedef struct _RemotePara{
    PVOID dwMessageBox;
    wchar_t strMessageBox[12];
}RemotePara;
// 遠端執行緒執行體  

DWORD __stdcall ThreadProc(RemotePara *Para)
{
    typedef int( *PMessageBox) (HWND, LPCWSTR, LPCWSTR, UINT);
    PMessageBox MessageBoxFunc = (PMessageBox)Para->dwMessageBox;
    MessageBoxFunc(NULL, Para->strMessageBox, Para->strMessageBox, MB_OK);

    return 0;
}


void EnableDebugPriv()   
{
    HANDLE hToken;
    LUID sedebugnameValue;
    TOKEN_PRIVILEGES tkp;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
        return;
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
    {
        CloseHandle(hToken);
        return;
    }
    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = sedebugnameValue;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL))
    {
        CloseHandle(hToken);
    }
}

int main(int argc, char *argv[])
{
    DWORD THREADSIZE = 1024;
    DWORD pID = 23060;
    DWORD byte_write;
    HANDLE hRemoteProcess, hThread;
    RemotePara myRemotePara, *pRemotePara;
    void *pRemoteThread;
    HINSTANCE hUser32;
    

    hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
    cout << hRemoteProcess << endl;

    if (!hRemoteProcess)
        return 0;
    // 在遠端程序地址空間分配虛擬記憶體  
    pRemoteThread = VirtualAllocEx(hRemoteProcess, 0, THREADSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    cout << pRemoteThread << endl;
    if (!pRemoteThread)
        return 0;
// 將執行緒執行體ThreadProc寫入遠端程序  
    
    if (!WriteProcessMemory(hRemoteProcess, pRemoteThread, &ThreadProc, THREADSIZE, 0))
    {
        VirtualFreeEx(hRemoteProcess, pRemoteThread, 1024, MEM_RELEASE);
        return 0;
    }
    //cout << &ThreadProc << endl;
    ZeroMemory(&myRemotePara, sizeof(RemotePara));

    hUser32 = LoadLibraryW(L"user32.dll");
    myRemotePara.dwMessageBox = (PVOID)GetProcAddress(hUser32, "MessageBoxW");
    cout << myRemotePara.dwMessageBox << endl;
    wcscat(myRemotePara.strMessageBox, L"Hello!"); //複製MessageBox函式的引數  
    //寫進目標程序       
    pRemotePara = (RemotePara *)VirtualAllocEx(hRemoteProcess, 0, sizeof(RemotePara), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    cout << pRemotePara << endl;
    if (!pRemotePara)
        return 0;
    if (!WriteProcessMemory(hRemoteProcess, pRemotePara, &myRemotePara, sizeof myRemotePara, 0))
    {
        VirtualFreeEx(hRemoteProcess, pRemotePara, sizeof(RemotePara), MEM_RELEASE);
        return 0;
    }
        
    // 啟動執行緒   
    hThread = CreateRemoteThread(hRemoteProcess, 0, 0, (LPTHREAD_START_ROUTINE)pRemoteThread, pRemotePara, 0, &byte_write);
    //myRemotePara.dwMessageBox(NULL, L"Hello", L"Hello", MB_OK);
    FreeLibrary(hUser32);
    CloseHandle(hRemoteProcess);

    system("pause");
    return 0;
}
複製程式碼

 

 注入成功:

實驗成功之前有個小插曲,就是同樣的NoDLLInject.exe,但是注入時就會報錯:

其原因就在於最開始被注入的HW.exe的原始碼是:

複製程式碼
#include <iostream>
#include <windows.h>
using namespace std;

int main()//指標陣列
{
    cout << "HelloWorld" << endl;
    system("pause");
    return 0;
}
複製程式碼

這裡沒有用到MessageBoxW,檢視其匯入表,也就沒有user32.dll:

相關推薦

程序注入學習

轉載請宣告出處:http://www.cnblogs.com/predator-wang/p/5076681.html   5. 無DLL注入(遠端程式碼注入) 在第三中方法種,我們啟動遠端執行緒時,執行緒函式是我們從Kernel32.dll中取得的LoadLibrary函式的地址為執行緒函式

IIC學習

過程 地址 i2c mage c學習 模塊 代碼 固定 fpga 這個黃色的模塊就是PCF8591,本設計中FPGA作為I2C主設備,PCF8591作為I2C從設備,從設備的地址由固定地址和可編程地址組成,我們的外設底板已將可編程地址A0、A1、A2接地. 詳細

實戰深度學習OpenCV庫

基本 numpy port 學習 test lin 庫文件 矩陣 價格 在上一節中,我們講到了OpenCV庫的安裝,現在我們來進行實戰,看如何利用Python來調用OpenCV庫。 一: 如果您的電腦是win10的系統,那麽請您按下win鍵,再按下空格鍵,輸入Pyth

如何發起、防禦和測試XSS攻擊,我們用DVWA來學習

上一篇我們瞭解了XSS攻擊的原理,並且利用DVWA嘗試了簡單的XSS攻擊,這一篇我們來實現更復雜的攻擊,然後探討防禦機制和測試理念。   前面我們通過指令碼注入讓網頁彈出了使用者cookie資訊,可以光彈窗是沒有什麼用的,接下來我們想辦法把這些資訊傳送出去。   2.1 使用反射型

NodeJS簡易部落格系統NodeJS入門學習

一、網路程式設計 1、小試牛刀 NodeJS本來的用途是編寫高效能Web伺服器。首先在這裡重複一下官方文件裡的例子,使用NodeJS內建的http模組簡單實現一個HTTP伺服器。 var http = require('http'); http.createSe

maven學習利用Profile構建不同環境的部署包

接上回繼續,專案開發好以後,通常要在多個環境部署,象我們公司多達5種環境:本機環境(local)、(開發小組內自測的)開發環境(dev)、(提供給測試團隊的)測試環境(test)、預釋出環境(pre)、正式生產環境(prod),每種環境都有各自的配置引數,比如:資料庫連線、遠端呼叫的ws地址等等。如果每個環境

Windows基礎篇學習

▲Windows登入密碼破解 使用啟動U盤破解(PE、深度) (U盤製作不多贅述) 使用U盤對C:\Windows\System32\config下的SAM檔案進行操作,在上文中對sam的講解中提到。 使用工具對hash破解(lc5、彩虹橋) 手動消除木馬 查詢開機啟動項

ORACLE學習

ORACLE學習(下) Select語句 Select語句功能 查詢語句語法 Select子句 From子句 Where子句 字串操作函式 CHAR和VARCHAR2型別 LONG和CLOB型別 LENGTH CONCAT和“||” UPPER、LOWER和INITCAP TRIM、LT

Linux 系統應用程式設計——程序間通訊

        在前面,我們學習了傳統的程序間通訊方式——無名管道(pipe)、有名管道(fifo)和訊號(signal)。         下面我們來學習 System V  IPC 物件: 1、共享記憶體(share memory); 2、訊號燈(semaohore);

Linux程序入門學習-認識程序

1.程序的概念 一個可執行的程式檔案(ELF格式)被載入到記憶體當中,然後讓CPU逐條執行其程式碼,根據程式碼作出相應的動作,這樣一個動態程序就產生了。因此,程序是一個動態變化的過程。 下面用一張圖來表示一個程式從編寫到最終執行的過程: 一段固化在磁碟

Linux程序入門學習-訊號通訊

訊號通訊 什麼是訊號? 在作業系統中,當我們無正常結束一程式時,可以用工作管理員強行結束這個程序。在unix/linux 中,具體的實現過程是通過程序A 生成一個訊號併發射出去,執行中的程序B捕獲到這個訊號然後根據這個訊號的特定意義做出相應的操作。 訊

Linux程序入門學習-程序啟動退出

1. 程序的退出 exit 函式用於程序退出 標頭檔案:#include <stdlib.h> 函式原型:void exit(int status); 引數:int status:退出狀態值(可以任意寫,值規定0 以上的正整數) 返回值:無

微信小程序開發學習

接受 ext 配置 微信小程序開發 onf error n) chan thead 一、各種JSON配置 1、小程序配置app.json 為小程序全局配置,包括所有頁面路徑、界面表現、網絡超時時間、底部tab等,類比APP開發中manifest配置。 2、工具配置proje

【半小時大話.net依賴注入詳解AutoFac+實戰Mvc、Api以及.NET Core的依賴注入

系列目錄 第一章|理論基礎+實戰控制檯程式實現AutoFac注入 第二章|AutoFac的使用技巧 第三章|實戰Asp.Net Framework Web程式實現AutoFac注入 第四章|實戰Asp.Net Core自帶DI實現依賴注入 第五章|實戰Asp.Net Core引入AutoFac的兩種方式

學號 2018-2019-20172309 《程序設計與數據結構》第三周學習總結

num 退出 單向 隊列 就是 5.1 選擇 ati imp 教材學習內容總結 教材學習內容總結 5.1 隊列概述 隊列的元素是按照FIFO方式處理的:第一個進入的元素,也就是第一個退出的元素。 隊列的處理方式與棧相反,棧的處理方式是LIFO。 隊列中的方法有enqueu

20172310 2017-2018《程序設計與數據結構》第四周學習總結

自己 yun class 插入 adt 調試 數組 清晰 增加 學號 2017-2018-2 《程序設計與數據結構》第四周學習總結 教材學習內容總結 第六章主要研究了列表的概念以及某些管理列表的方法。 列表集合 鏈表與列表集合之間的差別:鏈表是一種實現策略,使用引用來在對

20172310 2017-2018《程序設計與數據結構》第七周學習總結

列表 改進 詳細 運行 知識 null left 阻止 但我 20172310 2017-2018《程序設計與數據結構》(下)第七周學習總結 教材學習內容總結 本章學習的是二叉查找樹 11.1 概述 二叉查找樹(binay scarch tree)是種帶有附加屬性的二叉

程序注入學習

轉載請宣告出處:http://www.cnblogs.com/predator-wang/p/4792976.html 參考:http://andylin02.iteye.com/blog/459483 程序注入的方法分類如下:       帶DLL的注入 &

程序注入學習

轉載請宣告出處:http://www.cnblogs.com/predator-wang/p/5076279.html 3. 利用遠端執行緒注入DLL    1)、取得遠端程序的程序ID;   2)、在遠端程序空間中分配一段記憶體用來存放要注入的DLL完整路徑;&

PX4概念學習1——Linux程序、多執行緒基礎

【學習Freeape大神的uORB時,乘機補補有關Linux多程序、多執行緒的知識】 uORB(Micro Object Request Broker,微物件請求代理器)是PX4/Pixhawk系統中非常重要且關鍵的一個模組,它肩負了整個系統的資料傳輸任務,所有的感測器資料