小白之病毒分析- 网吧某监控软件。
本帖最后由 岁月静好。 于 2015-11-11 13:25 编辑前几天上传的样本,得到众基友指点后自己分析,第一次发分析帖流程可能有些混乱,大牛勿喷,有错误请指出,小白在学习中...在此感谢指点过我的人。
概述:Jw.exe为一个自解压文件,启动后释放出AnnexPro.exe,MainPro.exe,SysStart.sys,mswinsock.dll,MainProWbj.dll,CMClient,dll六个文件,详细分析了AnnexPro与MainPro两个文件,行为在下方都有详细说明,绿色部分为代码块,红色部分为关键说明。相关文件:AnnexPro.exeMainPro.exe
行为预览:Annexo.exe行为:
根据观察监控信息来看,Annexo.exe添加开机自启动,Annexo.exe创建互斥体检查是否启动MainPro.exe,如果发现进程被关闭则调用ShellExecuteA创建进程。如果自身进程被关闭,则调用ZwShutdownSystem关机(该为5秒检测一次),还有创建进程快照,检查窗口是否存在及文件是否完整等操作,下面流程未列出
0x1 mov edx,AnnexPro.0044FB0C ;ASCI"Global\Z_ANNEXPRO_ONE_FLAG"CALL to CreateMutexA from AnnexPro.004069FEpSecurity = NULLInitialOwner = FALSEMutexName = "Global\Z_ANNEXPRO_ONE_FLAG"
0x2 CreateMutexA pSecurity = NULLInitialOwner = FALSEMutexName = "Global\AnnexPro_MainPro_DrvStart"创建互斥体检查程序是否启动运行,判断信号互斥量是否存在,防止二次行为
0x3 OpenMutexA Access = 0x1F0001 Inheritable = FALSE MutexName = "Global\Z_NEEDAUTOUPDATE_TWO_FLAG" 打开与当前进程文件同名的信号互斥量,判断信号互斥量是否存在
0x4 CreateFileA FileName = "\\.\SysStart" Access = GENERIC_READ|GENERIC_WRITE ShareMode = 0 pSecurity = NULL Mode = OPEN_EXISTING Attributes = 0 hTemplateFile = NULL 创建文件SysStart.sys,目录在system/dirvers
0x5 CreateFileA FileName = "C:\Documents and Settings\Administrator\桌面\1\log\\2015102810.txt" Access = GENERIC_WRITE ShareMode = FILE_SHARE_READ pSecurity = NULL Mode = CREATE_ALWAYS Attributes = NORMAL hTemplateFile = NULL 创建文件log\\2015102810.txt,将取到的信息存入文件中 文件格式: 2015-10-28 10:25:03:==========Run========== 2015-10-28 10:25:03:Last Build : 2015年8月6日14:01:14
0x6 ReadFile hFile = 000001A0 (window) Buffer = 00C7E898 ;00C7E8E44D 5AMZ BytesToRead = 40 (64.) pBytesRead = 00C7E8D8 pOverlapped = NULL 创建一个名为MainPro的文件,读取文件,Buffer内容4D 5A,PE结构,可执行文件 文件已dump出来
0x7 Call AnnexPro.004258B0 jmp to shell32.ShellExecuteAShellExecuteA最终调用会在CreateProcessWCreateProcessW ModuleFileName = "C:\Documents and Settings\Administrator\桌面\1\MainPro.exe" CommandLine = ""C:\Documents and Settings\Administrator\桌面\1\MainPro.exe" " pProcessSecurity = NULL pThreadSecurity = NULL InheritHandles = FALSE CreationFlags = CREATE_NEW_CONSOLE|CREATE_UNICODE_ENVIRONMENT|CREATE_DEFAULT_ERROR_MODE pEnvironment = NULL CurrentDir = "C:\Documents and Settings\Administrator\桌面\1\" pStartupInfo = 00175D10 pProcessInfo = 00175D5C 创建进程启动MainPro.exe,当MainPro.exe进程不存在时则会继续进行创建。
Annexo.exe调用api的时候都是通过一个jmp跳到系统领空,而不是一般程序的直接调用,这样在导入表中就无法查找到这些重要的api,如下图所示:
MainPro.exe行为:MainPro.exe启动联网后会随机创建进程,因此在CreateProcess等系列函数下断点,没有断下来,根据监控信息得知,Hook了NtCreateProcess,NtCreateProcessEx这两个函数,联网会触发收发包函数send,recv函数下断点,随机进程名称,随机进程路径在rand函数下断点。MainPro.exe在调用api的时候也是通过一个jmp跳到系统领空,而不是一般程序的直接调用,这样在导入表中就无法查找到这些重要的api。
0x1RegOpenKeyExA hKey = HKEY_LOCAL_MACHINE;主键Subkey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Run";子键Reserved = 0x0;保留Access = KEY_ALL_ACCESS;权限pHandle = 0012FEF0打开注册表HKEY_LOCAL_MACHINE->SOFTWARE\Microsoft\Windows\CurrentVersion\Run 看程序是否自动启动数值名称:MicroBvd 数值数据:C:\WINDOWS\System32\AnnexPro.exe
0x2程序启动时首先创建随机数,暂不知道有何作用004190ACCall dword ptr ds:[<&winmm.timeGetTime>];记录开始时间xor edx,edx ;edx寄存器清零Mov ecx,03E8 ;ecx = 0X3E8 Div ecx ;ecx做除法Push edx ;余数,将余数做参数Call dword ptr ds:[<&msvcrt.srand>] ;srand(edx)Add esp,0x4Call dword ptr ds:[<&msvcrt.rand>] ;rand()
0x3通用注入流程:CreateProcess->GetThreadContext->ReadProcessMemory->ZwUnmapViewOfSection->VirtualAllocEx->WriteProcessMemory ->SetThreadContext->ResumeThread怀疑使用的API:MoveFileA GetMoudleHandleA CharNextA GetTempFileNameA GetTempPathA CreateDirectoryASHFileOperationA
Mov edi,dword ptr ds:[<&kernel32.GetProcAdress>]Push dump.00433B54 ;EnumProcess 列出系统的所有进程,包括详细文件名以及引用的所有动态库文件Push esiCall edi ;Call GetProcAddress 查找指定DLL的导出函数地址
Push dump.00433B40 ;EuumProcessMoudlesPush esiCall ediMov ebx,eaxPush dump.00433B28 ;GetMoudleFileNameExAPush esiMov dword ptr ss:,ebxCall edi
Push ecxPush 0x1000Push edxCall ebpEnumProcess
0x4004039F1Push eaxPush 0x0Push 0x410Call dword ptr ds:[<&kernel32.OpenProcess>];打开进程返回句柄,为后面使用
00403A17Push ecxPush 0x1000Push edxPush esiCall dword ptr ss: EnumProcessModules;枚举获取进程的所有模块
00403A3CPush 0x104Push eaxPush ecxPush esiCall dword ptr ss GetModuleFileNameExA;根据进程句柄获取进程文件名这里循环遍历进程,取得所有进程的加载的模块信息以及进程文件信息
0x5程序启动时send断下来Call to send from CMClient.005429F4Socket = 0x308Data = 001CF7A0DataSize = 97Flags = 0此处为Data内容
继续运行,在rand处断下,分析为第二段的内容,往下跟应该会有创建进程文件等操作。Push 0xFF ;255Push eaxCall dword ptr ds: ;ws2_32.gethostname 获取本机名称Lea ecx,dword ptr ss:Push ecxCall dword ptr ds: ;ws2_32.gethostbyname
Call dword ptr ds:;kernel32.GetComputerNameA
Call dword ptr ds: ;ws2_32.socketMov edi,dword ptr ds: ; ws2_32.WASCreateEventCall ediCall dword ptr ds: ;ws2_32.ntohsCall dword ptr ds: ;ws2_32.bind上面部分是socket操作,取得本机的一些信息,下面创建线程,设置线程优先级,至此“随机进程”还未出现,操作应该还在后面00419515 mov edi,dword ptr ds: ; kernel32.CreateThread 创建线程lea edx,dword ptr ss:push ebxpush edxpush 0x0push esipush MainPro.0041ADC0push 0x0push 0x0Call edi
Mov ebx,dword ptr ds:;kernel32.SetThreadPriority 设置线程优先级Push 0xFPush eaxMov dword ptr ds:,eaxCall ebx
rand函数地址004198f5 字符串地址00434244“以连接到服务器”思路:根据测试情况,MainPro.exe在连接服务器后会产生随机进程,因此在00434244出下断,说明已经连接服务器,创建进程的动作应该在后面,跟进。此后的操作Call 004126A0Call 004068A0Call 00411C20Call 004123A0Call dword ptr ds: kernel32.CreateProcessA在004125E6此处找到了进程创建操作,在这之上调用了GetSystemDirectory取得windows的系统目录。
IDA找到代码位置直接F5看操作。
v1处应为string(“xxx”),把v1的值拷贝给ComnandLine,之后调用CreateProcessA创建进程。分析到此完成。
MainPro.exe启动后进程的的监控情况,驱动实现,原理:利用PsSetCreateProcessNotifyRoutine函数。
还原了SysStart.sys的部分代码
NTSTATUS sub_4010E0(PCWSTR SourceString,PCWSTR String1)
{
UNICODE_STRING DestinationString;
/*
VOID
RtlInitUnicodeString(
IN OUT PUNICODE_STRINGDestinationString,
IN PCWSTRSourceString
);
*/
NTSTATUS var_28 = 0;
UNICODE_STRING ValueName;
RtlInitUnicodeString(&DestinationString,SourceString);
RtlInitUnicodeString(&ValueName,SourceString);
ObjectAttributes.Length = 0x18;
ObjectAttributes.RootDirectory = 0;
ObjectAttributes.Attrbutes = 0x40;
ObjectAttributes.ObjectName = &DestinationString;
ObjectAttributes.SecurityDescriptor = 0;
ObjectAttributes.SecurityQualityOfService = 0;
/*
NTSTATUS
ZwOpenKey(
OUT PHANDLEKeyHandle,
IN ACCESS_MASKDesiredAccess,
IN POBJECT_ATTRIBUTESObjectAttributes
);
*/
HANDLE KeyHandle;
var_24 = ZwOpenKey(KeyHandle,0xF003,&ObjectAttributes);
if(var_24 <= 0)
{
DbgPrint("ZwOpenKey Wrong\n");
return;
}
else
{
SIZE_T NumberOfBytes;
/*
PVOID
ExAllocatePool(
IN POOL_TYPEPoolType,
IN SIZE_TNumberOfBytes
);
*/
ExAllocatePool(0,NumberOfBytes);
/*
NTSTATUS
ZwQueryValueKey(
IN HANDLEKeyHandle,
IN PUNICODE_STRINGValueName,
IN KEY_VALUE_INFORMATION_CLASSKeyValueInformationClass,
OUT PVOIDKeyValueInformation,
IN ULONGLength,
OUT PULONGResultLength
);
*/
NumberOfBytes = 0x110;
var_24 = ZwQueryValueKey(KeyHandle,&ValueName,2,KeyValueInformation,NumberOfBytes);
if(var_24 >= 0)
{
}
else
{
DbgPrint("ZwQueryValueKey Wrong:%08x\n");
}
}
}
NTSTATUS sub_401450()
{
HANDLE ThreadHandle;
NTSTATUS v2;
UNICODE_STRING DestinationString;
KeInitializeEvent(&Event, SynchronizationEvent, 1u);
RtlInitUnicodeString(&DestinationString, L"This is a string for test!\n");
//创建系统线程
v2 = PsCreateSystemThread(&ThreadHandle, 0, 0, 0, &ClientId, StartRoutine, &DestinationString);
if ( ThreadHandle )
{
PsLookupThreadByThreadId(ClientId.UniqueThread, &Object);//查找ETHREAD
}
if ( v2 < 0 )
{
DbgPrint(aTestCreatethre);//" CreateThread Test Failed!\n"
}
ZwClose(ThreadHandle);
return KeWaitForSingleObject(&Event, 0, 0, 0, 0);
}
void StartRoutine(PVOID StartContext)
{
KeSetEvent(&Event,0,0);
while(!byte_4044CC)
{
dword_4044C0 = 1;
sub_4013C0(5000);
if ( dword_4044C0 == 1 && dword_404000 == 1 )
{
if ( dword_4044C4 )
{
DbgPrint(aNtshutdownsyst);
//关闭计算机
NtShutdownSystem(0);
}
else
{
dword_4044C4 = 1;
DbgPrint(aFirstNtshutdow);//"First NtShutdownSystem\n"
}
}
if ( dword_404000 == 2 )
{
sub_4013C0(5000);
}
}
}
进程监控的代码。
#include <ntifs.h>
#include "ntddk.h"
#define MAX_PATH 256
// 获取进程路径
VOID GetProcessPath(ULONG eprocess, PUNICODE_STRING pFilePath)
{
ULONG object;
PFILE_OBJECT FilePointer;
UNICODE_STRING name;//盘符
// EPROCESS -> SectionObject
if(MmIsAddressValid((PULONG)(eprocess + 0x138)))
{
object = (*(PULONG)(eprocess + 0x138));
// SECTION_OBJECT -> Segment
if(MmIsAddressValid((PULONG)((ULONG)object + 0x014)))
{
object = *(PULONG)((ULONG)object + 0x014);
// SEGMENT_OBJECT -> ControlArea
// 不是0x018
if(MmIsAddressValid((PULONG)((ULONG)object + 0x0)))
{
object = *(PULONG)((ULONG_PTR)object + 0x0);
// CONTROL_AREA -> FilePointer
if(MmIsAddressValid((PULONG)((ULONG)object + 0x024)))
{
object=*(PULONG)((ULONG)object + 0x024);
}
else return ;
}
else return ;
}
else return ;
}
else return ;
FilePointer = (PFILE_OBJECT)object;
ObReferenceObjectByPointer(
(PVOID)FilePointer,
0,
NULL,
KernelMode);
RtlVolumeDeviceToDosName(FilePointer->DeviceObject, &name); //获取盘符名
RtlCopyUnicodeString(pFilePath, &name); //盘符连接
RtlAppendUnicodeStringToString(pFilePath, &FilePointer->FileName); //路径连接
ObDereferenceObject(FilePointer); //关闭对象引用
}
VOID ProcessNotifyRoutine(
IN HANDLE ParentId,
IN HANDLE ProcessId,
IN BOOLEAN Create
)
{
NTSTATUS status = STATUS_SUCCESS;
PEPROCESS pEprocess = NULL;
UNICODE_STRING uniPath;
uniPath.Length = 0;
uniPath.MaximumLength = MAX_PATH * 2;
uniPath.Buffer = (PWSTR)ExAllocatePool(NonPagedPool, uniPath.MaximumLength);
// 创建进程
if (Create)
{
DbgPrint("*******----有----新----进----程----创----建----*******\r\n");
//父进程
DbgPrint("父进程信息\r\n");
DbgPrint(" PID:%d\r\n", ParentId);
status = PsLookupProcessByProcessId(ParentId, &pEprocess);
if (NT_SUCCESS(status))
{
GetProcessPath(pEprocess, &uniPath);
DbgPrint(" 路径: %wZ\r\n", &uniPath);
}
// 进程
DbgPrint("创建进程信息\r\n");
DbgPrint(" PID:%d\r\n", ProcessId);
status = PsLookupProcessByProcessId(ProcessId, &pEprocess);
if (NT_SUCCESS(status))
{
GetProcessPath(pEprocess, &uniPath);
DbgPrint(" 路径: %wZ\r\n", &uniPath);
}
}
// 结束进程
else
{
DbgPrint("*******----有----旧----进----程----退----出----*******\r\n");
// 父进程
//DbgPrint("父进程信息\r\n");
//DbgPrint(" PID:%d\r\n", ParentId);
//status = PsLookupProcessByProcessId(ParentId, &pEprocess);
//if (NT_SUCCESS(status))
//{
// GetProcessPath(pEprocess, &uniPath);
// DbgPrint(" 路径: %wZ\r\n", &uniPath);
//}
// 进程
DbgPrint("退出进程信息\r\n");
DbgPrint(" PID:%d\r\n", ProcessId);
status = PsLookupProcessByProcessId(ProcessId, &pEprocess);
if (NT_SUCCESS(status))
{
GetProcessPath(pEprocess, &uniPath);
DbgPrint(" 路径: %wZ\r\n", &uniPath);
}
}
ExFreePool(uniPath.Buffer);
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
DbgPrint("Stop Process Create/Delete Mon\r\n");
status = PsSetCreateProcessNotifyRoutine(ProcessNotifyRoutine, TRUE);
if (!NT_SUCCESS(status))
{
DbgPrint("Call PsSetCreateProcessNotifyRoutine Error!\r\n");
DbgPrint("Status Code: 0x%08X", status);
}
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pRegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("Start Process Create/Delete Mon\r\n");
pDriverObject->DriverUnload = DriverUnload;
status = PsSetCreateProcessNotifyRoutine(ProcessNotifyRoutine, FALSE);
if (!NT_SUCCESS(status))
{
DbgPrint("Call PsSetCreateProcessNotifyRoutine Error!\r\n");
DbgPrint("Status Code: 0x%08X", status);
return status;
}
return status;
} 网吧有公安部门安装的监控软件,你可以分析分析,爆爆菊花啥的 感谢分享
页:
[1]