一些木马和病毒程序常常使用计划任务程序来进行持久化,比如印度阿三写的Donot APT就非要用rundll32来注册自己的恶意dll。一怒之下我就写了C++代码专门针对藏在任务计划程序中的无文件攻击类型进行检测。如果主机被马感染了,可以迅速警报。
#define _WIN32_DCOM
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <vector>
#include <comdef.h>
#include <taskschd.h>
#include <string.h>
#pragma comment(lib, "taskschd.lib")
#pragma comment(lib, "comsupp.lib")
const char* FilelessAttack[] = { "rundll32", "powershell", "regsvr32", "cmd", "Psexec", "certutil", "mshta", "wmic", "msiexec" };
bool JudgeAction(BSTR actionstr);
int EnumTask(bool check)
{
// ------------------------------------------------------
// Initialize COM.
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr))
{
printf("\nCoInitializeEx failed: %x", hr);
return 1;
}
// Set general COM security levels.
hr = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
0,
NULL);
if (FAILED(hr))
{
printf("\nCoInitializeSecurity failed: %x", hr);
CoUninitialize();
return 1;
}
// ------------------------------------------------------
// Create an instance of the Task Service.
ITaskService* pService = NULL;
hr = CoCreateInstance(CLSID_TaskScheduler,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITaskService,
(void**)&pService);
if (FAILED(hr))
{
printf("Failed to CoCreate an instance of the TaskService class: %x", hr);
CoUninitialize();
return 1;
}
// Connect to the task service.
hr = pService->Connect(_variant_t(), _variant_t(),
_variant_t(), _variant_t());
if (FAILED(hr))
{
printf("ITaskService::Connect failed: %x", hr);
pService->Release();
CoUninitialize();
return 1;
}
// ------------------------------------------------------
// Get the pointer to the root task folder.
ITaskFolder* pRootFolder = NULL;
hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
pService->Release();
if (FAILED(hr))
{
printf("Cannot get Root Folder pointer: %x", hr);
CoUninitialize();
return 1;
}
// -------------------------------------------------------
// Get the registered tasks in the folder.
IRegisteredTaskCollection* pTaskCollection = NULL;
hr = pRootFolder->GetTasks(NULL, &pTaskCollection);
pRootFolder->Release();
if (FAILED(hr))
{
printf("Cannot get the registered tasks.: %x", hr);
CoUninitialize();
return 1;
}
LONG numTasks = 0;
hr = pTaskCollection->get_Count(&numTasks);
if (numTasks == 0)
{
printf("\nNo Tasks are currently running");
pTaskCollection->Release();
CoUninitialize();
return 1;
}
printf("\nNumber of Tasks : %d", numTasks);
TASK_STATE taskState;
for (LONG i = 0; i < numTasks; i++)
{
IRegisteredTask* pRegisteredTask = NULL;
hr = pTaskCollection->get_Item(_variant_t(i + 1), &pRegisteredTask);
if (SUCCEEDED(hr))
{
BSTR taskName = NULL;
BSTR strname = NULL;
ITaskDefinition* pTaskDefinition = NULL;
IRegistrationInfo* pRegistrationInfo = NULL;
IActionCollection* pActions = NULL;
IAction* Actions = NULL;
hr = pRegisteredTask->get_Name(&taskName);
if (SUCCEEDED(hr))
{
printf("\nTask Name: %S", taskName);
hr = pRegisteredTask->get_State(&taskState);
if (SUCCEEDED(hr))
{
if(taskState == 3)
{
printf("\n\t状态: 准备就绪");
}
else
printf("\n\t状态: 正在运行");
}
else
printf("\n\tCannot get the registered task state: %x", hr);
hr = pRegisteredTask->get_Definition(&pTaskDefinition);
if (SUCCEEDED(hr))
{
hr = pTaskDefinition->get_RegistrationInfo(&pRegistrationInfo);
if (SUCCEEDED(hr))
{
hr = pRegistrationInfo->get_Author(&strname);
if (SUCCEEDED(hr))
{
printf("\n\t: 注册信息:%S", strname);
}
hr = pRegistrationInfo->get_Description(&strname);
if (SUCCEEDED(hr))
{
printf("\n\t: 描述信息:%S", strname);
}
}
}
}
else
{
printf("\nCannot get the registered task name: %x", hr);
}
hr = pRegisteredTask->get_Definition(&pTaskDefinition);
if (SUCCEEDED(hr))
{
hr = pTaskDefinition->get_Actions(&pActions);
if (SUCCEEDED(hr))
{
IExecAction* pExecAction = NULL;
long number = 0;
hr = pActions->get_Count(&number);
if (SUCCEEDED(hr))
{
printf("\n\t: 执行动作数量:%d\n", number);
}
for (int i = 0; i < number; i++)
{
hr = pActions->get_Item(i+1, &Actions);
if (SUCCEEDED(hr))
{
hr = Actions->QueryInterface(IID_IExecAction, (void**)&pExecAction);
if (SUCCEEDED(hr))
{
hr = pExecAction->get_Path(&strname);
if (SUCCEEDED(hr))
{
printf("\n\t: 执行动作:%S ", strname);
bool result = JudgeAction(strname);
if (result)
{
printf("\n\t%S supecious action!!!: %S\n", taskName,strname);
}
}
hr = pExecAction->get_Arguments(&strname);
if (SUCCEEDED(hr) and strname != NULL)
{
printf("%S\n", strname);
}
}
}
}
}
}
pRegisteredTask->Release();
pActions->Release();
}
else
{
printf("\nCannot get the registered task item at index=%d: %x", i + 1, hr);
}
}
pTaskCollection->Release();
CoUninitialize();
return 0;
}
bool JudgeAction(BSTR actionstr)
{
char* action = WtoA(actionstr);
int size = sizeof(FilelessAttack) / sizeof(FilelessAttack[0]);//sizeof其作用是返回一个对象或类型所占的内存字节数,在windows下string是28.即便字符数量超过28,sizeof(A[0])的结果还是为28
for (int i = 0; i < size; i++)
{
if (strstr((const char*)action, FilelessAttack[i]) != NULL)
{
return true;
}
}
return false;
}