转:DLL注入大法—之利用特洛伊DLL进行注入

这种方法的原理就是由自己写一个与原有进程调用的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核心编程》

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Delphi是一种编程语言,而DLL(Dynamic-Link Library)是一种模块化的文件格式,用于存储代码和数据,可以被多个应用程序共享。DLL注入是一种技术,它允许将DLL文件加载到正在运行的进程中,并使得该进程能够调用DLL中的函数和使用其中的数据。 在Delphi中实现DLL注入的方法有很多种。一种常见的方法是使用Windows API函数LoadLibrary和GetProcAddress。通过调用LoadLibrary函数,将DLL文件加载到进程的虚拟地址空间中。然后使用GetProcAddress函数获取DLL中导出函数的地址,并将其传递给需要调用的函数。通过这种方式,可以在运行时将DLL注入到目标进程中,并且通过调用DLL中的函数来扩展进程的功能。 DLL注入在实际应用中有多种用途。例如,可以使用DLL注入来为某个程序添加额外的功能或修改程序的行为。DLL注入还可以用于实现一些调试和监控的功能。通过注入DLL,可以截获程序的输入和输出,或者在程序执行某些指定的操作时进行额外的处理。 在Delphi中实现DLL注入需要一定的编程知识和技巧。需要考虑目标进程的架构和权限限制,以及如何管理注入DLL的生命周期和资源管理。同时,还需要处理一些安全性和稳定性方面的问题,以确保注入过程不会对目标进程造成损害或崩溃。 总之,Delphi可以通过调用Windows API函数来实现DLL注入,从而扩展和修改进程的功能。但在实际应用中,需要考虑各种方面的问题,并且遵守相关的法律和规定,以确保注入操作的安全性和合法性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值