Start page: ARABART home
← All fifteen programs

KVC: Kemyam Virus Capture

1993 · C:\KVC\KVC.EXE

C:\KVC\KVC.EXE
KVC: Kemyam Virus Capture running in DOS

Loading KVC.EXE, 11 KB

Click the screen to type into the program.

An antivirus for Koko, an Egyptian virus that wiped hard drives and that no scanner on the market could find. KVC knows it byte by byte.

The story

No antivirus on the market could see Koko, a virus that was wiping hard disks across Egypt. KVC could. Version 1.05 asks the virus a question only Koko answers, then freezes it in memory without a restart. It repairs each program from the original bytes Koko carried inside itself. Its help screen promises a free new version for every new virus.

The virus no scanner could see

In 1993 a virus called Koko was spreading across PCs in Egypt, and it could wipe a hard disk. No antivirus on the market could find it. So Yasser and Ebrahim El-Etr took it apart by hand, learned its secrets, and turned them against it.

Koko lived in memory. Run one infected program and Koko stayed behind, like a background service that never stops. From then on it slipped a copy of itself into every program the PC ran. It signed each one with its name, KoKo (1). Most days it did nothing else you could see. Two days a year, it struck.

How Koko took over a PC
A PC's memory with slot 21h, slot 3, Koko and DOS, and a disk with three programs. Koko takes over slot 21h, stamps every program, and on July 29 the disk loses its data. MEMORY slot 21h → DOS→ Koko slot 3 unused→ DOS DOS Kokostays in memory DISK GAME.COM KoKo(1) WP.EXE KoKo(1) SHEET.EXE KoKo(1) the infected one data lost FEB 17the warning JUL 29disk wiped
Koko takes over slot 21h in memory, stamps every program on the disk, and wipes the disk on July 29. MEMORY slot 21h → DOS→ Koko slot 3 unused→ DOS Koko DOS DISK GAME.COM KoKo (1) WP.EXE KoKo (1) SHEET.EXE KoKo (1) data lost FEB 17the warning JUL 29disk wiped
  1. A clean PC. Every program asks DOS, the system, for everything through one door: slot 21h. Think of one API endpoint that every app on the machine calls.
  2. Someone runs a program that carries Koko. Koko moves into memory and stays there, even after that program ends.
  3. Koko writes its own address into slot 21h, so every request reaches Koko first. It keeps the real DOS address for itself, in slot 3, a slot normal programs never use.
  4. Now every program that starts gets a copy of Koko, signed KoKo (1).
  5. On February 17, Koko shows its warning on the screen.
  6. On July 29, the warning comes again, and the data on the hard disk is lost. So is the data on any floppy used that day.

Yasser and Ebrahim, of the KEMYAM Computer Group in Port Said, studied its code byte by byte until they knew every trick it had. Yasser’s verdict sits in KVC’s help screen: It is a funny virus, all its tricks are untricky.

Watch KVC catch it

This PC runs in your browser, with Koko in its memory and two programs that wear its marks. Type SCAN and watch Yasser’s own KVC.EXE find Koko, sound the alarm, freeze it, and repair both files.

C: THE DEMO PC

The screen shows what KVC prints when it is done: Koko found in memory and frozen, two files cleaned.

KVC.EXE here is his 1993 program, byte for byte. When it is done, HELLO.COM and GREET.EXE are identical to their clean originals, down to the last byte. Type DIR to see their sizes shrink back to 61 and 96 bytes, or run them: all they do now is say hello.

Hear the alarm

When KVC finds Koko in memory, it sounds a siren on the PC’s little speaker. A high tone and a low one, twenty times in a row, with no gap.

A PC speaker can only push its cone out or pull it back in. A timer chip in the PC ticks 1,193,182 times a second. KVC tells it how many ticks make one wave: 1,000 for the high tone, 1,600 for the low one. So the pitch comes out exact on every PC. Play his alarm, then drag the number and hear what the chip makes of it.

PC SPEAKER 10 ms of the wave KVC sends
The PC speaker's square wave: the speaker cone is pushed out, then pulled in, 1,193 times a second for the high tone and 746 times for the low one.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

