License Project Status: Active – The project has reached a stable, usable state and is being actively developed.

About Elkeid(AgentSmith-HIDS) Driver

Elkeid Driver is a one-of-a-kind Kernel Space HIDS agent designed for Cyber-Security.

Elkeid Driver hooks kernel functions via Kprobe, providing rich and accurate data collection capabilities, including kernel-level process execve probing, privilege escalation monitoring, network audition, and much more. The Driver treats Container-based monitoring as a first-class citizen as Host-based data collection by supporting Linux Namespace. Compare to User Space agents on the market, Elkeid provides more comprehensive information with massive performance improvement.

Elkeid has already been deployed massively for HIDS usage in world-class production environments. With its marvelous data collection ability, Elkeid also supports Sandbox, Honeypot, and Audition data requirements.

Notice

DO NOT insmod the ko in the production machines if you have not well tested it.

Quick Test

First you need install Linux Headers

# clone and build
git clone https://github.com/bytedance/Elkeid.git
cd Elkeid/driver/LKM/
make clean && make
< CentOS only: run build script instead >
sh ./centos_build_ko.sh

# load and test (should run as root)
insmod hids_driver.ko
dmesg | tail -n 20
test/rst -q
< "CTRL + C" to quit >

# unload
rmmod hids_driver

Pre-build Ko

How To Get

If all urls failed, please build elkeid kernel module yourself.

wget "http://lf26-elkeid.bytetos.com/obj/elkeid-download/ko/hids_driver_1.7.0.10_$(uname -r)_amd64.ko"

How to Test

You can test the kernel module with LTP (better with KASAN turned on). Here's the LTP-test-case configuration file for your reference: LTP-test-case.

About the compatibility with Linux distributions

DistroVersionx64 kernelSuffix
Debian8,9,103.16~5.4.X-
Ubuntu14.04,16.04,18.04,20.043.12~5.4.Xgeneric
CentOS6.X,7.X,8.X2.6.32.0~5.4.Xel6,el7,el8
Amazon24.9.X~4.14.Xamzn2
AlibabaCloudLinux34.19.X~5.10.Xal7,al8
EulerOSV2.03.10.X-

About ARM64 (AArch64) Support

  • Yes

About the compatibility with Kernel versions

  • Linux Kernel Version >= 2.6.32 && <= 6.3

About the compatibility with Containers

SourceNodename
Hosthostname
Dockercontainer name
K8spod name

Hook List

HookDataTypeNoteDefault
write1OFF
open2OFF
mprotect10only PROT_EXECOFF
nanosleep35OFF
connect42ON
accept43OFF
bind49ON
execve59ON
process exit60OFF
kill62OFF
rename82ON
link86ON
ptrace101only PTRACE_POKETEXT or PTRACE_POKEDATAON
setsid112ON
prctl157only PR_SET_NAMEON
mount165ON
tkill200OFF
exit_group231OFF
memfd_create356ON
dns query601ON
create_file602ON
load_module603ON
update_cred604only old uid ≠0 && new uid == 0ON
unlink605OFF
rmdir606OFF
call_usermodehelper_exec607ON
file_write608OFF
file_read609OFF
usb_device_event610ON
privilege_escalation611ON
port-scan detection612tunable via module param: psad_switchOFF

Anti Rootkit List

RootkitDataTypeDefault
interrupt table hook703ON
syscall table hook701ON
proc file hook700ON
hidden kernel module702ON

Driver TransData Pattern

Data Protocol

Every hit of the hook-points above will generate a record, and the records are separated by deliminator '\x17'.

Each record contains several data items, which are separated by deliminator '\x1e'.

A record generally contains Common Data and Private Data, with the exception of Anti-rootkit, which does NOT have Common Data.

Common Data

-------------------------------------------------------------------------------
|1        |2  |3  |4  |5   |6   |7   |8  |9   |10      |11       |12 |13      |
-------------------------------------------------------------------------------
|data_type|uid|exe|pid|ppid|pgid|tgid|sid|comm|nodename|sessionid|pns|root_pns|
-------------------------------------------------------------------------------

Write Data (1)

-----------
|14   |15 | 
-----------
|file||buf|
-----------

Open Data (2)

---------------------
|14   |15  |16      | 
---------------------
|flags|mode|filename|
---------------------

Mprotect Data (10)

-----------------------------------------------------
|14           |15       |16        |17     |18      |
-----------------------------------------------------
|mprotect_prot|owner_pid|owner_file|vm_file|pid_tree|
-----------------------------------------------------

Nanosleep Data (35)

----------
|14 |15  |
----------
|sec|nsec|
----------

Connect Data (42)

-----------------------------------
|14       |15 |16   |17 |18   |19 |
-----------------------------------
|sa_family|dip|dport|sip|sport|res|
-----------------------------------

Accept Data (43)

