In my previous post I covered my “Classic” Mac OS emulator set up. One of my goals of getting the emulator set up was to be able to look at and analyze viruses that affected older versions of Mac OS. I think taking a look at old viruses is interesting for two reasons. First, it provides a good overview of 68k assembly. Second, it provides an interesting perspective on the history of malicious software. The first virus I decided to look at is called INIT 29.
The Disinfectant 3.7.1 help file has a good short description of the virus:
The INIT 29 virus first appeared in late 1988. We do not know much about its origin. A second minor variant appeared in March, 1994. There are no significant difference between the two strains. The original strain is called “INIT 29 A”. The variant is called “INIT 29 B”.
INIT 29 is extremely virulent. It spreads very rapidly. Unlike Scores and nVIR, you do not have to run an application for it to become infected. Also, unlike Scores and nVIR, INIT 29 can and will infect almost any file, including applications, system files, and document files. Document files are infected, but they are not contagious. The virus can only spread via system files and application files.
An application infected with the INIT 29 virus can be easily identified using ResEdit. See an example in the screenshot below:
The first indicator is a
CODE resource of exactly 712 bytes. The second indicator can be seen in the jump table. Each executable has a
CODE resource with ID 0 that contains the jump table. If it’s a small application it might only have one or two entries in the table. Normally when the compiler builds an application it would create
CODE resources sequentially and similarly the jump table would also be laid out in a linear fashion. The first entry in the jump table points to the main entry point for the executable. In the case of the jump table above, the first entry in the jump table actually points to the
CODE resource with ID 3. You can see based on the resource names that ID 1 has a name of “Main” and is the largest section of code. This should be the entry point to the application but the INIT 29 virus has modified the jump table entry to point to itself instead.
The image below shows a section of the virus code. You can see how it has saved the original jump table entry to the
CODE resource with ID 1.
When an infected application is run it will call
UseResFile passing in a
refNum value of zero. This will retrieve the System resource file. It will then create a new entry in the
INIT resource section with an ID of 29. This is where the name of the virus comes from. The virus copies all 712 bytes of itself into this
INIT resource. This code will then be executed when the system starts up next.
Infected system file
An infected System file is also easy to identify using ResEdit. We can run an infected application in our emulator and then use ResEdit to compare the system file before and after detonation.
The left side of the image above is before running the infected application and the right side is after. You can see that after the infected application is run there is now a new
INIT resource with the ID 29 and a size of exactly 712 bytes. If we disassemble the virus code we can see the following:
INIT code is fairly short. It calls
GetTrapAddress passing in $A997 to get the address of the current
OpenResFile function. It checks to see if it’s already been patched and if it hasn’t it will save a pointer to the original function. Then it allocates 712 bytes on the system heap and makes a copy of itself there. Finally it calls
SetTrapAddress to install itself as the new
OpenResFile is an important system API. Any time the Finder has to open a file or run an executable it will make use of
OpenResFile to find out information about the file. Since it’s used so often it makes a great hook point for the virus to infect other files. The hijacked version of
OpenResFile first calls into the original operating system version of the function. This will load the resource file and set it as the current resource. The virus then looks to see if the file has any
CODE resources or not. If the file doesn’t have any
CODE resources then the virus creates an
INIT resource with ID 29 and copies it’s 712 bytes into it. This results in document files that contain the virus code but can’t infect anything else. If the opened resource does have a
CODE resource then the virus attempts to find a free ID to use. It will use the lowest free ID to create a new resource entry and copy it’s 712 bytes into it. After that it opens the
CODE resource with ID 0 and patches the jump table to point to the new resource that it just created. This results in the application running the virus code the next time it starts attempting to infect the System file.
With the INIT 29 virus attempting to infect every single resource file opened it’s easy to see why the Disinfectant help file called the virus “extremely virulent”. For the most part the virus is harmless and simply infects files. However, since it does hijack the startup of applications it is possible to notice a slow down when launching programs. It’s especially interesting to see just how much the virus accomplishes using only 712 bytes of code.