[转载]创建高权限进程

文章作者:sinister
信息来源:白细胞

Author: sinister
Email:   sinister@whitecell.org
Homepage:http://www.whitecell.org
Date:   2006-02-12

/*****************************************************************
文件名     : wssrun.c
描述       : 创建高权限进程
作者       : sinister
最后修改日期 : 2006.2.09

*****************************************************************/

//
// 写这个初衷是为了让 Windows 任务管理器可以结束掉一些服务
// 和僵死进程,用 pslist/pskill 之类工具无法获得象任务管理
// 器那样丰富的信息,还得来回切换,麻烦的很。最初想写个驱动
// 监视任务管理器运行,使用 SYSTEM 进程 TOKEN 替换来达到目的。
// 后来觉得通用性不好,就改用了这种方法。此方法还可使 regedit
// 查看、编辑 SAM 等注册表键,何乐而不为。
//
// wssrun taskmgr.exe
// wssrun regedit.exe
//

#include
#include
#include
#include
#include
#include
#include

#pragma comment(lib,"Shlwapi.lib")

/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 :
////////////////////////////////////////////////////////////////
// 功能 :提升当前进程权限
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2006.2.09
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历   史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////

BOOL
EnableDebugPriv( LPCTSTR szPrivilege )
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;

if ( !OpenProcessToken( GetCurrentProcess(),
                TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                &hToken ) )
{
  return FALSE;
}
if ( !LookupPrivilegeValue( NULL, szPrivilege, &sedebugnameValue ) )
{
  CloseHandle( hToken );
  return FALSE;
}

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

if ( !AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
{
  CloseHandle( hToken );
  return FALSE;
}

return TRUE;
}

/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 :
////////////////////////////////////////////////////////////////
// 功能 :通过指定进程名得到其进程 ID
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2006.2.09
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历   史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////

DWORD
GetProcessId( LPCTSTR szProcName )
{
PROCESSENTRY32 pe;
DWORD dwPid;
DWORD dwRet;
BOOL bFound = FALSE;

//
// 通过 TOOHLP32 函数枚举进程
//

HANDLE hSP = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if ( hSP )
{
  pe.dwSize = sizeof( pe );

  for ( dwRet = Process32First( hSP, &pe );
      dwRet;
      dwRet = Process32Next( hSP, &pe ) )
  {
    //
    // 使用 StrCmpNI 比较字符传,可忽略大小写
    //
    if ( StrCmpNI( szProcName, pe.szExeFile, strlen( szProcName ) ) == 0 )
    {
    dwPid = pe.th32ProcessID;
    bFound = TRUE;
    break;
    }
  }

  CloseHandle( hSP );

  if ( bFound == TRUE )
  {
    return dwPid;
  }
}

return NULL;
}

/////////////////////////////////////////////////////////////////
// 函数类型 :自定义工具函数
// 函数模块 :
////////////////////////////////////////////////////////////////
// 功能 : 创建具有高权限的进程
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2006.2.09
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历   史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////

