青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

saga's blog

突出重點,系統全面,不留死角

  C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
  33 Posts :: 2 Stories :: 185 Comments :: 0 Trackbacks

公告

QQ:34O859O5

常用鏈接

留言簿(15)

搜索

  •  

積分與排名

  • 積分 - 212382
  • 排名 - 124

最新評論

閱讀排行榜

評論排行榜

**轉載**
**我自己看了看這片文章,還不錯!程序也可以編譯出來**

文章作者:kiki
信息來源:邪惡八進制信息安全團隊(
www.eviloctal.com
本文章首發
黑色海岸線網絡安全技術論壇 ,后由kiki友情提交到邪惡八進制信息安全團隊

?????????攔截api的技術有很多種,大體分為用戶層和內核層的攔截.這里只說說用戶層的攔截.而用戶層也分為許多種:修改PE文件導入表,直接修改要攔截的api的內存(從開始到最后,使程序跳轉到指定的地址執行).不過大部分原理都是修改程序流程,使之跳轉到你要執行的地方,然后再返回到原地址.原來api的功能必須還能實現.否則攔截就失去作用了.修改文件導入表的方法的缺點是如果用戶程序動態加載(使用LoadLibrary和GetProcAddress函數),攔截將變得復雜一些.所以這里介紹一下第二種方法,直接修改api,當然不是全局的.(后面會說到)

  需要了解的一些知識:

  1.windows內存的結構屬性和進程地址空間

  2.函數堆棧的一些知識



一:win2000和xp的內存結構和進程地址空間

? windows采用4GB平坦虛擬地址空間的做法。即每個進程單獨擁有4GB的地址空間。每個進程只能訪問自己的這4GB的虛擬空間,而對于其他進程的地址空間則是不可見的。這樣保證了進程的安全性和穩定性。但是,這4GB的空間是一個虛擬空間,在使用之前,我們必須先保留一段虛擬地址,然后再為這段虛擬地址提交物理存儲器。可是我們的內存大部分都還沒有1GB,那么這4GB的地址空間是如何實現的呢?事實上windows采用的內存映射這種方法,即把物理磁盤當作內存來使用,比如我們打開一個可執行文件的時候,操作系統會為我們開辟這個4GB的地址空間:0x00000000--0xffffffff。其中0x00000000--0x7fffffff是屬于用戶層的空間.0x80000000--0xffffffff則屬于共享內核方式分區,主要是操作系統的線程調度,內存管理,文件系統支持,網絡支持和所有設備驅動程序。對于用戶層的進程,這些地址空間是不可訪問的。任何訪問都將導致一個錯誤。開辟這4GB的虛擬地址空間之后,系統會把磁盤上的執行文件映射到進程的地址空間中去(一般是在地址0x00400000,可以通過修改編譯選項來修改這個地址)而一個進程運行所需要的動態庫文件則一般從0x10000000開始加載。但是如果所有的動態庫都加載到這個位置肯定會引起沖突。因此必須對一些可能引起沖突的dll編譯時重新修改基地址。但是對于所有的操作系統所提供的動態庫windows已經定義好了映射在指定的位置。這個位置會隨著版本的不同而會有所改變,不過對于同一臺機器上的映射地址來說都是一樣的。即在a進程里映射的kernel32.dll的地址和在進程b里的kernel32.dll的地址是一樣的。對于文件映射是一種特殊的方式,使得程序不需要進行磁盤i/o就能對磁盤文件進行操作,而且支持多種保護屬性。對于一個被映射的文件,主要是使用CreateFileMapping函數,利用他我們可以設定一些讀寫屬性:PAGE_READONLY,PAGE_READWRITE,PAGE_WRITECOPY.第一參數指定只能對該映射文件進行讀操作。任何寫操作將導致內存訪問錯誤。第二個參數則指明可以對映射文件進行讀寫。這時候,任何對文件的讀寫都是直接操作文件的。而對于第三個參數PAGE_WRITECOPY顧名思義就是寫入時拷貝,任何向這段內存寫入的操作(因為文件是映射到進程地址空間的,對這段空間的讀寫就相當于對文件進行的直接讀寫)都將被系統捕獲,并重新在你的虛擬地址空間重新保留并分配一段內存,你所寫入的一切東西都將在這里,而且你原先的指向映射文件的內存地址也會實際指向這段重新分配的內存,于是在進程結束后,映射文件內容并沒有改變,只是在運行期間在那段私有拷貝的內存里面存在著你修改的內容。windows進程運行所需要映射的一些系統dll就是以這種方式映射的,比如常用的ntdll.dll,kernel32.dll,gdi32.dll.幾乎所有的進程都會加載這三個動態庫。如果你在一個進程里修改這個映射文件的內容,并不會影響到其他的進程使用他們。你所修改的只是在本進程的地址空間之內的。事實上原始文件并沒有被改變。
這樣,在后面的修改系統api的時候,實際就是修改這些動態庫地址內的內容。前面說到這不是修改全局api就是這個原因,因為他們都是以寫入時拷貝的方式來映射的。不過這已經足夠了,windows提供了2個強大的內存操作函數ReadProcessMemory和WriteProcessMemory.利用這兩個函數我們就可以隨便對任意進程的任意用戶地址空間進行讀寫了。但是,現在有一個問題,我們該寫什么,說了半天,怎么實現跳轉呢?現在來看一個簡單的例子:
MessageBox(NULL, "World", "Hello", 0);
我們在執行這條語句的時候,調用了系統api MessageBox,實際上在程序中我沒有定義UNICODE宏,系統調用的是MessageBox的ANSI版本MessageBoxA,這個函數是由user32.dll導出的。下面是執行這條語句的匯編代碼:
0040102A ? push ? ? 0
0040102C ? push ? ? offset string "Hello" (0041f024)
00401031 ? push ? ? offset string "World" (0041f01c)
00401036 ? push ? ? 0
00401038 ? call ? ? dword ptr [__imp__MessageBoxA@16 (0042428c)]
前面四條指令分別為參數壓棧,因為MessageBoxA是__stdcall調用約定,所以參數是從右往左壓棧的。最后再CALL 0x0042428c

看看0042428c這段內存的值:
0042428C 0B 05 D5 77 00 00 00
可以看到這個值0x77d5050b,正是user32.dll導出函數MessageBoxA的入口地址。

這是0x77D5050B處的內容,
77D5050B 8B FF ? ? ? ? ? mov ? ? ? edi,edi
77D5050D 55 ? ? ? ? ? ? push ? ? ebp
77D5050E 8B EC ? ? ? ? ? mov ? ? ? ebp,esp
理論上只要改變api入口和出口的任何機器碼,都可以攔截該api。這里我選擇最簡單的修改方法,直接修改api入口的前十個字節來實現跳轉。為什么是十字節呢?其實修改多少字節都沒有關系,只要實現了函數的跳轉之后,你能把他們恢復并讓他繼續運行才是最重要的。在CPU的指令里,有幾條指令可以改變程序的流程:JMP,CALL,INT,RET,RETF,IRET等指令。這里我選擇CALL指令,因為他是以函數調用的方式來實現跳轉的,這樣可以帶一些你需要的參數。到這里,我該說說函數的堆棧了。

總結:windows進程所需要的動態庫文件都是以寫入時拷貝的方式映射到進程地址空間中的。這樣,我們只能攔截指定的進程。修改目標進程地址空間中的指定api的入口和出口地址之間的任意數據,使之跳轉到我們的攔截代碼中去,然后再恢復這些字節,使之能順利工作。




二:函數堆棧的一些知識

? 正如前面所看到MessageBoxA函數執行之前的匯編代碼,首先將四個參數壓棧,然后CALL MessageBoxA,這時候我們的線程堆棧看起來應該是這樣的:

| ? | ? <---ESP
|返回地址|
|參數1|
|參數2|
|參數3|
|參數4|
|.. ? |

我們再看MessageBoxA的匯編代碼,
77D5050B 8B FF ? ? ? ? ? mov ? ? ? edi,edi
77D5050D 55 ? ? ? ? ? ? push ? ? ebp
77D5050E 8B EC ? ? ? ? ? mov ? ? ? ebp,esp
注意到堆棧的操作有PUSH ebp,這是保存當前的基址指針,以便一會兒恢復堆棧后返回調用線程時使用,然后再有mov ebp,esp就是把當前esp的值賦給ebp,這時候我們就可以使用 ebp+偏移 來表示堆棧中的數據,比如參數1就可以表示成[ebp+8],返回地址就可以表示成[ebp+4]..如果我們在攔截的時候要對這些參數和返回地址做任何處理,就可以使用這種方法。如果這個時候函數有局部變量的話,就通過減小ESP的值的方式來為之分配空間。接下來就是保存一些寄存器:EDI,ESI,EBX.要注意的是,函數堆棧是反方向生長的。這時候堆棧的樣子:
|....|
|EDI| <---ESP
|ESI|
|EBX|
|局部變量|
|EBP ? | ?
|返回地址|
|參數1|
|參數2|
|參數3|
|參數4|
|.. ? |

在函數返回的時候,由函數自身來進行堆棧的清理,這時候清理的順序和開始入棧的順序恰恰相反,類似的匯編代碼可能是這樣的:

pop edi
pop esi
pop ebx
add esp, 4
pop ebp
ret 0010
先恢復那些寄存器的值,然后通過增加ESP的值的方式來釋放局部變量。這里可以用mov esp, ebp來實現清空所有局部變量和其他一些空閑分配空間。接著函數會恢復EBP的值,利用指令POP EBP來恢復該寄存器的值。接著函數運行ret 0010這個指令。該指令的意思是,函數把控制權交給當前棧頂的地址的指令,同時清理堆棧的16字節的參數。如果函數有返回值的話,那在EAX寄存器中保存著當前函數的返回值。如果是__cdecl調用方式,則執行ret指令,對于堆棧參數的處理交給調用線程去做。如wsprintf函數。

這個時候堆棧又恢復了原來的樣子。線程得以繼續往下執行...
在攔截api的過程之中一個重要的任務就是保證堆棧的正確性。你要理清每一步堆棧中發生了什么。



三:形成思路
?
? 呵呵,不知道你現在腦海是不是有什么想法。怎么去實現攔截一個api?
? 這里給出一個思路,事實上攔截的方法真的很多,理清了一個,其他的也就容易了。而且上面所說的2個關鍵知識,也可以以另外的形式來利用。
? 我以攔截CreateFile這個api為例子來簡單說下這個思路吧:
?
? 首先,既然我們要攔截這個api就應該知道這個函數在內存中的位置吧,至少需要知道從哪兒入口。CreateFile這個函數是由kernel32.dll這個動態庫導出的。我們可以使用下面的方法來獲取他映射到內存中的地址:
? HMODULE hkernel32 = LoadLibrary("Kernel32.dll");
? PVOID dwCreateFile = GetProcAddress(hkernei32, "CreateFileA");
這就可以得到createfile的地址了,注意這里是獲取的createfile的ansic版本。對于UNICODE版本的則獲取CreateFileW。這時dwCreateFile的值就是他的地址了。對于其他進程中的createfile函數也是這個地址,前面說過windows指定了他提供的所有的dll文件的加載地址。
?
? 接下來,我們該想辦法實現跳轉了。最簡單的方法就是修改這個api入口處的代碼了。但是我們該修改多少呢?修改的內容為什么呢?前面說過我們可以使用CALL的方式來實現跳轉,這種方法的好處是可以為你的攔截函數提供一個或者多個參數。這里只要一個參數就足夠了。帶參數的函數調用的匯編代碼是什么樣子呢,前面也已經說了,類似與調用MessageBoxA時的代碼:

PUSH 參數地址
CALL 函數入口地址(這里為一個偏移地址)

執行這2條指令就能跳轉到你要攔截的函數了,但是我們該修改成什么呢。首先,我們需要知道這2條指令的長度和具體的機器代碼的值。其中PUSH對應0x68,而CALL指令對應的機器碼為0xE8,而后面的則分別對應攔截函數的參數地址和函數的地址。注意第一個是一個直接的地址,而第二個則是一個相對地址。當然你也可以使用0xFF0x15這個CALL指令來進行直接地址的跳轉。
下面就是計算這2個地址的值了,
對于參數和函數體的地址,要分情況而定,對于對本進程中api的攔截,則直接取地址就可以了。對于參數,可以先定義一個參數變量,然后取變量地址就ok了。
如果是想攔截其他進程中的api,則必須使用其他一些方法,最典型的方法是利用VirtualAllocEx函數來在其他進程中申請和提交內存空間。然后用WriteProcessMemory來分別把函數體和參數分別寫入申請和分配的內存空間中去。然后再生成要修改的數據,最后用WriteProcessMemory來修改api入口,把入口的前10字節修改為剛剛生成的跳轉數據。比如在遠程進程中你寫入的參數和函數體的內存地址分別為0x00010000和0x00011000,則生成的跳轉數據為 68 00 00 01 00 E8 00 10 01 00(PUSH 00010000 CALL 00011000),這樣程序運行createfile函數的時候將會先運行PUSH 00010000 CALL 00011000,這樣就達到了跳轉的目的。此刻我們應該時刻注意堆棧的狀態,對于CreateFile有
HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
可以看到其有7個參數,于是在調用之前,堆棧應該已經被壓入了這7個參數,堆棧的樣子:
|....| ? <---ESP
|createfile執行后的下一條指令地址|
|參數1|
|參數2|
|參數3|
|參數4|
|參數5|
|參數6|
|參數7|
|..|

這是執行到我們的跳轉語句:PUSH 00010000,于是堆棧又變了:

|....| ? <---ESP
|00010000|
|createfile執行后的下一條指令地址|
|參數1|
|參數2|
|參數3|
|參數4|
|參數5|
|參數6|
|參數7|
|..|

接著執行CALL 00011000,堆棧變為:
|...| <---ESP
|api入口之后的第11個字節的指令的地址| ?
|00010000|
|createfile執行后的下一條指令地址|
|參數1|
|參數2|
|參數3|
|參數4|
|參數5|
|參數6|
|參數7|
|..|

接下來就到了我們的攔截函數中拉,當然,函數肯定也會做一些類似動作,把EBP壓棧,為局部變量分配空間等。這時候堆棧的樣子又變了:

|EDI| <---ESP
|ESI|
|EBX|
|局部變量|
|EBP| ? <---EBP
|api入口之后的第11個字節的指令的地址| ?
|00010000|
|createfile執行后的下一條指令地址|
|參數1|
|參數2|
|參數3|
|參數4|
|參數5|
|參數6|
|參數7|
|..|

這時候,你想做什么就盡情地做吧,獲取參數信息,延緩執行CreateFile函數等等。拿獲取打開文件句柄的名字來說吧,文件名是第一個參數,前面說過我們可以用[EBP+8]來獲取參數,但是對照上面的堆棧形狀,中間又加了另外一些數據,所以我們用[EBP+16]來獲取第一個參數的地址。比如:
char* PFileName = NULL;
__asm{
MOV EAX,[EBP+16]
MOV [szFileName], EAX
}

比如我們用一個messagebox來彈出一個信息,說明該程序即將打開一個某謀路徑的文件句柄。但是有一個要注意的是,如果你想攔截遠程進程的話,對于那個攔截函數中所使用到的任何函數或者以任何形式的相對地址的調用都要停止。因為每個進程中的地址分配都是獨立的,比如上面的CALL MessageBoxA改成直接地址的調用。對于使用messagebox,我們應該定義一個函數指針,然后把這個指針的值賦值為user32.dll中導出該函數的直接地址。然后利用這個指針來進行函數調用。對于messagebox函數的調用可以這樣,在源程序中定義一個參數結構體,參數中包含一個導出函數的地址,把這個地址設為MessageBoxA的直接地址,獲取地址的方法就不說了。然后把這個參數傳給攔截函數,就可以使用拉。這也是利用一個參數的原因。類似代碼如下:


typedef struct _RemoteParam {
? DWORD dwMessageBox;
} RemoteParam, * PRemoteParam;

typedef int (__stdcall * PFN_MESSAGEBOX)(HWND, LPCTSTR, LPCTSTR, DWORD);//定義一個函數指針

//攔截函數
void HookCreateFile(LPVOID lParam)
{
RemoteParam* pRP = (RemoteParam*)lParam;//獲取參數地址
char* PFileName = NULL;//定義一個指針
__asm{
MOV EAX,[EBP+16]
MOV [szFileName], EAX //把CreateFile第一個參數的值,文件的路徑的地址傳 ? ? ? ? ? ? ? //給szFileName
}

//定 義一個函數指針
PFN_MESSAGEBOX pfnMessageBox = (PFN_MESSAGEBOX)pRP->dwMessageBox;

pfnMessageBox(NULL, PFileName, PFileName, MB_ICONINFORMATION |MB_OK);
//輸出要打開的文件的路徑
//.....
}

對于你要使用的其他函數,都是使用同樣的方式,利用這個參數來傳遞我們要傳遞的函數的絕對地址,然后定義這個函數指針,就可以使用了。


好了,接下來我們該讓被攔截的api正常工作了,這個不難,把他原來的數據恢復一下就可以了。那入口的10個字節。我們在改寫他們的時候應該保存一下,然后也把他放在參數中傳遞給攔截函數,呵呵,參數的作用可多了。接著我們就可以用WriteProcessMemory函數來恢復這個api的入口了,代碼如下:
PFN_GETCURRENTPROCESS pfnGetCurrentProcess = (PFN_GETCURRENTPROCESS)pRP->dwGetCurrentProcess;
PFN_WRITEPROCESSMEMORY pfnWriteProcessMemory = (PFN_WRITEPROCESSMEMORY)pRP->dwWriteProcessMemory;
?
if(!pfnWriteProcessMemory(pfnGetCurrentProcess(),
? ? ? ? ? ? ? ? ? ? ? ? ? ? (LPVOID)pfnConnect,
? ? ? ? ? ? ? ? ? ? ? ? ? ? (LPCVOID)pRP->szOldCode,
? ? ? ? ? ? ? ? ? ? ? ? ? ? 10,
? ? ? ? ? ? ? ? ? ? ? ? ? ? NULL))
pfnMessageBox(NULL, pRP->szModuleName1, pRP->szModuleName2, MB_ICONINFORMATION | MB_OK);
其中這些函數指針的定義和上面的類似。
而參數中的szoldcode則是在源程序中在修改api之前保存好,然后傳給攔截函數,在源程序中是用ReadProcessMemory函數來獲取他的前10個字節的:
ReadProcessMemory(GetCurrentProcess(),
? ? ? ? ? ? ? ? ? ? ? (LPCVOID)RParam.dwCreateFile,
? ? ? ? ? ? ? ? ? ? ? oldcode,
? ? ? ? ? ? ? ? ? ? ? 10,
? ? ? ? ? ? ? ? ? ? ? &dwPid)
strcat((char*)RParam.szOldCode, (char*)oldcode);


接下來如果你還繼續保持對該api的攔截,則又該用WriteProcessMemory 來修改入口了,跟前面的恢復入口是一樣的,只不過把szOldCode換成了szNewCode了而已。這樣你又能對CreateFile繼續攔截了。

好了,接下來該進行堆棧的清理了,也許你還要做點其他事情,盡管做去。但是清理堆棧是必須要做的,在函數結束的時候,因為在我們放任api恢復執行之后,他又return 到我們的函數中來了,這個時候的堆棧是什么樣子呢?
|EDI| <---ESP
|ESI|
|EBX|
|局部變量|
|EBP| ? <---EBP
|api入口之后的第11個字節的指令的地址| ?
|00010000|
|createfile執行后的下一條指令地址|
|參數1|
|參數2|
|參數3|
|參數4|
|參數5|
|參數6|
|參數7|
|..|

我們的目標是把返回值記錄下來放到EAX寄存器中去,把返回地址記錄下來,同時把堆棧恢復成原來的樣子。
首先我們恢復那些寄存器的值,接著釋放局部變量,可以用mov esp, ebp.因為我們不清楚具體的局部變量分配了多少空間。所以使用這個方法。


__asm
{POP EDI
POP ESI
POP EBX ? //恢復那些寄存器
MOV EDX, [NextIpAddr]//把返回地址放到EDX中,因為待會兒 ? ? ? ? ? ? //EBX被恢復后,線程中的所有局部變量就不能正常使用了。
? ? ?
MOV EAX, [RetValue]//返回值放到EAX中,當然也可以修改這個返回值
MOV ESP, EBP//清理局部變量
POP EBP//恢復EBP的值
ADD ESP, 28H //清理參數和返回地址,注意一共(7+1+1+1)*4
PUSH EDX //把返回地址壓棧,這樣棧中就只有這一個返回地址了,返回之后棧 ? ? ? //就空了
RET
}

這樣,一切就完成了,堆棧恢復了應該有的狀態,而你想攔截的也攔截到了。


四:后記
? 攔截的方式多種多樣,不過大體的思路卻都相同。要時刻注意你要攔截的函數的堆棧狀態以及在攔截函數中的對數據的引用和函數的調用(地址問題)。

?
//////////////////////////////////////////////////////////////////////
附錄:一個攔截CreateFile函數的簡單實現
//////////////////////////////////////////////////////////////////////
CODE:

#include <stdio.h>
#include <windows.h>
#include <Psapi.h>

#pragma comment(lib, "psapi.lib")

typedef struct _RemoteParam {
? DWORD dwCreateFile;
? DWORD dwMessageBox;
? DWORD dwGetCurrentProcess;
? DWORD dwWriteProcessMemory;
? unsigned char szOldCode[10];
? DWORD FunAddr;
} RemoteParam, * PRemoteParam;

typedef HANDLE (__stdcall * PFN_CREATEFILE)(LPCTSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE);
typedef int (__stdcall * PFN_MESSAGEBOX)(HWND, LPCTSTR, LPCTSTR, DWORD);
typedef BOOL (__stdcall * PFN_WRITEPROCESSMEMORY)(HANDLE,LPVOID,LPCVOID,SIZE_T,SIZE_T*);
typedef HANDLE (__stdcall * PFN_GETCURRENTPROCESS)(void);

#define PROCESSNUM 128
#define MYMESSAGEBOX "MessageBoxW"
#define MYCREATEFILE "CreateFileW"

void HookCreateFile(LPVOID lParam)
{

? RemoteParam* pRP = (RemoteParam*)lParam;


? DWORD NextIpAddr = 0;
? DWORD dwParamaAddr = 0;

? HANDLE RetFpHdl = INVALID_HANDLE_VALUE;
? LPCTSTR lpFileName;
? DWORD dwDesiredAccess;
? DWORD dwShareMode;
? LPSECURITY_ATTRIBUTES lpSecurityAttributes;
? DWORD dwCreationDisposition;
? DWORD dwFlagsAndAttributes;
? HANDLE hTemplateFile;
? PFN_CREATEFILE pfnCreatefile = (PFN_CREATEFILE)pRP->dwCreateFile;


? __asm
? {
? MOV EAX,[EBP+8]
? MOV [dwParamaAddr], EAX
? MOV EAX,[EBP+12] ? ? ?
? MOV [NextIpAddr], EAX
? MOV EAX,[EBP+16]
? MOV [lpFileName], EAX
? MOV EAX,[EBP+20]
? MOV [dwDesiredAccess],EAX
? MOV EAX,[EBP+24]
? MOV [dwShareMode],EAX
? MOV EAX,[EBP+28]
? MOV [lpSecurityAttributes],EAX
? MOV EAX,[EBP+32]
? MOV [dwCreationDisposition],EAX
? MOV EAX,[EBP+36]
? MOV [dwFlagsAndAttributes],EAX
? MOV EAX,[EBP+40]
? MOV [hTemplateFile],EAX ?
? }

? PFN_MESSAGEBOX pfnMessageBox = (PFN_MESSAGEBOX)pRP->dwMessageBox;
? int allowFlag = pfnMessageBox(NULL, lpFileName, NULL, MB_ICONINFORMATION | MB_YESNO);
?
? if(allowFlag == IDYES)
? {
? unsigned char szNewCode[10];
? int PramaAddr = (int)dwParamaAddr;
? szNewCode[4] = PramaAddr>>24;
? szNewCode[3] = (PramaAddr<<8)>>24;
? szNewCode[2] = (PramaAddr<<16)>>24;
? szNewCode[1] = (PramaAddr<<24)>>24;
? szNewCode[0] = 0x68;
?
? int funaddr = (int)pRP->FunAddr - (int)pfnCreatefile - 10 ;
? szNewCode[9] = funaddr>>24;
? szNewCode[8] = (funaddr<<8)>>24;
? szNewCode[7] = (funaddr<<16)>>24;
? szNewCode[6] = (funaddr<<24)>>24;
? szNewCode[5] = 0xE8;
?
?
? PFN_GETCURRENTPROCESS pfnGetCurrentProcess = (PFN_GETCURRENTPROCESS)pRP->dwGetCurrentProcess;
? PFN_WRITEPROCESSMEMORY pfnWriteProcessMemory = (PFN_WRITEPROCESSMEMORY)pRP->dwWriteProcessMemory;
? pfnWriteProcessMemory(pfnGetCurrentProcess(),
? ? ? ? ? ? ? ? (LPVOID)pfnCreatefile,
? ? ? ? ? ? ? ? (LPCVOID)pRP->szOldCode,
? ? ? ? ? ? ? ? 10,
? ? ? ? ? ? ? ? NULL);

? RetFpHdl = pfnCreatefile(lpFileName,
? ? ? ? ? ? ? ? ? dwDesiredAccess,
? ? ? ? ? ? ? ? ? dwShareMode,
? ? ? ? ? ? ? ? ? lpSecurityAttributes,
? ? ? ? ? ? ? ? ? dwCreationDisposition,
? ? ? ? ? ? ? ? ? dwFlagsAndAttributes,
? ? ? ? ? ? ? ? ? hTemplateFile);
? pfnWriteProcessMemory(pfnGetCurrentProcess(),
? ? ? ? ? ? ? ? (LPVOID)pfnCreatefile,
? ? ? ? ? ? ? ? (LPCVOID)szNewCode,
? ? ? ? ? ? ? ? 10,
? ? ? ? ? ? ? ? NULL);
? }


? __asm
? ? {POP EDI
? ? ? POP ESI
? ? ? POP EBX
? ? ? MOV EDX, [NextIpAddr]
? ? ? MOV EAX, [RetFpHdl]
? ? ? MOV ESP, EBP
? ? ? POP EBP
? ? ? ADD ESP, 28H
? ? ? PUSH EDX
? ? ? RET
? ? }

?
}



BOOL AdjustProcessPrivileges(LPCSTR szPrivilegesName)
{
? HANDLE hToken;
? TOKEN_PRIVILEGES tkp;

? if(!OpenProcessToken(GetCurrentProcess(),
? ? TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
? {
? ? return FALSE;
? }

? if(!LookupPrivilegeValue(NULL,szPrivilegesName,
? ? ? ? ? ? ? ? ? &tkp.Privileges[0].Luid))
? {
? ? CloseHandle(hToken);
? ? return FALSE;
? }
?
? tkp.PrivilegeCount = 1;
? tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
?
? if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(tkp),NULL,NULL))
? {
? ? CloseHandle(hToken);
? ? return FALSE;
? }
?
? CloseHandle(hToken);
? return TRUE;
}


void printProcessNameByPid( DWORD ProcessId )
{
? HANDLE pHd;
? HMODULE pHmod;
? char ProcessName[MAX_PATH] = "unknown";
? DWORD cbNeeded;
? pHd = OpenProcess( PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, ProcessId );
? if(pHd == NULL)
? ? return;
?
? if(!EnumProcessModules( pHd, &pHmod, sizeof(pHmod), &cbNeeded))
? ? return;
? if(!GetModuleFileNameEx( pHd, pHmod, ProcessName, MAX_PATH))
? ? return;
?
? printf( "%d\t%s\n", ProcessId, ProcessName);
? CloseHandle( pHd );
? return;
}


int main(void)
{

? if(!AdjustProcessPrivileges(SE_DEBUG_NAME))
? {
? ? ? printf("AdjustProcessPrivileges Error!\n");
? ? ? return -1;
? }

? DWORD Pids[PROCESSNUM];
? DWORD dwProcessNum = 0;
? if(!EnumProcesses(Pids, sizeof(Pids), &dwProcessNum))
? {
? ? ? printf("EnumProcess Error!\n");
? ? ? return -1;
? }
?
? for( DWORD num = 0; num < (dwProcessNum / sizeof(DWORD)); num++)
? ? ? printProcessNameByPid(Pids[num]);

? printf("\nAll %d processes running. \n", dwProcessNum / sizeof(DWORD));

? DWORD dwPid = 0;
? printf("\n請輸入要攔截的進程id:");
? scanf("%d", &dwPid);
?
? HANDLE hTargetProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, dwPid);
? if(hTargetProcess == NULL)
? {
? ? ? printf("OpenProcess Error!\n");
? ? ? return -1;
? }

? DWORD dwFunAddr = (DWORD)VirtualAllocEx(hTargetProcess, NULL, 8192,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
?
? if((LPVOID)dwFunAddr == NULL)
? {
? ? ? printf("申請線程內存失敗!\n");
? ? ? CloseHandle(hTargetProcess);
? ? ? return -1;
? }

? DWORD dwPramaAddr = (DWORD)VirtualAllocEx(hTargetProcess, NULL, sizeof(RemoteParam),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

? if((LPVOID)dwPramaAddr == NULL)
? {
? ? ? printf("申請參數內存失敗!\n");
? ? ? CloseHandle(hTargetProcess);
? ? ? return -1;
? }

? printf("\n線程內存地址:%.8x\n"
? ? ? ? "參數內存地址:%.8x\n",
? ? ? ? dwFunAddr, dwPramaAddr);
? ? RemoteParam RParam;
? ZeroMemory(&RParam, sizeof(RParam));
? HMODULE hKernel32 = LoadLibrary("kernel32.dll");
? HMODULE hUser32 = LoadLibrary("user32.dll");

? RParam.dwCreateFile = (DWORD)GetProcAddress(hKernel32, MYCREATEFILE);
? RParam.dwGetCurrentProcess = (DWORD)GetProcAddress(hKernel32, "GetCurrentProcess");
? RParam.dwWriteProcessMemory = (DWORD)GetProcAddress(hKernel32, "WriteProcessMemory");
? RParam.dwMessageBox = (DWORD)GetProcAddress(hUser32, MYMESSAGEBOX);
?
? unsigned char oldcode[10];
? unsigned char newcode[10];
? int praadd = (int)dwPramaAddr;
? int threadadd = (int)dwFunAddr;
? newcode[4] = praadd>>24;
? newcode[3] = (praadd<<8)>>24;
? newcode[2] = (praadd<<16)>>24;
? newcode[1] = (praadd<<24)>>24;
? newcode[0] = 0x68;
?
? int offsetaddr = threadadd - (int)RParam.dwCreateFile - 10 ;
? newcode[9] = offsetaddr>>24;
? newcode[8] = (offsetaddr<<8)>>24;
? newcode[7] = (offsetaddr<<16)>>24;
? newcode[6] = (offsetaddr<<24)>>24;
? newcode[5] = 0xE8;

? printf("NewCode:");
? for(int j = 0; j < 10; j++)
? ? ? printf("0x%.2x ",newcode[j]);
? printf("\n\n");



? if(!ReadProcessMemory(GetCurrentProcess(),
? ? ? ? ? ? ? ? ? (LPCVOID)RParam.dwCreateFile,
? ? ? ? ? ? ? ? ? oldcode,
? ? ? ? ? ? ? ? ? 10,
? ? ? ? ? ? ? ? ? &dwPid))
? {
? ? ? printf("read error");
? ? ? CloseHandle(hTargetProcess);
? ? ? FreeLibrary(hKernel32);
? ? ? return -1;
? }

? strcat((char*)RParam.szOldCode, (char*)oldcode);
? RParam.FunAddr = dwFunAddr;

? printf(
? ? ? ? "RParam.dwCreateFile:%.8x\n"
? ? ? ? "RParam.dwMessageBox:%.8x\n"
? ? ? ? "RParam.dwGetCurrentProcess:%.8x\n"
? ? ? ? "RParam.dwWriteProcessMemory:%.8x\n"
? ? ? ? "RParam.FunAddr:%.8x\n",
? ? ? ? RParam.dwCreateFile,
? ? ? ? RParam.dwMessageBox,
? ? ? ? RParam.dwGetCurrentProcess,
? ? ? ? RParam.dwWriteProcessMemory,
? ? ? ? RParam.FunAddr);
? printf("RParam.szOldCode:");
? for( int i = 0; i< 10; i++)
? ? ? printf("0x%.2x ", RParam.szOldCode[i]);
? printf("\n");
?
?
? if(!WriteProcessMemory(hTargetProcess, (LPVOID)dwFunAddr, (LPVOID)&HookCreateFile, 8192, &dwPid))
? {
? ? ? printf("WriteRemoteProcessesMemory Error!\n");
? ? ? CloseHandle(hTargetProcess);
? ? ? FreeLibrary(hKernel32);
? ? ? return -1;
? }

? if(!WriteProcessMemory(hTargetProcess, (LPVOID)dwPramaAddr, (LPVOID)&RParam, sizeof(RemoteParam), &dwPid))
? {
? ? ? printf("WriteRemoteProcessesMemory Error!\n");
? ? ? CloseHandle(hTargetProcess);
? ? ? FreeLibrary(hKernel32);
? ? ? return -1;
? }
?
? if(!WriteProcessMemory(hTargetProcess, (LPVOID)RParam.dwCreateFile, (LPVOID)newcode, 10, &dwPid))
? {
? ? ? printf("WriteRemoteProcessesMemory Error!\n");
? ? ? CloseHandle(hTargetProcess);
? ? ? FreeLibrary(hKernel32);
? ? ? return -1;
? }

? printf("\nThat's all, good luck :)\n");
? CloseHandle(hTargetProcess);
? FreeLibrary(hKernel32);
? return 0;
}
posted on 2007-01-22 16:49 saga.constantine 閱讀(1248) 評論(0)  編輯 收藏 引用 所屬分類: 轉的貼
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久中文在线| 夜夜夜久久久| 久久视频在线看| 欧美在线看片| 亚洲国产精品综合| 亚洲免费观看在线视频| 欧美午夜欧美| 久久精品视频在线看| 久久综合九色欧美综合狠狠| 亚洲精品一区二区三区av| 日韩一本二本av| 国产丝袜一区二区三区| 欧美高清视频www夜色资源网| 欧美精品在线极品| 久久精品人人做人人综合| 久久五月激情| 亚洲一区二区黄| 欧美一区午夜精品| 亚洲日本激情| 亚洲欧美在线网| 亚洲人成网站在线观看播放| 这里只有精品丝袜| 1024精品一区二区三区| 夜夜狂射影院欧美极品| 一区二区在线看| 中国成人在线视频| 在线观看视频一区二区| 亚洲一区免费观看| 亚洲免费av观看| 久久精品亚洲热| 亚洲欧美春色| 欧美黑人国产人伦爽爽爽| 欧美制服丝袜| 欧美三级乱码| 亚洲激情视频在线| 国外视频精品毛片| 亚洲视频精品在线| 一区二区日本视频| 老**午夜毛片一区二区三区| 久久国产66| 国产精品麻豆va在线播放| 91久久久一线二线三线品牌| 在线观看欧美视频| 欧美一区二区三区免费视频| 亚洲视频一区二区| 欧美区日韩区| 91久久国产综合久久91精品网站| 亚洲第一毛片| 久久综合狠狠综合久久综合88 | 国产精品日韩欧美一区二区| 亚洲激情偷拍| 亚洲开发第一视频在线播放| 久久免费精品视频| 久久蜜桃精品| 激情综合中文娱乐网| 欧美在线免费观看亚洲| 久久久久国产精品厨房| 国产日韩成人精品| 欧美精品日韩综合在线| 女同一区二区| 国产一区二区三区四区老人| 亚洲午夜精品福利| 午夜精品久久久久久久99樱桃 | 国产在线精品成人一区二区三区| 亚洲一区三区视频在线观看 | 最近中文字幕mv在线一区二区三区四区| 性色av一区二区怡红| 久久国产免费| 伊人久久大香线蕉综合热线 | 亚洲制服少妇| 欧美中在线观看| 国产在线视频欧美| 久久久久久高潮国产精品视| 你懂的视频一区二区| 亚洲国内精品在线| 欧美日韩国产成人在线91| 99在线精品视频在线观看| 亚洲一区二区在线免费观看视频 | 欧美成人免费在线视频| 亚洲精品综合精品自拍| 午夜在线成人av| 国产一区99| 老司机久久99久久精品播放免费| 欧美激情无毛| 亚洲一区二区三区免费视频| 国产精品你懂得| 久久久激情视频| 亚洲精品乱码久久久久久蜜桃91| 亚洲一区二区久久| 韩国av一区| 欧美日韩国产在线看| 亚洲淫片在线视频| 麻豆视频一区二区| 一区二区成人精品| 亚洲第一在线视频| 欧美精品一区在线发布| 欧美亚洲综合网| 亚洲激情视频在线播放| 欧美在线观看日本一区| 亚洲精品久久久久久久久久久| 国产精品美女久久久久av超清 | 一色屋精品亚洲香蕉网站| 欧美精品在线极品| 久久国产福利国产秒拍| 亚洲精品中文字幕在线观看| 久久久久久自在自线| 亚洲最新中文字幕| 黄色日韩网站视频| 国产精品美女诱惑| 牛牛国产精品| 欧美在线免费视屏| 亚洲最黄网站| 亚洲福利视频免费观看| 久久国产精品电影| 一本一本久久| 亚洲福利小视频| 国产一区二区三区在线观看精品| 欧美精品 国产精品| 亚洲精品日韩精品| 一区二区三区在线免费观看| 欧美二区不卡| 另类春色校园亚洲| 翔田千里一区二区| 一本色道久久加勒比88综合| 亚洲国产你懂的| 免费看黄裸体一级大秀欧美| 久久国内精品自在自线400部| 亚洲自拍偷拍麻豆| 中文欧美日韩| 亚洲视频一二三| 亚洲一区二区精品在线观看| av成人动漫| 一区二区三区高清视频在线观看| 91久久线看在观草草青青| 在线观看欧美黄色| 亚洲高清视频在线| 在线看片欧美| 亚洲国产片色| 亚洲日韩欧美视频一区| 亚洲精品黄网在线观看| 亚洲精品在线二区| 亚洲日本理论电影| 一本大道久久a久久精品综合| 亚洲精品永久免费| 一本色道久久综合亚洲二区三区| 99国产精品国产精品久久| 亚洲最黄网站| 亚洲一区在线看| 欧美一级免费视频| 欧美综合77777色婷婷| 久久精品在线视频| 美女啪啪无遮挡免费久久网站| 免费成人你懂的| 亚洲韩国日本中文字幕| 日韩天堂在线视频| 亚洲一区二区三区乱码aⅴ| 亚洲欧美日本另类| 久久成人一区| 欧美高清日韩| 国产精品入口尤物| 国内精品久久久久伊人av| 亚洲日本电影在线| 亚洲综合国产激情另类一区| 久久精品日产第一区二区| 欧美大片一区二区三区| 日韩午夜精品| 欧美一区二区高清| 欧美福利视频一区| 国产精品一区二区三区观看| 国产一区二区三区黄| 亚洲精品男同| 久久大逼视频| 亚洲精品1区2区| 午夜精品久久久久久| 欧美成人国产va精品日本一级| 欧美日韩中文字幕综合视频| 国内精品久久久久伊人av| 日韩视频在线一区二区三区| 久久精品国产久精国产一老狼| 亚洲韩国青草视频| 欧美一区二区视频在线观看2020| 欧美成人一区二区三区片免费| 国产精品久久久久久久9999| 在线国产精品播放| 亚洲欧美春色| 亚洲欧洲久久| 久久久久久久久综合| 欧美性色aⅴ视频一区日韩精品| 好看不卡的中文字幕| 亚洲欧美国产毛片在线| 欧美大片在线看免费观看| 亚洲影音一区| 欧美日韩美女一区二区| 亚洲黄色成人网| 久久精品在线播放| 亚洲综合欧美| 欧美性猛交xxxx乱大交蜜桃| 亚洲精品综合在线| 欧美成年人网站| 久久国产精品一区二区三区四区 |