《逆向工程核心原理》——DLL注入与卸载
阅读原文时间:2023年07月11日阅读:1

利用CreateRemoteThread

#include
#include
#include
#include
BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid;

if (!OpenProcessToken(GetCurrentProcess(),  
    TOKEN\_ADJUST\_PRIVILEGES | TOKEN\_QUERY,  
    &hToken))  
{  
    \_tprintf(L"OpenProcessToken error: %u\\n", GetLastError());  
    return FALSE;  
}

if (!LookupPrivilegeValue(NULL,           // lookup privilege on local system  
    lpszPrivilege,  // privilege to lookup  
    &luid))        // receives LUID of privilege  
{  
    \_tprintf(L"LookupPrivilegeValue error: %u\\n", GetLastError());  
    return FALSE;  
}

tp.PrivilegeCount = 1;  
tp.Privileges\[0\].Luid = luid;  
if (bEnablePrivilege)  
    tp.Privileges\[0\].Attributes = SE\_PRIVILEGE\_ENABLED;  
else  
    tp.Privileges\[0\].Attributes = 0;

// Enable the privilege or disable all privileges.  
if (!AdjustTokenPrivileges(hToken,  
    FALSE,  
    &tp,  
    sizeof(TOKEN\_PRIVILEGES),  
    (PTOKEN\_PRIVILEGES)NULL,  
    (PDWORD)NULL))  
{  
    \_tprintf(L"AdjustTokenPrivileges error: %u\\n", GetLastError());  
    return FALSE;  
}

if (GetLastError() == ERROR\_NOT\_ALL\_ASSIGNED)  
{  
    \_tprintf(L"The token does not have the specified privilege. \\n");  
    return FALSE;  
}

return TRUE;  

}

BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
{
HANDLE hProcess = NULL, hThread = NULL;
HMODULE hMod = NULL;
LPVOID pRemoteBuf = NULL;
DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);
LPTHREAD_START_ROUTINE pThreadProc;

// #1. 通过dwPID获取进程句柄  
if (!(hProcess = OpenProcess(PROCESS\_ALL\_ACCESS, FALSE, dwPID)))  
{  
    \_tprintf(L"OpenProcess(%d) failed!!! \[%d\]\\n", dwPID, GetLastError());  
    return FALSE;  
}

// #2. 在注入的目标进程中开辟内存,存储Dll的路径  
pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM\_COMMIT, PAGE\_READWRITE);

// #3. 写入DLL路径数据  
WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);

// #4. 获取LoadLibraryA() API  
hMod = GetModuleHandle(L"kernel32.dll");  
pThreadProc = (LPTHREAD\_START\_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");

// #5. 调用CreateRemoteThread  
hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);  
WaitForSingleObject(hThread, INFINITE);

CloseHandle(hThread);  
CloseHandle(hProcess);

return TRUE;  

}
BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName)
{
BOOL bMore = FALSE, bFound = FALSE;
HANDLE hSnapshot, hProcess, hThread;
HMODULE hModule = NULL;
MODULEENTRY32 me = { sizeof(me) };
LPTHREAD_START_ROUTINE pThreadProc;

// dwPID = notepad 进程id  
// 使用TH32CS\_SNAPMODULE 参数,获取加载到notepad 进程dll的名称  
hSnapshot = CreateToolhelp32Snapshot(TH32CS\_SNAPMODULE, dwPID);//句柄

bMore = Module32First(hSnapshot, &me);  
for (; bMore; bMore = Module32Next(hSnapshot, &me))//循环比较地址  
{  
    if (!\_tcsicmp((LPCTSTR)me.szModule, szDllName) ||  
        !\_tcsicmp((LPCTSTR)me.szExePath, szDllName))  
    {  
        bFound = TRUE;  
        break;  
    }  
}

if (!bFound)  
{  
    CloseHandle(hSnapshot);  
    return FALSE;  
}

if (!(hProcess = OpenProcess(PROCESS\_ALL\_ACCESS, FALSE, dwPID)))//获取目标进程的句柄  
{  
    \_tprintf(L"OpenProcess(%d) failed!!! \[%d\]\\n", dwPID, GetLastError());  
    return FALSE;  
}

hModule = GetModuleHandle(L"kernel32.dll");  
pThreadProc = (LPTHREAD\_START\_ROUTINE)GetProcAddress(hModule, "FreeLibrary");//获取FreeLibrary的api地址  
hThread = CreateRemoteThread(hProcess, NULL, 0,  
    pThreadProc, me.modBaseAddr,  
    0, NULL);      //卸载dll  
WaitForSingleObject(hThread, INFINITE);

CloseHandle(hThread);  
CloseHandle(hProcess);  
CloseHandle(hSnapshot);

return TRUE;  

}
int main()
{
std::cout << "Hello World!\n";
DWORD pID;
std::cout << "input pid:\n";
_tscanf(_T("%d"), &pID);
TCHAR dllPath[256] = { 0 };
std::cout << "input dll path:\n";
_tscanf(_T("%s"), dllPath);
if (!SetPrivilege(SE_DEBUG_NAME, TRUE)) {
printf("error \n");
getchar();
return 1;
}

// inject dll  
if (InjectDll(pID, dllPath)) {  
    \_tprintf(L"InjectDll(\\"%s\\") success!!!\\n", dllPath);  
    getchar();  
}

else {  
    \_tprintf(L"InjectDll(\\"%s\\") failed!!!\\n", dllPath);  
    getchar();  
}  
printf("input 'q' to ejection\\n");  
if (getchar() == 'q') {  
    if (EjectDll(pID, dllPath)) {  
        printf("ejection success!\\n");  
    }  
    else  
    {  
        printf("ejection error!\\n");  
    }  
}  
return 0;  

}