修改一个结束进程的程序

理论:
今天在pediy上看到了一篇文章 http://bbs.pediy.com/showthread.php?t=70971
是关于关闭进程的一篇文章,它采用关闭进程的方法,是自己实现了native api的调用。这样可以有效的防止ring3环下的hook. 其中获取操作系统版本的信息的方法,是从当前进程的peb中获得的。即,fs:[0]在ring3下指向当前线程环境块_teb, 在_teb偏移30h的位置是PEB. 也就是说fs:[30h]指向当前进程环境块。
lkd> dt _peb
ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x003 SpareBool        : UChar
   +0x004 Mutant           : Ptr32 Void
   +0x008 ImageBaseAddress : Ptr32 Void
   +0x00c Ldr              : Ptr32 _PEB_LDR_DATA
   +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
   +0x014 SubSystemData    : Ptr32 Void
   +0x018 ProcessHeap      : Ptr32 Void
   +0x01c FastPebLock      : Ptr32 _RTL_CRITICAL_SECTION
   +0x020 FastPebLockRoutine : Ptr32 Void
   +0x024 FastPebUnlockRoutine : Ptr32 Void
   +0x028 EnvironmentUpdateCount : Uint4B
   +0x02c KernelCallbackTable : Ptr32 Void
   +0x030 SystemReserved   : [1] Uint4B
   +0x034 AtlThunkSListPtr32 : Uint4B
   +0x038 FreeList         : Ptr32 _PEB_FREE_BLOCK
   +0x03c TlsExpansionCounter : Uint4B
   +0x040 TlsBitmap        : Ptr32 Void
   +0x044 TlsBitmapBits    : [2] Uint4B
   +0x04c ReadOnlySharedMemoryBase : Ptr32 Void
   +0x050 ReadOnlySharedMemoryHeap : Ptr32 Void
   +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void
   +0x058 AnsiCodePageData : Ptr32 Void
   +0x05c OemCodePageData : Ptr32 Void
   +0x060 UnicodeCaseTableData : Ptr32 Void
   +0x064 NumberOfProcessors : Uint4B
   +0x068 NtGlobalFlag     : Uint4B
   +0x070 CriticalSectionTimeout : _LARGE_INTEGER
   +0x078 HeapSegmentReserve : Uint4B
   +0x07c HeapSegmentCommit : Uint4B
   +0x080 HeapDeCommitTotalFreeThreshold : Uint4B
   +0x084 HeapDeCommitFreeBlockThreshold : Uint4B
   +0x088 NumberOfHeaps    : Uint4B
   +0x08c MaximumNumberOfHeaps : Uint4B
   +0x090 ProcessHeaps     : Ptr32 Ptr32 Void
   +0x094 GdiSharedHandleTable : Ptr32 Void
   +0x098 ProcessStarterHelper : Ptr32 Void
   +0x09c GdiDCAttributeList : Uint4B
   +0x0a0 LoaderLock       : Ptr32 Void
   +0x0a4 OSMajorVersion   : Uint4B
+0x0a8 OSMinorVersion   : Uint4B
   +0x0ac OSBuildNumber    : Uint2B
   +0x0ae OSCSDVersion     : Uint2B
   +0x0b0 OSPlatformId     : Uint4B
   +0x0b4 ImageSubsystem   : Uint4B
   +0x0b8 ImageSubsystemMajorVersion : Uint4B
   +0x0bc ImageSubsystemMinorVersion : Uint4B
   +0x0c0 ImageProcessAffinityMask : Uint4B
   +0x0c4 GdiHandleBuffer : [34] Uint4B
   +0x14c PostProcessInitRoutine : Ptr32     void
   +0x150 TlsExpansionBitmap : Ptr32 Void
   +0x154 TlsExpansionBitmapBits : [32] Uint4B
   +0x1d4 SessionId        : Uint4B
   +0x1d8 AppCompatFlags   : _ULARGE_INTEGER
   +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER
   +0x1e8 pShimData        : Ptr32 Void
   +0x1ec AppCompatInfo    : Ptr32 Void
   +0x1f0 CSDVersion       : _UNICODE_STRING
   +0x1f8 ActivationContextData : Ptr32 Void
   +0x1fc ProcessAssemblyStorageMap : Ptr32 Void
   +0x200 SystemDefaultActivationContextData : Ptr32 Void
   +0x204 SystemAssemblyStorageMap : Ptr32 Void
   +0x208 MinimumStackCommit : Uint4B

