sicurezza informatica · 2017. 10. 11. · push operation (1 of 2) • a 32-bit push operation...

48
Sicurezza Informatica Lez. 2 Assembler (II parte) A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Upload: others

Post on 22-Aug-2021

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Sicurezza Informatica

Lez. 2 Assembler (II parte)

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 2: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Memory Layout

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 3: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Memory Layout

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 4: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Stack

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 5: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Where is stored msg?

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 6: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Why on the stack and not in .data?

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 7: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Executable structure

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 8: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 9: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Stack

•  Many CPU’s have built-in support for a stack A stack is a Last-In First-Out (LIFO) list

•  The stack is an area of memory that is organized in this fashion. The PUSH instruction adds data to the stack and the POP instruction removes data

•  The data removed is always the last data added •  The ESP register contains the address of the data that would be

removed from the stack. This data is said to be at the top of the stack •  The processor references the SS register automatically for all stack

operations. Also, the CALL, RET, PUSH, POP, ENTER, and LEAVE instructions all perform operations on the current stack.

•  Data can only be added in double word units. That is, one can not push a single byte on the stack

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 10: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Stack

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 11: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Runtime Stack

•  Managed by the CPU, using two registers •  SS (stack segment) •  ESP (stack pointer) *

* SP in Real-address mode

00000006 ESP00001000

Offset

00000FF8

00000FF4

00000FF0

00000FFC

Page 12: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

PUSH

•  The PUSH instruction inserts a double word on the stack by subtracting 4 from ESP and then stores the double word at [ESP]

!

•  The 80x86 also provides a PUSHA instruction that pushes the values of EAX, EBX, ECX, EDX, ESI, EDI and EBP registers (not in this order)

pushl src ! à !subl $4,%esp!! ! ! ! !movl src,(%esp)!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 13: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

PUSH Operation (1 of 2) •  A 32-bit push operation decrements the stack pointer

by 4 and copies a value into the location pointed to by the stack pointer.

00000006 00000006

ESP

00001000

00000FFC

00000FF8

00000FF4

00000FF0

000000A5

ESP00001000

BEFORE

00000FFC

00000FF8

00000FF4

00000FF0

AFTER

Page 14: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

PUSH Operation (2 of 2) •  This is the same stack, after pushing two more

integers:

00000006

ESP

00001000

Offset

00000FFC

00000FF8

00000FF4

00000FF0

000000A5

00000001

00000002

The stack grows downward. The area below ESP is always available (unless the stack has overflowed).

Page 15: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

POP

•  The POP instruction reads the double word at [ESP] and then adds 4 to ESP

•  The popa instruction, recovers the original values of the registers saved by the pusha!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

!popl dest ! à movl (%esp),dest!! ! ! ! addl $4,%esp!

Page 16: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

POP Operation •  Copies value at stack[ESP] into a register or variable. •  Adds n to ESP, where n is either 2 or 4.

•  depends on the operand receiving the data

BEFORE AFTER

00000006

000000A5

00000001

00000002 ESP

00000006

000000A5

00000001 ESP

00001000

00000FFC

00000FF8

00000FF4

00000FF0

00001000

00000FFC

00000FF8

00000FF4

00000FF0

Page 17: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Esercizio

•  Scrivere un programma in assembler che inverte il contenuto di una stringa data.

•  Esempio: •  Data la stringa: Hello World! •  Stampa la stringa: !dlroW olleH

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 18: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Function call

•  Calling and returning •  How does caller function jump to callee function? •  How does callee function jump back to the right place in caller

function? •  Passing parameters

•  How does caller function pass parameters to callee function? •  Storing local variables

•  Where does callee function store its local variables? •  Handling registers

•  How do caller and callee functions use same registers without interference?

•  Returning a value •  How does callee function send return value back to caller function?

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 19: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Calling and returning

•  How does caller function jump to callee function? •  I.e., Jump to the address of the callee’s first instruction

•  How does the callee function jump back to the right place in caller function?

•  Jump to the instruction immediately following the most-recently-executed call instruction

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 20: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

CALL/RET

•  The 80x86 provides two instructions that use the stack to make calling subprograms quick and easy. The CALL instruction makes an unconditional jump to a subprogram and pushes the address of the next instruction on the stack.

•  The RET instruction pops off an address and jumps to that address.

•  When using these instructions, it is very important that one manage the stack correctly so that the right number is popped off by the RET instruction

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 21: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Implementation of Call

