本文是結合參考資料對CVE-2014-3153的分析,固然各位看官能夠看最後的資料,他們寫的比我好。php
在看CVE-2014-3153以前咱們用參考資料4中例子來熟悉下這類漏洞是如何產生的:html
/** * 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; }
編譯上面的代碼(假設編譯後的可執行文件名爲mylist)並執行
node
$ ./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]的棧地址,故有繼續執行app
$./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值,固然咱們並不會知足於此。ide
另:咱們知道TowelRoot root工具就是利用這個CVE,爲了防止他人拷貝和重打包,使用了O-LLVM來混淆ndk代碼(固然這是另外的課題了,這裏是記錄下,你能夠看譯]使用O-LLVM和NDK對Android應用進行混淆 來熟悉概念)。函數
參考資料:工具
1 CVE-2014-3153 分析以及利用this
3 CVE-2014-3153筆記.net