-----------------------------------
|14       |15 |16   |17 |18   |19 |
-----------------------------------
|sa_family|dip|dport|sip|sport|res|
-----------------------------------

Bind Data (49)

-------------------------
|14       |15 |16   |17 |
-------------------------
|sa_family|sip|sport|res|
-------------------------

Execve Data (59)

-----------------------------------------------------------------------------------------------------
|14  |15      |16   |17    |18 |19   |20 |21   |22       |23      |24 |25        |26 |27        |28 |
-----------------------------------------------------------------------------------------------------
|argv|run_path|stdin|stdout|dip|dport|sip|sport|sa_family|pid_tree|tty|socket_pid|ssh|ld_preload|res|
-----------------------------------------------------------------------------------------------------

Note:

  • socket_exe/dip/dport/sip/sport/sa_family is collected from the process's fds

  • ssh/ld_preload is collected from the process's env

Process Exit Data (60)

Only contains fields in Common Data

Kill Data (62)

----------------
|14        |15 |
----------------
|target_pid|sig|
----------------

Rename Data (82)

-------------------------
|14      |15      |16   |
-------------------------
|old_name|new_name|sb_id|
-------------------------
-------------------------
|14      |15      |16   |
-------------------------
|old_name|new_name|sb_id|
-------------------------

Ptrace Data (101)

----------------------------------------------
|14            |15        |16  |17  |18      |
----------------------------------------------
|ptrace_request|target_pid|addr|data|pid_tree|
----------------------------------------------

Setsid Data (112)

Only contains fields in Common Data

Prctl Data (157)

_________________
|14    |15      | 
-----------------
|option|new_name|
-----------------

Mount Data (165)

_____________________________________
|14      |15 |16       |17    |18   | 
-------------------------------------
|pid_tree|dev|file_path|fstype|flags|
-------------------------------------

Tkill data (200)

----------------
|14        |15 |
----------------
|target_pid|sig|
----------------

Exit Group Data (231)

Only contains fields in Common Data

Memfd Create Data (356)

______________
|14    |15   | 
--------------
|fdname|flags|
--------------

Dns Query Data (601)

--------------------------------------------------
|14   |15       |16 |17   |18 |19   |20    |21   |
--------------------------------------------------
|query|sa_family|dip|dport|sip|sport|opcode|rcode|
--------------------------------------------------

Create File data (602)

----------------------------------------------------------
|14 	  |15 |16   |17 |18   |19       |20        |21   |
----------------------------------------------------------
|file_path|dip|dport|sip|sport|sa_family|socket_pid|sb_id|
----------------------------------------------------------

Load Module Data (603)

---------------------------
|14      |15      |16     |
---------------------------
|ko_file|pid_tree|run_path|
---------------------------

Update Cred Data (604)

----------------------
|14      |15     |16 | 
----------------------
|pid_tree|old_uid|res|
----------------------
------
|14  |
------
|file|
------

Rmdir Data (606)

------
|14  |
------
|file|
------

call_usermodehelper_exec Data (607)

-------------------------
|1        |2  |3   |4   |
-------------------------
|data_type|exe|argv|wait|
-------------------------

File Write Data (608)

------------
|14  |15   |
------------
|file|sb_id|
------------
Need to join the to-watch list through Diver Filter, see "About Driver Filter" section for details

File Read Data (609)

------------
|14  |15   |
------------
|file|sb_id|
------------
Need to join the to-watch list through Diver Filter, see "About Driver Filter" section for details

USB Device Event Data (610)

-----------------------------------------
|14          |15          |16    |17    |
-----------------------------------------
|product_info|manufacturer|serial|action|
-----------------------------------------
action = 1 is USB_DEVICE_ADD
action = 2 is USB_DEVICE_REMOVE

Privilege Escalation (611)

------------------------------
|14   |15      |16    |17    |
------------------------------
|p_pid|pid_tree|p_cred|c_cred|
------------------------------
p_cred = uid|euid|suid|fsuid|gid|egid|sgid|fsgid
c_cred = uid|euid|suid|fsuid|gid|egid|sgid|fsgid

Port-scan attack detection (612)

------------------------------------------
|1   |2        |3  |4    |5  |6    |7    |
------------------------------------------
|type|sa_family|sip|sport|dip|dport|flags|
------------------------------------------

Proc File Hook (700)

-----------------------
|1        |2          |
-----------------------
|data_type|module_name|
-----------------------

Syscall Table Hook Data (701)

--------------------------------------
|1        |2          |3             |
--------------------------------------
|data_type|module_name|syscall_number|
--------------------------------------

Hidden Kernel Module Data (702)

-----------------------
|1        |2          |
-----------------------
|data_type|module_name|
-----------------------

Interrupt Table Hook Data (703)

----------------------------------------
|1        |2          |3               |
----------------------------------------
|data_type|module_name|interrupt_number|
----------------------------------------

About Driver Filter

