创建SYSTEM用户权限的进程

来源:互联网 发布:贾雷德·戴蒙德 知乎 编辑:程序博客网 时间:2024/05/06 13:16

#include <stdio.h>
#include <windows.h>
#include <Tlhelp32.h>
#include <AccCtrl.h>
#include <Aclapi.h>


typedef NTSTATUS (WINAPI *pfRtlAdjustPrivilege)(
ULONG Privilege,
BOOLEAN Enable,
BOOLEAN CurrentThread,
PBOOLEAN Enabled);

void AdjustPrivilege()
{
pfRtlAdjustPrivilege RtlAdjustPrivilege = NULL;
RtlAdjustPrivilege = (pfRtlAdjustPrivilege)GetProcAddress(GetModuleHandle("NTDLL.DLL"), "RtlAdjustPrivilege");
if(RtlAdjustPrivilege)
{
   BOOLEAN blPev;
   RtlAdjustPrivilege(20, TRUE, FALSE, &blPev);
   printf("提权成功: %d\n", blPev);
}
}


DWORD GetProcessID( LPSTR lpName)
{
if(!lpName)
{
   return 0;
}
HANDLE        hProcessSnap = NULL;
BOOL          bRet      = FALSE;
PROCESSENTRY32 pe32      = {0};
DWORD    dwProcessId = 0;

hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
   return dwProcessId;

pe32.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hProcessSnap, &pe32))
{
   do
   {
    if(stricmp(pe32.szExeFile, lpName) == 0)
    {
     dwProcessId = pe32.th32ProcessID;
     CloseHandle (hProcessSnap);
     return dwProcessId;
    }
   }
   while (Process32Next(hProcessSnap, &pe32));
}

CloseHandle(hProcessSnap);
return dwProcessId;
}


BOOL CreateSystemProcess(LPTSTR szProcessName, LPTSTR szCmdLine)
{
HANDLE hProcess;
HANDLE hToken, hNewToken;
DWORD dwPid;

PACL pOldDAcl = NULL;
PACL pNewDAcl = NULL;
BOOL bDAcl;
BOOL bDefDAcl;
DWORD dwRet;

PACL pSacl = NULL;
PSID pSidOwner = NULL;
PSID pSidPrimary = NULL;
DWORD dwAclSize = 0;
DWORD dwSaclSize = 0;
DWORD dwSidOwnLen = 0;
DWORD dwSidPrimLen = 0;

DWORD dwSDLen;
EXPLICIT_ACCESS ea;
PSECURITY_DESCRIPTOR pOrigSd = NULL;
PSECURITY_DESCRIPTOR pNewSd = NULL;

STARTUPINFO si;
PROCESS_INFORMATION pi;
CHAR szFullCmdLine[512] = {0};

BOOL bError;

AdjustPrivilege();

dwPid = GetProcessID("winlogon.exe");
if(dwPid == 0)
{
   bError = TRUE;
   goto Cleanup;
}

hProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, dwPid );
if ( hProcess == NULL )
{
   printf( "OpenProcess() = %d\n", GetLastError() );  
   bError = TRUE;
   goto Cleanup;
}

if ( !OpenProcessToken( hProcess, READ_CONTROL | WRITE_DAC, &hToken ) )
{
   printf( "OpenProcessToken() = %d\n", GetLastError() );
   bError = TRUE;
   goto Cleanup;
}


// 设置 ACE 具有所有访问权限
ZeroMemory( &ea, sizeof( EXPLICIT_ACCESS ) );
BuildExplicitAccessWithName(
   &ea,
   "Everyone",
   TOKEN_ALL_ACCESS,
   GRANT_ACCESS,
   0 );

