老技術,新學習,API HOOK MessageBox簡介 — 另外還收集了JMP指令的用法

來源:互聯網
上載者:User
// HookAPI.cpp : Defines the entry point for the console application.//// 總結:將原API函數指標前加一個彙編的0xe9無條件跳轉值, 將系統調用的API函數跳轉到自訂的函數上來執行#include "stdafx.h"#include <windows.h>#include <iostream>using namespace std;typedef int (WINAPI *pMessageBoxDef)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);char szOldMessageBox[5] = {0};char szJmpMyMessageBox[5] = {(char)0xe9}; // 0xe9, 程式無條件跳轉pMessageBoxDef pMessageBox = NULL;int WINAPI MyMessageBox(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType){wcout<<L"hWnd:"<<(int)hWnd<<endl;wcout<<L"lpText:"<<lpText<<endl;wcout<<L"lpCaption:"<<lpCaption<<endl;wcout<<L"uType:"<<uType<<endl<<endl;WriteProcessMemory((void*)-1, pMessageBox, szOldMessageBox, 5, NULL);MessageBoxW(hWnd, lpText, lpCaption, uType);WriteProcessMemory((void*)-1, pMessageBox, szJmpMyMessageBox, 5, NULL);return 0;}int main(){DWORD dwJmpAddr = 0;HMODULE hModule = LoadLibrary(_T("User32.Dll"));pMessageBox = (pMessageBoxDef)GetProcAddress(hModule, "MessageBoxW");dwJmpAddr = (DWORD)MyMessageBox - (DWORD)pMessageBox - 5;memcpy(szJmpMyMessageBox+1, &dwJmpAddr, 4);FreeLibrary(hModule);ReadProcessMemory((void*)-1, pMessageBox, szOldMessageBox, 5, NULL);//讀出原來的前5個位元組WriteProcessMemory((void*)-1, pMessageBox, szJmpMyMessageBox, 5, NULL);//寫入我們處理後的5個位元組MessageBoxW(GetForegroundWindow(), L"Inline Hook:MessageBox", L"HOOK API", MB_OK);MessageBoxW(GetForegroundWindow(), L"Hello World", L"Win32", MB_OK);return 0;}

//////////////////////////////////////////////////////////////////////////////////////////////

jmp指令 

解釋:

n       jmp為無條件轉移,可以只修改IP,也可以同時修改CS和IP;

n       jmp指令要給出兩種資訊:

n       轉移的目的地址

n       轉移的距離(段間轉移、段內短轉移,段內近轉移)

格式:

一.Jump short 標號

   這種格式的 jmp 指令實現的是段內短轉移,它對IP的修改範圍為 -128~127,也就是說,它向前轉移時可以最多越過128個位元組,向後轉移可以最多越過127個位元組。

 

樣本:

assume cs:codesg

codesg segment

  start:mov ax,0

          jmp short s

          add ax,1

       s:inc ax

codesg ends

end start

 

說明:上面的程式執行後, ax中的值為 1 ,因為執行  jmp short s 後 ,越過了add ax,1 ,IP 指向了標號 s處的 inc ax。也就是說,程式只進行了一次ax加1操作。

 

注意:

n       彙編指令jmp short s 對應的機器指令應該是什麼樣的呢?

n       我們先看一下別的彙編指令和其對應的機器指令

 

 

可以看到,在一般的彙編指令中,彙編指令中的idata(立即數),不論它是表示一個資料還是記憶體單元的位移地址,都會在對應的機器指令中出現,因為CPU執行的是機器指令,它必須要處理這些資料或地址。

 

n       但是:當我們查看jmp short s或jmp 0008所對應的機器碼,卻發現了問題。

 

看到了嗎?機器碼中並不含有立即數。為什麼呢,解釋如下

n       在“jmp short 標號”指令所對應的機器碼中,並不包含轉移的目的地址,而包含的是轉移的位移。

n       這個位移,使編譯器根據彙編指令中的“標號”計算出來的。

