Log Parser 2.2 and Log Parser Studio

At first I thought to title this post the same as the catchphrase of Log Parser: "The Whole World Is Your Database!"

But then I decided that was a bit too exciting for what I actually wanted to talk about.

So I just discovered Log Parser Studio a few days ago. LPS is a graphical frontend to Log Parser; quite similar to how SQL Management Studio is a GUI frontend to interacting with SQL Server.  I am, quite frankly, ashamed that I didn't already know about it. It's fantastic.

The thing is... Log Parser is a command-line utility that uses a very SQL-esque language to interact with logs. What kind of logs, you ask?  Any kind of logs! That's right... you can use it to query the Windows Security Event Log, or you can use it to query a folder full of IIS web server logs, or you can use it to query a log full of your own personal electric utility bills from last year!

However, Log Parser itself is a very complex, albeit powerful and flexible, command-line utility. Maybe you want something a little more user-friendly to get you started. That's exactly where Log Parser Studio, the GUI frontend, comes in to play.

As a little demonstration, I installed Log Parser 2.2 on my workstation. Then I downloaded Log Parser Studio to my workstation. I fired it up as a Windows application, and I pointed it to the remote IIS logs directory of this very web server. I then right-clicked on "IIS: Request per Hour" and chose "Run report now." As if I had just run a SQL query in SQL Management Studio, this window popped up:

 

Log Parser Studio Query*Click for Bigger*

This data is probably every single HTTP GET request made per hour, rather than a count of hits made by unique IP addresses, but the point is you now have this amazing utility that will parse practically any amount of data you can think of from any source of data you can think of. Go check it out and see how Log Parser is even capable of generating pie charts and bar charts and all sorts of crazy things using this data!

Antivirus and .NET-ception

So I was playing around the other day with a couple of antivirus products for Windows, trying to see if I could figure out ways to evade detection, (it was a slow day.) I feel very ambivalent pretty much hate antivirus software. As an IT guy, I know that it's a necessary evil, and every once in a while it does legitimately catch something that would have infected your system, but:

  • AV software often negatively impacts the performance of the entire system, unless you make so many concessions on what it doesn't scan that it practically defeats the purpose. I mean, yeah, your website probably would perform better if I excluded the entire inetpub folder, but then who's going to slow down that e-mail spam bot that you went and got yourself infected with? 
  • You might as well consider the installation of AV software on your machine a permanent modification. Just try and cleanly uninstall that crap I dare you.
  • False sense of security. Some AV products might be slightly better or worse than others, but none of them are approaching perfect. And none of them are a replacement for bad habits, such as clicking on all the links on that popup window that didn't get blocked by your web browser for some reason when you went to that one website with farm animals on it... I mean... I wouldn't know anything about that.

So the European Institute for Computer Antivirus Research (EICAR) made up this string of ASCII characters that antivirus product vendors and users can use to test their AV products. You can put it in a text file or in an executable file or whatever, and it's supposed to trigger the AV on your machine. Depending on your AV settings, even copying the EICAR string to your clipboard might trigger your antivirus. The "on-access" scanning of antivirus products uses a file system filter driver to intercept all disk I/O, or whenever an IRP_MJ_CREATE is issued for a file, but unless the AV product is also configured to actively scan memory and network activity, then you can evade it as long as your "evil code" stays in memory and doesn't touch the disk.

So I was playing around in Powershell and C#, and I wrote this rather silly bit of script... er, code... or scrode? It's a Powershell script that uses the Add-Type cmdlet to load in a C# class on the fly. That C# class in turn, contains code to compile some more code on the fly, and turn it into an executable. (Finally the Inception reference starts to make sense.) So just for fun I download the EICAR test file from the internet (which triggers some AV products, but not others, depending on how they're configured.) Now that I have the evil EICAR string in memory, I compile my executable, which does not itself contain any malicious code, so it won't trigger AV. Then I run that new process and pass the EICAR data to it as a parameter. In this way, I feel like I was able to get "malicious" data onto the computer and into a process that could then do whatever it wants with it - all without triggering the antivirus on the system because the EICAR data never touched the disk.

$SourceCode = @"
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CSharp;
using System.CodeDom.Compiler;

public class EvilClass
{
    public static void Main(string[] args)
    {
        var csc = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });
        var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" }, Environment.GetEnvironmentVariable("temp") + "\\evil.exe", true);
        parameters.GenerateExecutable = true;
        CompilerResults results = csc.CompileAssemblyFromSource(parameters,
        @"using System;
		  using System.Reflection;
          class AnotherEvilClassInsideAnotherEvilClass 
			{				
				public static void Main(string[] args)
				{					
					string msg = ""Data in evil.exe Main(): "" + args[0];
					System.Console.WriteLine(msg);					
				}
            }");
        results.Errors.Cast<CompilerError>().ToList().ForEach(error => Console.WriteLine(error.ErrorText));		
    }
}
"@

Add-Type -TypeDefinition $SourceCode -Language CSharp

