Bitdefender Hypervisor Memory Introspection
deploy.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "../common.h"
6 
7 typedef void * (filp_open_fn)(const char *filename, int flags, unsigned short mode);
8 typedef int (filp_close_fn)(void *filp, void *id);
9 typedef void * (vmalloc_fn)(unsigned long size);
10 typedef unsigned int (__kernel_write_fn)(void *file, const void *buf, unsigned int count, long long *pos);
11 typedef int (kernel_write_fn)(void *file, const char *buf, size_t count, unsigned long pos);
12 typedef void (vfree_fn)(void *ptr);
13 typedef char ** (argv_split_fn)(unsigned int gfp, const char *str, int *argcp);
14 typedef void (argv_free_fn)(char **argv);
15 typedef void *(call_usermodehelper_setup_fn)(const char *path, char **argv, char **envp, unsigned long gfp_mask,
16  int (*init)(void *info, void *new), void (*cleanup)(void *info), void *data);
17 typedef int (call_usermodehelper_exec_fn)(void *sub_info, int wait);
18 typedef void (do_exit_fn)(long code);
19 typedef int (printk_fn)(const char *fmt, ...);
20 
21 #pragma pack(push, 1)
22 struct data {
24  struct {
25  unsigned long hypercall;
26  unsigned long completion;
27  unsigned long error;
28  } token;
29 
31  struct {
44  } func;
45 
47  struct {
48  unsigned long kernel_version;
49 
50  unsigned long vmalloc_size;
51  char root[1];
52  char name[128];
53 
54  struct {
55  unsigned long wait_proc;
56  unsigned long wait_exec;
57  } umh;
58  } args;
59 };
60 
61 #pragma pack(pop)
62 
64 struct data _data __section(".adata") __aligned(1) = { 0 };
65 
66 extern void *__address;
67 
69 int call_usermodehelper(const char *path, char **argv, char **envp, unsigned int wait)
70 {
71  unsigned long gfp_mask = GFP_KERNEL;
72  void *info = _data.func.call_usermodehelper_setup(path, argv, envp, gfp_mask, NULL, NULL, NULL);
73  if (!info)
74  {
75  breakpoint_2(_data.token.error, _data.func.call_usermodehelper_setup, info);
76  return -1;
77  }
78 
79  return _data.func.call_usermodehelper_exec(info, wait);
80 }
81 
82 
84 void deploy(void)
90 {
91  int ret = 0;
92  void *file = _data.func.filp_open(_data.args.root, O_CREAT | O_RDWR | O_TRUNC, 0400);
93  if (IS_ERR_VALUE(file))
94  {
95  breakpoint_1(_data.token.error, _data.func.filp_open);
96  return;
97  }
98 
99  void *ptr = _data.func.vmalloc(_data.args.vmalloc_size);
100  if (!ptr)
101  {
102  breakpoint_1(_data.token.error, _data.func.vmalloc);
103  goto _exit;
104  }
105 
106  unsigned int count = 0;
107  long long pos = 0;
108  do
109  {
110  count = breakpoint_1(_data.token.hypercall, ptr);
111  if (count == 0)
112  {
113  break;
114  }
115 
116  if (_data.args.kernel_version <= KERNEL_VERSION(2, 6, 72))
117  {
118  ret = _data.func.kernel_write(file, ptr, count, pos);
119  if (ret < 0)
120  {
121  breakpoint_1(_data.token.error, _data.func.__kernel_write);
122  goto _exit;
123  }
124 
125  pos += ret;
126  }
127  else
128  {
129  ret = _data.func.__kernel_write(file, ptr, count, &pos);
130  if (ret < 0)
131  {
132  breakpoint_1(_data.token.error, _data.func.__kernel_write);
133  goto _exit;
134  }
135  }
136  } while (count);
137 
138  breakpoint(_data.token.completion);
139 
140 _exit:
141  if (file)
142  {
143  _data.func.filp_close(file, 0);
144  }
145 
146  if (ptr)
147  {
148  _data.func.vfree(ptr);
149  }
150 
151  if (ret < 0)
152  {
153  char *argv_remove[4];
154  argv_remove[0] = "/bin/rm";
155  argv_remove[1] = "-f";
156  argv_remove[2] = _data.args.root;
157  argv_remove[3] = NULL;
158 
159  char *envp[4];
160  envp[0] = "HOME=/";
161  envp[1] = "TERM=linux";
162  envp[2] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
163  envp[3] = NULL;
164 
165  call_usermodehelper(argv_remove[0], argv_remove, envp, _data.args.umh.wait_exec);
166  }
167 }
168 
169 
170 __fn_naked __section(".start")
171 void trampoline(void)
179 {
180  deploy();
181 
182  __exit;
183  __do_exit(__address, _data.func.do_exit, _data.func.vfree);
184 }
#define O_CREAT
Definition: common.h:20
__default_fn_attr int call_usermodehelper(const char *path, char **argv, char **envp, unsigned int wait)
Definition: deploy.c:69
struct data::@2 args
The arguments of the agent.
unsigned long kernel_version
The version of the kernel.
Definition: deploy.c:48
#define KERNEL_VERSION(K, Patch, Sublevel)
Definition: common.h:60
struct data::@0 token
The tokens used to communicate with Intocore.
call_usermodehelper_exec_fn * call_usermodehelper_exec
Definition: deploy.c:41
unsigned long hypercall
Definition: kthread.c:17
kernel_write_fn * kernel_write
Definition: deploy.c:34
char root[1]
The root path; allways &#39;/&#39;.
Definition: deploy.c:51
static __default_fn_attr unsigned long breakpoint(unsigned long token)
Generate INT3 instruction for hypercall.
Definition: common.h:167
int() kernel_write_fn(void *file, const char *buf, size_t count, unsigned long pos)
Definition: deploy.c:11
#define GFP_KERNEL
Definition: common.h:15
#define IS_ERR_VALUE(x)
Definition: common.h:66
#define O_RDWR
Definition: common.h:19
void *() vmalloc_fn(unsigned long size)
Definition: deploy.c:9
__default_fn_attr void init(void)
Allocates memory for detours and agents.
Definition: init.c:15
int() filp_close_fn(void *filp, void *id)
Definition: deploy.c:8
call_usermodehelper_setup_fn * call_usermodehelper_setup
Definition: deploy.c:40
#define __fn_naked
Definition: common.h:79
#define __exit
Generates the exit asm-code for agents.
Definition: common.h:120
#define __section(S)
Definition: common.h:76
#define breakpoint_1(token, p1)
Hypercall using 1 argument.
Definition: common.h:177
unsigned long wait_proc
The value of UMH_WAIT_PROC.
Definition: deploy.c:55
filp_close_fn * filp_close
Definition: deploy.c:33
#define __default_fn_attr
Definition: common.h:78
#define breakpoint_2(token, p1, p2)
Hypercall using 2 argument.
Definition: common.h:185
char name[128]
The name of the deployed file.
Definition: deploy.c:52
#define O_TRUNC
Definition: common.h:22
filp_open_fn * filp_open
Definition: deploy.c:32
void * __address
int() call_usermodehelper_exec_fn(void *sub_info, int wait)
Definition: deploy.c:17
unsigned long wait_exec
The value of UMH_WAIT_EXEC.
Definition: deploy.c:56
struct data::@5::@6 umh
__kernel_write_fn * __kernel_write
Definition: deploy.c:35
struct data _data __aligned(1)
The section used for this agent is .adata&#39;.
struct data::@1 func
The functions used by this agent.
unsigned long vmalloc_size
The size of allocation.
Definition: kthread.c:32
unsigned int() __kernel_write_fn(void *file, const void *buf, unsigned int count, long long *pos)
Definition: deploy.c:10
argv_split_fn * argv_split
Definition: deploy.c:38
void() argv_free_fn(char **argv)
Definition: deploy.c:14
void() do_exit_fn(long code)
Definition: deploy.c:18
unsigned long completion
Definition: kthread.c:18
void *() call_usermodehelper_setup_fn(const char *path, char **argv, char **envp, unsigned long gfp_mask, int(*init)(void *info, void *new), void(*cleanup)(void *info), void *data)
Definition: deploy.c:15
vfree_fn * vfree
Definition: deploy.c:37
#define __do_exit(address, do_exit_fn, vfree_fn)
Pushes the exit address on the stack and jumps to the &#39;do_exit&#39; function in order to terminate the th...
Definition: common.h:126
__default_fn_attr void deploy(void)
Creates a file using the provided name and writes the content given by Introcore in the file...
Definition: deploy.c:84
do_exit_fn * do_exit
Definition: deploy.c:42
unsigned long error
Definition: kthread.c:19
__fn_naked void trampoline(void)
The trampoline of the agent.
Definition: deploy.c:171
vmalloc_fn * vmalloc
Definition: deploy.c:36
argv_free_fn * argv_free
Definition: deploy.c:39
int() printk_fn(const char *fmt,...)
Definition: deploy.c:19
char **() argv_split_fn(unsigned int gfp, const char *str, int *argcp)
Definition: deploy.c:13
Definition: kthread.c:14
printk_fn * printk
Definition: deploy.c:43
void *() filp_open_fn(const char *filename, int flags, unsigned short mode)
Definition: deploy.c:7
void() vfree_fn(void *ptr)
Definition: deploy.c:12