如果我們在第一行程式後加上Mov bx,0000,你會發器機器碼沒變,還是EB03,為什麼呢?jmp 0008對應的位移就是0003大家可以回憶一下cpu中指令的執行流程,就會發現當執行完EB03後,ip=ip+2=0005,大家注意看EB03後面有個03,表示再向後三個單位,這樣就到了0008這個位移處了。所以我們說包含 的是轉移的位移。

 

轉移位移具體的計算方法如

 

 

 

二.還有一種和指令“jmp short 標號”功能相近的指令格式:

    jump near ptr 標號

    實現的時段內近轉移。

指令“jmp near ptr 標號”的功能為:(IP)=(IP)+16位位移。

n           指令“jmp near ptr 標號”的說明:

n                 (1)16位位移=“標號”處的地址-jmp指令後的第一個位元組的地址;

n                 (2)near ptr指明此處的位移為16位位移,進行的是段內近轉移;

n                 (3)16位位移的範圍為

   -32769~32767,用補碼錶示;

n                 (4)16位位移由編譯器在編譯時間算出。

我們發現jump short 標號與jump near ptr 標號非常相似,不同點在哪兒呢?實際上就是跳轉的範圍,看下面一段代碼:

assume cs:codesg

codesg segment

  start:mov ax,0

          jmp near ptr s

          add ax,1

         dw 200 dup(2)此處表示產生若干條彙編指令,從而產生多個地址,方便測試

          s:inc ax

codesg ends

end start

 

如果我們將此處的jmp near ptr s 改為jmp short s,那麼編譯時間會報這樣的錯誤 jump out of range by 276 bytes,即jump越界了。也就是說:

在編譯的時候由編譯器算出是8位還是16位位移。8位位移的範圍是2的7次方,而16位位移的範圍是2的15次方。

 

三.回顧前面講的jmp指令,其對應的機器碼中並沒有轉移的目的地址,而是相對於當前IP的轉移位移。

指令 “jmp far ptr 標號”

   實現的是段間轉移,又稱為遠轉移

n       指令 “jmp far ptr 標號” 功能如下:

n       (CS)=標號所在段的段地址;

n       (IP)=標號所在段中的位移地址。

n       far ptr指明了指令用標號的段地址和位移地址修改CS和IP。

執行個體:

assume cs:codesg

           codesg segment

           start:mov ax,0

                     mov bx,0

               jmp far ptr  s

               db 256 dup (0)

               s: add ax,1

                 inc ax

           codesg ends

           end start

分析:用U命令查看後

 

“0B 01 BD 0B” 是目的地址在指令中的儲存順序,高地址的“BD 0B”是轉移的段地址:0BBDH,低地址的“0B 01” 是位移地址:010BH。看到了嗎?標號所在的段地址與位移地址為:0BBD:010B,可能是位於另一個程式碼片段中。

前面三者的區別,我用代碼總結一下,大家一看就明白了:

jmp   short   xxx和jmp   near   ptr   xxx可以寫成jmp   xx   
  例如:   。。。   
  jmp   exit   
  。。。   
        exit: mov   ax,4c00h   
        int   21h   
  。。。   

 2.jmp   far   ptr   xxx   
        code1   segment   
  。。。   
  jmp far   ptr   new_seg   
  。。。   
        code1 ends   
        code2 segment   
  。。。   
        new_seg:   
  。。。   
        code2 ends  

 

現在我們再來看第四種:

四.先看代碼,再來闡述:

JMP   DWORD   PTR   XXXX是段間間接定址   
  由xxxx的定址方式求得位移地址(假如是adress後),【adress】和【adress+2】分別就是轉移目的地址得位移地址和段地址   
  還是舉個例吧:   
  code1 segment   
  。。。   
  jmp dword   ptr   [bx][di]   
  。。。   
  code1 ends   
  code2 segment   
  。。。   
  jmp_here:   
  。。。   
  code2 ends   
  設(ds)=1000h,(di)=0300h,(bx)=0150h,則adress=10000h+150h+300h=10450h,即轉移目的地址jmp_here的值存放在以10450h地址開始的4個位元組中   
    
  jmp   word   ptr   adress是段內間接定址

