32位彙編第三講,RadAsm,IDE的配置和使用,以及彙編代碼注入方式

 

 

    32位彙編第三講,RadAsm,IDE的配置和使用,以及彙編代碼注入方式

一丶RadAsm的配置和使用

用了怎麼長時間的命令行方式,咱們發現了幾個問題c++

1.沒有代碼提醒功能編程

2.編寫代碼很慢,記不住各類聲明windows

那麼如今有大神,已經幫咱們作了一個IDE環境,就是RadAsm,首先簡單介紹一下界面安全

(對於這個IDE(最新版是3.0)我已經打包好了,有中文版本,和英文版本)app

咱們須要配置一下環境函數

1.配置編譯環境,配置lib文件庫,配置Debug調試器

打開後會彈出工具

 

1.1 配置調試器路徑

首先這裏咱們注意下面的幾個選項字體

1.編譯選項 Assemble : 這個是默認的便可,若是你是編譯32位程序,那麼咱們就用 /c /coff 便可,後面幾個默認spa

2.鏈接選項 link:  通常是默認的,他是默認生成windows的程序,若是咱們有控制檯的程序,那麼咱們能夠手工去編譯,命令行

也能夠經過它的項目,新建項目的時候選擇指定的

3.擴展的調試器 External debugger: 這個則配置咱們od所在的路徑便可,3.0版本已經能夠支持選擇調試器了,之前的版本則是你指定文件夾,默認的調試器是Ollydbg.exe,因此咱們名字還要改成這個才能夠

4.library: 庫的路徑,有時候你編寫彙編程序,會使用lib庫,也會使用inc文件,那麼能夠把咱們昨天的MASM32的庫路徑放到這裏,也能夠用高版本的,好比vc++6.0的,或者vs系列的都是能夠的

注意:

  上面配置的編譯選項,以及鏈接選項,咱們都是安裝的MASM32的,也就是昨天提供的工具,咱們把它的路徑設置爲環境變量,這樣就能夠用編譯的指令了,例如 /c /coff ....,若是你沒有安裝,或者沒有配置環境變量,那麼計算機就會找不到編譯器,進而你的/c /coff就是錯誤的,因此咱們還須要設置環境變量

1.2 RadAsm 3.0版本設置環境變量

  上面咱們已經設置了調試器.下面咱們設置環境變量

點擊 Option -> Environment

彈出界面

能夠看到有三個路徑:

path include lib

分別加上咱們的MASM 目錄便可.

例如Path

你的Masm路徑\bin

include 路徑

 

 lib 路徑同上

 建議使用Radasm 3.0 雖然是英文版.都是單詞都很簡單. 之前的我用了下有Bug. 例如程序運行以後不關閉.

2.RadAsm的字體設置,以及中文亂碼問題解決

關於RadAsm的字體,以及中文亂碼,網上有不少解決方法,這裏我只對當前最新版本的RadAsm3.0作一個講解

選擇代碼編輯

從上往下看

1.第一個紅框,選擇的是Masm的背景顏色,以及主題,這個能夠自由設置很少作講解

2.第二個紅框,Tab Size 4,這裏是編寫彙編代碼的時候Tab製表符,的距離,咱們能夠設置爲2個

3.第三個紅框,分別有個Code(代碼按鈕),和Line Number(行號的按鈕)

這裏則是設置代碼字體的大小,還有行號顯示的大小

首先中文亂碼問題,打開code(代碼編輯)

在這裏設置代碼字體的時候,必定注意要把下面的語言換成  ""中文 GB2312 " 而不是默西歐語言

選擇了便可解決中文亂碼的問題

 三丶創建RadAsm工程,以及編譯編譯鏈接,和調試

1.打開 Project(項目) - > new Project(新建項目)

2.選擇項目編譯的語言,(這裏我使用masm),選擇項目生成的路徑

默認便可

編寫咱們的第一段代碼,而且調試輸出

1,編譯鏈接一塊兒執行

,

快捷鍵是Ctrl + F5  編譯運行