20 tones, high then low, with no gap: 1,193 Hz and 746 Hz, 65 ms each.

TIMER CHIP one number sets the pitch

1,193,182 ticks a second ÷ 1,000 = 1,193 Hz

His two:
For engineers: the siren, line by line
KVC.EXE 080C-083E, the alarm
080C mov cx,14h ; 20 tones
080F cmp ax,3E8h ; was the last tone the high one?
0814 mov ax,3E8h ; high: the clock divided by 1,000
081A mov ax,640h ; low: divided by 1,600
081F mov al,0B6h / out 43h,al ; timer channel 2: make a square wave
0824 out 42h,al / mov al,ah / out 42h,al ; the divisor, low byte then high byte
082A in al,61h / or al,3 / out 61h,al ; connect the timer to the speaker
0832 mov cx,0FF00h / loop $ ; hold the tone: 65,280 turns of the loop
0838 loop 080F ; next tone
083A in al,61h / and al,0FCh / out 61h,al ; speaker off
The pitch comes from the timer chip, so it never changes. The length comes from the waiting loop: 65 ms a tone on a 10 MHz 286, the speed the site’s emulator gives his programs.

One secret question

A virus that lives in memory needs a way to ask, am I already here? Koko’s question was a number, FF0Ch, and its answer was C0C1h. Yasser and Ebrahim found that handshake and turned it into a detector.

It works like finding a hidden service on a machine: send a request that only that service understands, and see if its handshake comes back. A clean PC has never heard the question. A PC with Koko answers it every time. Flip Koko on and off, and send a few requests.

MEMORY who answers slot 21h
KVC sends a request through slot 21h. With Koko in memory the request reaches Koko first; Koko answers the secret question itself and passes every other request on to DOS. KVC.EXEasks slot 21hthe door for all Koko nobody here DOSthe system passes it on FF0C KVC asks through slot 21h. Koko, when it is in memory, answers the secret question itself and passes other requests on to DOS. KVC.EXEasks slot 21hthe door for all Koko nobody here DOSthe system passes it on FF0C

Koko is in memory. Send the secret question and see who answers.

KVC.EXE his three lines
mov ax,0FF0Ch; the secret question
int 21h; ask through slot 21h
cmp ax,0C0C1h; Koko's answer?
The same idea in JavaScript
const reply = await dos({ ax: 0xFF0C });// a request no real service has
if (reply.ax === 0xC0C1)// the handshake only Koko knows
alarm('Koko is in memory');

KVC asks this question first, every time it runs, before it looks at a single file. The same number marks Koko’s EXE files too. Koko writes C0C1h into their headers, and that is the first thing KVC checks in every EXE it opens.

Switched off with its own hiding place

DOS had no task manager. You could not stop a program that sat in memory. So KVC did something smarter: it used the back door Koko had built for itself.

Koko kept the real DOS address in slot 3 so it could still reach DOS itself. KVC talks to DOS through that same slot, so its calls skip Koko completely. Then it copies slot 3 into slot 21h. Every program now reaches DOS directly, and Koko’s code sits in memory with nothing pointing at it. Frozen.

In JavaScript terms, Koko had monkey-patched the system call and kept the original in a spare variable. KVC found the spare and put the original back:

