CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Steve Hebert's Development Blog

Steve's Blog - From .Net to dotMath and everything in between.

November 2005 - Posts

  • Aurora/Nail Virus - a simple virus that has stumped the anti-virus firms

    The latest word on anti-virus firms  focuses on their inability to adjust to the rootkits that are running around in the wild these days.  Companies such as Symantec, McAfee and Trend Micro do not have rootkit detection and removal capabilities.

     

    While rootkit detection and removal appears to require an architectural change, it appears that not only rootkits are giving the anti-virus firms fits.  Back in July, I posted one of my most viewed posts – the Aurora (Nail.exe) spyware fix . At the time I posted the fix, I decided to leave it off the main feed of CodeBetter because it has nothing to do with .Net.  Given the technical nature and the fact that most anti-virus firms are still unable to deal with the threat, I really wonder what my yearly anti-virus subscriptions are worth.  The Aurora/Nail virus is also known as ‘adware/betterinternet’ and information is available on all three names across the 'net. When I first ran into the problem, Symantec's product was able to detect the virus 10-20% of the time.  When it did detect the virus, it claimed to have removed it, but it only reappeared after successive reboots. 

     

    This is an interesting virus because it contacts a central server to locate popups.  Once installed, the program keeps itself running on the local machine using virtually random filenames.  These processes all focus on running the application side of the virus and appear to keep a couple of things in place as I discussed in my initial blog entry. The program does not have an uninstall, and in response to criticism the company provides a removal tool surrounded by questions. 

      

    Given that this virus/spyware has a huge achilles heel that I revealed back in July, I am hearing that several major virus vendors still cannot remove it in spite of correctly identifying it.  This has me wondering, how are the anti-virus corporations working to adjust the underlying shifts in virus activity?  How can this simple virus be stumping them for so long and how will they address rootkits when a simple problem gives them so much trouble?  The new wave of virus attacks go far beyond the mechanics of identifying payloads and providing signature updates – I wonder how much longer it will take anti-virus firms to shake up their R&D departments to change their approach?   

     

    If you have a tool that actually removes this virus, I’d be very interested in hearing.  Right now I’m hearing from many people that their anti-virus solutions do not successfully remove the Aurora/BetterInternet/Nail virus.  I’d love to be able to pass along a functional removal for myself and others.

     

     

  • remote event log reading - code for a command line utility

    Here's the code for a command-line utility I've written for gathering EventLog information from remote testing/production machines on our network.  I've found the utility to be pretty handy and can be xcopy'd without any other assemblies.  While the utility writes all information out to the Console, it is 'comma-delimeter safe' so you can redirect the output to a file and open it in excel.

    I know I could install bits to read the logs over RSS, but in a large company with oversight on the servers getting these types of tools installed is a pain.  This tool also allows me to parameterize the time range - and since we're reviewing these at regular intervals it makes reading far easier. Every solution has its place - this may work well for others.

    If you want to use the code below, just create a command line c# application and paste the two classes into the project.  The first class - EventLogReader - implements main(args) and does some simple house-cleaning.  The second class - EventScanner - does the actual work of deciding which messages to write.  While I haven't had a need to parameterize the EventType, this would be a nice addition.  If you make any mods, I only ask that you let me know so I can link to your work.

    The syntax for the program is:  EventLogReader logName timeWindow [machineName]

    If you want to grab the last 24 hours of log errors from your application log, use...
       EventLogReader "Application Log" 24

    If you want to grab the last 24 of application log entries from a remote machine, use...
       EventLogReader "Application Log" 24 Mongo

    Disclaimer:  The code listed below is offered without any warranty expressed or implied.  This is despite anything stated before, after or during this posting.  If you use the code and it causes you any problems, you assume full responsibility for the problems and obsolve the author of any form of responsibility.

    I should have been a lawyer...  now, onto the code.

    class EventLogReader

    {

          /// <summary>

          /// The main entry point for the application.

          /// </summary>

          [STAThread]

          static void Main(string[] args)

          {

          if( args != null )

          {

             if( args.Length < 2 || args.Length >3 )

             {

                Console.WriteLine( WriteParmUsageMessage( "Invalid parameter list" ));

                return;

             }

             string machineName = string.Empty;

             string logName = args[0];

             string stimeWindow = args[1];

     

     

             if( args.Length > 2 )

                machineName = args[2];

     

     

             double timeWindow = 0;

     

             try

             {

     

                timeWindow = Convert.ToDouble(stimeWindow);

                if( timeWindow < 0 )

                {

                   Console.WriteLine( WriteParmUsageMessage( "Invalid time window parameter - must be a positive integer value"));

                   return;

                }

             }

             catch( Exception  )

             {

                Console.WriteLine( WriteParmUsageMessage( "Invalid time window parameter - must be a positive integer value"));

                return;

             }

     

     

             EventScanner es = new EventScanner();

     

             try

             {

                es.WriteEventLog( logName, machineName, timeWindow );

             }

             catch( Exception e )

             {

                WriteParmUsageMessage(string.Format("Unhandled exception while communicating with the event log:\n{0}", e.Message ));

                return;

             }

          }

          }

     

       static private string WriteParmUsageMessage( string message )

       {

          return string.Format("EventLogReader Error\n{0}:\n    EventLogReader logName timeWindow [machineName]", message );

       }

    }

     

     

     

    public class EventScanner

    {

       private DateTime _cutoffDate = DateTime.MinValue;

     

       // CreateCutoff( hours ) : this function substracts the number of hours from the current

       //   time to create a time window for reported log entries

       private void CreateCutoff( double hours )

       {

          _cutoffDate = DateTime.Now.AddHours( hours * -1);

     

          Console.WriteLine( "Event Log Snapshot from {0} {1} through {2} {3}", _cutoffDate.ToShortDateString(), _cutoffDate.ToShortTimeString(), DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString());

       }

     

     

       // CreateEventLogReader( logName, machineName ) : This function creates an eventlog

       //    object for the associated log name and machine name (if passed).

       public EventLog CreateEventLogReader( string logName, string machineName )

       {

          EventLog log = null;

     

          if( machineName.Length > 0 )

             log = new EventLog(logName, machineName );

          else

             log = new EventLog(logName);

     

          return log;

       }

     

     

       // WriteEventLog() : This function takes the log name and attaches to it

       public void WriteEventLog(string logName, string machineName, double hours)

       {

          // first, we'll open the log

          using( EventLog log = CreateEventLogReader( logName, machineName ))

          {

             // next we'll create our timespan of interest (hours subtracted from current time)

             CreateCutoff(hours);

     

             // finally, we'll scan the log for entries we're looking for.

             // NOTE: here is where you can change the entry type based on what you are seeking

             foreach( EventLogEntry entry in log.Entries )

             {

                if(  entry.TimeWritten >= _cutoffDate && entry.EntryType == EventLogEntryType.Error)

                   Console.WriteLine( string.Format("{0},{1} {2},{3}", entry.Source, entry.TimeWritten.ToShortDateString(), entry.TimeWritten.ToShortTimeString(), FormatMessage(entry.Message)  ));

     

                entry.Dispose();

             }

          }

       }

     

       // the following string fragment appears on each log entry - apparently due to a

       // translation dll not being loaded.

       private const string _messageFormatIndicator = "following replacement strings:";

     

       private string FormatMessage(string entry)

       {

          string newEntry = entry;

     

          // make certain the generic handler error is ignored

          int truncPosition = entry.IndexOf( _messageFormatIndicator ) ;

     

          if( truncPosition >= 0 )

          {

             truncPosition += _messageFormatIndicator.Length;

             newEntry = entry.Substring( truncPosition, entry.Length - truncPosition );

          }

     

          // get rid of CR/LF combinations for easier reading

          newEntry = newEntry.Replace("\n", "{LF}");

          newEntry = newEntry.Replace("\r", "{CR}");

     

          // get rid of embedded commas to prevent CSV parsing problems

          newEntry = newEntry.Replace(",", "_");

     

          return newEntry;

       }

    }

     

     

  • worst. program. ever.

    Last night, I grabbed my video camera and hooked it up to my pc to create a DVD of some home movies.

    I haven't done this in a while, so I dusted off my copy of Pinnacle Studio 9, installed all the patches and started working.  This program just randomly crashes - sometimes with errors, sometimes it just disappears.  The product is not usable for more than 5-10 minutes at a time. 

    After doing some checking, I found that Studio 9 has a reputation around the web.  It's interesting because people who review it give it good marks for features - even I like the interface, the organization and the features.  But the crashes are so pervasive that I cannot believe they've been having the same problems for 2 years with this product.  

    I see they are coming out with version 10, but given they have never fixed the errors in 9, I won't consider the product for another year.

    I have never seen a product so buggy - I can't believe they ever released it.

  • TCPView and Close Connection - how'd he do that?

    On my new project,  I've been helping to trace down problems with 3rd party/backend libraries exhibiting bad behaviors. 

    In tracking down these behaviors, I've been using TCPView to watch connections and see how the application is behaving on the wire.  TCPView is a product written by Mark Russinovich and made available at SysInternals.com  that interactively displays active TCP connections.  If you've never spent an afternoon browsing through the utilities at SysInternals, you are way past due. Russinovich utilities have always had a cool factor where you inevitably go "I didn't know you could do that". In addition to being far more useful than NetStat, TCPView has one feature that is really compelling - "Close Connection".

    This function gives me a thought - can I target an application for programmatic 'pulled-wire' testing without having to disconnect the wire on my box? 

    Mark makes the code for his enhanced version of netstat - which he calls NetStatP - available for free, but he doesn't float up the implementation for Close Connection.  All of the other code I have rewritten in C#, now if I could just find Close Connection.... I've been digging in MSDN and Google, but without success. 

    I wonder if his Close Connection implementation could be used to hound an application and close all of its open connections? 

    BTW:  I'm late to the game on Russinovich's blog - subscribed!

  • Report from the trenches - lessons from a 1.0 product

     I’ve spent the last couple of months in a new job, new project, etc..  The project I’m working on deals with securities data and the application's scope is very interesting.  We’re using a combination of ASPX and ASMX services for the consumer-facing services and WinForms apps on the back-end. 

     

    When I started the position, the team was starting a 1.0 release push.  This push has been interesting and I’m sure I’ll be writing more about this in the future.  This process has made me think about universal traits you watch out for when walking into a project.  I think every project does some of these things well and need work on others – finding the right balance for a given project involves continuously questioning the whole process.

     

    • Get so good at integration that it becomes second nature.  Daily builds, build tools, automated versioning, etc.. The sooner you get to this state, the easier testing, validation and cycle time become. 
    • Question 3rd party components ruthlessly.  Assume bad behavior, assume memory leaks, assume bandwidth hogging – make the components prove they can run in your environment. 
    • Use 3rd party testing tools.  Take a look at the testing landscape – tools that allow you to push your code and analyze its behavior.  For hammering on your website or webservices, check out ANTS Load.  For analyzing your code for efficiency and speed – check out profilers.  You can also use these tools to help validate any 3rd party components.
    • Put testing front and center.  Focus first on pushing the testing V into your development process.  Everything else in terms of test driven development, lean management and others will flow from this focus.  Some of these methods will fit your project, some will not – but continuously look to improve.
    • Shared database connections are (more than likely) a code smell.  If you are looking at elusive connections problems that cannot be easily reproduced – look for this.

     

    Enough for now, back to figuring out how TCPView works...

More Posts

Our Sponsors

Free Tech Publications