C2的心跳设计
红队研发:C2的心跳设计
本文涉及到的技术,仅供红队研究学习
C2中的心跳数据包一般可以认为就是携带了主机元数据信息(基础信息)的网络数据包,比如携带了当前IP,机器名,用户名等。
如果你用c#等高级语言开发,可以把这些信息封装到一个类里面,然后序列化加密传输即可。
public classMetaData
{
private Guid MachineID { get; set; }
privatestring MachineName { get; set; }
privatestring User { get; set; }
privatestring Privilege { get; set; }
privatebool IsAdmin { get; set; }
privatestring InternalIp { get; set; }
privatestring OsVersion { get; set; }
privatestring WindowFormTitle { get; set; }
}里面有些信息比如想获取当前窗口,这种经常变动的字段,每次发送心跳数据的时候重新获取一下就可以了。
在UI上动态显示心跳计时
类似于Cobaltstrike,每个agent都对应一个动态的心跳计时,按每秒动态增加,如果在设置的sleep时间到了,收到了心跳包,那么心跳计时归0,重新开始。
得益于UI数据绑定的机制,在Avalonia或者WPF中我们可以很轻松的实现这个效果。
在之前的文章中,有提到过数据绑定的这个概念,在Avalonia中可以将数据控件和数据模型进行绑定,比如在datagrid中,可以和某个类进行绑定,每列通过绑定不同的类字段,从事实现数据元素的UI显示。
<DataGrid.DataContext>
<model:AgentDisplayModel></model:AgentDisplayModel>
</DataGrid.DataContext>
<DataGrid.Columns>
<DataGridTextColumn Header="computer" Width="11*" Binding="{Binding HostName}"/>
<DataGridTextColumn Header="user" Width="11*" Binding="{Binding UserName}" />
<DataGridTextColumn Header="remote" Width="11*" Binding="{Binding Remote}"/>
<DataGridTextColumn Header="ip" Width="11*" Binding="{Binding InIpAddress}" />
<DataGridTextColumn Header="os" Width="11*" Binding="{Binding OSVersion}"/>
<DataGridTextColumn Header="privilege" Width="11*" Binding="{Binding Privilege}" />
<DataGridTextColumn Header="window" Width="14*" Binding="{Binding CurrentWindow}" />
<DataGridTextColumn Header="last" Width="8*" Binding="{Binding Last}"/>
</DataGrid.Columns>这里我们的datagrid绑定了AgentDisplayModel这个数据模型(类):
public class AgentDisplayModel
{
public Guid Id { get; set; }
public string HostName { get; set; }
public string UserName { get; set; }
public string Remote;
public string InIpAddress { get; set; }
public string OSVersion { get; set; }
public string Privilege { get; set; }
public string CurrentWindow;
public string Last;
}其中Last我们用来显示心跳的部分。
这里还涉及到一个问题,就是我们的心跳数据是一只在变动的,如果像上面这样直接定义一个类然后绑定,后续数据更新的话,UI界面的内容是不会变动的,所以这里又涉及到了一个交叫INotifyPropertyChanged的东西。
在WPF中,INotifyPropertyChanged 是一个接口,用于通知客户端(通常是UI)属性值的变化。它是数据绑定机制的核心组件之一,特别是在MVVM(Model-View-ViewModel)模式中广泛使用
说白了如果你想你的数据动态变化的时候,需要一种机制去通知UI,让UI同时发生变化,这里就用到了这个属性,所以这里我们的类需要继承一下这个接口,并需要声明PropertyChanged事件,实现OnPropertyChanged方法(至于为啥这样,只能说就这流程)
public classAgentDisplayModel:INotifyPropertyChanged
{
public Guid Id { get; set; }
publicstring HostName { get; set; }
publicstring UserName { get; set; }
publicstring Remote { get; set; }
publicstring InIpAddress { get; set; }
publicstring OSVersion { get; set; }
publicstring Privilege { get; set; }
publicstring CurrentWindow;
public DateTime AccessTime;
privatestring _Last;
publicstring Last
{
get { return _Last; }
set { _Last = value; OnPropertyChanged(nameof(Last));}
}
publicevent PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
这里注意多了个AccessTime这个字段,这个用来记录接收到agent心跳时的完整时间。
UI动态变化逻辑有了,现在还需要实现一个心跳递增的逻辑,也即没接收到新的心跳数据的时候,心跳计时每秒递增。
计时器
我们这里可以设定一个每秒触发一次的计时器,这个计时器用来对当前时间和上一次收到心跳数据的AccessTime做比较,计算差值,从而实现心跳递增的效果。
计时器:
TTimer = new System.Timers.Timer(1000);
TTimer.Elapsed += UpdateHeartBeat;
TTimer.AutoReset = true;
TTimer.Enabled = true;
TTimer.Start();计时器函数的逻辑就是一个时间的比较,计算出秒数的差值,并更新到Last这个成员上,这个类成员也是我们绑定在UI上的,这样就实现心跳的效果了:
public void UpdateHeartBeat(Object source, ElapsedEventArgs e)
{
for (int i = 0; i < AgentList.Count; i++)
{
var totalSeconds = (DateTime.UtcNow.ToLocalTime() - AgentList[i].AccessTime).TotalSeconds;
AgentList[i].Last = $"{totalSeconds}s";
}
}AgentList是存储了主机信息的列表,因为我们agent肯定不止一台。

