简介
由于各进程内存空间隔离,所以要想修改目标进程的数据,就需要先注入到目标进程中,
这里介绍最常见的一种注入方法,也就是远程线程注入
工作原理
先从目标进程中申请一段内存,保存注入的DLL路径,然后获取 LoadLibraryW
函数的地址,
作为 CreateRemoteThread
创建线程的函数,参数就是DLL的路径。同理还可以注入自定义
的shellcode代码,来实现其他的操作。注意x86和x64程序需要对应版本的DLL才能注入
相关代码
设置进程调试权限 SE_DEBUG_NAME
的函数如下所示(注:不提权也能注入)
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <windows.h> BOOL EnableDebugPrivilege() { HANDLE hToken = NULL; TOKEN_PRIVILEGES priv = { 1,{ 0, 0, SE_PRIVILEGE_ENABLED } }; BOOL ret = LookupPrivilegeValueW(0, SE_DEBUG_NAME, &priv.Privileges[0].Luid); if (!ret) return FALSE; ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken); if (!ret) return FALSE; ret = AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof(priv), 0, 0); CloseHandle(hToken); return ret; }
|
如果想要注入到UWP程序中,还需要给DLL文件设置 ALL APPLICATION PACKAGES
访问权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <accctrl.h> #include <aclapi.h> #include <sddl.h> BOOL SetAccessControl(PCWSTR pPath) { if (!pPath || !pPath[0]) return FALSE;
PACL pACLCurr = NULL; PSECURITY_DESCRIPTOR pSecurity = NULL; DWORD dwError = GetNamedSecurityInfoW(pPath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pACLCurr, NULL, &pSecurity); if (dwError != ERROR_SUCCESS) return FALSE;
PSID pSID = NULL; PACL pACLNew = NULL; BOOL bRet = FALSE; do { if(!ConvertStringSidToSidW(L"S-1-15-2-1", &pSID)) break;
EXPLICIT_ACCESSW stExplicit = { 0 }; stExplicit.grfAccessPermissions = GENERIC_ALL; stExplicit.grfAccessMode = SET_ACCESS; stExplicit.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; stExplicit.Trustee.TrusteeForm = TRUSTEE_IS_SID; stExplicit.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; stExplicit.Trustee.ptstrName = (PWSTR)pSID;
dwError = SetEntriesInAclW(1, &stExplicit, pACLCurr, &pACLNew); if (dwError != ERROR_SUCCESS) break;
dwError = SetNamedSecurityInfoW((PWSTR)pPath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pACLNew, NULL); if (dwError != ERROR_SUCCESS) break;
bRet = TRUE; } while (0);
if (pSecurity) LocalFree((HLOCAL)pSecurity); if (pACLNew) LocalFree((HLOCAL)pACLNew); if (pSID) LocalFree((HLOCAL)pSID); return bRet; }
|
获取目标进程PID的函数为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <tlhelp32.h> DWORD GetPidByName(PCWSTR pName) { if (!pName) return 0; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == INVALID_HANDLE_VALUE) return 0; PROCESSENTRY32W pe32 = { 0 }; pe32.dwSize = sizeof(PROCESSENTRY32W); if (!Process32FirstW(hSnapshot, &pe32)) { CloseHandle(hSnapshot); return 0; } do { if (!_wcsicmp(pe32.szExeFile, pName)) { CloseHandle(hSnapshot); return pe32.th32ProcessID; } ZeroMemory(&pe32, sizeof(PROCESSENTRY32W)); pe32.dwSize = sizeof(PROCESSENTRY32W); } while (Process32NextW(hSnapshot, &pe32)); CloseHandle(hSnapshot); return 0; }
|
注入到目标进程的函数为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| BOOL LoadInjectDll(DWORD dwPid, PCWSTR pPath) { if (!dwPid || !pPath) return FALSE; HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); if (!hProcess) return FALSE; BOOL result = FALSE; do { SIZE_T nLen = (wcslen(pPath) + 1) * sizeof(WCHAR); PVOID pBuffer = VirtualAllocEx(hProcess, NULL, nLen, MEM_COMMIT, PAGE_READWRITE); if (!pBuffer) break; SIZE_T nRet = 0; if (!WriteProcessMemory(hProcess, pBuffer, pPath, nLen, &nRet)) break; if (nLen != nRet) break; PTHREAD_START_ROUTINE pFunc = (PTHREAD_START_ROUTINE)GetProcAddress( GetModuleHandleW(L"Kernel32"), "LoadLibraryW"); if (!pFunc) break; HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, pFunc, pBuffer, 0, NULL); if (!hThread) break; CloseHandle(hThread); result = TRUE; } while (0); CloseHandle(hProcess); return result; }
|