除此之外,还可以直接从内核共享区 _KUSER_SHARED_DATA中获得,这个办法已经在前面文章中说明了 http://hi.baidu.com/combojiang/blog/item/6f9b5802e3d8ef094bfb518d.html

代码如下

#include <stdio.h>
#include <windows.h>
#include <Tlhelp32.h>
#include <Ntsecapi.h>

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

typedef long NTSTATUS;
#define NT_SUCCESS(status)   ((NTSTATUS)(status) >= 0)

DWORD dwZwOpenThread = 0;
DWORD dwZwTerminateThread = 0;
DWORD dwZwClose = 0;

void CurrentProcess_AdjustTokenPrivileges()
{
   BOOL bRet = FALSE;
   HANDLE hTokenHandle = NULL;
   TOKEN_PRIVILEGES tp;
   LUID luid;
  
   bRet = ::OpenProcessToken((HANDLE)::GetCurrentProcess(), 0xF01FF, &hTokenHandle);
   if ( FALSE == bRet )
   {
     printf("OpenProcessToken error: %u/n", ::GetLastError());
     goto FunReturn;
   }
  
   if ( 0 == ::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid) )
   {
     printf("LookupPrivilegeValue error: %u/n", ::GetLastError());
     goto FunReturn;
   }
  
   tp.PrivilegeCount = 1;
   tp.Privileges[0].Luid = luid;
   tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  
   if ( 0 == ::AdjustTokenPrivileges(hTokenHandle, 0, &tp, sizeof(TOKEN_PRIVILEGES), 0, 0) )
   {
     printf("AdjustTokenPrivileges error: %u/n", ::GetLastError());
     goto FunReturn;
   }
  
FunReturn:
  
   if ( NULL != hTokenHandle )
   {
     CloseHandle(hTokenHandle);
     hTokenHandle = NULL;
   }
}

DWORD GetProcessID(char *szProcessName)
{
   HANDLE hSnapshot = NULL;
   PROCESSENTRY32 ProEntry;
   DWORD dwProcessID = 0;
  
   hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   if ( INVALID_HANDLE_VALUE == hSnapshot )
   {
     printf("CreateToolhelp32Snapshot error: %u/n", ::GetLastError());
     hSnapshot = NULL;
     goto FunReturn;
   }
  
   ProEntry.dwSize = sizeof(PROCESSENTRY32);
   if ( FALSE == ::Process32First(hSnapshot, &ProEntry) )
   {
     printf("Process32First error: %u/n", ::GetLastError());
     goto FunReturn;
   }
  
   do
   {
     if ( 0 == _strnicmp(szProcessName, (char *)ProEntry.szExeFile, (int)strlen(szProcessName)) )
     {
       dwProcessID = (DWORD)ProEntry.th32ProcessID;
       break;
     }
    
   } while( ::Process32Next(hSnapshot, &ProEntry) );
  
FunReturn:
  
   if ( NULL != hSnapshot )
   {
     CloseHandle(hSnapshot);
     hSnapshot = NULL;
   }
  
   return dwProcessID;
}

void Call_sysenter()
{
   __asm
   {
     mov edx, esp
     _emit 0x0f
     _emit 0x34
     retn
   }
}

void Call_ZwOpenThread()
{
   __asm
   {
     mov eax, dwZwOpenThread
     call Call_sysenter
    
     retn 10h
   }    
}

