CVE-2014-3153分析和利用

   本文是结合参考资料对CVE-2014-3153的分析,当然各位看官可以看最后的资料,他们写的比我好。

  在看CVE-2014-3153之前我们用参考资料4中例子来熟悉下这类漏洞是如何产生的:

/**
 * An example of bug that can be exploited through stack manipulation
 * Use -m32 to compile as 32 bit app, so that the int size is the same as pointer size
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct node {
       const char *value;
       struct node *next;
       struct node *prev;
};

struct list {
       struct node *head;
       struct node *tail;
};

void list_add(struct list *lst, struct node *newnode)
{
    if (lst->head==NULL) {
        lst->head = newnode;
        lst->tail = newnode;
    } else {
        newnode->prev = lst->tail;
        lst->tail->next = newnode;
        lst->tail = newnode;
    }
}

struct node * list_remove_last(struct list *lst) 
{
    struct node *result;
    result = lst->tail;

    if (lst->head==lst->tail) { /*zero or 1 element*/
        lst->head = lst->tail = NULL;
    } else  {
        lst->tail = lst->tail->prev;
        lst->tail->next = NULL;
    }
    return result;
}

void list_print(struct list *lst)
{
    struct node *tmp;
    tmp = lst->head;
    while (tmp) {
        printf("Value = %s\n", tmp->value);
        tmp = tmp->next;
    }
}

void list_add_new(struct list *lst, const char *val)
{
    struct node *newnode  = (struct node *)malloc(sizeof(struct node));
    newnode->next = NULL;
    newnode->value = strdup(val);
    list_add(lst, newnode);
}    


void print_with_end_of_list(struct list *lst)
{
    struct node instack;
    instack.next = 0;
    instack.value = "--END OF LIST--";

    printf("Not a buggy function\n");

    list_add(lst, &instack);
    list_print(lst);
    /*we ignore the returned node*/
    list_remove_last(lst);
}


void buggy_print_with_end_of_list(struct list *lst)
{
    int dummy_var1; /*see the article to see why i introduced this*/
    int dummy_var2;
    int dummy_var3;

    struct node instack;

    printf("a buggy function, here is the location of value on stack %p\n", &instack.value);

    instack.next = 0;
    instack.value = "--END OF LIST--";


    list_add(lst, &instack);
    list_print(lst);
    /*we 'forgot' to remove the list element*/

}

void a_function_to_exploit(int element_number, void * value)
{
    int i;
    int buf[10];
    if (element_number==-1) { /*print addressed of buf*/
        for (i=0; i < 10; i++) {
            printf("location of buf[%d] is %p\n", i, &buf[i]);
        }
        return;
    }

    buf[element_number] = (int)value;    

}


int main(int argc, char * argv[])
 {
    struct list mylist;
    mylist.head = NULL;
    mylist.tail = NULL;
    int pos;
    char *val;

    /*we have one parameter*/
    pos = -1;
    if (argc==3) {
        pos = atoi(argv[1]);
        val = argv[2];
    }       

    printf("we will use pos: %d\n", pos);

    list_add_new(&mylist, "Alpha");
    list_add_new(&mylist, "Beta");
    print_with_end_of_list(&mylist);
    buggy_print_with_end_of_list(&mylist);

    a_function_to_exploit(pos, val);

    list_print(&mylist);

    /*this is just a demo, i am skipping the cleanup code*/
    return 0;
}
View Code

 

  编译上面的代码(假设编译后的可执行文件名为mylist)并执行

$ ./mylist 
we will use pos: -1
Not a buggy function
Value = Alpha
Value = Beta
Value = --END OF LIST--
a buggy function, here is the location of value on stack 0xffd724a4
Value = Alpha
Value = Beta
Value = --END OF LIST--
location of buf[0] is 0xffd72488
location of buf[1] is 0xffd7248c
location of buf[2] is 0xffd72490
location of buf[3] is 0xffd72494
location of buf[4] is 0xffd72498
location of buf[5] is 0xffd7249c
location of buf[6] is 0xffd724a0
location of buf[7] is 0xffd724a4
location of buf[8] is 0xffd724a8
location of buf[9] is 0xffd724ac
Value = Alpha
Value = Beta
Value = --END OF LIST--

 

  根据上面的执行结果我们知道buggy_print_with_end_of_list函数新增list的value值的栈地址刚好对应a_function_to_exploit函数中buf[7]的栈地址,故有继续执行

$./mylist 7 HACKED
we will use pos: 7
Not a buggy function
Value = Alpha
Value = Beta
Value = --END OF LIST--
a buggy function, here is the location of value on stack 0xffd3bd34
Value = Alpha
Value = Beta
Value = --END OF LIST--
Value = Alpha
Value = Beta
Value = HACKED

 

  执行结果上面符合,buf[7]存储着“HACKED”字符串的地址,刚好是list.value的地址,所以在最后输出"HACKER“。当然这个是bug,它引用了函数中的局部变量(函数返回后,局部变量的值会被后续的代码覆盖导致,导致重大bug)。这个例子告诉我们可以在类似的bug中我们可以操控list值,当然我们并不会满足于此

  

 

 

 另:我们知道TowelRoot root工具就是利用这个CVE,为了防止他人拷贝和重打包,使用了O-LLVM来混淆ndk代码(当然这是另外的课题了,这里是记录下,你可以看译]使用O-LLVM和NDK对Android应用进行混淆 来熟悉概念)。

 

 

参考资料:

CVE-2014-3153 分析以及利用

2  cve2014-3153 漏洞之详细分析与利用

CVE-2014-3153笔记

Exploiting the Futex Bug and uncovering Towelroot

posted @ 2016-01-22 09:44  vendanner  阅读(1306)  评论(0编辑  收藏  举报