Write-Host "Downloading some evil code from the internet and displaying it in the console..."
ForEach($_ in $(New-Object System.Net.Webclient).DownloadData('http://eicar.org/download/eicar.com'))
{
	$evilString += [char]$_
	Write-Host $([char]$_) -NoNewLine -ForegroundColor Red
}
Write-Host "`nGenerating evil.exe..."
[EvilClass]::Main([String]::Empty)
Write-Host "Executing evil.exe..."
& $Env:TEMP\evil.exe $evilString
Write-Host "Deleting evil.exe..."
Remove-Item $Env:TEMP\evil.exe

And here is the scrode in action:

Powershell power

Web Server Upgrade

Nothing too exciting to share right now, except that I upgraded this web server this morning from 2008 R2 to Server 2012.  The upgrade went perfectly, all my settings and applications were migrated properly, and most importantly the server was upgraded to IIS 8 and .NET 4.5 with no issues. I figured if there were going to be any problems, it was going to be there, since this website relies heavily on .NET.

I was able to remove the GUI shell, but I had to leave the "Graphical Management Tools and Infrastructure" feature enabled, as the server warned me that some certain important bits like IIS and SMTP might stop working without it. :P

A Minor (Literally) Windows Bug?

So I was reading Windows Internals 6th ed. Pt II the other day, specifically the chapter about crash dumps, when I noticed something odd. It was in the output of the .dumpdebug command in the kernel debugger. Just to make sure it wasn't just a typo in the book, I have reproduced the oddity here:

Windbg

I have simply launched Windbg, loaded up a crash dump file, and issued the command .dumpdebug. In the header, you see the MajorVersion is 0f. The MinorVersion is 1db1. The MinorVersion I understand. 1db1 is hexadecimal and in decimal it translates to 7601. Most administrators will immediately realize the number 7601 as belonging to Windows 7 or 2008 R2 with service pack 1.

But what is the MajorVersion? 0F in hexadecimal translates to 15 in decimal. But what does 15 mean? This version of Windows is 6. The full version string displayed when I open up a Command Prompt on this machine for instance, is 6.1.7601. Major version = 6, minor version = 1, build number = 7601. Right?

So why does the kernel debugger show the MajorVersion of Windows to be 15? I wonder if I've found a bug...

Mystery of the Performance Counters with Negative Denominators!

So I finally solved a bit of a mystery, after wondering about it off an on for about 6 months.

A lot of us out there use some sort of monitoring program like SCOM that gathers some performance counter data from all of the servers in your environment, and uses that data to produce messages such as:

WARNING: Hey man, the CPU usage on SERVER01 is really high and has been for a while, so, you might wanna' go check that out.

But every once in a while, if for some reason the performance counters needed are unavailable, your monitoring application might say something like this:

ERROR: Unable to get performance counter data for SERVER01.

Well that happens to me somewhat frequently. Sometimes it's an error in the monitoring application, or sometimes the agent machine needs a lodctr /R or winmgmt /resync or something like that. But every once in a while it's more difficult to solve than that. I logged on to SERVER01 to see if I could simply add the performance counters needed to Perfmon. The objects and instances were there, but one of them looked odd. Then I decided to use typeperf.exe to get some data from the counters:

 

perfmon error

 

typeperf error

A counter with a negative denominator value was detected? Now contrary to that screenshot above, the -1's were intermittent, and would actually change to normal values for a few seconds, and then go back to negative ones. It was as if the scale of that counter was offset, and whenever real CPU load would occur, the counter would increase to positive values, but then as the CPU usage dropped back down closer to zero, the counter would fall below zero again.  Hmm... if you do a search for something like "missing performance counters," or "a counter with a negative denominator value," you'll get plenty of good links, as missing or corrupt performance counters are a somewhat common issue. Such as this, or this. Notice in that last link, that there is a vague reference to it being caused by "intermittent timing issues in the performance data handlers for many counters." The article fails however to offer any advice or anything more concrete than that. lodctr /R and winmgmt /resyncperf and all that usual stuff did nothing to help.

So I sat back and thought some more about the scope of the problem. I have only seen this issue two or three times in my career. The two cases I could remember both seemed to be on VMware virtual machines. One of them was a Windows 2003 operating system, and then a couple months later I saw it again on a Windows 2008 R2 VM. That phrase from that one KB stuck with me... "intermittent timing issues," and that made me think of hardware timing issues. But since these were VMs, they didn't exactly have hardware per se... but maybe it had something to do with the way in which the virtual machines communicate with their physical host. I was so close to figuring out the answer, but at the time I shrugged it off and shelved the issue in my mind for a while.

Then about a week ago the issue popped up again. Long story short, it turns out it was this all along:

VMware tools

Unchecking that "Time synchronization between the virtual machine and the ESX server" in the VMware tools app on the VM made the problem go away. Ugh. The answer had been so simple all along, yet it alluded me for months.

I feel better now that I at least have a solution for that particular scenario.  Now... back to Hyper-V.