Elkeid driver supports allowlist to filter out unwanted data. We provide two types of allowlists, 'exe' allowlist and 'argv' allowlist. 'exe' allowlist acts on execve/create file/dns query/connect hooks, while 'argv' allowlist only acts on execve hook. For performance and stability concerns, both 'exe' and 'argv' allowlist only supports 64-elements-wide capacity.

allowlist driver is in: /dev/hids_driver_allowlist

OperationsFlagExample
ADD_EXECVE_EXE_SHITELISTY(89)echo Y/bin/ls > /dev/someone_allowlist
DEL_EXECVE_EXE_SHITELISTF(70)echo F/bin/ls > /dev/someone_allowlist
DEL_ALL_EXECVE_EXE_SHITELISTw(119)echo w/del_all > /dev/someone_allowlist
EXECVE_EXE_CHECKy(121)echo y/bin/ls > /dev/someone_allowlist && dmesg
ADD_EXECVE_ARGV_SHITELISTm(109)echo m/bin/ls -l > /dev/someone_allowlist
DEL_EXECVE_ARGV_SHITELISTJ(74)echo J/bin/ls -l > /dev/someone_allowlist
DEL_ALL_EXECVE_ARGV_SHITELISTu(117)echo u/del_all > /dev/someone_allowlist
EXECVE_ARGV_CHECKz(122)echo z/bin/ls -l > /dev/someone_allowlist && dmesg
PRINT_ALL_ALLOWLIST.(46)echo ./print_all > /dev/someone_allowlist && dmesg
ADD_WRITE_NOTIFIW(87)echo W/etc/passwd > /dev/someone_allowlist or echo W/etc/ssh/ > /dev/someone_allowlist support dir
DEL_WRITE_NOTIFIv(120)echo v/etc/passwd > /dev/someone_allowlist
ADD_READ_NOTIFIR(82)echo R/etc/passwd > /dev/someone_allowlist or echo R/etc/ssh/ > /dev/someone_allowlist support dir
DEL_READ_NOTIFIs(115)echo s/etc/passwd > /dev/someone_allowlist
DEL_ALL_NOTIFIA(65)echo A/del_all_file_notift > /dev/someone_allowlist

Filter define is:

#define ADD_EXECVE_EXE_SHITELIST 89         /* Y */
#define DEL_EXECVE_EXE_SHITELIST 70         /* F */
#define DEL_ALL_EXECVE_EXE_SHITELIST 119    /* w */
#define EXECVE_EXE_CHECK 121                /* y */
#define PRINT_ALL_ALLOWLIST 46              /* . */
#define ADD_EXECVE_ARGV_SHITELIST 109       /* m */
#define DEL_EXECVE_ARGV_SHITELIST 74        /* J */
#define DEL_ALL_EXECVE_ARGV_SHITELIST 117   /* u */
#define EXECVE_ARGV_CHECK 122               /* z */

#define ADD_WRITE_NOTIFI 87                 /* W */
#define DEL_WRITE_NOTIFI 120                /* v */
#define ADD_READ_NOTIFI 82                  /* R */
#define DEL_READ_NOTIFI 115                 /* s */
#define DEL_ALL_NOTIFI 65                   /* A */

Performance Stats of Elkeid Driver

Testing Environment(VM):

CPUIntel(R) Xeon(R) Platinum 8260 CPU @ 2.40GHz 8 Core
RAM16GB
OS/KernelDebian9 / Kernel Version 4.14

Testing Load:

syscallltp
connect./runltp -f syscalls -s connect -t 5m
bind./runltp -f syscalls -s bind -t 5m
execve./runltp -f syscalls -s execve -t 5m
security_inode_create./runltp -f syscalls -s open -t 5m
ptrace./runltp -f syscalls -s ptrace -t 5m

Key kprobe Handler Testing Result(90s)

hook function nameAverage Delay(us)TP99(us)TP95(us)TP90(us)
connect_syscall_handler0.74543.50171.9041.43
connect_syscall_entry_handler0.06750.30.1630.1149
udp_recvmsg_handler9.129068.704318.535715.9528
udp_recvmsg_entry_handler0.58827.56310.78110.3665
bind_handler2.255810.05258.19967.041
bind_entry_handler0.47041.01800.82340.6739
execve_entry_handler6.926212.28249.4378.638
execve_handler15.210236.090325.927223.068
security_inode_create_pre_handler1.55237.94545.58063.1441
ptrace_pre_handler0.20390.46480.2540.228

udp_recvmsg_handler will work only if the port is equal 53 or 5353

Original Testing Data: Benchmark Data

About Deploy

You can use DKMS or Pre-packaged ko file

  • install driver: insmod hids_driver.ko
  • remove driver: first you need kill userspace agent and rmmod hids_driver.ko

Known Bugs

License

Elkeid kernel module are distributed under the GNU GPLv2 license.