about Injection
被说成是 black paper..... 俺只是技术研究,没其它目的.....
代码优化
bool EnablePrivilege(LPCTSTR lpszPrivilege, bool bEnable)
{
HANDLE TokenHandle = NULL;
//
if ( FALSE == ::OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &TokenHandle) )
{
return false;
}
TOKEN_PRIVILEGES tkp;
// Get LUID for SeDebugPrivilege
if( FALSE == ::LookupPrivilegeValue(NULL, lpszPrivilege, &tkp.Privileges[0].Luid) )
{
::CloseHandle(TokenHandle);
return false;
}
tkp.PrivilegeCount = 1;
#ifndef SE_PRIVILEGE_REMOVED
#define SE_PRIVILEGE_REMOVED 0X00000004
#endif
if( bEnable )
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tkp.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;
if ( FALSE == AdjustTokenPrivileges(TokenHandle, FALSE, &tkp, 0, NULL, NULL) )
{
::CloseHandle(TokenHandle);
return false;
}
::CloseHandle(TokenHandle);
return true;
}
bool RemoteLoadDLL(DWORD dwProcessID, const char* pszDLLPath)
{
typedef HMODULE (WINAPI *LoadLibraryPointor)(LPCTSTR);
LoadLibraryPointor pfnLoadLibrary = NULL;
HMODULE hKernel32 = NULL;
//Get address to LoadLibrary and FreeLibrary
if (pfnLoadLibrary == NULL)
{
hKernel32 = ::GetModuleHandle("kernel32.dll");
if ( hKernel32 == NULL )
{
return false;
}
pfnLoadLibrary = (LoadLibraryPointor)GetProcAddress(hKernel32, "LoadLibraryA");
if (pfnLoadLibrary == NULL)
{
::FreeLibrary(hKernel32);
return false;
}
}
if( !EnablePrivilege(SE_DEBUG_NAME, true) )
return false;
HANDLE process = ::OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ|PROCESS_QUERY_INFORMATION, TRUE, dwProcessID);
if ( process == NULL )
{
::EnablePrivilege(SE_DEBUG_NAME, false);
return false;
}
PVOID memory = ::VirtualAllocEx(process, NULL, strlen(pszDLLPath)+1, MEM_COMMIT, PAGE_READWRITE);
if ( memory == NULL )
{
::EnablePrivilege(SE_DEBUG_NAME, false);
::CloseHandle(process);
return false;
}
if ( FALSE == ::WriteProcessMemory(process, memory, (LPVOID)pszDLLPath, strlen(pszDLLPath)+1, NULL) )
{
::EnablePrivilege(SE_DEBUG_NAME, false);
::VirtualFreeEx(process, memory, strlen(pszDLLPath)+1, MEM_RELEASE);
::CloseHandle(process);
return false;
}
// Inject Code
DWORD dwThreadID = 0;
HANDLE hRemoteHandle = ::CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pfnLoadLibrary, memory, 0, &dwThreadID);
if ( hRemoteHandle == NULL )
{
::EnablePrivilege(SE_DEBUG_NAME, false);
::VirtualFreeEx(process, memory, strlen(pszDLLPath)+1, MEM_RELEASE);
::CloseHandle(process);
return false;
}
::WaitForSingleObject(hRemoteHandle, INFINITE);
DWORD dwReturn = 0;
if( FALSE == ::GetExitCodeThread(hRemoteHandle, &dwReturn) )
{
::EnablePrivilege(SE_DEBUG_NAME, false);
::CloseHandle(hRemoteHandle);
::VirtualFreeEx(process, memory, strlen(pszDLLPath)+1, MEM_RELEASE);
::CloseHandle(process);
return false;
}
::EnablePrivilege(SE_DEBUG_NAME, false);
::CloseHandle(hRemoteHandle);
::VirtualFreeEx(process, memory, strlen(pszDLLPath)+1, MEM_RELEASE);
::CloseHandle(process);
::FreeLibrary(hKernel32);
if( dwReturn == NULL )
return false;
else
return true;
}
HMODULE GetProcessModule(DWORD dwPID, LPCTSTR czDllName)
{
HMODULE hMod = NULL;
BOOL bFound = FALSE;
HANDLE hModuleSnap = NULL;
MODULEENTRY32 me32 = {0};
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
if (hModuleSnap == INVALID_HANDLE_VALUE)
return (FALSE);
// Fill the size of the structure before using it.
me32.dwSize = sizeof(MODULEENTRY32);
// Walk the module list of the process, and find the module of
// interest. Then copy the information to the buffer pointed
// to by lpMe32 so that it can be returned to the caller.
if (Module32First(hModuleSnap, &me32))
{
do
{
if(0 == lstrcmpi(czDllName, me32.szExePath))
{
hMod = me32.hModule;
}
}
while (hMod == NULL && Module32Next(hModuleSnap, &me32));
}
else
{
hMod = NULL; // could not walk module list
}
// Do not forget to clean up the snapshot object.
CloseHandle(hModuleSnap);
return hMod;
}
bool RemoteUnLoadDLL(DWORD dwProcessID, const char* pszDLLPath)
{
typedef BOOL (WINAPI *FreeLibraryFunType)(HMODULE hModule);
FreeLibraryFunType pfnFreeLibrary = NULL;
HMODULE hKernel32 = NULL;
//Get address to FreeLibrary
if (pfnFreeLibrary == NULL)
{
hKernel32 = ::GetModuleHandle("kernel32.dll");
if ( hKernel32 == NULL )
{
return false;
}
pfnFreeLibrary = (FreeLibraryFunType)GetProcAddress(hKernel32, "FreeLibrary");
if (pfnFreeLibrary == NULL)
{
::FreeLibrary(hKernel32);
return false;
}
}
if( !EnablePrivilege(SE_DEBUG_NAME, true) )
return false;
HANDLE process = ::OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ|PROCESS_QUERY_INFORMATION, TRUE, dwProcessID);
if ( process == NULL )
{
::EnablePrivilege(SE_DEBUG_NAME, false);
return false;
}
HMODULE hUnloadDll = GetProcessModule(dwProcessID, pszDLLPath);
if( hUnloadDll == NULL )
return true;
// Inject Code
DWORD dwThreadID = 0;
HANDLE hRemoteHandle = ::CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pfnFreeLibrary, (LPVOID)hUnloadDll, 0, &dwThreadID);
if ( hRemoteHandle == NULL )
{
::EnablePrivilege(SE_DEBUG_NAME, false);
::CloseHandle(process);
return false;
}
::WaitForSingleObject(hRemoteHandle, INFINITE);
DWORD dwReturn = 0;
if( FALSE == ::GetExitCodeThread(hRemoteHandle, &dwReturn) )
{
::EnablePrivilege(SE_DEBUG_NAME, false);
::CloseHandle(hRemoteHandle);
::CloseHandle(process);
return false;
}
::EnablePrivilege(SE_DEBUG_NAME, false);
::CloseHandle(hRemoteHandle);
::CloseHandle(process);
::FreeLibrary(hKernel32);
if( dwReturn == FALSE )
return false;
else
return true;
}
目前存在的已知问题:
1. 未考虑 64 位机器
2. 未考虑 DLL 加载失败的处理 (2010.02.05-23:38 已经 Fixed)3. 提权后没有恢复 (2010.02.07-17:15 已经Fixed)
4. 在 RemoteUnloadDLL 时,采用的是重定位DLL句柄的方法,有人跟我反应这种方法不安全,但我暂时还没想到什么情况下会引发问题。目标程序的输出结果是:
DLL_PROCESS_ATTACH C:\Documents and Settings\Administrator\桌面\demo\test\Debug\test.exe
DLL_THREAD_DETACH C:\Documents and Settings\Administrator\桌面\demo\test\Debug\test.exe
The thread 0x878 has exited with code 13500416 (0xCE0000).
DLL_THREAD_ATTACH C:\Documents and Settings\Administrator\桌面\demo\test\Debug\test.exe
DLL_PROCESS_DETACH C:\Documents and Settings\Administrator\桌面\demo\test\Debug\test.exe
The thread 0x624 has exited with code 1 (0x1).
(开始不明白,结果看了DLL_THREAD_DETACH 认识误区后就明白了)又一天就这么过去了~