BOOL
CreateSystemProcess( LPTSTR szProcessName )
{
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;

BOOL bError;

if ( !EnableDebugPriv( "SeDebugPrivilege" ) )
{
  printf( "EnableDebugPriv() to failed!/n" );

  bError = TRUE;
  goto Cleanup;
}

//
// 选择 WINLOGON 进程
//
if ( ( dwPid = GetProcessId( "WINLOGON.EXE" ) ) == NULL )
{
  printf( "GetProcessId() to failed!/n" );  

  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 足够
//

//
// 利用具有所有权限的 TOKEN,创建高权限进程
//
if ( !CreateProcessAsUser( hNewToken,
                  NULL,
                  szProcessName,
                  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;
}

void
main( int argc, char** argv )
{
if ( argc < 2 )
{
  printf( "Usage: wssrun /n" );
  return ;
}

if ( CreateSystemProcess( argv[1] ) == FALSE )
{
  printf( "wssrun: CreateSystemProcess() to failed!/n" );
  return ;
}
}

WSS(Whitecell Security Systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
WSS 主页:http://www.whitecell.org/
WSS 论坛:http://www.whitecell.org/forums/

 

时间: 2024-08-29 09:33:54

[转载]创建高权限进程的相关文章

c#如何让管理员权限的进程创建一个普通进程

问题描述 c#如何让管理员权限的进程创建一个普通进程 如题,现在用c#写了一个控制台程序并以administrator身份运行,如何让它创建一个当前用户(普通用户)身份的普通权限进程. 解决方案 权限提升很复杂,资料也很少,最好的方法是构建一个服务来完成高权限的工作.见我的另一个提问http://ask.csdn.net/questions/162747 解决方案二: 用Process.Start调用runas命令可以做到. 解决方案三: CreateProcessAsUser() 解决方案四:

分析Linux内核创建一个新进程的过程【转】

转自:http://www.cnblogs.com/MarkWoo/p/4420588.html 前言说明 本篇为网易云课堂Linux内核分析课程的第六周作业,本次作业我们将具体来分析fork系统调用,来分析Linux内核创建新进程的过程 关键词:fork, 系统调用,进程 *运行环境:** Ubuntu 14.04 LTS x64 gcc 4.9.2 gdb 7.8 vim 7.4 with vundle 分析 分析方法说明 PCB包含了一个进程的重要运行信息,所以我们将围绕在创建一个新进程时

如何创建高质量的百度经验?

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 百度经验,作为百度自身的产品,也被众多众多网站推广人员所重视.随着百度百科.百度知道.百度贴吧等平台对链接审核的加强,众人把眼光都移向了百度自身的其他产品,百度经验由于目前对链接的审核还算宽松,所以备受关注.后来,百度经验对参考资料这块所添加的链接进行了跳转,又让很多网站推广人员心寒了一把.但是话又说回来,现在很多传统的链接形式所能传递的权重

oracle数据库用户创建、权限分配

oracle|创建|数据|数据库 1.数据库安装时的参数设定下面数据库所用的版本为ORACLE 9I (9.2.0),安装数据库时,数据库系统会创建一个数据库实例,其中:安装目录选为:\oracle,数据库名与数据库SID号都输入:ora9i ,其中的字符集必须选为:ZHS16GBK(否则以后进行跨平台操作时对中文的操作将比较困难).2.数据库用户的创建.权限的分配数据库安装完成后,有两个系统级的用户: 1.          system 默认密码为:manager 2.          s

用Rails创建高质量Web应用

越来越多的企业开始选择Rails作为Web应用的框架.Rails曾经还主要是一些轻公司的选择,但今天一些"重"企业(比如保险.金融等行业的企业)也开始把Rails纳入内部应用甚至外部应用的考虑范围.我最近服务过的客户是国外某大型保险公司,该公司就选择了Rails来创建他们的保险销售网站. 选择Rails的原因,是因为它快速构建的能力,是因为它是Web开发的DSL.但是否选择了Rails就代表了高效开发?是否在Rails上创建的Web应用就一定是高质量的?答案是否定的.从我参与过的几个R

mysql创建各种权限用户的命令

用命令创建各种权限的mysql帐号的方法如下(一定要先进入mysql,在mysql命令下执行以下的语句): 1. 创建一个用户,并拥有创建数据库,修改字段,删除表,对表增删改查的权限,和支持远程甚至任何地方登陆的权限(差不多相当于root帐号的权限): grant select,insert,update,delete,create,drop,alter on *.* to reson1@"%" identified by "123456"; grant selec

Linux系统小技巧(2):利用ps工具统计CPU消耗高的进程和统计消耗CPU或者内存的百分比

CPU消耗高往往是系统异常的一种表现.因为平常检查系统运行有哪些进程,都是使用ps工具.因此,出现这种情况时,如果能够通过ps工具搜寻出CPU消耗高的线程,则对进一步搜寻线索或者排查应该有帮助. 下面我们讨论两个相关的小技巧. 首先,我们得了解一下进程的概念.我们都很熟悉进程了,那么,线程是什么呢?引用Andrew S. Tanenbaum的话,就是 进程认为自己独占一台主机:线程认为自己独占一颗CPU. 所以,一个进程可能包含多个线程.但是考察CPU消耗问题,只考虑进程而不考虑线程是不够的.就

linux下exec创建一个gcc进程来编译代码,如何判定编译是否成功?

问题描述 linux下exec创建一个gcc进程来编译代码,如何判定编译是否成功? 代码在下面-- 1 #include 2 #include 3 #include 4 #include 5 #include 6 8 char * cmdargv[20] = {0}; 9 int main(void) 10 { 11 pid_t pid; 13 int retval; 16 17 while(1){ 20 if((pid = fork()) < 0){ 21 perror("fork&qu

创建高质量的外链建设

摘要: 一个网站在不同阶段有着不同的优化方法,那么今天要跟大家分享的是百度收录新站后,前期该如何去优化? 一.网站架构:网站的架构基本在建站之初就已经确定了,但在前期随着优化关 一个网站在不同阶段有着不同的优化方法,那么今天要跟大家分享的是百度收录新站后,前期该如何去优化? 一.网站架构:网站的架构基本在建站之初就已经确定了,但在前期随着优化关键词的排名变化,我们在网站首页展现的版块可以相应的改动,注意:只是版块的小改动小调整,切记大改动 二.外链:前期的话,网站本身的外链是比较少的.那么在外链