转:DLL注入大法—之HOOK注入

我原来写过有关HOOK的介绍,如果你看过了或者是以前写过HOOK程序,那么你已经会这种DLL注入了。它其它就是为系统或某个线程安装一个钩子。这里要说的是,如果是全局钩子,那么你的DLL将会在进程调用时载入到任意一个调用的进程的地址空间中,这样是相当浪费资源的。因此我在下载的演示中就只对某一个指定的线程安装线程钩子。

  1、用BCB建立一个DLL工程(如果你用的是VC或其它,请自己对照),输入以下代码:

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

// 文件: UnitLib.cpp

// 说明: 演示利用钩子技术进行DLL注入.

// 将本DLL中的代码注入到指定的进程空间.

// 作者: 陶冶(无邪)

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


// 函数声明

extern "C" __declspec(dllexport) __stdcall

bool SetHook(DWORD dwThreadId);

extern "C" __declspec(dllexport) __stdcall

LRESULT CALLBACK MyProc(int nCode, WPARAM wParam, LPARAM lParam);


static HHOOK hHook = NULL; // 钩子句柄

static HINSTANCE hInst; // 当前DLL句柄


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

{

hInst = hinst;

return 1;

}

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

// 安装钩子函数

bool __declspec(dllexport) __stdcall SetHook(DWORD dwThreadId)

{

if (dwThreadId != 0)

{

MessageBox(NULL, ("DLL已经注入!nThreadId = " +

IntToStr(dwThreadId)).c_str(),"DLL",

MB_ICONINFORMATION + MB_OK);

    // 安装指定线程的钩子

hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)MyProc,

hInst,dwThreadId);

if (hHook != NULL)

return true;

}else

{

MessageBox(NULL, "DLL即将从记事本进程空间中撤出!","DLL",

MB_ICONINFORMATION + MB_OK);

return (UnhookWindowsHookEx(hHook));

}

return true;

}


// 钩子函数

LRESULT CALLBACK __declspec(dllexport) __stdcall

MyProc(int nCode, WPARAM wParam, LPARAM lParam)

{

  // 因为只是演示DLL注入,所以这里什么也不做,交给系统处理

return (CallNextHookEx(hHook, nCode, wParam, lParam));

}

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


该DLL中有两个函数,一个为安装钩子函数(SetHook),另一个为钩子函数(MyProc)。其中安装钩子函数提供了一个参数,由该参数指定安装到哪个线程,如果该参数为0,则卸载钩子。

  编译该工程,即生成我们要用来注入到指定进程中的DLL文件了。

    

2、建立测试工程。用BCB建立一个应用程序工程,在窗体中添加两个按钮,一个用来安装线程钩子,一个用来卸载。代码如下:

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

// SetHook函数原型声明

typedef BOOL (WINAPI *LPSETHOOK)(unsigned long dwThreadId);


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

__fastcall TfrmMain::TfrmMain(TComponent* Owner)

: TForm(Owner)

{

}

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

// 安装钩子

void __fastcall TfrmMain::Button1Click(TObject *Sender)

{

String szPath;

LPSETHOOK lproc;

HANDLE hDll;

BOOL bRet;

PROCESS_INFORMATION info;

STARTUPINFO start;


memset(&start, 0, sizeof(start));

// 取得要载入的DLL文件名

szPath = Application->ExeName;

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

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

szPath = szPath + "/DllLib.dll";

  // 载入DLL

hDll = LoadLibrary(szPath.c_str());

if (hDll != NULL)

{

lproc = (LPSETHOOK)GetProcAddress(hDll,"SetHook");

if (lproc != NULL)

{

// 因为没有适当的工具可以取得线程ID,也为了简单起见,所以这里新创建了一个记事本进程,以便取得它的线程ID,对其安装钩子,把我们的DLL注入到记事本进程中。

bRet = CreateProcess(NULL,

"c:/winnt/system32/notepad.exe",

NULL,

NULL,

TRUE,

0,

NULL,

NULL,

&start,

&info);

if (bRet != 0)

{

if((*lproc)(info.dwThreadId) == false)

ShowMessage("Sethook failed with error " +

IntToStr(GetLastError()));

}

else

{

ShowMessage("CreateProcess failed with error " +

IntToStr(GetLastError()));

}

}

}

}

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

// 卸载钩子

void __fastcall TfrmMain::Button2Click(TObject *Sender)

{

String szPath;

LPSETHOOK lproc;

HANDLE hDll;


szPath = Application->ExeName;

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

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

szPath = szPath + "/DllLib.dll";

hDll = LoadLibrary(szPath.c_str());

if (hDll != NULL)

{

lproc = (LPSETHOOK)GetProcAddress(hDll,"SetHook");

if (lproc != NULL)

(*lproc)(0);

}

}

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

  接下来生成可执行文件,点击第一个安装钩子按钮,然后你就可以用我们最开始写的查看模块的工具来查看了,你将会在模块中看到你刚才DLL的路径及文件名,这表明我们已经成功地将自己的DLL注入到了记事本进程空间。点击卸载按钮后,再查看记事本进程中的模块,将不会看到我们DLL文件的完整文件名,这表明已经成功撤消了对记事本进程的注入。

 

  • 0
    点赞
  • 1
    收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值