win遇到强制结束进程失败的问题

原始代码:

   现在函数有入参,进程号:DWORD processID

    // 如下代码结束进程:
    HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, processID );

     if ( hProcess == NULL )
    {
         return ;
    }
    TerminateProcess( hProcess, 0xf291 );
    CloseHandle( hProcess );

TerminateProcess()需要传递一个进程的句柄,不是进程ID,可以用
OpenProcess()返回一个进程句柄。然后结束之!
如果用OpenProcess()不能打开这个句柄,也就是说返回了NULL,
需要提升进程的特权,也就是调用特权然后再用openProcess()打开再结束就可以了。
给进程加特权的函数:AdjustTokenPrivileges

改进后代码:

bool  KillMakeSure(DWORD processID){
     bool  bResult =  true  ;
    HANDLE hProcess;
    HANDLE hProcessToken;
    TOKEN_PRIVILEGES tp;
    TOKEN_PRIVILEGES oldtp;
    DWORD dwSize =  sizeof  (TOKEN_PRIVILEGES);
    LUID luid;
     // open handle of target process
     if  (processID == 0){
         //! input process id error
         return   false  ;
    }

    OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hProcessToken);
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);

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

     /* Adjust Token privileges */
     if (! AdjustTokenPrivileges(
        hProcessToken,
        FALSE,
        &tp,
         sizeof (TOKEN_PRIVILEGES),
        (PTOKEN_PRIVILEGES)oldtp,
        &dwSize ) )
    {
        CloseHandle (hProcessToken);
         return  false  ;
    }

    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
     if ( (hProcess == NULL) ){
         //! open failed
        bResult =  false ;
    }
     if (TerminateProcess(hProcess,0)) {
         //! kill success
        bResult =  true ;
    }
     else {
         //! kill failed
        bResult =  false ;
    }

     /* disable SE_SYSTEMTIME_NAME again <---- 假如不需要撤销,就不需要调用此函数了,那么第一个函数的最后2个参数也可以不要了 */     
    AdjustTokenPrivileges (hProcessToken,
                            FALSE,
                            &oldtp,
                            dwSize,
                            NULL,
                            NULL);
     if  (GetLastError() != ERROR_SUCCESS)
    {
        bResult =  false ;
    }

     CloseHandle (hProcessToken);
    CloseHandle( hProcess );
     return  bResult;
}


相关英文文档
==========================================================================================================================

Adjusting Process Token Privileges

As some of you know, Windows NT is a far more secure OS than Windows 9x, both from a User and Developer standpoint. For a developer, this aspect of NT brings a new challenge: Getting programs to work both under 9x and NT comfortably.

Under NT, many of the Win32 API functions require that the process has a certain level of privilege to execute, which is a good thing, and a great advance on security, compared to 9x. But this also involves more work for the programmer, because some times he’s responsible for getting the program to work for user’s which do not have Administrator privileges. Don’t believe that just because you’re not doing low level stuff, or changing user, rights or whatever, you won’t need to know this, because you will. A specific example, theSetSystemTime() call: It’s simple, just changes the system time, but requires that the process has SE_SYSTEMTIME_NAME privilege on it’s tokens, which is not enabled by default.

But, What’s an access token? A token is:

 A group of security attributes permanently attached to a process when a user logs on to the operating system. An access token contains privileges and security identifiers for a user, global group, or local group. The privileges regulate the use of some system services and the security identifiers regulate access to objects that are protected by access-control lists (ACLs). There are two kinds of access token: primary and impersonation.

When adjusting a process access tokens, you have to be careful to leave the tokens in the state they were in. Don’t assume that you can just change them and leave it like that (unless you are enabling the SE_SHUTDOWN_NAME privilege, in which case it doesn’t matter), you should always return them to the state you found them. Following this simple rule ensures that your program won’t cause security troubles later. 

Now, let’s go a little deeper. What’s the whole purpose of tokens? Tokens are created by the Local Security Authority (lsass.exe), and allow the system to keep track of some information related to the process. The most important information a process token holds is the SID of the user account the process is running under. It also carries the list of SID’s for groups the user is member of, and, obviously, which privileges the user has been granted. All this allows the system to easily determine if the process should be granted access to a protected resource. Another important thing the token carries is a default DACL (Discretionary Access Control List) that is used to assign default security settings to objects (i.e. files) created by the process in behalf of the user. Keep in mind that this DACL is only used if the process doesn’t explicitly supply a security descriptor when the object is created.

