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

saga's blog

突出重點,系統(tǒng)全面,不留死角

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

公告

QQ:34O859O5

常用鏈接

留言簿(15)

搜索

  •  

積分與排名

  • 積分 - 212858
  • 排名 - 124

最新評論

閱讀排行榜

評論排行榜

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

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

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

  需要了解的一些知識:

  1.windows內(nèi)存的結構屬性和進程地址空間

  2.函數(shù)堆棧的一些知識



一:win2000和xp的內(nèi)存結構和進程地址空間

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

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

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

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




二:函數(shù)堆棧的一些知識

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

| ? | ? <---ESP
|返回地址|
|參數(shù)1|
|參數(shù)2|
|參數(shù)3|
|參數(shù)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+偏移 來表示堆棧中的數(shù)據(jù),比如參數(shù)1就可以表示成[ebp+8],返回地址就可以表示成[ebp+4]..如果我們在攔截的時候要對這些參數(shù)和返回地址做任何處理,就可以使用這種方法。如果這個時候函數(shù)有局部變量的話,就通過減小ESP的值的方式來為之分配空間。接下來就是保存一些寄存器:EDI,ESI,EBX.要注意的是,函數(shù)堆棧是反方向生長的。這時候堆棧的樣子:
|....|
|EDI| <---ESP
|ESI|
|EBX|
|局部變量|
|EBP ? | ?
|返回地址|
|參數(shù)1|
|參數(shù)2|
|參數(shù)3|
|參數(shù)4|
|.. ? |

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

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

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



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

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

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

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

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

接著執(zhí)行CALL 00011000,堆棧變?yōu)椋?br />|...| <---ESP
|api入口之后的第11個字節(jié)的指令的地址| ?
|00010000|
|createfile執(zhí)行后的下一條指令地址|
|參數(shù)1|
|參數(shù)2|
|參數(shù)3|
|參數(shù)4|
|參數(shù)5|
|參數(shù)6|
|參數(shù)7|
|..|

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

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

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

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


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

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

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

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

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

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


好了,接下來我們該讓被攔截的api正常工作了,這個不難,把他原來的數(shù)據(jù)恢復一下就可以了。那入口的10個字節(jié)。我們在改寫他們的時候應該保存一下,然后也把他放在參數(shù)中傳遞給攔截函數(shù),呵呵,參數(shù)的作用可多了。接著我們就可以用WriteProcessMemory函數(shù)來恢復這個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);
其中這些函數(shù)指針的定義和上面的類似。
而參數(shù)中的szoldcode則是在源程序中在修改api之前保存好,然后傳給攔截函數(shù),在源程序中是用ReadProcessMemory函數(shù)來獲取他的前10個字節(jié)的:
ReadProcessMemory(GetCurrentProcess(),
? ? ? ? ? ? ? ? ? ? ? (LPCVOID)RParam.dwCreateFile,
? ? ? ? ? ? ? ? ? ? ? oldcode,
? ? ? ? ? ? ? ? ? ? ? 10,
? ? ? ? ? ? ? ? ? ? ? &dwPid)
strcat((char*)RParam.szOldCode, (char*)oldcode);


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

好了,接下來該進行堆棧的清理了,也許你還要做點其他事情,盡管做去。但是清理堆棧是必須要做的,在函數(shù)結束的時候,因為在我們放任api恢復執(zhí)行之后,他又return 到我們的函數(shù)中來了,這個時候的堆棧是什么樣子呢?
|EDI| <---ESP
|ESI|
|EBX|
|局部變量|
|EBP| ? <---EBP
|api入口之后的第11個字節(jié)的指令的地址| ?
|00010000|
|createfile執(zhí)行后的下一條指令地址|
|參數(shù)1|
|參數(shù)2|
|參數(shù)3|
|參數(shù)4|
|參數(shù)5|
|參數(shù)6|
|參數(shù)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 //清理參數(shù)和返回地址,注意一共(7+1+1+1)*4
PUSH EDX //把返回地址壓棧,這樣棧中就只有這一個返回地址了,返回之后棧 ? ? ? //就空了
RET
}

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


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

?
//////////////////////////////////////////////////////////////////////
附錄:一個攔截CreateFile函數(shù)的簡單實現(xiàn)
//////////////////////////////////////////////////////////////////////
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èi)存失敗!\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("申請參數(shù)內(nèi)存失敗!\n");
? ? ? CloseHandle(hTargetProcess);
? ? ? return -1;
? }