__declspec(naked) void   My_ZwOpenThread(DWORD dwThreadID)
{
   __asm
   {
     sub esp, 20h
     mov ecx, [esp+24h]
      xor eax, eax
      lea edx, [esp]
      push edx
      mov [esp+4h], eax
      mov [esp+10h], eax
      mov [esp+18h], eax
      mov [esp+14h], eax
      mov [esp+1Ch], eax
      mov [esp+20h], eax
      lea eax, [esp+0Ch]
      push eax
      mov [esp+0Ch], ecx
      push 4Bh
      lea ecx, [esp+30h]
      push ecx
      mov dword ptr [esp+18h], 18h
      call Call_ZwOpenThread

      neg eax
      **b eax, eax
      not eax
      and eax, [esp+24h]
      add esp, 20h
     retn
   }
}

void My_ZwTerminateThread(HANDLE hThread, DWORD dwExitCode)
{
   __asm
   {
     mov eax, dwZwTerminateThread
     call Call_sysenter

     retn 8
   }
}

void My_ZwClose(HANDLE hThread)
{
   __asm
   {
     mov eax, dwZwClose
     call Call_sysenter

     retn 4
   }
}

void TerminateProcess_Thread(DWORD dwProcessID)
{
   HANDLE hSnapshot = NULL;
   HANDLE hThread = NULL;
   DWORD hThreadID = 0, dwRet = 0;
   THREADENTRY32 ThreadEntry;
  
   hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessID);
   if ( INVALID_HANDLE_VALUE == hSnapshot )
   {
     printf("CreateToolhelp32Snapshot error: %u/n", ::GetLastError());
     hSnapshot = NULL;
     goto FunReturn;
   }
  
   ThreadEntry.dwSize = sizeof(THREADENTRY32);
   if ( FALSE == ::Thread32First(hSnapshot, &ThreadEntry) )
   {
     printf("Thread32First error: %u/n", ::GetLastError());
     goto FunReturn;
   }
  
   do
   {
     if ( ThreadEntry.th32OwnerProcessID != dwProcessID )
       continue;

     hThread = NULL;
     hThreadID = ThreadEntry.th32ThreadID;
     __asm
     {
       push hThreadID
       call My_ZwOpenThread

       mov hThread, eax
     }

     if ( NULL == hThread )
       continue;

     My_ZwTerminateThread((HANDLE)hThread, 0);
     My_ZwClose(hThread);
    
   } while( ::Thread32Next(hSnapshot, &ThreadEntry) );
  
FunReturn:
  
   if ( NULL != hSnapshot )
   {
     CloseHandle(hSnapshot);
     hSnapshot = NULL;
   }
}

int main(int argc, char * argv[])
{
   DWORD dwRet = 0;
   DWORD dwOSMajorVersion = 0, dwOSMinorVersion = 0;
   DWORD dwProcessID = 0;

    if ( argc != 2 || argc > 2 )
      goto FunReturn;

   CurrentProcess_AdjustTokenPrivileges();

   __asm
   {
     push ecx
     mov eax, fs:[30h]
     mov ecx, [eax+0A8h]
     mov dwOSMinorVersion, ecx
     xor ecx,ecx  
     mov ecx, [eax+0A4h]
     mov dwOSMajorVersion, ecx
     xor ecx,ecx
     pop ecx
   }

   if ( 5 != dwOSMajorVersion )   //不是 Windows Server 2003 R2,Windows Server 2003,Windows XP,Windows 2000.
   {
     printf("not Windows Server 2003 R2,Windows Server 2003,Windows XP,Windows 2000.");
     goto FunReturn;
   }

   if ( 1 == dwOSMinorVersion )
   {
     //printf("Xp System./n");
     dwZwOpenThread = 0x80;
     dwZwTerminateThread = 0x102;
     dwZwClose = 0x19;
   }
   else if ( 2 == dwOSMinorVersion )
   {
     //printf("Windows Server 2003 R2,Windows Server 2003,Windows XP Professional x64 Edition./n");
     dwZwOpenThread = 0x10B;
     dwZwTerminateThread = 0x86;
     dwZwClose = 0x1B;
   }
   else if ( 0 != dwOSMinorVersion )
   {
     dwZwOpenThread = 0x6F;
     dwZwTerminateThread = 0x0E1;
     dwZwClose = 0x18;
   }

   dwProcessID = GetProcessID((char *)argv[argc - 1]);
   if ( 0 == dwProcessID )
     goto FunReturn;

   TerminateProcess_Thread(dwProcessID);

FunReturn:
   return dwRet;
}