if ( !GetKernelObjectSecurity(
   hToken,
   DACL_SECURITY_INFORMATION,
   pOrigSd,
   0,
   &dwSDLen ))
{
   // 第一次调用给出的参数肯定返回这个错误,这样做的目的是
   // 为了得到原安全描述符 pOrigSd 的长度
   if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
   {
    pOrigSd = ( PSECURITY_DESCRIPTOR ) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSDLen );
    if ( pOrigSd == NULL )
    {
     printf( "Allocate pSd memory to failed!\n" );

     bError = TRUE;
     goto Cleanup;
    }

    // 再次调用才正确得到安全描述符 pOrigSd
    if ( !GetKernelObjectSecurity(
     hToken,
     DACL_SECURITY_INFORMATION,
     pOrigSd,
     dwSDLen,
     &dwSDLen ) )
    {
     printf( "GetKernelObjectSecurity() = %d\n", GetLastError() );
     bError = TRUE;
     goto Cleanup;
    }
   }
   else
   {
    printf( "GetKernelObjectSecurity() = %d\n", GetLastError() );
    bError = TRUE;
    goto Cleanup;
   }
}

// 得到原安全描述符的访问控制列表 ACL
if ( !GetSecurityDescriptorDacl( pOrigSd, &bDAcl, &pOldDAcl, &bDefDAcl ) )
{
   printf( "GetSecurityDescriptorDacl() = %d\n", GetLastError() );

   bError = TRUE;
   goto Cleanup;
}

// 生成新 ACE 权限的访问控制列表 ACL
dwRet = SetEntriesInAcl( 1, &ea, pOldDAcl, &pNewDAcl );
if ( dwRet != ERROR_SUCCESS )
{
   printf( "SetEntriesInAcl() = %d\n", GetLastError() );
   pNewDAcl = NULL;

   bError = TRUE;
   goto Cleanup;
}

if ( !MakeAbsoluteSD( pOrigSd,
   pNewSd,
   &dwSDLen,
   pOldDAcl,
   &dwAclSize,
   pSacl,
   &dwSaclSize,
   pSidOwner,
   &dwSidOwnLen,
   pSidPrimary,
   &dwSidPrimLen ) )
{
   // 第一次调用给出的参数肯定返回这个错误,这样做的目的是
   // 为了创建新的安全描述符 pNewSd 而得到各项的长度
   if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
   {
    pOldDAcl = ( PACL ) HeapAlloc( GetProcessHeap(),
     HEAP_ZERO_MEMORY,
     dwAclSize );
    pSacl = ( PACL ) HeapAlloc( GetProcessHeap(),
     HEAP_ZERO_MEMORY,
     dwSaclSize );
    pSidOwner = ( PSID ) HeapAlloc( GetProcessHeap(),
     HEAP_ZERO_MEMORY,
     dwSidOwnLen );
    pSidPrimary = ( PSID ) HeapAlloc( GetProcessHeap(),
     HEAP_ZERO_MEMORY,
     dwSidPrimLen );
    pNewSd = ( PSECURITY_DESCRIPTOR ) HeapAlloc( GetProcessHeap(),
     HEAP_ZERO_MEMORY,
     dwSDLen );

    if ( pOldDAcl == NULL ||
     pSacl == NULL ||
     pSidOwner == NULL ||
     pSidPrimary == NULL ||
     pNewSd == NULL )
    {
     printf( "Allocate SID or ACL to failed!\n" );

     bError = TRUE;
     goto Cleanup;
    }

    // 再次调用才可以成功创建新的安全描述符 pNewSd
    // 但新的安全描述符仍然是原访问控制列表 ACL
    if ( !MakeAbsoluteSD( pOrigSd,
     pNewSd,
     &dwSDLen,
     pOldDAcl,
     &dwAclSize,
     pSacl,
     &dwSaclSize,
     pSidOwner,
     &dwSidOwnLen,
     pSidPrimary,
     &dwSidPrimLen ) )
    {
     printf( "MakeAbsoluteSD() = %d\n", GetLastError() );

     bError = TRUE;
     goto Cleanup;
    }
   }
   else
   {
    printf( "MakeAbsoluteSD() = %d\n", GetLastError() );

    bError = TRUE;
    goto Cleanup;
   }
}

