Windows动态沙箱实现--进程回调监控

        前面讨论了沙箱的目标,今天开始落实代码实现,从功能实现的先后顺序上,我们优先实现4个回调:进程回调、镜像回调、线程回调、注册表回调,今天实现进程回调。

注册进程回调函数的关键API是PsSetCreateProcessNotifyRoutine,如果要使回调生效,需要在VS链接器命令行中添加 /INTEGRITYCHECK :

 该函数在高系统中还有Ex版本,读者自行查阅,函数原型如下:

NTSTATUS PsSetCreateProcessNotifyRoutine(
  _In_  PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
  _In_  BOOLEAN Remove
);

参数说明:

NotifyRoutine:我们自己的回调函数地址,函数原型如下:

VOID ProcessNotify(PEPROCESS Process, HANDLE hProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo)

Remove: 是否移除目标回调。我们是注册新的,所以是FALSE;

Status=PsSetCreateProcessNotifyRoutineEx(ProcessNotify, FALSE);

下面是我们的回调代码实现,核心功能是获取当前创建的进程PID、全路径、命令行、父进程PID、父进程全路径信息。需要注意的是,这里获取的父进程信息有可能是假的,最常见的就是启动服务、shellcode注入启动或者借助UpdateProcThreadAttribute伪造父进程启动。这类的伪装,我们需要在后续的InfinityHook里实现发现并进行关联标注。

//该API的使用需要声明
extern "C" PVOID NTAPI PsGetProcessWow64Process(PEPROCESS Process);

VOID ProcessNotify(PEPROCESS Process, HANDLE hProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo)
{
    if (KeGetCurrentIrql() != PASSIVE_LEVEL)
        return;

  
    //进程创建
    if (CreateInfo)
    {
        //判断进程类别
        BOOLEAN bwow64 = PsGetProcessWow64Process(Process) ? TRUE : FALSE;


        char filename[256] = { 0 };
        char cmdline[256] = { 0 };
        char parpath[256] = { 0 };
        StringUnicodeToAnsi(CreateInfo->ImageFileName, filename, CreateInfo->ImageFileName->Length);
        StringUnicodeToAnsi(CreateInfo->CommandLine, cmdline, CreateInfo->CommandLine->Length);

        StringToLower(filename);
        StringToLower(cmdline);


        char ctime[64] = { 0 };
        GetTimeString(ctime);

        GetProcPathByPid((HANDLE)CreateInfo->ParentProcessId, parpath);
        char sfomat[] = "{\"st\":\"ProcessNotify进程启动\",\"type\":%d,\"id\":%d,\"time\":\"%s\",\"ppid\":%d,\"ppath\":\"%s\",\"pid\":%d,\"path\":\"%s\",\"cmd\":\"%s\"}\n";

        char* cbuf = (char*)kMalloc(0x1000);
        sprintf(cbuf, sfomat, 1, 1, ctime, CreateInfo->ParentProcessId, parpath, hProcessId, filename, cmdline);
        DbgPrint("[procK]%s", cbuf);
        kFree(cbuf);

    }
    else
    {
        //进程销毁

    }
}

所使用到的自定义函数:

    PVOID kMalloc(SIZE_T size)
    {
        PVOID pTmp = (PVOID)ExAllocatePoolWithTag(NonPagedPool, size, 'clm3');
        if (pTmp)
        {
            RtlZeroMemory(pTmp, size);
        }
        return pTmp;
    }

    VOID kFree(PVOID pMem)
    {
        if (pMem)
        {
            ExFreePoolWithTag(pMem, 'clm3');
            pMem = 0;
        }
    }



BOOLEAN  GetProcPathByPid(HANDLE hdPid, char* cPath)
{
	BOOLEAN bOk = FALSE;
	PEPROCESS pEpro = 0;
	PFILE_OBJECT FileObject=0;
	PUNICODE_STRING ImageName;
	char parname[512] = { 0 };
	if ((int)hdPid == 4)
	{
		char system[] = "System";
		strcpy(cPath, system);
		bOk = TRUE;
	}
	else
	{
		auto spath = GetProcPathByPid((ULONG)hdPid);
		if (spath.length() > 0)
		{
			strcpy(cPath, spath.c_str());
			bOk = TRUE;
		}
		else
		{
			if (NT_SUCCESS(PsLookupProcessByProcessId(hdPid, &pEpro)))
			{
				if (NT_SUCCESS(PsReferenceProcessFilePointer(pEpro, &FileObject)))
				{
					if (NT_SUCCESS(SeLocateProcessImageName((PEPROCESS)pEpro, &ImageName)))
					{
						StringUnicodeToAnsi(ImageName, parname, ImageName->Length);
						StringToLower(parname);
						strcpy(cPath, parname);
						bOk = TRUE;
					}
				}
				if (FileObject)
					ObDereferenceObject(FileObject);
			}
			if (pEpro)
				ObDereferenceObject(pEpro);
		}
		
	}

	return bOk;
}

模板函数:

template <typename U, typename A>
BOOLEAN StringUnicodeToAnsi(U pUnicode, A szAnsiBuf, int nABuflen)
{
    ANSI_STRING ansiBuf;
    BOOLEAN		bResult = FALSE;
    ansiBuf.Buffer = (char*)kMalloc(2048);
    ansiBuf.MaximumLength = 2048;
    if (MmIsAddressValid((PVOID)pUnicode) && MmIsAddressValid(szAnsiBuf))
    {
        auto Status = RtlUnicodeStringToAnsiString(&ansiBuf, (PUNICODE_STRING)pUnicode, FALSE);
        if (NT_SUCCESS(Status))
        {
            if (ansiBuf.Length < nABuflen)
            {
                memcpy(szAnsiBuf, ansiBuf.Buffer, ansiBuf.Length);
                bResult = TRUE;
            }
        }
    }
    kFree(ansiBuf.Buffer);
    return bResult;
}

template <typename T>
NTSTATUS StringToLower(T szBuf)
{
    NTSTATUS st;
    if (szBuf && MmIsAddressValid(szBuf))
    {
        while (*szBuf)
        {
            if (*szBuf >= 'A' && *szBuf <= 'Z')
            {
                *szBuf += 0x20;
            }
            szBuf++;
        }
        st = STATUS_SUCCESS;
    }
    else
    {
        st = STATUS_UNSUCCESSFUL;
    }
    return st;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值