dll注入基礎教程_第1頁
dll注入基礎教程_第2頁
dll注入基礎教程_第3頁
dll注入基礎教程_第4頁
dll注入基礎教程_第5頁
已閱讀5頁,還剩4頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

首先要明白什么是線程說到線程就不得不提到進程SDK文檔里是這樣描述的進程是一個正在運行的程序,它擁有自己的地址空間,擁有自己的代碼、數據和其他系統資源。一個進程包含了一個或者多個運行在此進程內的線程。說白了,其實進程就是一個磁盤上的程序載入內存執行后的東西打開任務管理器看看,里面有好多進程...從定義上看出進程一定要有線程,線程是進程內存中的獨立實體。講了這么多廢話其實就是想說程序運行后就變成了進程,你的代碼由線程來執行。回到正題上,線程插入是什么呢?就是把一個線程弄到別的進程執行你也許覺得奇怪,自己不是有個進程好好的嗎?其實這個作用大了,先說說開頭提到的木馬一來,有些比較由經驗的用戶有時會打開任務管理器,發現陌生進程?!想想你的木馬還能活嗎?那么插入Explorer等關鍵進程,你還想用電腦的話最好不要殺那個進程(不信試試)二來,大家現在都裝防火墻了,網絡連接經常會被慮掉,木馬豈不是沒用了?好,插入IE,防火墻想慮?除非你不想看網頁當然,還有很多用處,比如插入系統級別的進程,哈哈,我們有RingO權限了,(不要告訴我你不知道Ring0...就是連物理內存都可以寫的超級權限)HookAPI也需要把代碼注入別的進程知道了他的作用想知道怎么實現吧?別著急,慢慢來首先,這個應該屬于系統編程,系統編程就不能不知道APIAPI是什么?簡單點講就是Windows為我們提供的一些函數,利用他們我們可以做很多事情Delphi花了很大力氣用VCL還有一些亂七八糟的類把讓我們可以盡量不要API所以會編程序但不了解API還是可能的API被封裝在kernel32.dll、user32.dll等動態鏈接庫里,程序使用時候把DLL映射到自己的內存了編寫的時候我們通常需要從DLL導出這些函數functionBeep;external'kernel32.dll'name'Beep';這樣導出一個beep函數當然,實際上不要這么麻煩Delphi已經把這些導出聲明寫在一些單元里面了(比如windows單元)useswindows后就可以直接用了(而且建立窗口時候默認就會引用很多單元)所以實際上我們可以直接用的這個理解一下就好了開始講線程插入了一般來說線程插入有2種方法DLL注入直接的遠程線程插入DLL注入編寫的時候比較簡單,方法也多,但有個缺點進程會多出個模塊來,可能被發現遠程線程是直接修改對方內存的方法,雖然隱蔽性好,但是不小心可能會出點問題,比如你讓不能有界面的進程彈出個窗口,不能上網的進程開個端口,那就等著系統崩潰吧今天重點講DLL注入首先要知道什么是DLL,dll就是動態鏈接庫,大家應該知道吧?怎么編寫DLL呢?和寫普通程序差不多是一樣的新建一個工程,選DLLWizard發現了吧?除了program改成library剩下幾乎是一樣的,只是需要程序加載他的入口點我們先編寫個簡單的DLLlibraryTestDll;usesWindows;{$R*.res}procedurefunc_a;beginMessageBox(0,'Ilovedelphi','FunctionformTsetDLL',0);end;procedurefunc_b(MSG:pchar);beginMessageBox(0,MSG,'FunctionformTsetDLL',0);end;beginfunc_a;func_b('Ilikeittoo!');end.就是那個testdll.dpr看得懂吧,彈出2個信息框好了保存下,F9運行??出錯,哈哈,DLL是不能直接運行的那怎么辦?編譯下(按過F9就不用了,也會編譯好)看見那個DLL了吧?我們弄個程序加載它的入口點新建一個普通程序加一個按鈕按鈕事件只要寫一句loadlibrary('testdll.dll');MainShow.dpr運行,單擊按鈕,怎么養?彈出東西了吧當然DLL還可以做函數庫,資源庫等今天暫不討論現在DLL懂得寫了吧?就是program改成library而已你可以寫自己的程序了DLL會寫了,現在的問題就是怎么注入了我們目的只是讓對方的程序運行一句loadlibrary('testdll.dll');而已一切就OK了通常有這么幾種注入方法利用全局消息鉤子Win32下程序一般都要用收發消息用鉤子函數下全局鉤子,程序收到任何消息都加載我們的DLL的入口點當然,用這種方法DLL進入后要判斷自己是不是被插進目標進程是的話,執行代碼不是退出這個方法很麻煩但通用性很好,只要WINDOWS都可以用(但是有的系統進程消息是勾不住的,所以注入不了)早期的DLL注入大部分是用這個原理實現的寫注冊表寫 HKEY_LOCAL_MAHINE\Software\Microsoft\WindowsNT\CurrentVersion\Windows\AppInit_DLLs但是只能是NT下,而且必須是調用過user32.dll(Windows的一個內核,只要有界面的程序都調用它)的程序,在開機后所有程序會自動加載DLL,但是這個dll不能被卸載,而且不能調用某些函數,不然系統會掛掉(有危險性哦)不推薦使用利用遠程線程注入來實現DLL注入只要能打開句柄,就能成功(強吧?)而且實現起來比較簡單缺點就是9X內核的有點難度(也不是很困難)我們今天就講利用遠程線程注入來實現DLL注入吧!你可能要問,既然剛才說了遠程線程可以直接注入一個線程,為什么還要多此一舉反過來再調用DLL呢?這是因為,遠程線程技術一般是直接對目標程序的內存進行操作我們知道不同程序的虛擬內存是不一樣的所以很多函數的地址不一定一樣而程序運行的時候實際上是Call函數地址進行函數調用的所以我們要注意計算很多偏移之類的這是非常煩瑣的事情而且像上面說的讓不能有界面的進程彈出個窗口,那就不好玩了而DLL呢?DLL調用時其實是被映射到進程內存里面DLL擁有自己的導入表、資源、函數等東西,實際上就是一個完整的程序映入內存后和執行一個程序效果是一樣的這樣我們就不用考慮那些亂七八糟的東西,只要安心的寫功能即可好了,要明白遠程線程首先當然要把程序本地線程搞清楚了不知道大家編多線程程序的時候是不是都用tthread類?反正我是不喜歡那個我們看看Windows給我們的原始API吧(tthread類也是用它寫的)functionCreateThread(lpThreadAttributes:Pointer;//安全指針一般nil就可以了dwStackSize:DWORD;//線程初始化尺寸,一般用0,獲得與主線程一樣尺寸(不夠自己會增加,別擔心)lpStartAddress:TFNThreadStartRoutine;//一個指向要執行線程函數的指針,這個函數必須遵守Stdcall約定,并且可帶一個參數,參數必須是指針類型lpParameter:Pointer;//函數的參數dwCreationFlagS:DWORD;//控制創建標志,用0表示線程立刻執行varlpThreadId:DWORD)//返回標識變量我覺得沒什么用,反正句柄都有了:THandle;//返回線程的句柄stdcall;//標準調用Windows下API—般都是標準調用大家先看下看起來似乎比較復雜,等下舉個例子我們把DLL源碼里面的func_b拷到剛才那個EXE上稍微修改下procedurefunc_b(MSG:pchar);stdcall;beginMessageBox(0,MSG,'FunctionformTsetDLL',0);sleep(lOOOO);//線程暫停N久(不超過10s)end;加上2個按鈕第一個procedureTForm1.Button2Click(Sender:TObject);beginfunc_b('123');end;第二個procedureTForm1.Button3Click(Sender:TObject);vartid:longword;//放返回值,不放她不讓執行,郁悶str:pchar;//便于獲得pointerbeginstr:='123';createthread(nil,0,@func_b,//函數名前面加@是得到函數指針pointer(str),//雖然str也是指針,但是delphi就是要pointer型的,那就轉一下類型0,tid);//tid純屬放著占格式的,一般我們用不到end;//上面CreateThread看得懂吧,幾乎都是默認設置,以后套下去用就是了實際上都是調用func_b,只是第二個過程用了信新線程但是效果是不一樣的第一個按鈕按下彈出窗口后,程序卡死了(暫停10000)第二個卻不會為什么呢?我們可以這樣理解窗口看做一個主線程,執行func_b,彈出窗口,然后主線程掛起,于是卡死了而第二個過程創建一個新線程,新線程執行func_b,彈出窗口,掛起10000,但是由于主線程沒有掛起,所以看起來關掉窗口后沒什么事情發生(實際上那個線程還在偷偷執行,直到線程代碼運行完,只是它卡死不會影響你)這個如果明白了那么下面就容易理解了看看這個函數functionCreateRemoteThread(hProcess:THandle;lpThreadAttributes:Pointer;dwStackSize:DWORD;lpStartAddress:TFNThreadStartRoutine;lpParameter:Pointer;dwCreationFlags:DWORD;varlpThreadId:DWORD):THandle;stdcall;除了函數名不一樣,下面的參數多了個hProcess:THandle;,剩下的完全一樣呵呵,這個東西就是本節課的關鍵了先看函數名就知道是干什么用的了‘創建遠程線程'用法和剛才基本一致就是hProcess:THandle是什么呢?這里要填的是被注入線進程的句柄什么是句柄?打個比方,對象是一個門,句柄就是那個把手,通過句柄我們可以對門進行操作也就是說我們利用句柄來操作某些東西(包括進程、線程等等)你有沒有注意到,CreateThread和CreateRemoteThread都返回一個THandle,也就是線程的句柄還有loadlibrary也會返回DLL的句柄,我們可以利用他們對相關對象進行操作那么怎么獲得進程句柄呢?一般采用先得到進程PID再用下面的函數取得句柄functionOpenProcess(dwDesiredAccess:DWORD;//訪問標志一般填寫PROCESS_ALL_ACCESS,這樣這個句柄可以獲得最大操作權限bInheritHandle:BOOL;//可否繼承,這個跟子程序有關,無所謂了,填false和true都可以,反正我們自己能操作久可以dwProcessId:DWORD)://要獲得句柄的進程IDTHandle;stdcall;//返回句柄有時候會返回0,說明打開句柄失敗了一般是你的權限不夠(比如你想對Winlogon這些系統級程序操作)這時候我們需要提升權限一般Debug權限就可以了(其實操作權限里面最高了)提升的過程我寫好了直接調用就可以了(修改進程令牌到Debug級別,為什么這樣寫這里不詳細講了,自己去網上搜索下)procedureGetDebugPrivs;varhToken:THandle;tkp:TTokenPrivileges;retval:dword;beginIf(OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGESorTOKEN_QUERY,hToken))thenbeginLookupPrivilegeValue(nil,'SeDebugPrivilege',tkp.Privileges[0].Luid);tkp.PrivilegeCount:=1;tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken,False,tkp,0,nil,retval);end;end;不會暈吧?應該記得我剛才提到了要PID,那怎么得到呢?一般用FindWindow和GetWindowThreadProcessId配合的到這樣寫先varPid:longword;//儲存那個PIDGetWindowThreadProcessId(FindWindow('Notepad',nil),@PID);這樣就找到筆記本的PID,再如'Shell_TrayWnd'可以找到Explorer的窗口類名據說可以用SPY++查詢,不過這東西我沒見過,呵呵當然還可以枚舉進程判斷進程名等等這個先告一段落。好了,拿Windows的筆記本下手吧procedureTmyForm.Button4Click(Sender:TObject);varh:longword;//PID和THandle的類型其實都是longword,改個名字而已,所以可以通用beginwinexec('notepad',1);//運行筆記本GetWindowThreadProcessId(FindWindow('notepad',nil),@h);//得到Pid存在hh:=OpenProcess(PROCESS_ALL_ACCESS,False,h);//得到handle存在h,后面那個是變量pid,算完放到前面的h是句柄(兩個不同的東西,只是類型一樣而已)sleep(2000);//等2秒TerminateProcess(h,O);//關閉筆記本,h是那個句柄,0表示正常退出end;運行起來就是打開一個筆記本,大約2s狗關掉它不知道大家看懂了沒有,沒有不要緊,只是為了證明我們可以拿到一個課操作的進程句柄好像萬事具備了吧?那試試遠程線程了吧再建一個按鈕前面的還是這樣寫,再把那個建立線程的拷過來改成CreateRemoteThread加上h參數procedureTmyForm.Button5Click(Sender:TObject);varh:longword;tid:longword;str:pchar;beginstr:='123';winexec('notepad',1);GetWindowThreadProcessId(FindWindow('notepad',nil),@h);h:=OpenProcess(PROCESS_ALL_ACCESS,False,h);CreateRemoteThread(h,nil,0,@func_b,pointer(str),0,tid);end;運行起來筆記本出來了,對話框也出來了...可是對話框卻不是我們弄的那個,是個報錯的看看寫了什么內存'0x00000000'不能為'writen'為什么呢?記得我剛才說的么遠程線程是在別的程序里運行一個線程相當于讓里一個函數執行CreateThread所以,函數的地址不一定是一樣的,更何況筆記本里面怎么可能會有func_b這個我們自己寫的函數呢這么一來當然要出錯了這下傻了,那怎么注入我們要的函數呢?記得我們要講什么嗎?-利用遠程線程進行DLL注入我們可以把函數寫在DLL里面,用遠程線程讓目標進程加載它這樣函數就執行了我們只要想辦法讓對方程序loadlibrary('testdll.dll');那就OK了看看LoadLibrary的原型functionLoadLibrary(lpLibFileName:PAnsiChar):HMODULE;stdcall;你應該發現了它和線程要求的函數格式幾乎一樣參數是指針型PAnsiChar就是pchar,—個指向字符串的指針返回HMODULE,HM0DULE實質是longword(改個名字而已)那就遠程運行它吧這時候你可能會想,LoadLibrary的地址要怎么得到呢?要知道,LoadLibrary是一個API(在Kernel32.dll里面),實際上,每個Win32程序都需要里面的函數所以,大部分程序運行代碼前會裝入這個DLL,把里面的函數映射到自己的內存了這么一來,只要是這個DLL里面同一個函數在所有的進程里地址都是一樣的哈哈,這樣就容易了地址我們一般用GetProcAddressfunctionGetProcAddress(hModule:HMODULE;//模塊句柄,DLL被加載后就成立模塊,等下告訴大家怎么得到這個lpProcName:LPCSTR//函數在DLL中的導出名LoadLibrary實際上是LoadLibraryA//這個大家看看DelphiWindows單元的源碼就知道了):FARPROC;stdcall;//返回指針那些類型看得亂亂的吧,不要管他們,在Delphi上不鼠標停在函數上,類型的原型就出來了好了現在是怎么得到那個模塊的句柄的問題用GetModuleHandlefunctionGetModuleHandle(lpModuleName:PChar)//模塊名,DLL被加載后就成立模塊,所以就是DLL的文件名了:HMODULE;stdcall;//返回模塊句柄好了。知道了這些得到函數地址就容易了GetProcAddress(GetModuleHandle('KERNEL32.DLL'),'LoadLibraryA');一句搞定問題似乎都解決了吧?先別高興,不要忘記了,它還帶了個參數,就是那個DLL的名字參數類型是一個指向字符串地址的指針這個是個大問題,一來你不能保證別人的程序內存里有這個字符串二來有你也不知道他的位置,這可怎么辦呢?自己寫!我們把那個字符串寫到對方內存里呵呵,很霸道的方法,但的確是個好方法不廢話了,開始我們首先要在目標進程申請一塊內存,以便把那個參數寫進去申請內存用VirtualAllocEx,看看它的原型functionVirtualAllocEx(hProcess:THandle;//目標進程句柄,這個不用說了吧lpAddress:Pointer;//分配內存位置,一般用nil,這樣會在系統認為最合適的位置分配dwSize:DWORD;//分配的地址范圍,也就是大小了flAllocationType:DWORD;//如何分配地址,一般用MEM_COMMIT為指定空間提交物理內存flProtect:DWORD//該段內存的保護類型,PAGE_READWRITE表示可讀可寫):Pointer;stdcall;//返回內存地址,哈哈,這就是我們要的那個參數的指針了好了,分配完內存當然是要把我們的數據寫過去了這時候需要用到WriteProcessMemory來寫進程的內存functionWriteProcessMemory(hProcess:THandle;//目標進程句柄constlpBaseAddress:Pointer;//要寫的內存地址,就填我們那個參數的指針lpBuffer:Pointer;//數據的地址,我們把字符串存這里,讓他拷nSize:DWORD;//要拷貝的數據長度//字符串在Windows定義是以null(就是16進制的0)結尾的//所以長度就是字符串的長度+1varlpNumberOfBytesWritten:DWORD)//返回的什么東西,沒什么用:BOOL;stdcall;//返回成功或失敗我們來寫個完整的代碼吧procedureTmyForm.Button6Click(Sender:TObject);varh:longword;//放句柄,中間順便暫放下PIDtmp:longword;//這個專門來占格式收集垃圾DllName:pchar;Mysize:longword;//放字符串長度Parameter:pointer;//放那個參數的指針(位置在目標進程內)beginDLLName:='Testdll.dll';Mysize:=strlen(Dllname)+1;winexec('notepad',1);GetWindowThreadProcessId(FindWindow('notepad',nil),@h);h:=OpenProcess(PROCESS_ALL_ACCESS,False,h);Parameter:=VirtualAllocEx(h,nil,Mysize,MEM_COMMIT,PAGE_READWRITE);WriteProcessMemory(h,Parameter,Pointer(DllName),MySize,tmp);CreateRemoteThread(h,nil,0,GetProcAddress(GetModuleHandle('KERNEL32.DLL'),'LoadLibraryA'),Parameter,0,tmp);end;又看到那兩個熟悉的對話框了哈哈,這么說我們成功了如把那個DLL換成其他的功能,那就..

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論