3

I was experimenting with some hex scanner sources.

Following code works but is very slow:

Public Class frmMain

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LoadFile.Click

        Dim ArrayHold() As Byte
        Dim Index As Integer = 0
        Dim Str As New StringBuilder
        Dim tStr As String = ""
        Dim tempStr As String = ""
        Dim IndexEnd As Integer = 0
        Dim InputString As String = ""

        OpenDia.Filter = "All Files|*.*"

        If OpenDia.ShowDialog = Windows.Forms.DialogResult.OK Then
            Dim myStreamReader As StreamReader = Nothing
            myStreamReader = File.OpenText(OpenDia.FileName)
            InputString = myStreamReader.ReadToEnd()
            ArrayHold = Encoding.Default.GetBytes(InputString)

            Do
                IndexEnd = Index + 9

                For x As Integer = Index To IndexEnd

                    If x > UBound(ArrayHold) Then
                        tempStr = tempStr
                    Else
                        tStr = UCase(Convert.ToString(ArrayHold(x), 16))

                    If tStr.Length < 2 Then tStr = "0" & tStr

                    Str.Append(tStr)
                    tempStr = tempStr & Chr(ArrayHold(x))

                    End If
                Next

                Index = Index + 10
            Loop While IndexEnd < UBound(ArrayHold)

            If InStr(1, Str.ToString, "58354f2150254041505b345c505a58353428505e2937434329377d2445494341522d5354414e4441", vbTextCompare) Then
                Label1.Text = "Eicar-test-signature virus Detected!"
            End If
        End If
    End Sub
End Class

To speed it up I can use this format in XML file:

?xml version="1.0"?>
<signatures>
  <signature>
    <name>Eicar-Test-Signature</name>
      <hex>58354f2150254041505b345c505a58353428505e2937434329377d2445494341522d5354414e4441</hex>
  </signature>
  <signature>
    <name>Mid/Kakworm-Z</name>
      <hex>66732e4372656174655465787446696c652877642b276b616b2e72656727293b74322e77726974652827524547454449</hex>
  </signature>
</signatures>

But I don't know how to read and implement XML files in VB.NET. Is it hard and can anyone help?

Charles
  • 50,943
  • 13
  • 104
  • 142
Jedi
  • 153
  • 1
  • 3
  • 8
  • Why are you looping through the string one character at a time? Why not simply do an `If str = "58354...."` check? – Tim Sep 21 '13 at 16:20
  • @Tim You mean like If Str.ToString = "68696869" Then ? It is still slow though. – Jedi Sep 21 '13 at 16:26
  • You can reduce your code to 1 single loop (a For Loop) - that will reduce the amount of time to build the string. If I have time, I'll post a code sample. – Tim Sep 21 '13 at 16:29
  • @Tim Ok thanks,I will try to implement something myself.What about xml reading? – Jedi Sep 21 '13 at 16:30
  • 2
    I'd look at using LINQ to XML - parse the XML into a Dictionary (String, String), with the name as the key and the hex signature as the value. – Tim Sep 21 '13 at 16:31
  • @Tim Ok thanks.I will stick with single loop. – Jedi Sep 21 '13 at 16:47
  • If your question is about working with XML, please be more specific about what needs to be done, i.e. include sample input and output. Exclude irrelevant information (working with HEX signatures). Always try to ask one question at a time. – Victor Zakharov Sep 21 '13 at 16:48
  • Actually, I'd make the key the signature and the name the value, that way all you need to do is see if the signature exists as key in the dictionary, and if it does get the name from the value of the key. Also, you can reduce this to a simple StringBuilder call and use `PadLeft` to add a leading 0 if needed - strings are immutable so at the end of your process you're going to have a lot of strings laying around. Something like this `Str.Append(UCase(Convert.ToStrign(ArrayHold(x), 16).PadLeft(2, "0"c)`. Unfortunately I've got to go or I'd post an example of LINQ to XML. – Tim Sep 21 '13 at 16:51
  • @Neolisk It is not writing XML files but reading it.As you can see,my XML file includes Hex string and name.Form/code should scan selected file to see if it containts any hexes from XML file,if yes,show it's name. check my xml format. – Jedi Sep 21 '13 at 16:51
  • @Jedi - one last thing before I go. Parse the XML into a Dictionary (or some other structure); if you parse the XML file each time you want to check a signature, you'll be slowing yourself down again. – Tim Sep 21 '13 at 16:52
  • @Tim Thanks for your help.You can post example (later) if it's not problem. – Jedi Sep 21 '13 at 16:53
  • I guess I'll help you with the XML read example then. Please bear with me. – Victor Zakharov Sep 21 '13 at 16:55

2 Answers2

4

Okay, here is an example of how you can read your XML file:

Dim xml = <?xml version="1.0"?>
          <signatures>
            <signature>
              <name>Eicar-Test-Signature</name>
              <hex>58354f2150254041505b345c505a58353428505e2937434329377d2445494341522d5354414e4441</hex>
            </signature>
            <signature>
              <name>Mid/Kakworm-Z</name>
              <hex>66732e4372656174655465787446696c652877642b276b616b2e72656727293b74322e77726974652827524547454449</hex>
            </signature>
          </signatures>

Dim dict As New Dictionary(Of String, String)
For Each signature As XElement In xml.Root.Elements
  dict.Add(signature.<name>.Value, signature.<hex>.Value)
Next

Instead of having embedded XML in your code (as in above example), you would probably be using XDocument.Load or XDocument.Parse.

Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151
  • 1
    It works and is faster than original code.I'll mark it as solution for now.Thanks! – Jedi Sep 21 '13 at 17:05
  • Good answer, though I think it would be quicker to have the signature as the key and the name as value when it comes to checking the signature. – Tim Sep 21 '13 at 17:13
  • @Tim: Thanks. Luckily the syntax allows for an easy change like that. :) – Victor Zakharov Sep 21 '13 at 17:17
2

Neolisk covered the LINQ to XML part nicely. Here's a way to simplify your loop to one single For loop, using Step. Also, it uses the StreamReader in a Using block, which will ensure that the StreamReader is properly closed and disposed of.

If OpenDia.ShowDialog = Windows.Forms.DialogResult.OK Then

    Using myStreamReader As StreamReader = File.OpenText(openDia.FileName)

        ArrayHold = Encoding.Default.GetBytes(myStreamReader.ReadToEnd())
    End Using

    Dim arrayLength As Integer = ArrayHold.Length - 1

    For i As Integer = 0 To arrayLength Step 10
        Str.Append(UCase(Convert.ToString(ArrayHold(i), 16).PadLeft(2, "0"c)))
    Next

    If dict.ContainsKey(Str.ToString()) Then
        Label1.Text = dict(str.ToString())
    End If 
End If

This uses StringBuilder without the extra strings and should give a minor boost in performance as well, though I'm betting your biggest hit was looping through the string you build one character at a time, checking each character.

Edit

Added code for checking the dictionary (based on Neolisk's answer for parsing the XML to a dictionary) for completeness.

Tim
  • 28,212
  • 8
  • 63
  • 76