WinXP下监视进程的创建

2024-03-05 03:08
文章标签 创建 进程 监视 winxp

本文主要是介绍WinXP下监视进程的创建,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在winxp下进程的创建无非是使用System,Winexec,ShellExecute,CreateProcess等库函数和系统API.但是为了实现对进程创建的监视,我们一般都是拦截这些api,这样工作量会很大.而实际上这些函数最终都会调用ntdll.dll所导出的ZwCreateProcessEx函数,由他填入服务索引号,并软中断进入内核模式.只要Hook了该函数就能有效地从用户层监视进程的创建.但是有人会说,在2000和Xp下不是有NtCreateProcess和ZwCreateProcess么,实际上今天晚上我自己动手试了下,上述这两者,首先他们是一个函数,其次,在Xp下创建进程的时候,根本不会使用到他们...

 首先看下ZwCreateProcessEx的定义(参考win2k/xp native api refernce):

typedef NTSTATUS (*NTCREATEPROCESSEX)(
   OUT PHANDLE ProcessHandle,
   IN ACCESS_MASK DesiredAccess,
   IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
   IN HANDLE ParentProcess,
   IN BOOLEAN InheritObjectTable,
   IN HANDLE SectionHandle OPTIONAL,
   IN HANDLE DebugPort OPTIONAL,
   IN HANDLE ExceptionPort OPTIONAL,
   IN HANDLE Unknown ); 

我们需要的只是拦截他,目前暂时具体参数的功能就不谈了,具体实现方式就不说了,在前面的<用户层下拦截API的原理与实现>中已经讲得很清楚拉.如果你忘记了,具体见:http://redcoder.blog.sohu.com/2183228.html下面是这次实验的代码,拦截了ZwCreateProcessEx函数:

编译环境:WinXp Sp2 + vc6.0

代码:
--------------------------------------------------------------------------------

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

#define STATUS_SUCCESS  0
#define HOOKFUCTIONSIZE 10240      //定义拦截函数体的大小,以字节为单位,且以4kb为基本单位
#define HOOKEDAPIPARAMNUMINBYTE 36 //定义被拦截的api的函数的参数的大小,以字节为单位

typedef unsigned long NTSTATUS;
typedef unsigned long SYSTEM_INformATION_CLASS;

typedef struct _RemoteParam{
LPVOID          lpFunAddr;
LPVOID          lpWriteProcessMemory;
unsigned char   szOldCode[12];
unsigned char   szNewCode[12];
LPVOID          lpMessageBox;
}RemoteParam, * PRemoteParam;

typedef BOOL (__stdcall * PFN_WRITEPROCESSMEMORY)(HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T*);
typedef int  (__stdcall * PFN_MESSAGEBOX)(HWND, LPCTSTR, LPCTSTR, DWORD);

typedef
NTSTATUS
(__stdcall * PFN_ZWCREATEPROCESSEX)(
PHANDLE,
ACCESS_MASK,
LPVOID,
HANDLE,
BOOLEAN,
HANDLE,
HANDLE,
HANDLE,
HANDLE
);

