zoukankan      html  css  js  c++  java
  • delphi 以系统权限运行程序的代码

    program sysrun;
    
    uses
    Windows, SysUtils, tlhelp32, AccCtrl, AclAPI;
    
    function findprocess(TheProcName: string): DWORD;
    var
    isOK: Boolean;
    ProcessHandle: Thandle;
    ProcessStruct: TProcessEntry32;
    begin
    ProcessHandle := createtoolhelp32snapshot(Th32cs_snapprocess, 0);
    processStruct.dwSize := sizeof(ProcessStruct);
    isOK := process32first(ProcessHandle, ProcessStruct);
    Result := 0;
    while isOK do
    begin
    if Trim(UpperCase(TheProcName)) = Trim(UpperCase(ProcessStruct.szExeFile)) then
    begin
    Result := ProcessStruct.th32ProcessID;
    CloseHandle(ProcessHandle);
    exit;
    end;
    isOK := process32next(ProcessHandle, ProcessStruct);
    end;
    CloseHandle(ProcessHandle);
    end;
    
    procedure SetPrivilege;
    var
    TPPrev, TP: TTokenPrivileges;
    TokenHandle: THandle;
    dwRetLen: DWORD;
    lpLuid: TLargeInteger;
    begin
    OpenProcessToken(GetCurrentProcess, TOKEN_ALL_ACCESS, TokenHandle);
    if (LookupPrivilegeValue(nil, 'SeDebugPrivilege', lpLuid)) then
    begin
    TP.PrivilegeCount := 1;
    TP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
    TP.Privileges[0].Luid := lpLuid;
    AdjustTokenPrivileges(TokenHandle, False, TP, SizeOf(TPPrev), TPPrev, dwRetLen);
    end;
    CloseHandle(TokenHandle);
    end;
    
    /////////////////////////////////////////////////////////////////
    
    function CreateSystemProcess(szProcessName: LPTSTR): BOOL;
    var
    hProcess: THANDLE;
    hToken, hNewToken: THANDLE;
    dwPid: DWORD;
    pOldDAcl: PACL;
    pNewDAcl: PACL;
    bDAcl: BOOL;
    bDefDAcl: BOOL;
    dwRet: DWORD;
    pSacl: PACL;
    pSidOwner: PSID;
    pSidPrimary: PSID;
    dwAclSize: DWORD;
    dwSaclSize: DWORD;
    dwSidOwnLen: DWORD;
    dwSidPrimLen: DWORD;
    dwSDLen: DWORD;
    ea: EXPLICIT_ACCESS;
    pOrigSd: PSECURITY_DESCRIPTOR;
    pNewSd: PSECURITY_DESCRIPTOR;
    si: STARTUPINFO;
    pi: PROCESS_INFORMATION;
    bError: BOOL;
    label Cleanup;
    begin
    pOldDAcl := nil;
    pNewDAcl := nil;
    pSacl := nil;
    pSidOwner := nil;
    pSidPrimary := nil;
    dwAclSize := 0;
    dwSaclSize := 0;
    dwSidOwnLen := 0;
    dwSidPrimLen := 0;
    pOrigSd := nil;
    pNewSd := nil;
    SetPrivilege;
    //选择 WINLOGON 进程
    dwPid := findprocess('WINLOGON.EXE');
    if dwPid = High(Cardinal) then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);
    if hProcess = 0 then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    if not OpenProcessToken(hProcess, READ_CONTROL or WRITE_DAC, hToken) then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    // 设置 ACE 具有所有访问权限
    ZeroMemory(@ea, Sizeof(EXPLICIT_ACCESS));
    BuildExplicitAccessWithName(@ea, 'Everyone', TOKEN_ALL_ACCESS, GRANT_ACCESS, 0);
    if not GetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, pOrigSd, 0, dwSDLen) then
    begin
    //第一次调用给出的参数肯定返回这个错误,这样做的目的是为了得到原安全描述符 pOrigSd 的长度
    if GetLastError() = ERROR_INSUFFICIENT_BUFFER then
    begin
    pOrigSd := HeapAlloc(GetProcessHeap(), $00000008, dwSDLen);
    if pOrigSd = nil then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    // 再次调用才正确得到安全描述符 pOrigSd
    if not GetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, pOrigSd, dwSDLen, dwSDLen) then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    end
    else
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    end; //GetKernelObjectSecurity()
    // 得到原安全描述符的访问控制列表 ACL
    if not GetSecurityDescriptorDacl(pOrigSd, bDAcl, pOldDAcl, bDefDAcl) then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    // 生成新 ACE 权限的访问控制列表 ACL
    dwRet := SetEntriesInAcl(1, @ea, pOldDAcl, pNewDAcl);
    if dwRet <> ERROR_SUCCESS then
    begin
    pNewDAcl := nil;
    bError := TRUE;
    goto Cleanup;
    end;
    if not MakeAbsoluteSD(pOrigSd, pNewSd, dwSDLen, pOldDAcl^, dwAclSize, pSacl^, dwSaclSize, pSidOwner, dwSidOwnLen, pSidPrimary, dwSidPrimLen) then
    begin
    {第一次调用给出的参数肯定返回这个错误,这样做的目的是为了创建新的安全描述符 pNewSd 而得到各项的长度}
    if GetLastError = ERROR_INSUFFICIENT_BUFFER then
    begin
    pOldDAcl := HeapAlloc(GetProcessHeap(), $00000008, dwAclSize);
    pSacl := HeapAlloc(GetProcessHeap(), $00000008, dwSaclSize);
    pSidOwner := HeapAlloc(GetProcessHeap(), $00000008, dwSidOwnLen);
    pSidPrimary := HeapAlloc(GetProcessHeap(), $00000008, dwSidPrimLen);
    pNewSd := HeapAlloc(GetProcessHeap(), $00000008, dwSDLen);
    if (pOldDAcl = nil) or (pSacl = nil) or (pSidOwner = nil) or (pSidPrimary = nil) or (pNewSd = nil) then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    {再次调用才可以成功创建新的安全描述符 pNewSd
    但新的安全描述符仍然是原访问控制列表 ACL}
    if not MakeAbsoluteSD(pOrigSd, pNewSd, dwSDLen, pOldDAcl^, dwAclSize, pSacl^, dwSaclSize, pSidOwner, dwSidOwnLen, pSidPrimary, dwSidPrimLen) then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    end
    else
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    end;
    {将具有所有访问权限的访问控制列表 pNewDAcl 加入到新的
    安全描述符 pNewSd 中}
    if not SetSecurityDescriptorDacl(pNewSd, bDAcl, pNewDAcl, bDefDAcl) then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    // 将新的安全描述符加到 TOKEN 中
    if not SetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, pNewSd) then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    // 再次打开 WINLOGON 进程的 TOKEN,这时已经具有所有访问权限
    if not OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, hToken) then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    // 复制一份具有相同访问权限的 TOKEN
    if not DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, nil, SecurityImpersonation, TokenPrimary, hNewToken) then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    ZeroMemory(@si, Sizeof(STARTUPINFO));
    si.cb := Sizeof(STARTUPINFO);
    {不虚拟登陆用户的话,创建新进程会提示
    1314 客户没有所需的特权错误}
    ImpersonateLoggedOnUser(hNewToken);
    {我们仅仅是需要建立高权限进程,不用切换用户
    所以也无需设置相关桌面,有了新 TOKEN 足够}
    // 利用具有所有权限的 TOKEN,创建高权限进程
    if not CreateProcessAsUser(hNewToken, nil, szProcessName, nil, nil, FALSE, 0, nil, nil, si, pi) then
    begin
    bError := TRUE;
    goto Cleanup;
    end;
    bError := FALSE;
    Cleanup:
    if pOrigSd = nil then HeapFree(GetProcessHeap(), 0, pOrigSd);
    if pNewSd = nil then HeapFree(GetProcessHeap(), 0, pNewSd);
    if pSidPrimary = nil then HeapFree(GetProcessHeap(), 0, pSidPrimary);
    if pSidOwner = nil then HeapFree(GetProcessHeap(), 0, pSidOwner);
    if pSacl = nil then HeapFree(GetProcessHeap(), 0, pSacl);
    if pOldDAcl = nil then HeapFree(GetProcessHeap(), 0, pOldDAcl);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    CloseHandle(hToken);
    CloseHandle(hNewToken);
    CloseHandle(hProcess);
    if bError then Result := FALSE else Result := True;
    
    end;
    begin
    CreateSystemProcess(pchar(extractfilepath(paramstr(0)) + aa.exe'));
    end.
  • 相关阅读:
    show parameters和强制索引失效
    ALTER INDEX 始末
    ADMIN OPTION和GRANT ANY OBJECT PRIVILEGE的问题
    oracle正则表达式函数简单总结(一)
    简单说一下Native Dynamic SQL(动态sql)和包DBMS_SQL
    金山快盘的文件上传
    桶中取黑白球问题
    读书笔记:编程之美求二进制数中1的个数
    vim配置文件.vimrc
    JVM内存管理
  • 原文地址:https://www.cnblogs.com/blogpro/p/11453651.html
Copyright © 2011-2022 走看看