轉:DLL注入大法—之利用特洛伊DLL進行注入

來源:互聯網
上載者:User
這種方法的原理就是由自己寫一個與原有進程調用的DLL具有相同介面函數的DLL,再用我們的DLL替換原有的DLL。在替換的過程中,由我們自己編寫感興趣的函數替換原有函數,而對其它不感興趣的函數,則以函數轉寄的形式調用原有DLL中的函數。這裡面有個前提,就是你在編寫DLL時你必須知道原有DLL中的函數都有哪些,以免導至其它進程調用DLL時找不到相應的API函數,特別是在替換系統DLL檔案時更要小心。

下面就來示範一下這種方式。我是這樣做的,首先寫一個DLL作為被替換的DLL,名為DllLib.dll(最後更名為_DllLib.dll),然後寫特洛伊DLL,名為TroyDll.Dll(最後更名為原有DLL名,即DllLib.dll),與DllLib.Dll具有相同的API函數過程,但是對其中的一個API函數做更改,使其完成我們的工作,因為另外還有一個API函數需要對其進行函數轉寄,轉給原來的DLL,即(更名為_DllLib.dll的DllLib.dll)。這時我們的測試程式本來是調用的DllLib.dll的,但由於DllLib.dll已經被TroyDll.dll替換了,所以測試程式實際上調用的是TroyDll.dll,而對於做轉寄的函數,則是通過TroyDll.Dll調用DllLib.dll(更名後的_DllLib.dll)完成的。此時我們的特洛伊DLL實際上已經注入到我們的測試程式的進程空間中來了。

1、編寫本來的DLL。DllLib.dll(更名後為_DllLib.dll)的代碼如下:

//===========================================================================

// 檔案: UnitLib.cpp

// 說明: 示範用特洛伊DLL進行DLL注入.這個是本身的DLL,另一個特洛伊DLL將

// 對它進行函數轉寄,並實現另外的功能.

// 作者: 陶冶(無邪)

//===========================================================================

// 函式宣告

extern "C" __declspec(dllexport) __stdcall void About();

extern "C" __declspec(dllexport) __stdcall int Add(int a, int b);

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)

{

return 1;

}

//---------------------------------------------------------------------------

void __declspec(dllexport) __stdcall About()

{

try

{

MessageBox(NULL,"這是本來的DLL檔案!","原來的DLL",

MB_ICONINFORMATION + MB_OK);

}catch(Exception &e)

{

MessageBox(NULL,e.Message.c_str(),"DllLib",MB_OK);

}

}

// 兩數相加(注意:這裡是兩數相加)

int __declspec(dllexport) __stdcall Add(int a, int b)

{

return (a + b);

}

2、編寫特洛伊DLL。TroyDll.dll的代碼如下:

//===========================================================================

// 檔案: UnitTroy.cpp

// 說明: 這個是特洛伊DLL,呆會將它的DLL檔案更改為要替換的DLL檔案名稱

// 作者: 陶冶

//===========================================================================

extern "C" __declspec(dllexport) __stdcall void About();

extern "C" __declspec(dllexport) __stdcall int Add(int a, int b);

int Multiply(int a, int b);

// DLL中的函數原形聲明

typedef void (WINAPI *ABOUT)();

typedef int (WINAPI *ADD)(int a, int b);

static String szDllName;

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)

{

szDllName = Application->ExeName;

szDllName = szDllName.SubString(0,szDllName.Length()

- String(StrRScan(szDllName.c_str(),'/')).Length());

// 更名後的DllLib.dll檔案名稱

szDllName = szDllName + "/_DllLib.dll";

return 1;

}

//---------------------------------------------------------------------------

void __declspec(dllexport) __stdcall About()

{

// 直接做函數轉寄

HANDLE hDll = NULL;

hDll = LoadLibrary(szDllName.c_str());

ABOUT about;

try

{

if (hDll != NULL)

{

about = (ABOUT)GetProcAddress(hDll,"About");

if (about != NULL)

about();

}

else

MessageBox(NULL,"載入原來的DLL錯誤!", "特洛伊DLL",

MB_ICONINFORMATION + MB_OK);

}catch(Exception &e)

{

MessageBox(NULL,e.Message.c_str(),"DllTroy",MB_OK);

}

}