1.編譯快捷鍵 是 F5 會生成obj中間文件

3.連接快捷鍵是 Ctrl + Alt + F5   將obj文件生成exe

4. 編譯並鏈接 shift + alt + f5 直接將編譯鏈接在一塊兒了.

4.調試快捷鍵是 Ctrl + D 它會默認打開咱們的OD調試器,而且附加咱們的程序,咱們試一下

 

打開了咱們的OD調試器,而且開始調試了

 

打開了咱們的OD調試器,而且開始調試了

其他功能,本身嘗試,若是不會配置,也能夠在下方評論,那麼我看到則會幫你解決,而後若是有好心人看到也會幫你一把

 二丶彙編程序的注入代碼,注入32位計算機,而且彈出個信息框

一丶遠程線程注入的講解

在講解彙編程序注入代碼的時候,咱們須要先明白,遠程線程注入的原理,我會寫一個遠程線程開發的例子,這樣有助於咱們理解彙編注入

咱們總共須要幾步

     /*1.查找窗口,獲取窗口句柄*/

    /*2.根據窗口句柄,得到進程的PID*/

    /*3.根據進程的PID,得到進程的句柄*/

    /*4.根據進程的句柄,給進程申請額外內存空間*/

    /*5.調用WriteProcessMemory,給進程寫入DLL的路徑*/

    /*6.建立遠程線程,執行咱們的代碼*/

    /*7.調用退出代碼,釋放遠程線程的dll*/

每一步單獨講解

咱們新建一個MFC 對話框程序,添加一個按鈕,這個按鈕專門響應注入的實現

第一步: 查找窗口,得到窗口句柄(採用WindowsAPI FindWindow,傳入窗口名稱,而後找到則返回對應的窗口句柄)

    HWND hWnd = FindWindow("","計算器");
    if(NULL == hWnd)
    {
        return;              //失敗則返回
    }

第二步: 根據窗口句柄,查找進程PID (調用 GetWindowThreadProcessId API,傳入窗口句柄,而後經過第二個參數把進程的PID給咱們的參數)

  

  /*2.根據窗口句柄,得到進程的PID*/
    DWORD DwPid = 0;
    GetWindowThreadProcessId(hWnd,&DwPid); //這個函數會返回線程的ID,可是咱們不關心,因此沒有加返回值

第三步: 根據進程PID,返回進程的句柄(OpenProcess,參數一,權限 參數二,句柄是否繼承,參數三,進程的pid)

 /*3.根據進程的PID,得到進程的句柄*/
    HANDLE hProHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,DwPid);  //參數一,選擇全部權限,參數二,不繼承給false,參數三,給咱們上面得到的pid的值
    if(NULL == hProHandle)
    {
        return;
    }

第四步: 給遠程進程申請空間,而且返回空間的首地址(調用的API 是VirtualAllocEx)