One thing I haven’t mentioned so far is that threads can also have tokens associated, which you can get at via the OpenThreadToken() api. However, you’ll soon notice that most of the time calling this api will fail. Why? Because usually a thread won’t have a token attached, in which case the system will use the token of the process the thread is running on. When a thread does have a token attached to it, it’s because it is impersonating another user, in which case it is said that the thread runs under a different security context. Is important to notice that a thread can also impersonate the same user account the process is running under, via the ImpersonateSelf() api.

There are some basic steps to adjusting the tokens, so let’s review them, and later I’ll present an example.

  1. Call OpenProcessToken() with at least the TOKEN_ADJUST_PRIVILEGE and TOKEN_QUERY flags.
  2. Use LookupPrivilegeValue() to get the LUID (Locally Unique Identifier) of the privilege you want to adjust.
  3. Call AdjustTokenPrivileges() to adjust the tokens.
  4. Do whatever calls you need to do to accomplish your task.
  5. Call AdjustTokenPrivileges() again to set the old privileges back and leave the tokens as found.
  6. Close the Token handle.

Let’s see an example: Here we enable the SE_SYSTEMTIME_NAME privilege to be able of setting the system time:


HANDLE      hToken;     /* process token */
TOKEN_PRIVILEGES tp;    /* token provileges */
TOKEN_PRIVILEGES oldtp;    /* old token privileges */
DWORD    dwSize = sizeof (TOKEN_PRIVILEGES);          
LUID     luid;          

/* now, set the SE_SYSTEMTIME_NAME privilege to our current*  process, so we can call SetSystemTime()*/if (!OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
   &hToken)){
   printf ("OpenProcessToken() failed with code %d\n", GetLastError());
   return 1;}if (!LookupPrivilegeValue (NULL, SE_SYSTEMTIME_NAME, &luid)){
   printf ("LookupPrivilege() failed with code %d\n", GetLastError());
   CloseHandle (hToken);
   return 1;}

ZeroMemory (&tp, sizeof (tp));
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

/* Adjust Token privileges */if (!AdjustTokenPrivileges (hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), 
         &oldtp, &dwSize)){
   printf ("AdjustTokenPrivileges() failed with code %d\n", GetLastError());
   CloseHandle (hToken);
   return 1;}
      
/* Set time */if (!SetSystemTime (&stCurrentTime)){
   printf ("SetSystemTime() failed with code %d\n", GetLastError());
   CloseHandle (hToken);
   return 1;}

/* disable SE_SYSTEMTIME_NAME again */
AdjustTokenPrivileges (hToken, FALSE, &oldtp, dwSize, NULL, NULL);if (GetLastError() != ERROR_SUCCESS){
   printf ("AdjustTokenPrivileges() failed with code %d\n", GetLastError());
   CloseHandle (hToken);
   return 1;}
   
CloseHandle (hToken);

As you can see from the example, it’s not really a hard thing to do, but requires several non trivial calls just to do a simple task.

Finally, let’s consider some linguistic issues. What exactly the difference between aprivilege and a right is, that’s something most people don’t clearly understand. The problem is terminology. The original Windows NT docs referred to privileges as Advanced User Rights, which doesn’t help much, either.

One way to clarify things is by understanding that permissions (a.k.a. rights) are alwaysassociated to a particular object. You have the permission to open a file, to read from it, etc. There are a set of generic rights, but every object type supplies it’s own rights that only make sense for it. The system knows what rights a user have to access an object by looking at the ACL (Access Control List) associated with the object. Usually, ACL’s are saved along with the object, so they are persistent if the object itself is. For example, a file’s ACL is saved along with it on disk.

 Privileges, on the other hand, are associated with particular actions on the system, and are granted to users, not objects. Privileges allow a user to override permissions, and this is why you have to be careful when granting them. A user with SE_RESTORE_NAME privilege could easily overwrite almost any file on the system..

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值