? printf("\n線程內(nèi)存地址:%.8x\n"
? ? ? ? "參數(shù)內(nèi)存地址:%.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 閱讀(1254) 評論(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>
            中国女人久久久| 亚洲一区二区三区免费视频| 亚洲全黄一级网站| 影音先锋中文字幕一区| 一区二区视频免费在线观看| 国产日韩在线不卡| 在线观看91久久久久久| 亚洲人妖在线| 欧美一级视频免费在线观看| 久久精品2019中文字幕| 巨乳诱惑日韩免费av| 久热精品视频| 亚洲毛片播放| 亚洲欧美日韩在线综合| 久久久久久久欧美精品| 欧美大片在线观看| 国产精品白丝jk黑袜喷水| 国产欧美日韩一区二区三区在线 | 欧美激情国产高清| 亚洲美女黄网| 久久精品九九| 欧美日韩一区二区三区| 国产日韩欧美不卡在线| 亚洲电影第三页| 亚洲综合三区| 免费视频一区二区三区在线观看| 亚洲人成网站在线观看播放| 亚洲人成在线播放| 欧美在线高清视频| 欧美日韩视频在线观看一区二区三区| 国产人久久人人人人爽| 亚洲另类视频| 老司机aⅴ在线精品导航| 一区二区三区四区五区在线| 久久综合精品一区| 亚洲日本无吗高清不卡| 欧美亚洲免费| 亚洲国产日韩一级| 久久精品夜色噜噜亚洲aⅴ| 亚洲性夜色噜噜噜7777| 国产精品你懂的在线欣赏| 亚洲一区日本| 性感少妇一区| 国产精品久久中文| 性久久久久久久久| 亚洲伊人一本大道中文字幕| 久久夜色精品国产亚洲aⅴ| 欧美一区91| 日韩视频免费观看高清在线视频| 99国产精品国产精品久久| 亚洲国产日韩欧美综合久久| 欧美一级淫片aaaaaaa视频| 国产性天天综合网| 欧美亚洲免费| 亚洲一区日韩在线| 国产欧美日韩综合| 亚洲在线一区| 女主播福利一区| 一区二区三区视频在线播放| 免费久久精品视频| 久热re这里精品视频在线6| 蜜桃av一区二区三区| 日韩性生活视频| 免费在线亚洲欧美| 欲香欲色天天天综合和网| 欧美综合二区| 欧美一级二级三级蜜桃| 国产乱码精品1区2区3区| 亚洲欧美日韩另类| 一本色道久久88精品综合| 欧美性久久久| 久久国产日韩| 久久久久国产一区二区| 亚洲电影免费观看高清完整版在线 | 亚洲国产日韩欧美在线动漫| 久久人人九九| 亚洲日本中文字幕免费在线不卡| 亚洲韩国精品一区| 欧美日韩另类在线| 欧美一级午夜免费电影| 久久精品国产清自在天天线| 一区国产精品| 亚洲激情网址| 欧美性色综合| 久久久久久香蕉网| 欧美/亚洲一区| 亚洲一区三区视频在线观看| 欧美一区二区三区在线免费观看| 尤物精品国产第一福利三区| 亚洲国产另类精品专区| 欧美日韩亚洲国产一区| 久久精品99国产精品酒店日本| 久久精品理论片| 国产一区二区三区久久| 久久激情婷婷| 欧美国产一区二区| 欧美一区二区视频在线观看2020| 久久精品人人爽| 日韩视频欧美视频| 午夜精品成人在线| 夜夜嗨av色一区二区不卡| 亚洲欧美国产精品va在线观看| 黄色成人精品网站| 一本到高清视频免费精品| 一区二区三区在线高清| 亚洲视频国产视频| 亚洲人成7777| 久久成人人人人精品欧| 亚洲一区在线观看免费观看电影高清| 久久精品国产免费| 性色av一区二区三区红粉影视| 老牛国产精品一区的观看方式| 亚洲综合视频网| 欧美国产欧美亚洲国产日韩mv天天看完整| 午夜欧美电影在线观看| 欧美精品福利| 欧美激情精品久久久| 国产亚洲a∨片在线观看| 一区二区三区高清在线| 亚洲人www| 久热精品在线视频| 久久亚洲精品网站| 国产一区二区久久久| 亚洲自拍另类| 午夜精品一区二区三区四区 | 欧美日韩国产天堂| 欧美成人国产一区二区| 国产在线播放一区二区三区| 亚洲一区二区免费视频| 亚洲专区一二三| 欧美日韩成人| 亚洲片在线资源| 日韩一区二区高清| 欧美国产第二页| 亚洲人成人77777线观看| 亚洲国产色一区| 麻豆精品一区二区综合av| 美女精品在线观看| 在线观看欧美| 久久夜色精品亚洲噜噜国产mv| 欧美一级久久久| 国产午夜精品美女视频明星a级 | 亚洲毛片视频| 欧美日本簧片| 亚洲伦理在线免费看| av成人动漫| 国产精品久久777777毛茸茸| 一本一本a久久| 午夜精品一区二区三区电影天堂| 国产精品国产馆在线真实露脸| 亚洲网在线观看| 欧美一区二区三区四区高清 | 一本一本久久a久久精品综合妖精| 麻豆成人综合网| 欧美成人国产一区二区| 亚洲精品一区二区在线| 欧美国产亚洲视频| 亚洲婷婷在线| 久久这里有精品15一区二区三区| 狠狠色综合一区二区| 麻豆成人在线播放| 一区二区日韩伦理片| 久久激情一区| 亚洲日本激情| 国产精品护士白丝一区av| 欧美亚洲综合久久| 欧美国产精品日韩| 亚洲婷婷国产精品电影人久久| 国产精品亚洲成人| 美女脱光内衣内裤视频久久网站| 亚洲国产精品综合| 午夜在线视频一区二区区别| 好吊成人免视频| 欧美日韩久久| 久久久欧美精品sm网站| 亚洲美女电影在线| 久久久久在线| 亚洲四色影视在线观看| 激情成人av| 国产精品久久久久久久久久免费| 午夜精品国产更新| 亚洲精品1区| 国产日韩欧美精品一区| 久久亚洲欧美| 国产精品s色| 亚洲精品久久嫩草网站秘色| 亚洲国产成人在线视频| 亚洲免费婷婷| 亚洲韩国精品一区| 国产精品蜜臀在线观看| 欧美成人小视频| 亚洲欧美日韩精品一区二区| 亚洲国产三级网| 久久久综合视频| 亚洲欧美日韩国产成人| 亚洲黄色三级| 国内精品久久久久久| 国产精品免费一区豆花| 欧美日产在线观看| 欧美成年人视频网站|