分析:
这个代码在vc6下运行,会出现栈帧混乱。 程序会崩溃掉。 下面是我修改后的代码,在vc6下测试通过。

#include <stdio.h>
#include <windows.h>
#include <Tlhelp32.h>
#include <Ntsecapi.h>

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

typedef long NTSTATUS;
#define NT_SUCCESS(status) ((NTSTATUS)(status) >= 0)

DWORD dwZwOpenThread = 0;
DWORD dwZwTerminateThread = 0;
DWORD dwZwClose = 0;

void CurrentProcess_AdjustTokenPrivileges()
{
BOOL bRet = FALSE;
HANDLE hTokenHandle = NULL;
TOKEN_PRIVILEGES tp;
LUID luid;

bRet = ::OpenProcessToken((HANDLE)::GetCurrentProcess(), 0xF01FF, &hTokenHandle);
if ( FALSE == bRet )
{
printf("OpenProcessToken error: %u/n", ::GetLastError());
goto FunReturn;
}

if ( 0 == ::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid) )
{
printf("LookupPrivilegeValue error: %u/n", ::GetLastError());
goto FunReturn;
}

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

if ( 0 == ::AdjustTokenPrivileges(hTokenHandle, 0, &tp, sizeof(TOKEN_PRIVILEGES), 0, 0) )
{
printf("AdjustTokenPrivileges error: %u/n", ::GetLastError());
goto FunReturn;
}

FunReturn:

if ( NULL != hTokenHandle )
{
CloseHandle(hTokenHandle);
hTokenHandle = NULL;
}
}

DWORD GetProcessID(char *szProcessName)
{
HANDLE hSnapshot = NULL;
PROCESSENTRY32 ProEntry;
DWORD dwProcessID = 0;

hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if ( INVALID_HANDLE_VALUE == hSnapshot )
{
printf("CreateToolhelp32Snapshot error: %u/n", ::GetLastError());
hSnapshot = NULL;
goto FunReturn;
}

ProEntry.dwSize = sizeof(PROCESSENTRY32);
if ( FALSE == ::Process32First(hSnapshot, &ProEntry) )
{
printf("Process32First error: %u/n", ::GetLastError());
goto FunReturn;
}

do
{
if ( 0 == _strnicmp(szProcessName, (char *)ProEntry.szExeFile, (int)strlen(szProcessName)) )
{
dwProcessID = (DWORD)ProEntry.th32ProcessID;
break;
}

} while( ::Process32Next(hSnapshot, &ProEntry) );

FunReturn:

if ( NULL != hSnapshot )
{
CloseHandle(hSnapshot);
hSnapshot = NULL;
}

return dwProcessID;
}

__declspec(naked) void Call_sysenter()
{
__asm
{
mov edx, esp
_emit 0x0f
_emit 0x34
retn
}
}

__declspec(naked) void _stdcall Call_ZwOpenThread()
{
__asm
{
mov eax, dwZwOpenThread
call Call_sysenter

retn 10h
}
}

__declspec(naked) void My_ZwOpenThread(DWORD dwThreadID)
{
__asm
{
sub esp, 20h
mov ecx, [esp+24h]
xor eax, eax
lea edx, [esp]
push edx
mov [esp+4h], eax
mov [esp+10h], eax
mov [esp+18h], eax
mov [esp+14h], eax
mov [esp+1Ch], eax
mov [esp+20h], eax
lea eax, [esp+0Ch]
push eax
mov [esp+0Ch], ecx
push 4Bh
lea ecx, [esp+30h]
push ecx
mov dword ptr [esp+18h], 18h
call Call_ZwOpenThread

neg eax
sbb eax, eax
not eax
and eax, [esp+24h]
add esp, 20h
retn 4h
}
}