/*4.根據進程的句柄,給進程申請額外內存空間*/
    LPVOID lpAddr = VirtualAllocEx(hProHandle,NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
    if(NULL == lpAddr)
    {
        return ;
    }
VirtualAllocEx說明:
第一個參數: 進程的句柄
第二個參數: 指定位置分配內存,給NULL爲默認幫咱們找塊地方申請內存(不過這個地址會返回,因此不關心)
第三個參數: 內存分配多大,咱們給了4096個字節大小,也就是一個分頁(1000H)
第四個參數: 是否當即申請,仍是保留這塊內存,只能給咱們用,可是還沒申請,咱們選擇當即申請
第五個參數: 權限,你申請的這塊內存是什麼內存,只能讀,仍是隻能寫,仍是隻能執行,咱們選擇所有,可讀可寫可執行

第五步:調用WriteProcessMemory將咱們的Dll路徑,寫入到遠程進程中

/*5.調用WriteProcessMemory,給進程寫入DLL的路徑*/
    char szBuf[MAX_PATH] = {NULL};
    GetCurrentDirectory(sizeof(szBuf),szBuf); //這三行代碼主要是拼接咱們的DLL,DLL是咱們本身寫的
    strcat(szBuf,"StaticDll.dll");       //DLL這裏就不寫了,用個人吧,我會發上去的
BOOL bRet
= WriteProcessMemory(hProHandle,lpAddr,szBuf,strlen(szBuf)+1,NULL); if(!bRet) { return; }
WriteProcessMemory講解:
第一個參數: 進程的句柄,能夠用咱們上面的OpenProcess返回的
第二個參數: 你要寫入的地址,地址使咱們VirtualAllocEx申請以後返回的(就是你要往哪一個地址寫內容)
第三個參數: 你寫入的內容是什麼,寫入的內容使咱們的Dll路徑,上面已經拼接好了
第四個參數: 你寫入的內容的大小是多大,這裏咱們用strlen求出來了
第五個參數: 實際寫入的個數,咱們不關心,若是你想知道,則定義一個變量,而後 取地址傳入便可,由於是個指針

第六步: 遠程進程開闢線程,調用LoadLibrary,加載咱們的dll,而大家知道,當dll被加載的時候,會有信息

因此咱們在咱們的dll裏面寫入咱們本身的代碼,好比這個dll被加載的時候,咱們執行咱們的代碼,

這裏個人代碼就是找到計算器,而後給它加個菜單,而且響應消息

    HANDLE hThreadHandle = CreateRemoteThread(hProHandle,
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)LoadLibrary,
        lpAddr,
        0,
        NULL);
核心代碼就在這裏,咱們必需要知道,咱們如今加載咱們的DLL,而咱們的DLL被加載的時候,就要執行本身的代碼
因此這個時候就能夠執行代碼了
CreateRemoteThread講解:
第一個參數: 進程的句柄(你要往哪一個進程開闢線程)
第二個參數: 安全屬性,句柄能否繼承,不須要給NULL
第三個參數: 棧的大小,給0則默認
第四個參數: 函數執行,咱們要開闢線程,開闢的線程叫作loadLibrary
第五個參數: 開闢線程傳入的參數,咱們知道,線程只有一個參數,而如今正好load也是一個參數,因此加載的參數就是咱們的
寫入遠程進程內存的dll路徑,而dll路徑一旦啓動,則會執行本身的代碼(核心,必定掌握)
第六個參數: 建立的標誌,默認給0
第七個參數: 線程的ID,不須要知道,給NULL

咱們嘗試一下是否能夠成功注入計算器,而且加入菜單

已經成功注入了.對於完整的代碼,我會放到課堂資料中,可是這幾步,必定要親自手動弄明白

(備註: 我是使用VC++6.0編寫代碼,是MFC程序,固然你也能夠用高版本,參考我這個,是同樣的

對於DLL,我也會發,大家能夠本身去寫本身的DLL,好比一個空DLL會有DLL main,也就是dll的入口點

當第一次加載的時候會來信息什麼的,因此能夠在裏面寫代碼.dll靠本身,這裏只提供思路)

二丶彙編代碼的注入

注意,別看博客天天內容不多,其實你想真正掌握,沒有2-3個小時就不算掌握,當你真正明白這個知識點了,那才叫掌握,而不是看一遍就走的,自覺得已經會了,千萬不要眼高手低

好比上面的遠程線程注入,原理是什麼,雖然我代碼給你了,當你知道原理了,那麼代碼本身就會寫了

原理: 原理就是找到進程,利用VirtualAllocEX給他開闢個空間,利用他的返回值,會返回這個空間的地址

而後再利用WriteProcessMemory給這塊空間寫入DLL的路徑,最後利用遠程線程(CreateRemoteThread)

把loadlibrary當作線程回調執行,傳入的參數就是遠程進程空間咱們寫入的DLL路徑,

這樣至關於當另外一個進程 調用了LoadLibray,而且加載咱們的DLL,而利用DLL被加載會執行的機制,

而後在咱們的DLL中寫入被加載時候的代碼便可.

(對於爲何咱們肯定loadlibary在遠程進程中,其實這個是系統的特性,重要你軟件一啓動,就必然要有dll的支持

而咱們調用的loadlibary就在這些dll中)