VOID HookApi(LPVOID lParam)
{
RemoteParam* Rpm = (RemoteParam*)lParam;
PFN_ZWCREATEPROCESSEX pfnZwCreateprocessEx = (PFN_ZWCREATEPROCESSEX)Rpm->lpFunAddr;
PFN_WRITEPROCESSMEMORY pfnWriteProcessMemory = (PFN_WRITEPROCESSMEMORY)Rpm->lpWriteProcessMemory;
PFN_MESSAGEBOX pfnMessageBox = (PFN_MESSAGEBOX)Rpm->lpMessageBox;

char sztest[8] = {'h', 'e', 'l', 'l', 'o', '.', '.', '/0'};
  


PHANDLE ProcessHandle = NULL;
ACCESS_MASK DesiredAccess = 0;
LPVOID ObjectAttributes = NULL;
HANDLE InheritFromProcessHandle = NULL;
BOOLEAN InheritHandles = TRUE;
HANDLE SectionHandle = NULL;
HANDLE DebugPort = NULL;
HANDLE ExceptionPort = NULL;
HANDLE reserv = NULL;


NTSTATUS Retvalue = STATUS_SUCCESS; //定义要拦截的api的默认返回植
DWORD NextIpAddr = 0;
DWORD dwParamaAddr = 0;

DWORD temp1 = 0;

__asm
{
 MOV EAX, [EBP + 12]
 MOV [NextIpAddr], EAX
 MOV EAX, [EBP + 16]
 MOV [ProcessHandle], EAX
 MOV EAX, [EBP + 20]
 MOV [DesiredAccess], EAX
 MOV EAX, [EBP + 24]
 MOV [ObjectAttributes], EAX
 MOV EAX, [EBP + 28]
 MOV [InheritFromProcessHandle], EAX
 MOV EAX, [EBP + 32]
 MOV [temp1], EAX
 MOV EAX, [EBP + 36]
 MOV [SectionHandle], EAX 
 MOV EAX, [EBP + 40]
 MOV [DebugPort], EAX
 MOV EAX, [EBP + 44]
 MOV [ExceptionPort], EAX
 MOV EAX, [EBP + 48]
 MOV [reserv], EAX 
}

InheritHandles = (BOOLEAN)temp1;


//这里可以做你的事情了,比如我只想弹出一个对话框,其实也可以在让api完成之后再做些东西
   pfnMessageBox(NULL, sztest, sztest, 0);  

pfnWriteProcessMemory((HANDLE)0XFFFFFFFF, Rpm->lpFunAddr, (LPCVOID)Rpm->szOldCode, 12, NULL);
//让api真正执行,这里换成你要拦截的api
Retvalue = pfnZwCreateprocessEx(ProcessHandle,
                             DesiredAccess,
           ObjectAttributes,
           InheritFromProcessHandle,
           InheritHandles,
           SectionHandle,
           DebugPort,
           ExceptionPort,
           reserv);

//再次恢复对他的拦截
pfnWriteProcessMemory((HANDLE)0XFFFFFFFF, Rpm->lpFunAddr, (LPCVOID)Rpm->szNewCode, 12, NULL);

 
  DWORD dwStackSize = 12 + HOOKEDAPIPARAMNUMINBYTE;
 
  //这里对拦截函数堆栈的恢复,必须放在最后
  __asm
  {
   POP EDI     //注意如果你编译生成的debug版本的程序则需要把这
   POP ESI     //三个注释去掉
   POP EBX
   MOV ECX, [dwStackSize]
   MOV EDX, [NextIpAddr]
   MOV EAX, [Retvalue]
   MOV ESP, EBP
   POP EBP
   ADD ESP, ECX //12 + HOOKEDAPIPARAMNUMINBYTE  //恢复堆栈
   PUSH EDX
   RET
  }
}


//
//************************************************************************
//模块名字:AdjustProcessPrivileges(LPCSTR)
//模块功能:修改调用进程的权限
//返回数值:成功返回TRUE,失败返回FALSE
//参数可以为下列值:
// #define SE_BACKUP_NAME        TEXT("SeBackupPrivilege")
// #define SE_RESTORE_NAME       TEXT("SeRestorePrivilege")
// #define SE_SHUTDOWN_NAME      TEXT("SeShutdownPrivilege")
// #define SE_DEBUG_NAME         TEXT("SeDebugPrivilege")
//

BOOL AdjustProcessPrivileges(LPCSTR lpPrivilegesName)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if(!OpenProcessToken((HANDLE)0XFFFFFFFF,
 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
 return FALSE;
}

if(!LookupPrivilegeValue(NULL, lpPrivilegesName, &tkp.Privileges[0].Luid))
{
 CloseHandle(hToken);
 return FALSE;
}

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

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

CloseHandle(hToken);
return TRUE;
}


int SetHook(DWORD dwPid, LPCTSTR lpApiName, LPCTSTR lpExportDllName, LPVOID lpHookFunAddr)
{
if(!AdjustProcessPrivileges(SE_DEBUG_NAME))
{
 printf("-----AdjustProcessPrivileges error../n");
 return -1;
}
printf("1:AdjustProcessPrivileges ok/n");

//获取要拦截的api的地址
HMODULE hExportDll = LoadLibrary(lpExportDllName);
if(hExportDll == NULL)
{
 printf("-----LoadLibrary error../n");
 return -1;
}


LPVOID lpApiAddr = GetProcAddress(hExportDll, lpApiName);
if(lpApiAddr == NULL)
{
 printf("-----GetProcAddress %s error../n", lpApiName);
 FreeLibrary(hExportDll);
 return -1;
}

//打开进程句柄
HANDLE hTargetProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
                                       FALSE, dwPid);
if(hTargetProcess == NULL)
{
 printf("-----OpenProcess %d error../n", dwPid);
 FreeLibrary(hExportDll);
 return -1;
}