slots[0x21] = slots[0x03];   // every program reaches DOS directly again
MEMORY the two slots
Slot 21h first points at Koko and slot 3 at DOS. KVC copies slot 3 into slot 21h, so every request reaches DOS and Koko is cut off. KVC slot 21h→ DOS slot 3→ DOS Koko DOS cut off Slot 21h first points at Koko and slot 3 at DOS. KVC copies slot 3 into slot 21h, and Koko is cut off. KVC slot 21h→ DOS slot 3→ DOS Koko DOS cut off
SCREEN
Found  --KoKo (1) virus--  active in  RAM
##### Virus Freezed #####
KVC.EXE freezing Koko
  1. 07EDask:push cs / pop ds
  2. 07EFmov ax,0FF0Ch; the secret question
  3. 07F2int 21h; through slot 21h
  4. 07F4cmp ax,0C0C1h; Koko's answer?
  5. 07F7jne clean; no: nobody is there
  6. 07F9mov ah,9 / mov dx,found; Found...
  7. 080Bint 3; print, via slot 3
  8. 080Cmov cx,20; the alarm: 20 tones
  9. 083Aout 61h,al; speaker off
  10. 0840mov ax,3503h; what is in slot 3?
  11. 0843int 3; answer: the real DOS
  12. 0846mov dx,bx; keep that address
  13. 0848mov ax,2521h; into slot 21h
  14. 084Bint 3
  15. 085Cmov again,1; second look
  16. 0862jmp ask
  17. 0864clean:cmp again,0
  18. 086Cmov ah,9 / mov dx,freezed; Freezed
  19. 0871int 21h; slot 21h is safe
  20. 0873ret; on to the files
The same in C
  1. int again = 0;
  2. ask:
  3. if (dos(0xFF0C) == 0xC0C1) {// Koko answered
  4. puts3(again ? REBOOT : FOUND);// print through slot 3
  5. siren(20);
  6. real = getvect3(0x03);
  7. setvect3(0x21, real);// slot 21h = DOS
  8. if (again) return;// a second copy: reboot
  9. again = 1;
  10. goto ask;
  11. }
  12. if (again) puts(FREEZED);
Watches
AX
0900
21h
→ DOS slot 21h, the door every program uses
03h
→ DOS slot 3, where Koko parked the real DOS
2nd
yes is this the second look?
Help

Koko’s code is still in memory, but no program can reach it. Frozen. KVC goes on to clean the disk. Had a second copy still answered, KVC would have sounded the alarm again and told the user to restart from a clean disk after cleaning.

Koko could load itself into memory more than once. KVC was ready for that as well. After freezing, it asks the question again. If a second copy still answers, KVC sounds the alarm again and tells the user plainly what to do. Once the files are clean, turn the PC off and start it from a clean system disk.

For engineers: why slot 3

Slot 3 is the breakpoint interrupt, INT 3, which only debuggers use. Its instruction is a single byte, CCh. Koko copied the DOS entry point there, so INT 3 became a private line to DOS. KVC makes three calls on that line: AH = 09h to print, AX = 3503h to read vector 3 (DOS hands back its own address in ES:BX), and AX = 2521h to write that address into vector 21h. None of them passes through Koko’s handler.

Every file rebuilt, byte for byte

Koko had to keep each program working, or people would notice. So it carried the original bytes inside its own body. KVC needed no backup: it rebuilt every file from what Koko carried.

KVC walks every folder on the disk and opens every program. There are two kinds. A COM program is a plain run of code that starts at its first byte, like a script. An EXE starts with a header, a small manifest that tells DOS where to begin. Koko had a trick for each, and KVC undid each one. Step through both repairs on the real bytes of the demo’s two files.

HELLO.COM a COM program

1,844 bytes · clean, it was 61

The first 64 bytes

8CC805040050B800015033C0CB08004B6F4B6F202831290A0D244C4C4F2E434F4D2C206120636C65616E206C6974746C652070726F6772616D2E0D0A24000000

Koko’s the program’s filler

What KVC reads

KVC’s own copy50 B8 00 01 50 33 C0 CB 08 00 KoKo (1) 0A 0D 24
body + 243D 00 = 61, the original size
body + 34B409BA0C01CD21B8004CCD2148656C6C6F21204920616D204845 the 26 bytes Koko covered
body + 295BF 00 01 BE 22 01 Koko’s own repair code
HELLO.COM as Koko left it: 1,844 bytes. It was 61. Koko wrote 26 bytes of its own over the start and added its body, 1,780 bytes, to the end.
Mark 1. KVC reads the first 26 bytes and compares bytes 5 to 25 with its own copy of Koko’s start: a jump into the body, then Koko’s name, KoKo (1). All 21 match.
Bytes 3 and 4 say where the body starts, counted in blocks of 16 bytes: 4 blocks, so byte 64.
Mark 2. 295 bytes into the body, KVC expects Koko’s own code for putting a program back together. It is there, so this is Koko for sure. A file with only one mark is left untouched: KVC repairs only what it fully recognizes.
Koko kept the 26 bytes it covered, 34 bytes into its body. KVC writes them back over the start.
Koko also kept the original size, 61 bytes, 24 bytes into its body. KVC cuts the file there. Koko’s 1,783 bytes are gone.
Last, the file’s date and time go back as they were. HELLO.COM is the same 61 bytes it was before Koko, byte for byte. Run it in the demo above: it says hello and nothing else.
GREET.EXE an EXE program