廢話補多少,會的人請看今天重要的知識,彙編代碼注入

首先,前邊介紹了RadAsm的IDE環境,那麼咱們利用他創建一個Dlg彙編程序

1.首先,新建工程,建立一個窗口程序

(由於對於RadAsm3.0不太熟悉,因此這裏不用3.0了,仍是用2.2.2.0)

選擇win32 app

選擇 dialog app

生成的時候注意ID和窗口名

,對於ID,和IDname,咱們須要本身去定義宏

而後在窗口過程函數相應咱們的消息

注意,對於資源,咱們必須單獨編譯,快捷鍵是 shift + F5

Ctrl + F5 編譯運行

如今已經能夠正常執行了

咱們OD看一下,

Ctrl + D

下斷點以後,消息來了,咱們知道了WM_COMMAND消息是0x111,因此就直接調用MessageBox函數了

 開始遠程線程彙編代碼的編寫(因時間問題,今天只會講解一個思路,具體的實現代碼回去本身去寫一下)

明天公佈答案,以及坑

看彙編代碼,咱們會執行上面的那幾個步驟

先把變量定義出來

  LOCAL @hWnd:HWND              ;查找窗口返回窗口句柄
  LOCAL @hProcessHandle:HANDLE: ;進程句柄
  LOCAL @dwPid:DWORD            ;進程的PID
  LOCAL @lpBuf:PVOID            ;遠程進程開闢空間的首地址
  LOCAL @hThread:HANDLE         ;線程的句柄
  LOCAL @dwExitCode:DWORD       ;退出代碼,獲取的是遠程load的返回值
                    ;這些變量都是定義在窗口過程函數中

第一步,判斷按鈕ID,而且查找窗口句柄

;1.解析低位,得到按鈕消息,而且查找窗口句柄
    invoke FindWindow,NULL, offset g_szWindowName
    mov @hWnd,eax     ;把返回值給@hWnd
     .if eax == NULL
      ret
    .endif

第二步:得到進程的PID

invoke GetWindowThreadProcessId, @hWnd, addr @dwPID

第三步: 得到進程句柄

invoke OpenProcess,PROCESS_ALL_ACCESS, FALSE, @dwPID

  mov @hProcess, eax
  .if eax == NULL
   ret
  .endif

第四步:申請內存空間

invoke VirtualAllocEx,@hProcess, NULL, 1000h, MEM_COMMIT, PAGE_EXECUTE_READWRITE
        mov @lpBuff, eax
        .if eax == NULL
          invoke ShowLastError
          ret
        .endif

第五步: 直接寫入代碼,寫入(按照之前,是往內存寫入DLL路徑,這裏咱們把代碼寫進去)

invoke WriteProcessMemory,@hProcess, 
                                   @lpBuff, 
                                   INJECT_CODE,         ;代碼的標號
                                   start - INJECT_CODE,     ;起始位置-標號等於實際大小
                                   NULL

標號是寫在代碼區的上面的

一會OD調試一下看看

至於爲何寫入的代碼要ret 4,也就是start上面的那句話,是由於

下面咱們調用CreateRemoteThread的時候,其中一個參數是@lpbuf,咱們是當作函數調用的,因此壓入一個返回地址

第六步: 建立遠程線程

invoke CreateRemoteThread,@hProcess, NULL, 0, @lpBuf, NULL, 0, NULL
        mov @hThread, eax
        .if eax == NULL
          ret
        .endif

        invoke WaitForSingleObject,@hThread, INFINITE  等待結束
        invoke GetExitCodeThread, @hThread, addr @dwExitCode 獲取loadlibrary的返回值
他的返回值實際上是dll在內存中的實例句柄,因此咱們須要釋放掉.(釋放本身能夠搜一下,暫時先把主要的講了)

OD分析 明天講解,今天先熟悉一下代碼,內容比較多,消化一下

 課堂資料:

  連接:http://pan.baidu.com/s/1o7B9f2i 密碼:5kcu

相關文章
相關標籤/搜索