明白了吧,代碼已經描述得很清楚了。

現在,關於jump的用法用一個圖全部總結一下:

 

 

 

 

 

 

 

 

 

格式

描述

舉例

類別

說明

jmp 16位寄存器

以16位寄存器的值改變IP

jmp ax

段內轉移

 

jmp 段地址:位移地址

以立即數改變段地址和位移地址

jmp 0045H:0020H

段間轉移

 

jmp short 標號

以標號地址後第一個位元組的地址來改變IP,實際上這個功能可以作如下描述:
(IP)=(IP)+8bit位移
8bit位移指的是從jmp指令後第一個位元組開始算起

jmp short sign

段內短轉移

對IP的修改範圍是-128->127,實際演算法是編譯器根據當前IP指標的指向來計算到底位移多少個位元組來指向下一條指令,下面這段代碼就會出編譯錯誤
jmp short s
dw 200 dup(2)
s: mov ax,4
因為跳轉超過了範圍

jmp near ptr 標號

以標號地址後第一個字的地址來改變IP,
實際上這個功能可以作如下描述:
(IP)=(IP)+16bit位移
16bit位移指的是從jmp指令後第一個位元組開始算起

jmp near ptr sign

段內近轉移

對IP的修改範圍是-32768->32767

jmp far ptr標號

以標號的段地址和指令地址同時改變CS和IP

jmp far ptr sign

段間轉移

 

jmp word ptr 記憶體位址

以記憶體位址單元處的字修改IP,記憶體單元可以以任何合法的方式給出

jmp word ptr ds:[si]
jmp word ptr ds:[0]
jmp word ptr [bx]
jmp word ptr [bp+si+idata]

段內轉移

 

jmp dword ptr記憶體位址

以記憶體位址單元處的雙字來修改指令,高地址內容修改CS,低地址內容修改IP,記憶體位址可以以任何合法的方式給出

jmp dword ptr [bx]

段間轉移

s1 segment
dw 0a0bh, 0c0dh
s1 ends

mov ax,s1
mov ds,ax
jmp dword ptr ds:[0]

 

 

前面我們講到了,jmp是指無條件的跳轉,我們知道,在c,或java或c#中總會存在這樣或那樣的條件判斷,那麼彙編中如何進行有條件的跳轉呢?

1. jcxz指令 jcxz指令為有條件轉移指令,所有的有條件轉移指令都是短轉移,在對應的機器碼中包含轉移的位移,而不是目的地址。對IP的修改範圍都為-128~127。

指令格式:jcxz 標號 

   (如果(cx)=0,則轉移到標號處執行。)

 

 

2.含義:

n       jcxz 標號 指令操作:

n       當(cx)=0時,(IP)=(IP)+8位位移)

n       8位位移=“標號”處的地址-jcxz指令後的第一個位元組的地址;

n       8位位移的範圍為-128~127,用補碼錶示;

n       8位位移由編譯器在編譯時間算出。

n       當(cx)=0時,什麼也不做(程式向下執行)。

 3.執行個體:

我們從 jcxz的功能中可以看出,指令“jcxz 標號”的功能相當於:

   if((cx)==0)jmp short 標號;

 (這種用C語言和組合語言進行的綜合描述,或許能使你對有條件指令理解得更加清楚。)

 

當然,有條件的跳轉還有其它多種情況,不過原理是一樣的。現在我們再來看看破解外掛中常用的迴圈指令:loop

n       loop指令為迴圈指令,所有的迴圈指令都是短轉移,在對應的機器碼中包含轉移的位移,而不是目的地址。對IP的修改範圍都為-128~127。

n       指令格式:loop 標號

    ((cx))=(cx)-1,如果(cx)≠0,轉移到標號處執行。

轉自:http://www.cnblogs.com/sunt/archive/2010/11/25/1887657.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.