•  call subprogram1 becomes:!pushl %eip!jmp subprogram1 !!!!!ESP à!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Saved EIP!

Page 22: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Implementation of ret

•  ret becomes:!•  pop %eip!

• ESP à!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Saved EIP!

Page 23: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Passing Parameters

•  How does caller function pass parameters to callee function?

•  Attempted solution: Pass parameters in registers •  Problem: Cannot handle nested function calls •  Also: How to pass parameters that are longer than 4 bytes?

•  Caller pushes parameters before executing the call instruction

•  Parameters are pushed in the reverse order •  Push the nth parameter first •  Push 1° parameter last

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 24: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Parameter

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!ESP before à call

Page 25: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Parameter

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!

Saved EIP!ESP after à call

Callee addresses params relative to ESP: Param 1 as 4(%esp)

Page 26: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Parameter

•  After returning to the caller, the caller pops the parameters from the stack !… ! ! ! !sub:!# Push parameters ! !…!pushl $5 ! ! !movl 4(%esp),var1!pushl $4 ! ! !movl 8(%esp),var2!pushl $3 ! ! !movl 12(%esp), var3!call sub ! ! !…!# Pop parameters ! !ret!addl $12, %esp!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 27: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

%ebp

•  As callee executes, ESP may change •  E.g., preparing to call another function

•  It can be very error prone to use ESP when referencing parameters. To solve this problem, the 80386 supplies another register to use: EBP. This register’s only purpose is to reference data on the stack

•  Use EBP as fixed reference point to access params

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 28: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Using EBP (prolog)

•  A subprogram before overwriting ebp first save the old value of EBP on the stack and then set EBP to be equal to ESP. This allows ESP to change as data is pushed or popped off the stack without modifying EBP

pushl %ebp!! !movl !%esp, %ebp!! !(sub !Local_bytes, %esp)!

•  Regardless of ESP, the subprogram can reference param 1 as 8(%ebp), param 2 as 12(%ebp), etc.

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 29: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Using ebp (epilog)

•  Before returning, callee must restore ESP and EBP to their old values executing the epilog

movl %ebp, %esp!popl %ebp!ret!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 30: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Enter/Leave

•  The ENTER instruction performs the prologue code and the LEAVE performs the epilogue

•  The ENTER instruction takes two immediate operands. •  For the C calling convention, the second operand is always 0.

The first operand is the number bytes needed by local variables. The LEAVE instruction has no operands

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 31: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Epilogo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!

Saved EIP!

Old EBP!Ebp à

Esp à

movl %ebp, %esp popl %ebp ret

à

Page 32: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Epilogo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!

Saved EIP!

Old EBP!Esp = Ebp à movl %ebp, %esp popl %ebp ret

à

Page 33: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Epilogo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!

Saved EIP!Esp à movl %ebp, %esp popl %ebp ret

à

Ebp à

Page 34: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Epilogo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Parameter n!

Parameter …!

Parameter 1!Esp à

movl %ebp, %esp popl %ebp ret à

Ebp à

Page 35: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Storing local variables •  Where does callee function store its local variables? •  Local variables:

•  Short-lived, so don’t need a permanent location in Memory •  Size known in advance, so don’t need to allocate on the

heap

•  The function just uses the top of the stack •  Local variables of the callee are allocated on the

stack by moving the stack pointer •  subl $8,%esp #allocate memory for 2 integers!

•  Reference local variables as negative offsets relative to EBP!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 36: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Registers Handling

•  How do caller and callee functions use same registers without interference?

•  Callee may use a register that the caller also is using •  Solution: save the registers on the stack

•  Someone must save old register contents •  Someone must later restore the register contents

•  Define a convention for who saves and restores which registers

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 37: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Registers handling

•  Caller-save registers EAX, EBX, ECX … (when necessary…) •  Saves on stack before call •  Restores from stack after call

•  Callee-save registers EAX, EBX, ECX … (when necessary) •  Saves on stack after prolog •  Restores from stack before epilog

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 38: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Stack Frame

•  Any active function has its own stack frame •  Stack frame contains:

•  Return address (Saved EIP) •  Old EBP •  Saved register values •  Local variables •  Parameters to be passed to callee function

•  ESP points to top (low memory) of current stack frame

•  EBP points to bottom (high memory) of current stack frame

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 39: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Esempio: stack.c

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

#include <stdio.h>!int main() {!

!int x = foo( 10 );!!printf( "the value of x = %d\n", x );!!return 0;!!}!