int __declspec(dllexport) __stdcall Add(int a, int b)

{

int nRet;

HANDLE hDll = NULL;

ADD add;

hDll = LoadLibrary(szDllName.c_str());

if (hDll != NULL)

{

// 為了方便示範,這裡再做一次函數轉寄,以便看到本來應該返回的值。

add = (ADD)GetProcAddress(hDll,"Add");

if (add != NULL)

nRet = add(a, b);

ShowMessage("這是本來DLL中的調用結果:" + IntToStr(nRet));

}

else

MessageBox(NULL, "載入本來的DLL錯誤!", "特洛伊DLL", MB_OK);

// 將原來完成兩數相加的更改為兩數相乘,返回兩數的積。

nRet = Multiply(a, b);

return nRet;

}

int Multiply(int a, int b)

{

return (a * b);

}

3、編寫測試工程。在表單中添加兩個按鈕,分別調用DllLib.dll中的兩個API函數。代碼如下:

typedef (WINAPI *ABOUT)();

typedef int (WINAPI *ADD)(int a, int b);

//---------------------------------------------------------------------------

__fastcall TfrmMain::TfrmMain(TComponent* Owner)

: TForm(Owner)

{

}

//---------------------------------------------------------------------------

void __fastcall TfrmMain::FormCreate(TObject *Sender)

{

m_szDllName = Application->ExeName;

m_szDllName = m_szDllName.SubString(0,m_szDllName.Length()

- String(StrRScan(m_szDllName.c_str(),'/')).Length());

m_szDllName = m_szDllName + "/DllLib.dll";

}

//---------------------------------------------------------------------------

// 調用About()函數

void __fastcall TfrmMain::Button1Click(TObject *Sender)

{

HANDLE hDll;

ABOUT about;

try

{

hDll = LoadLibrary(m_szDllName.c_str());

if (hDll != NULL)

{

about = (ABOUT)GetProcAddress(hDll,"About");

if (about != NULL)

about();

}

}catch(Exception &e)

{

MessageBox(Handle, e.Message.c_str(), "ERROR",MB_OK);

}

}

//---------------------------------------------------------------------------

// 調用Add()函數

void __fastcall TfrmMain::Button2Click(TObject *Sender)

{

HANDLE hDll;

ADD add;

int nRet;

hDll = LoadLibrary(m_szDllName.c_str());

if (hDll != NULL)

{

add = (ADD)GetProcAddress(hDll,"Add");

if (add != NULL)

nRet = add(10, 2);

ShowMessage("從特洛伊DLL中返回的結果 : " + IntToStr(nRet));

}

}

4、測試。將DllLib.dll更名為_DllLib.dll,將TroyDll.dll更名為DllLib.dll,即完成了DLL的替換。下面運行我們的測試工程,單擊調用About()函數的按鈕,因為About()是通過DllLib.dll(即TroyDll.dll)做的函數轉寄(轉以給原DLL,即_DllLib.dll),所以看到的是原DLL(即_DllLib.dll)中彈出的資訊框。此時用查看進程模組的工具來查看進程空間,你會發現,你的特洛伊DLL(更名後的DllLib.dll)已經成功以注入到了測試程式的進程空間中了。

單擊調用Add()函數的按鈕,你會看到本來是完成兩數相加的,返回的結果卻是兩數的積,因為我們已經在特洛伊DLL中對它做了手腳。這下是利用它的關鍵了。WINDOWS登入時的GINA,知道吧,想得到別人登入的密碼嗎?那麼就是用這種方法了,把MSGINA.dll這個東西給它替換成自己的DLL,再複雜的密碼也照樣得到啊,一點也不費精神,呵呵~。(想自己寫嗎?看看《WinLogon登入管理和GINA簡介》吧)

環境:

WIN2000 Server + BCB 6.0

附:本文相關程式碼

參考:《WINDOWS核心編程》

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.