2,132 bytes · clean, it was 96

The header fields KVC reads and repairs
FieldMeansValue
bytes 2 to 5file size2,132
bytes 14 to 17where the stack starts0004:C0C1
bytes 20 to 23where the program starts0004:0100
byte 352the first instructions that runEB 60 90 EA
Koko’s bodytwo pieces of Koko’s code20 + 20 bytes
GREET.EXE as Koko left it: 2,132 bytes. It was 96. Its header, the part that tells DOS how to start the program, now starts it inside Koko’s body.
Mark 1. The header’s starting stack value reads C0C1h: the same number Koko gives as its answer in memory.
KVC follows the header to where the program starts, byte 352. Mark 2: Koko’s first instructions, EB 60 90 EA.
Marks 3 and 4: two more pieces of Koko’s code, deep in its body. Both match, so this is Koko for sure.
Koko kept the four start values it replaced, 77 bytes past its start. KVC writes them back into the header: the program starts at its own first byte again, with its own stack.
The original file ended 256 bytes before Koko’s start, at byte 96. KVC cuts it there and writes the new size into the header.
GREET.EXE is the same 96 bytes it was before Koko, byte for byte.

Before it writes a single byte, KVC checks two of Koko’s marks in a COM file and four in an EXE. If a file shows only some of them, KVC leaves it alone and asks the user to contact the KEMYAM Computer Group. It unlocks read-only files before repairing them, so protected programs get cleaned too. Two switches shape a scan: /NS checks one folder only, and /NC reports without cleaning.

For engineers: the COM check and repair
KVC.EXE 0D76-0EF0, condensed
0D76 mov cx,1Ah / mov ah,3Fh ; read the first 26 bytes
0D88 mov di,059Fh / mov cx,15h ; his copy of Koko's start and name, 21 bytes
0D8F repe cmpsb ; mark 1
0D99 mov dl,[0514h] / mov dh,[0515h] ; bytes 3 and 4: where the body starts
0DA1 shl dx,1 (4 times) ; blocks of 16 bytes into a byte count
0DD8 add dx,127h ; body + 295
0E12 repe cmpsb ; mark 2: BF 00 01 BE 22 01
0E8D mov ax,5700h / int 21h ; keep the date and time
0EC3 call 07A0h ; reopen for writing, read-only cleared
0EEC int 21h ; AH = 40h: write the 26 saved bytes at the start
0EF0 mov ax,5701h / int 21h ; date and time back
His C code then cuts the file to the size saved at body + 24 with chsize(). KVC is C for the walk through the folders and assembly for everything that touches the virus.
Then and now
1991 to 19932026Why it is the same idea
Fixed bytes at fixed places: KoKo (1), Koko’s repair code, a stack value of C0C1h Antivirus signatures and YARA rules The fastest, surest way to name a known family.
Asking the virus its own “are you there?” question Using malware’s own markers, like the WannaCry kill-switch domain in 2017 The attacker’s own check becomes the defender’s tool.
Pointing slot 21h back at DOS Isolating a process so nothing can reach it Stop it first, clean up second.
Rebuilding each file from the bytes Koko carried An EDR rollback that restores changed files Undo exactly what was done, no more.

Every Byte of KVC.EXE

Each square is one byte of the program in memory, colored by what it is. Tap a part to open it in the full map, down to the single instruction.

C:\KVC\KVC.EXE