int foo( int i ) {!!int ii = i + i;!!int iii = bar( ii );!!int iiii = iii;!!return iiii;!!}!

int bar( int j ) {!!int jj = j + j;!!return jj;!!}!

Compiliamo con il comando gcc –S stack.c - o stack.s!

Page 40: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Lo stack che ci aspettiamo

jj

Ret. Addr. foo

j

iiii

iii ii

Ret. Addr. main

i

x

ESP à

bar

foo

main A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Saved EBP

Saved EBP

Page 41: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Assembler: main

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

.file "stack.c"! .section .rodata!.LC0:! .string "the value of x = %d\n"! .text!.globl main! .type main, @function!main:! leal 4(%esp), %ecx! andl $-16, %esp! pushl -4(%ecx)! pushl %ebp! movl %esp, %ebp! pushl %ecx! subl $36, %esp! movl $10, (%esp)! call foo! movl %eax, -8(%ebp)! movl -8(%ebp), %eax! movl %eax, 4(%esp)! movl $.LC0, (%esp)! call printf! movl $0, %eax! addl $36, %esp! popl %ecx! popl %ebp!

Page 42: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Assembler : foo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

.globl foo! .type foo, @function!foo:! pushl %ebp! movl %esp, %ebp! subl $24, %esp! movl 8(%ebp), %eax! addl %eax, %eax! movl %eax, -12(%ebp)! movl -12(%ebp), %eax! movl %eax, (%esp)! call bar! movl %eax, -8(%ebp)! movl -8(%ebp), %eax! movl %eax, -4(%ebp)! movl -4(%ebp), %eax! leave! ret! .size foo, .-foo!

Page 43: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Assembler: foo

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

.globl bar! .type bar, @function!bar:! pushl %ebp! movl %esp, %ebp! subl $16, %esp! movl 8(%ebp), %eax! addl %eax, %eax! movl %eax, -4(%ebp)! movl -4(%ebp), %eax! leave! ret! .size bar, .-bar!

Page 44: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Compilazione ottimizzata

Non Ottimizzata

.globl bar! .type bar, @function!bar:! pushl %ebp! movl %esp, %ebp! subl $16, %esp! movl 8(%ebp), %eax! addl %eax, %eax! movl %eax, -4(%ebp)! movl -4(%ebp), %eax! leave! ret! .

Ottimizzata

.globl bar! .type bar,@function!bar:! pushl %ebp! movl %esp, %ebp! movl 8(%ebp), %eax! addl %eax, %eax! popl %ebp! ret! !

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 45: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Compilazione ottimizzata

Non Ottimizzata .globl foo! .type foo, @function!foo:!

pushl %ebp! movl %esp, %ebp! subl $24, %esp! movl 8(%ebp), %eax! addl %eax, %eax! movl %eax, -12(%ebp)!

movl -12(%ebp), %eax! movl %eax, (%esp)! call bar! movl %eax, -8(%ebp)! movl -8(%ebp), %eax! movl %eax, -4(%ebp)!

movl -4(%ebp), %eax! leave! ret!

Ottimizzata .globl foo! .type foo, @function!foo:! pushl %ebp! movl %esp, %ebp! subl $4, %esp! movl 8(%ebp), %eax! addl %eax, %eax! movl %eax, (%esp)! call bar! leave! ret!

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 46: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

Esercizio

•  Risolvere i seguenti esercizi e descrivere quali sono i principi di funzionamento della soluzione adottata

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Page 47: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Esercizio 1

/* stack1-stdin.c *! * specially crafted to feed your brain by gera

InsecureProgramming */!!#include <stdio.h>!!int main() {!!int cookie;!!char buf[80];!

!!printf("buf: %08x cookie: %08x\n", &buf, &cookie);!!gets(buf);!

!!if (cookie == 0x41424344)!! !printf("you win!\n");!

}!

Page 48: Sicurezza Informatica · 2017. 10. 11. · PUSH Operation (1 of 2) • A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location pointed to by

A.A. 2013/2014 Sicurezza Informatica © Danilo Bruschi

Esercizio 2

/* stack2-stdin.c *! * specially crafted to feed your brain by gera */!!#include <stdio.h>!!int main() {!!int cookie;!!char buf[80];!

!!printf("buf: %08x cookie: %08x\n", &buf, &cookie);!!gets(buf);!

!!if (cookie == 0x01020305)!

! !printf("you win!\n");!}!