__declspec(naked) void My_ZwTerminateThread(HANDLE hThread, DWORD dwExitCode)
{
__asm
{
mov eax, dwZwTerminateThread
call Call_sysenter
retn 8
}
}

__declspec(naked) void My_ZwClose(HANDLE hThread)
{
__asm
{
mov eax, dwZwClose
call Call_sysenter

retn 4
}
}

void TerminateProcess_Thread(DWORD dwProcessID)
{
__asm
{
push ESP
}
HANDLE hSnapshot = NULL;
HANDLE hThread = NULL;
DWORD hThreadID = 0, dwRet = 0;
THREADENTRY32 ThreadEntry;

hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessID);
if ( INVALID_HANDLE_VALUE == hSnapshot )
{
printf("CreateToolhelp32Snapshot error: %u/n", ::GetLastError());
hSnapshot = NULL;
goto FunReturn;
}

ThreadEntry.dwSize = sizeof(THREADENTRY32);
if ( FALSE == ::Thread32First(hSnapshot, &ThreadEntry) )
{
printf("Thread32First error: %u/n", ::GetLastError());
goto FunReturn;
}

do
{
if ( ThreadEntry.th32OwnerProcessID != dwProcessID )
continue;

hThread = NULL;
hThreadID = ThreadEntry.th32ThreadID;
__asm
{
push hThreadID
call My_ZwOpenThread
mov hThread, eax
}

if ( NULL == hThread )
continue;

My_ZwTerminateThread((HANDLE)hThread, 0);
My_ZwClose(hThread);

} while( ::Thread32Next(hSnapshot, &ThreadEntry) );

FunReturn:

if ( NULL != hSnapshot )
{
CloseHandle(hSnapshot);
hSnapshot = NULL;
}

__asm
{
pop ESP
}
}

int main(int argc, char * argv[])
{
DWORD dwRet = 0;
DWORD dwOSMajorVersion = 0, dwOSMinorVersion = 0;
DWORD dwProcessID = 0;

if ( argc != 2 || argc > 2 )
goto FunReturn;

CurrentProcess_AdjustTokenPrivileges();

__asm
{
push ecx
mov eax, fs:[30h] //从共享区获取版本信息
mov ecx, [eax+0A8h]
mov dwOSMinorVersion, ecx
xor ecx,ecx
mov ecx, [eax+0A4h]
mov dwOSMajorVersion, ecx
xor ecx,ecx
pop ecx
}

if ( 5 != dwOSMajorVersion ) //不是 Windows Server 2003 R2,Windows Server 2003,Windows XP,Windows 2000.
{
printf("not Windows Server 2003 R2,Windows Server 2003,Windows XP,Windows 2000.");
goto FunReturn;
}

if ( 1 == dwOSMinorVersion )
{
//printf("Xp System./n");
dwZwOpenThread = 0x80; //ssdt中的函数序号
dwZwTerminateThread = 0x102;
dwZwClose = 0x19;
}
else if ( 2 == dwOSMinorVersion )
{
//printf("Windows Server 2003 R2,Windows Server 2003,Windows XP Professional x64 Edition./n");
dwZwOpenThread = 0x10B;
dwZwTerminateThread = 0x86;
dwZwClose = 0x1B;
}
else if ( 0 != dwOSMinorVersion )
{
dwZwOpenThread = 0x6F;
dwZwTerminateThread = 0x0E1;
dwZwClose = 0x18;
}

dwProcessID = GetProcessID((char *)argv[argc - 1]);
if ( 0 == dwProcessID )
goto FunReturn;

TerminateProcess_Thread(dwProcessID);

FunReturn:
return dwRet;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值