//申请拦截函数内存空间
LPVOID lpFunAddr = VirtualAllocEx(hTargetProcess, NULL, HOOKFUCTIONSIZE,
                                     MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(lpFunAddr == NULL)
{
 printf("-----VirtualAllocEx for remotefuction error../n");
 FreeLibrary(hExportDll);
 CloseHandle(hTargetProcess);
 return -1;
}

//申请远程参数空间
LPVOID lpParamaAddr = VirtualAllocEx(hTargetProcess, NULL, sizeof(RemoteParam),
                                        MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(lpParamaAddr == NULL)
{
 printf("-----VirtualAllocEx for remoteparam error../n");
 FreeLibrary(hExportDll);
 VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
 CloseHandle(hTargetProcess);
 return -1;
}

printf("2:Alloc remote memory for the hook fuction and param ok/n");


//设置远程参数,下一步要把参数写入要拦截的远程进程地址空间
RemoteParam RParam;
ZeroMemory(&RParam, sizeof(RParam));

unsigned char oldcode[12];
unsigned char newcode[12];
DWORD dwError = 0;
if(!ReadProcessMemory((HANDLE)0XFFFFFFFF,
 lpApiAddr,
 oldcode,
 12,
 &dwError))
{
 printf("-----ReadProcessMemory from lpApiName error../n");
 FreeLibrary(hExportDll);
 VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
 VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
 CloseHandle(hTargetProcess);
 return -1;
}
//生成跳转指令,这将覆盖要拦截的api的前十个字节
int praadd = (int)lpParamaAddr;
int threadadd = (int)lpFunAddr;
newcode[4] = praadd>>24;
newcode[3] = (praadd<<8)>>24;
newcode[2] = (praadd<<16)>>24;
newcode[1] = (praadd<<24)>>24;
newcode[0] = 0x68;  //PUSH lpParamaAddr

int offsetaddr = threadadd - (int)lpApiAddr - 10 ;
newcode[9] = offsetaddr>>24;
newcode[8] = (offsetaddr<<8)>>24;
newcode[7] = (offsetaddr<<16)>>24;
newcode[6] = (offsetaddr<<24)>>24;
newcode[5] = 0xE8;  //CALL lpFunAddr

newcode[10] = 0x90;
newcode[11] = 0x90;

for(int j = 0; j < 12; j++)
{
 RParam.szOldCode[j] = oldcode[j];
 RParam.szNewCode[j] = newcode[j];
}
RParam.lpFunAddr = lpApiAddr;

HMODULE hKernel32 = LoadLibrary("Kernel32.dll");
if(hKernel32 == NULL)
{
 printf("-----LoadLibrary Kernel32.dll error../n");
 FreeLibrary(hExportDll);
 VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
 VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
 CloseHandle(hTargetProcess);
 return -1;
}

RParam.lpWriteProcessMemory = GetProcAddress(hKernel32, "WriteProcessMemory");
if(RParam.lpWriteProcessMemory == NULL)
{
 printf("-----GetProcAddress WriteProcessMemory from Kernel32.dll error../n");
 FreeLibrary(hExportDll);
 VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
 VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
 CloseHandle(hTargetProcess);
 FreeLibrary(hKernel32);
 return -1;
}

//以上皆为必须,下面可以为自己的拦截函数中所需要用的一些变量以及系统api放到参数中去
HMODULE hUser32 = LoadLibrary("User32.dll");
if(hUser32 == NULL)
{
 printf("-----LoadLibrary User32.dll error../n");
 FreeLibrary(hExportDll);
 VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
 VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
 CloseHandle(hTargetProcess);
 FreeLibrary(hKernel32);
 return -1;
}

RParam.lpMessageBox = GetProcAddress(hUser32, "MessageBoxA");
if(RParam.lpMessageBox == NULL)
{
 printf("-----GetProcAddress MessageBoxA from User32.dll error../n");
 FreeLibrary(hExportDll);
 VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
 VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
 CloseHandle(hTargetProcess);
 FreeLibrary(hKernel32);
 FreeLibrary(hUser32);
 return -1;
}

FreeLibrary(hUser32);
printf("3:Generate remoteparam ok/n");

//下面为必须部分
//把参数写入要拦截的远程进程地址空间
if(!WriteProcessMemory(hTargetProcess, lpParamaAddr, (LPVOID)&RParam, sizeof(RParam), &dwError))
{
 printf("-----WriteProcessMemory for remoteparam error../n");
 FreeLibrary(hExportDll);
 VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
 VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
 CloseHandle(hTargetProcess);
 FreeLibrary(hKernel32);
 return -1;
}
printf("4:WriteProcessMemory for remoteparam ok/n");
//把拦截函数体写入目标进程地址空间
if(!WriteProcessMemory(hTargetProcess, lpFunAddr, lpHookFunAddr, HOOKFUCTIONSIZE, &dwError))
{
 printf("-----WriteProcessMemory for remotefuction error../n");
 FreeLibrary(hExportDll);
 VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
 VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
 CloseHandle(hTargetProcess);
 FreeLibrary(hKernel32);
 return -1;
}
printf("5:WriteProcessMemory for remotefuction ok/n");
//把新的跳转指令写入要拦截的目标进程的要拦截的api的函数的前十字节
if(!WriteProcessMemory(hTargetProcess, lpApiAddr , (LPVOID)newcode, 12, &dwError))
{
 printf("-----Modify remote api error../n");
 FreeLibrary(hExportDll);
 VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
 VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
 CloseHandle(hTargetProcess);
 FreeLibrary(hKernel32);
 return -1;
}
   printf("6:Modify remote api %s ok/n", lpApiName);

//show..
printf("---------------------------------------------------------------------------/n"
    "You hava hooked pid: %d ,and the infomation of this hooking are as follows:/n"
    "API name: %s/n"
    "API addr: 0x%.8x/n"
    "Module name: %s/n"
    "Module addr: 0x%.8x/n"
    "Remote parama addr: 0x%.8x/n"
    "Remote thread addr: 0x%.8x/n"
    "RemoteParam.lpFunAddr: 0x%.8x/n"
    "RemoteParam.lpWriteProcessMemory: 0x%.8x/n"
    "RemoteParam.lpMessageBox: 0x%.8x/n",
    dwPid,
    lpApiName,
          lpApiAddr,
    lpExportDllName,
    hExportDll,
    lpParamaAddr,
    lpFunAddr,
    RParam.lpFunAddr,
    RParam.lpWriteProcessMemory,
    RParam.lpMessageBox);

printf("RemoteParam.szOldCode: ");
for(int i = 0; i < 12; i++)
{
 printf("0x%x ", RParam.szOldCode[i]);
}

printf("/nRemoteParam.szNewCode: ");
for(i = 0; i < 12; i++)
{
 printf("0x%x ", RParam.szNewCode[i]);
}

printf("/nThat's all, good luck ^_^/n");
Sleep(10000);


//收工,清理资源
FreeLibrary(hExportDll);
CloseHandle(hTargetProcess);
FreeLibrary(hKernel32);
return 0;
}


int main(void)
{//注意这里第一个参数是你要选择监视的进程的ID,我这里是选的我的explorer.exe
SetHook(1564, "NtCreateProcessEx", "ntdll.dll", &HookApi);
 

 

引自: http://www.hacker.cn/Get/xtaq/0691410230498975.shtml
 

这篇关于WinXP下监视进程的创建的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/775140

相关文章

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

手把手教你idea中创建一个javaweb(webapp)项目详细图文教程

《手把手教你idea中创建一个javaweb(webapp)项目详细图文教程》:本文主要介绍如何使用IntelliJIDEA创建一个Maven项目,并配置Tomcat服务器进行运行,过程包括创建... 1.启动idea2.创建项目模板点击项目-新建项目-选择maven,显示如下页面输入项目名称,选择

C#如何优雅地取消进程的执行之Cancellation详解

《C#如何优雅地取消进程的执行之Cancellation详解》本文介绍了.NET框架中的取消协作模型,包括CancellationToken的使用、取消请求的发送和接收、以及如何处理取消事件... 目录概述与取消线程相关的类型代码举例操作取消vs对象取消监听并响应取消请求轮询监听通过回调注册进行监听使用Wa

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

[Linux]:进程(下)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:Linux学习 贝蒂的主页:Betty’s blog 1. 进程终止 1.1 进程退出的场景 进程退出只有以下三种情况: 代码运行完毕,结果正确。代码运行完毕,结果不正确。代码异常终止(进程崩溃)。 1.2 进程退出码 在编程中,我们通常认为main函数是代码的入口,但实际上它只是用户级

顺序表之创建,判满,插入,输出

文章目录 🍊自我介绍🍊创建一个空的顺序表,为结构体在堆区分配空间🍊插入数据🍊输出数据🍊判断顺序表是否满了,满了返回值1,否则返回0🍊main函数 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞+关注+评论+收藏(一键四连)哦~ 🍊自我介绍   Hello,大家好,我是小珑也要变强(也是小珑),我是易编程·终身成长社群的一名“创始团队·嘉宾”

Maven创建项目中的groupId, artifactId, 和 version的意思

文章目录 groupIdartifactIdversionname groupId 定义:groupId 是 Maven 项目坐标的第一个部分,它通常表示项目的组织或公司的域名反转写法。例如,如果你为公司 example.com 开发软件,groupId 可能是 com.example。作用:groupId 被用来组织和分组相关的 Maven artifacts,这样可以避免

批处理以当前时间为文件名创建文件

批处理以当前时间为文件名创建文件 批处理创建空文件 有时候,需要创建以当前时间命名的文件,手动输入当然可以,但是有更省心的方法吗? 假设我是 windows 操作系统,打开命令行。 输入以下命令试试: echo %date:~0,4%_%date:~5,2%_%date:~8,2%_%time:~0,2%_%time:~3,2%_%time:~6,2% 输出类似: 2019_06