进程隐藏——病毒分析

样本是从看雪上扒下来的,原文作者在动态分析的时候提到这个样本在运行的过程中,会有隐藏进程的操作,分析学习一下。

样本信息

32位程序在这里插入图片描述
查壳:无壳
在这里插入图片描述

静态分析

样本进去之后逻辑相对简单:
在这里插入图片描述
首先对执行参数进行判断,接着拼接目标进程的路径,之后对资源段的数据进行处理。
在这里插入图片描述
通过程序逻辑,不难判断出,通过定位资源段的数据,在进行解密操作,再结合之前获取svchost进程的路径,不难猜测,资源段的数据揭秘出来应该是一个PE文件,在之后的操作里边会对svchost进程进行注入操作。
查看资源段数据解密算法:
在这里插入图片描述
把资源段的数据复制出来手动进行解密:
在这里插入图片描述
解密代码:(将资源段的数据复制出来,之后进行解密操作,解密结果放在另一个文件里)

#include <stdio.h>
#include <Windows.h>
void main()
{
	HANDLE pFile,hFile;
	DWORD fileSize;
	char *buffer, *tmpBuf;
	DWORD dwBytesRead, dwBytesToRead, tmpLen;

	pFile = CreateFileA("C:\\Users\\sam\\Desktop\\1.txt", GENERIC_READ|GENERIC_WRITE,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,        //打开已存在的文件 
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (pFile == INVALID_HANDLE_VALUE)
	{
		printf("open file error!\n");
		CloseHandle(pFile);
	}
	fileSize = GetFileSize(pFile, NULL);          //得到文件的大小
	buffer = (char *)malloc(fileSize);
	memset(buffer, 0, fileSize);
	dwBytesToRead = fileSize;
	dwBytesRead = 0;
	tmpBuf = buffer;
	ReadFile(pFile, tmpBuf, dwBytesToRead, &dwBytesRead, NULL);
	for (int i = 0; i < fileSize; i++)
	{
		*(BYTE *)(i + tmpBuf) ^= 0x41;
	}
	hFile = CreateFileA("C:\\Users\\sam\\Desktop\\2.txt", GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ,
		NULL,
		CREATE_ALWAYS,        //打开已存在的文件 
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	WriteFile(hFile, tmpBuf, fileSize, &dwBytesRead, NULL);
	CloseHandle(pFile);
}

解密结果:(很明显是一个PE文件)
在这里插入图片描述
解密之后的PE文件之后再来分析,接下来查看对解密出来PE文件的下一步操作,也是整个进程隐藏的关键部分:
开始还是正常的PE文件的校验以及创建进程,获取线程上下文的操作:
在这里插入图片描述
之后将进程映像基址存储到缓冲区中,执行NtUnmapViewOfSection来卸载映像(此处将模块从内存空间卸载,以达到进程隐藏的目的)
在这里插入图片描述
之后将整个PE文件循环写入到申请的内存空间
在这里插入图片描述
最后,将新的进程映像基址存储修正到线程上下文结构中,之后修正入口点,重新恢复线程,完成程序的创建的隐藏
在这里插入图片描述
在分析资源段数据解密出的PE文件之前,还有一个问题需要解决:

Context->Ebx+8 中问什么会存储映像基址

这是因为Context->Ebx指向的是当前进程的PEB结构,PEB偏移8的地方即为映像基址:
在这里插入图片描述
验证过程:
验证Demo:(在进程创建的时候,采用挂起的方式创建)

#include <stdio.h>
#include <WINDOWS.H>

int main(int argc, char* argv[])
{
	// 挂起方式创建进程
	STARTUPINFO si = { 0 };
	si.cb = sizeof(si);
	PROCESS_INFORMATION pi;
	CreateProcessW(L"C:\\Tools\\Editor\\Notepad++\\notepad++.exe",NULL,NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL,(LPSTARTUPINFOW) &si, &pi);
	// 获取线程上下文
	CONTEXT context;
	context.ContextFlags = CONTEXT_FULL;
	GetThreadContext(pi.hThread, &context);
	// 获取入口点
	DWORD dwEntryPoint = context.Eax;
	printf("入口点: %x\n", dwEntryPoint);
	// 获取ImageBase
	DWORD baseAddress = (context.Ebx + 8);
	printf("入口点: %x\n", baseAddress);
}

验证过程:
1、Windbg双机调试
2、进入双机调试环境之后,用OD附加之后调试到进程创建,这个时候可以用Proexp查看进程列表,同时也可以在Windbg中查看系统中近程列表。
在这里插入图片描述
在这里插入图片描述
在Windbg中执行

!Process 0 0

查看系统进程列表,其中会包含目标进程的PEB信息:
在这里插入图片描述
和上边的调试信息相对比,可以相对应。

Context->Ebx   -----》PEB

接下来继续分析,解密出来的PE文件
在这里插入图片描述
进去之后可以看出来是具有键盘记录功能的文件
在这里插入图片描述
之后将相关的击键记录写入到文件里边:
在这里插入图片描述
目标文件:
在这里插入图片描述
其实释放出来的PE文件,功能相对比较简单。可以直观的看出该PE文件的功能就是实现简单的键盘记录。
样本功能总结:从静态分析的角度来看,该样本在运行之后会从资源段的数据解密释放出一个PE文件(释放到内存空间,文件不落地),释放的目标PE文件会注入到以挂起方式创建的svchost进程(替换),之后采用进程隐藏技术将PE文件从内存中卸载(以此来达到隐藏进程的目的)。
PS:原文作者提到了动态分析的结果,但是这个样本我拿到之后,直接运行会产生报错。

总结:

这个样本里边使用的进程隐藏的技巧如下:
1:以挂起的方式创建进程
2:获取挂起进程的线程上下文
3:执行NtUnmapViewOfSection将映像从内存中卸载
4:申请内存空间之后将PE文件重新写入内存空间
5:之后修正线程入口点以及线程上下文中的映像基址
6: 恢复线程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值