【问题标题】:WriteProcessMemory to SYSTEM process with SeDebugPrivilege enabled. (C, Vista)启用 SeDebugPrivilege 的 WriteProcessMemory 到 SYSTEM 进程。 (C,远景)
【发布时间】:2010-11-11 05:26:39
【问题描述】:

我有兴趣将 DLL 注入到我的 Vista 机器上的 SYSTEM 拥有的进程中。我将使用 VirtualAllocEx、WriteProcessMemory 和 CreateRemoteThread 的传统方法来解决这个问题。但是,因为这将在 SYSTEM 进程上运行,所以我在打开目标进程之前在注入进程上启用了 SeDebugPivilege。


int EnableDebugPriv(LPCTSTR name) {
    HANDLE hToken;
    LUID luid;
    TOKEN_PRIVILEGES tkp;

    if(!OpenProcessToken(GetCurrentProcess(),
                         /*TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY*/
                         TOKEN_ALL_ACCESS,
                         &hToken))
        return 0;

    if(!LookupPrivilegeValue(NULL,name,&luid))
        return 0;

    tkp.PrivilegeCount=1;
    tkp.Privileges[0].Luid=luid;
    tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;

    if(!AdjustTokenPrivileges(hToken,false,&tkp,sizeof(tkp),NULL,NULL))
    {
        printf("!AdjustTokenPrivileges - %d\n",GetLastError());
        return 0;
    }
    if(GetLastError()==ERROR_NOT_ALL_ASSIGNED)
    {
        return 0;
    }

    CloseHandle(hToken);
    return 1;
}

SE_DEBUG_NAME 常量作为名称传递。

启用SeDebugPrivilege后,我经历了打开目标进程、定位LoadLibrary、分配空间、将DLL路径写入内存、创建线程(一路检查所有返回值)的过程:


if(NULL==(p=OpenProcess(PROCESS_ALL_ACCESS,FALSE,(DWORD)pid)))
...
if(NULL==(loadLib=(LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), 
                                         "LoadLibraryA")))
...
if(NULL==(dllBuff=(LPVOID)VirtualAllocEx(p,
                                         NULL,
                                         strlen(dllPath)+1,
                                         MEM_RESERVE|MEM_COMMIT,
                                         PAGE_READWRITE)))
...
if(NULL==WriteProcessMemory(p,
                            (LPVOID)dllBuff,
                            dllPath,
                            strlen(dllPath),
                            &written))
...
if(!CreateRemoteThread(p,
                       NULL,
                       NULL,
                       (LPTHREAD_START_ROUTINE)loadLib,
                       (LPVOID)dllBuff,
                       NULL,
                       NULL))
...

dllPath 是 DLL 路径的 char*(很明显),pid 是目标进程的 PID。这两个值都是通过命令行获取的,并在使用前进行验证。

我遇到的问题是,在 CreateRemoteThread 返回 8(“存储空间不足”)之前,什么都没有返回错误。但是,WriteProcessMemory 没有向进程写入任何字节。调用后,写入的变量始终为 0。没有写入字节,但函数没有失败。我不确定为什么会这样。我查看了其他权限,例如承诺对所有进程的写访问权限的 SeRestorePrivilege,但没有任何作用。

我正在以管理员权限执行此程序。

注意:此 WriteProcessMemory 和 CreateRemoteThread 问题仅在我针对更高权限的用户(SYSTEM、LOCAL SERVICE 等)运行此程序时发生。它完全适用于我拥有的程序(相同的权限)。

编辑:这是整个源代码的链接。 http://pastebin.com/m77110d8e 除了基本的错误检查之外没有什么其他的了,但也许它会有所帮助?

【问题讨论】:

  • 创建线程隐式分配目标进程中的堆栈。不知道为什么所有这些都失败了。

标签: c++ windows winapi dll windows-vista


【解决方案1】:

这与 Vista 或更高版本的 Windows 中的会话隔离有关。查看 Cain 和 Abel 等声称 Vista 功能的密码转储工具的源代码或反汇编代码。本质上该过程是相同的,但您将为 CreateRemoteThread 调用不同的函数(对不起,我不认为该函数已导出,您只需要找到它,因此反汇编工作软件可能是最好的选择)。

【讨论】:

  • 今晚我将研究 CreateRemoteThread 的问题。感谢您的信息和提示。但是,为什么用 WriteProcessMemory 写入 0 个字节?这也有不同/并行的功能吗?谢谢您的帮助。任何其他提示将不胜感激。
  • 我可以理解没有字节被写入,但不是缺少错误代码......虽然仔细想想,这个功能不是大多数调试器也使用的吗?
【解决方案2】:

您可以尝试使用RtlCreateUserThread,而不是 CreateRemoteThread。此例程不关心目标进程所在的会话。只要记住让线程在结束前调用 RtlExitUserThread。这些线程不会像 CreateThread/CreateRemoteThread 那样自行清理。

reactos code 可以让您很好地了解这些例程在做什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多