通过修改peb中的命令行参数字段实现进程创建的劫持

文章介绍了恶意软件如何通过修改进程对象中的PEB结构体的命令行参数字段来实现浏览器主页劫持。在进程创建回调函数中,当用户层进程尚未初始化时,篡改命令行参数可以达到劫持目的。示例代码展示了如何在Windows系统中进行这种修改。
摘要由CSDN通过智能技术生成

    之前分析过的一些恶意软件中会使用这种方法来进行浏览器的主页劫持,其原理就是在进程创建回调函数中处理进程的创建消息。这个时候由于应用层的进程实体还没有开始初始化,所以通过命令行参数篡改来实现劫持;假如这个时候应用层的进程实体已经创建并完成初始化,修改命令行参数就达不到预期的作用(因为完成初始化后,peb中的命令行参数字段就不再需要了,不会重复初始化这个过程)。

   下面示例展示了如何修改命令行参数:以abcdefg.exe进程为例,其完整文件路径为:"C:\Users\1909\Desktop\abcdefg.exe";进修改后变为:"C:\Users\1909\Desktop\abcdefg.exe"  -124,当然也可以变为:"C:\Users\1909\Desktop\abcd.exe"  -124。

/*
演示如何修改进程对象中的peb中命令行参数字段

这种方法常见的被用在浏览器主页篡改

也可以用来观察其他进程启动的命令行参数


之所以可以这要操作的原因时:当进程创建回调函数收到进程创建的通知时,内核中的进程对象已经创建,
但是用户层的进程还是一个空壳,还没有申请用户层的资源,连主线程的没有启动。从这里可以联想到,
如果在这个时候对应用层的某个api进行的话,可能时机太早了,模块可能都还有加载。


*/


typedef struct _RTL_USER_PROCESS_PARAMETERS {
    BYTE           Reserved1[16];
    PVOID          Reserved2[10];
    UNICODE_STRING ImagePathName;
    UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS;

typedef struct _PEB {
    BYTE                          Reserved1[2];
    BYTE                          BeingDebugged;
    BYTE                          Reserved2[1];
    PVOID                         Reserved3[2];
    PPEB_LDR_DATA                 Ldr;
    PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
    BYTE                          Reserved4[104];
    PVOID                         Reserved5[52];
    PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
    BYTE                          Reserved6[128];
    PVOID                         Reserved7[1];
    ULONG                         SessionId;
} PEB, * PPEB;

NTSTATUS TamperProcessCommandLine(PEPROCESS process)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	LONG CompareResult=0;

	UNICODE_STRING string1;
	UNICODE_STRING append;
	WCHAR* NewCommandLine=NULL;

	if (process)
	{
		PPEB peb = PsGetProcessPeb(process);

		if (peb)
		{
			KAPC_STATE ApcState;
			//
			//如果不附加目标进程,会导致后面的peb访问异常
			//
			KeStackAttachProcess(process, &ApcState);

			DbgPrint("before CommandLine:%wZ\n", &(peb->ProcessParameters->CommandLine));

			RtlInitUnicodeString(&string1, L"\"C:\\Users\\1909\\Desktop\\abcdefg.exe\"");
			//DbgPrint("string1:%wZ\n", &string1);
			CompareResult = RtlCompareUnicodeString(&string1, &(peb->ProcessParameters->CommandLine), FALSE);
			
			if (wcsstr(peb->ProcessParameters->CommandLine.Buffer, L"abcdefg.exe"))
			{
				DbgPrint("CommandLine.Length:%d,CommandLine.MaxiumLength:%d\n", peb->ProcessParameters->CommandLine.Length, peb->ProcessParameters->CommandLine.MaximumLength);

				RtlInitUnicodeString(&append, L" -124");

				NewCommandLine = (WCHAR*)ExAllocatePool(NonPagedPool, 512);
				if (NewCommandLine)
				{
					wcscpy(NewCommandLine, peb->ProcessParameters->CommandLine.Buffer);
					wcscat(NewCommandLine, append.Buffer);

					wcscpy(peb->ProcessParameters->CommandLine.Buffer, NewCommandLine);
					peb->ProcessParameters->CommandLine.Length = (USHORT)wcslen(NewCommandLine) * 2;
					peb->ProcessParameters->CommandLine.MaximumLength = (USHORT)wcslen(NewCommandLine) * 2 + 2;

					DbgPrint("after CommandLine:%wZ\n", &(peb->ProcessParameters->CommandLine));

					status = STATUS_SUCCESS;
				}
			}

			KeUnstackDetachProcess(&ApcState);
		}
	}
	if (NewCommandLine)
	{
		ExFreePool(NewCommandLine);
		NewCommandLine = NULL;
	}
	return status;
}

效果截图:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows C语言驱动可以通过调用PsLookupProcessByProcessId函数获取进程的EPROCESS结构体,然后通过EPROCESS结构体Peb字段获取进程PEB结构体,最后通过PEB结构体的ProcessParameters字段获取进程命令行参数。具体实现可以参考以下代码: ``` NTSTATUS GetProcessCommandLine(PUNICODE_STRING pCommandLine, HANDLE hProcessId) { NTSTATUS status = STATUS_SUCCESS; PEPROCESS pEprocess = NULL; PPEB pPeb = NULL; PRTL_USER_PROCESS_PARAMETERS pProcessParameters = NULL; KAPC_STATE state; // 获取进程EPROCESS结构体 status = PsLookupProcessByProcessId(hProcessId, &pEprocess); if (!NT_SUCCESS(status)) { return status; } // 获取进程PEB结构体 KeStackAttachProcess((PKPROCESS)pEprocess, &state); pPeb = PsGetProcessPeb(pEprocess); if (pPeb == NULL) { KeUnstackDetachProcess(&state); ObDereferenceObject(pEprocess); return STATUS_UNSUCCESSFUL; } // 获取进程命令行参数 pProcessParameters = pPeb->ProcessParameters; if (pProcessParameters == NULL || pProcessParameters->CommandLine.Length == 0) { KeUnstackDetachProcess(&state); ObDereferenceObject(pEprocess); return STATUS_UNSUCCESSFUL; } // 复制命令行参数到输出参数 status = RtlUnicodeStringCopy(pCommandLine, &pProcessParameters->CommandLine); if (!NT_SUCCESS(status)) { KeUnstackDetachProcess(&state); ObDereferenceObject(pEprocess); return status; } KeUnstackDetachProcess(&state); ObDereferenceObject(pEprocess); return STATUS_SUCCESS; } ``` 调用该函数时,需要传入进程ID和一个UNICODE_STRING类型的输出参数pCommandLine,函数会将进程命令行参数复制到pCommandLine
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值