// 将具有所有访问权限的访问控制列表 pNewDAcl 加入到新的
// 安全描述符 pNewSd 中
if ( !SetSecurityDescriptorDacl( pNewSd, bDAcl, pNewDAcl, bDefDAcl ) )
{
   printf( "SetSecurityDescriptorDacl() = %d\n", GetLastError() );

   bError = TRUE;
   goto Cleanup;
}

// 将新的安全描述符加到 TOKEN 中
if ( !SetKernelObjectSecurity( hToken, DACL_SECURITY_INFORMATION, pNewSd ) )
{
   printf( "SetKernelObjectSecurity() = %d\n", GetLastError() );

   bError = TRUE;
   goto Cleanup;
}

// 再次打开 WINLOGON 进程的 TOKEN,这时已经具有所有访问权限
if ( !OpenProcessToken( hProcess, TOKEN_ALL_ACCESS, &hToken ) )
{
   printf( "OpenProcessToken() = %d\n", GetLastError() );  

   bError = TRUE;
   goto Cleanup;
}

// 复制一份具有相同访问权限的 TOKEN
if ( !DuplicateTokenEx( hToken,
   TOKEN_ALL_ACCESS,
   NULL,
   SecurityImpersonation,
   TokenPrimary,
   &hNewToken ) )
{
   printf( "DuplicateTokenEx() = %d\n", GetLastError() );  

   bError = TRUE;
   goto Cleanup;
}


ZeroMemory( &si, sizeof( STARTUPINFO ) );
si.cb = sizeof( STARTUPINFO );

// 不虚拟登陆用户的话,创建新进程会提示
// 1314 客户没有所需的特权错误
ImpersonateLoggedOnUser( hNewToken );


// 我们仅仅是需要建立高权限进程,不用切换用户
// 所以也无需设置相关桌面,有了新 TOKEN 足够

sprintf(szFullCmdLine, "\"%s\" %s", szProcessName, szCmdLine);
printf("%s\n", szFullCmdLine);

// 利用具有所有权限的 TOKEN,创建高权限进程
if ( !CreateProcessAsUser( hNewToken,
   NULL,
   szFullCmdLine,
   NULL,
   NULL,
   FALSE,
   NULL, //NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
   NULL,
   NULL,
   &si,
   &pi ) )
{
   printf( "CreateProcessAsUser() = %d\n", GetLastError() );  

   bError = TRUE;
   goto Cleanup;
}

bError = FALSE;

Cleanup:
if ( pOrigSd )
{
   HeapFree( GetProcessHeap(), 0, pOrigSd );
}
if ( pNewSd )
{
   HeapFree( GetProcessHeap(), 0, pNewSd );
}
if ( pSidPrimary )
{
   HeapFree( GetProcessHeap(), 0, pSidPrimary );
}
if ( pSidOwner )
{
   HeapFree( GetProcessHeap(), 0, pSidOwner );
}
if ( pSacl )
{
   HeapFree( GetProcessHeap(), 0, pSacl );
}
if ( pOldDAcl )
{
   HeapFree( GetProcessHeap(), 0, pOldDAcl );
}

CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
CloseHandle( hToken );
CloseHandle( hNewToken );
CloseHandle( hProcess );

if ( bError )
{
   return FALSE;
}

return TRUE;
}


int _tmain(int argc, _TCHAR* argv[])
{
if(argc > 0)
{
   char szCmdline[512] = {0};
   for(int i=2; i<argc; i++)
   {
    strcat(szCmdline, " ");
    strcat(szCmdline, argv[i]);
   }

   printf("%s\n", szCmdline);
   CreateSystemProcess(argv[1], szCmdline);
}

//getchar();
return 0;

原创粉丝点击