Monday, April 21, 2008

RE: NTDebugging Puzzler 0x00000003 (Matrix Edition) Some assembly required

So the Microsoft Advanced Windows Debugging and Troubleshooting blog put out a puzzler based on reverse engineering assembler into something meaningful, say C/C++. I took a look at the assembly listing and decided it would be a fun break from work to decompile that into something. About 30 minutes later I wound up with some source that compiles down to nearly the same listing as theirs.

Phew, I've still got it! It took me some time monkeying around with the order of the local variables to get the same space added for the locals as in their example. Other than that it was pretty straight forward.
puzzler3.cpp
#include <stdlib.h>
#include <string.h>

/** Sort an input string's characters in descending order
*
*/
// puzzler3!myfun [c:\source\puzzler\puzzler3\puzzler3\puzzler3.cpp @ 20]:
void myfun(char* arg0)
// 20 00cc1480 55 push ebp
// 20 00cc1481 8bec mov ebp,esp
// 20 00cc1483 81ecf0000000 sub esp,0F0h
// 20 00cc1489 53 push ebx
// 20 00cc148a 56 push esi
// 20 00cc148b 57 push edi
{
//union { // [ebp-0F0h]
// struct {
size_t arg0_len; // [ebp-08h]
// unsigned int pad0; // [ebp-0Ch]
// unsigned int pad1; // [ebp-10h]
size_t ii; // [ebp-14h]
// unsigned int pad2; // [ebp-18h]
// unsigned int pad3; // [ebp-1Ch]
size_t len_temp; // [ebp-20h]
// unsigned int pad4; // [ebp-24h]
// unsigned int pad5; // [ebp-28h]
char x; // [ebp-29h]
// };
// unsigned char local_variables[240];
//}; // local variables

// //set local variables to unusual values for buffer checking
//memset(local_variables,
// 0xCCCCCCCCU,
// sizeof(local0)/sizeof(unsigned int)
//); // 20 00cc148c 8dbd10ffffff lea edi,[ebp-0F0h]
// 20 00cc1492 b93c000000 mov ecx,3Ch
// 20 00cc1497 b8cccccccc mov eax,0CCCCCCCCh
// 20 00cc149c f3ab rep stos dword ptr es:[edi]

len_temp = strlen(arg0); // 26 00cc149e 8b4508 mov eax,dword ptr [ebp+8]
// 26 00cc14a1 50 push eax
// 26 00cc14a2 e803fcffff call puzzler3!ILT+165(_strlen) (00cc10aa)
// 26 00cc14a7 83c404 add esp,4
// 26 00cc14aa 8945e0 mov dword ptr [ebp-20h],eax
// 28 00cc14ad 8b45e0 mov eax,dword ptr [ebp-20h]
// 28 00cc14b0 8945f8 mov dword ptr [ebp-8],eax

for(arg0_len = len_temp; arg0_len > 0; arg0_len--)
// 28 00cc14b5 8b45f8 mov eax,dword ptr [ebp-8]
// 28 00cc14b8 83e801 sub eax,1
// 28 00cc14bb 8945f8 mov dword ptr [ebp-8],eax
// 28 00cc14b3 eb09 jmp puzzler3!myfun+0x3e (00cc14be)
// 28 00cc14be 837df800 cmp dword ptr [ebp-8],0
// 28 00cc14c2 7e60 jle puzzler3!myfun+0xa4 (00cc1524)
{
// 30 00cc14c4 c745ec00000000 mov dword ptr [ebp-14h],0
// 30 00cc14cb eb09 jmp puzzler3!myfun+0x56 (00cc14d6)
for(ii = 0; ii < (arg0_len - 1); ii++)
// 30 00cc14cd 8b45ec mov eax,dword ptr [ebp-14h]
// 30 00cc14d0 83c001 add eax,1
// 30 00cc14d3 8945ec mov dword ptr [ebp-14h],eax

// 30 00cc14d6 8b45f8 mov eax,dword ptr [ebp-8]
// 30 00cc14d9 83e801 sub eax,1
// 30 00cc14dc 3945ec cmp dword ptr [ebp-14h],eax
// 30 00cc14df 7d41 jge puzzler3!myfun+0xa2 (00cc1522)
{
//char temp0 = arg0[ii]; // 32 00cc14e1 8b4508 mov eax,dword ptr [ebp+8]
// 32 00cc14e4 0345ec add eax,dword ptr [ebp-14h]
// 32 00cc14e7 0fbe08 movsx ecx,byte ptr [eax]
//char temp1 = arg0[ii + 1]; // 32 00cc14ea 8b5508 mov edx,dword ptr [ebp+8]
// 32 00cc14ed 0355ec add edx,dword ptr [ebp-14h]
// 32 00cc14f0 0fbe4201 movsx eax,byte ptr [edx+1]


// 32 00cc14f4 3bc8 cmp ecx,eax
// 32 00cc14f6 7e28 jle puzzler3!myfun+0xa0 (00cc1520)
if(arg0[ii + 1] > arg0[ii])
{
x = arg0[ii]; // 34 00cc14f8 8b4508 mov eax,dword ptr [ebp+8]
// 34 00cc14fb 0345ec add eax,dword ptr [ebp-14h]
// 34 00cc14fe 8a08 mov cl,byte ptr [eax]
// 34 00cc1500 884dd7 mov byte ptr [ebp-29h],cl

arg0[ii] = arg0[ii+1]; // 35 00cc1503 8b4508 mov eax,dword ptr [ebp+8]
// 35 00cc1506 0345ec add eax,dword ptr [ebp-14h]
// 35 00cc1509 8b4d08 mov ecx,dword ptr [ebp+8]
// 35 00cc150c 034dec add ecx,dword ptr [ebp-14h]
// 35 00cc150f 8a5101 mov dl,byte ptr [ecx+1]
// 35 00cc1512 8810 mov byte ptr [eax],dl
arg0[ii+1] = x; // 36 00cc1514 8b4508 mov eax,dword ptr [ebp+8]
// 36 00cc1517 0345ec add eax,dword ptr [ebp-14h]
// 36 00cc151a 8a4dd7 mov cl,byte ptr [ebp-29h]
// 36 00cc151d 884801 mov byte ptr [eax+1],cl
}
} // 38 00cc1520 ebab jmp puzzler3!myfun+0x4d (00cc14cd)
} // 40 00cc1522 eb91 jmp puzzler3!myfun+0x35 (00cc14b5)

// return and ensure our stack is still correct
return; // 41 00cc1524 5f pop edi
// 41 00cc1525 5e pop esi
// 41 00cc1526 5b pop ebx
// 41 00cc1527 81c4f0000000 add esp,0F0h
// 41 00cc152d 3bec cmp ebp,esp
// 41 00cc152f e820fcffff call puzzler3!ILT+335(__RTC_CheckEsp) (00cc1154)
// 41 00cc1534 8be5 mov esp,ebp
// 41 00cc1536 5d pop ebp
// 41 00cc1537 c3 ret
}

puzzler3_driver.cpp
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void myfun(char *arg0);

int main(int argc, char* argv[])
{
char *test = NULL;

test = (char *)calloc(strlen(argv[0]) + 1, sizeof(char));
strcpy(test, argv[0]);

printf("%s\n", test);
myfun(test);
printf("%s\n", test);

return 0;
}

You'll need an MSVC compiler, probably circa VS2k5 or later, with /Od /GS /RTC1 /FA /Fa"bin\\" to get a listing that'll look like their listing.

Friday, April 18, 2008

Lessons Learned Transporting Patients

I've learned quite a few things lately transporting patients. Correction, I've relearned quite a few things transporting patients. It isn't like I did not already know what to do, or what I was expected to do, I'm just new. Green. Wet behind the ears. A pain in the ass for admit nurses.

No matter how much of a Real American Badass(tm) you are, no matter how Rain Man-esque you are with numbers, always have your run sheet in front of you when you call in to the hospital. Nothing makes you look like more of an idiot than rattling off a long set of vitals to the admit nurse and then fumbling a curveball question thrown at you like, "his age?" Your lack of an automatic response to this question lets them know you're now covering the phone to ask the patient.

Also, if you have any doubt what any of the medications your patient is on are for, take the 30 seconds to look them up in your field guide. The physician may only be quizzing you when they ask if the patient is on a specific class of drugs, but wouldn't you rather have the correct answer for them than say you are unsure what one of the medications is for?

The biggest problem I've found is not that I'm lacking any of the training necessary to fulfill my position as an EMT, just that it isn't automatic for me yet. You can imagine the level of frustration with myself considering my talents in other fields.

Wednesday, April 9, 2008

Shell Context Menu Slow to Open

Recently I've had a problem on my home machine where when right clicking on various shell items (not every shell item) could take 1-2 minutes to bring up the context menu. Explorer would go 'Not Responding', yet take up 0% CPU. Obviously something was blocking in Explorer, and I figured it to be one of my context menu handlers. Context menu handlers are buried within the registry in an expansive set of keys for literally every type of file system object on your computer. Locating every context menu handler is a tall order, but with a little help from Google, I found that NirSoft has an amazing tool called ShellExView which allows you to view all hooks into the Shell, and disable them en masse.

The first step I took was disabling every Context Menu and Property Sheet handler. Then I restarted my machine, and prepared to slowly re-enable them until I found the offending handler. ShellExView has a cool sort method to sort by company, which I tried first, but found no relief. Eventually I discovered that no matter how many things I disabled, my context menu was still slow as dirt.

Then I cut off my network card. Windows loves to take its time trying to find UNC paths--as you're well aware if you've ever mistyped a network share into Start/Run--so I chanced to gather that some shell verb pointed to something on a network path that was no longer there. Viola! Without a network connection my shell context menu's came up at regular speed.

How on earth do I easily find the culprit? There is some shell verb with a UNC path being referenced, and the Registry is a mighty large place. Once again NirSoft1 came to the rescue with their Registry search tool RegScanner. Set it to search for "\\" and stand back for the deluge of UNC paths found in your registry. Open and delete2 any branches that look like [Something\shell\*\command] and have a UNC path in the key. Mine was a program I used once on a Samba share that somehow made its way into my Open list.

Once I removed the offending key, it was back to business as usual.

1. nota bene: I did not intend for this to be a NirSoft shill post, but they really do have the two most useful tools for diagnosing Shell hook problems.

2. nota bene: if you aren't willing to live with toasting your Windows install, you may be inclined to export any keys you delete. I, however, am not so inclined.

Monday, April 7, 2008

Zooming Objects Inside a WPF ItemsControl

Previously I've shown how to zoom objects in WPF using either an attached property or directly binding a LayoutTransform. If you'd like to zoom objects inside of an ItemsControl, you can use a slight variation on the direct binding strategy.

First you should style the ItemsPanel template for your ItemsControl, in this case a ListBox.
<ItemsPanelTemplate x:Key="ZoomedItemsPanel">
<StackPanel IsItemsHost="True">
<StackPanel.LayoutTransform>
<ScaleTransform
ScaleX="{Binding Path=Value, ElementName=ZoomSlider}"
ScaleY="{Binding Path=Value, ElementName=ZoomSlider}" />
</StackPanel.LayoutTransform>
</StackPanel>
</ItemsPanelTemplate>

Then your ListBox can reference the ZoomedItemsPanel and enjoy zooming on just its contents!
<Label Content="Zoom: "
Target="{Binding ElementName=ZoomSlider}" />
<Slider x:Name="ZoomSlider"
Minimum="0.25"
Value="1"
Maximum="5"
SmallChange="0.5"
LargeChange="1.0" />
<ListBox ItemsPanel="{DynamicResource ZoomedItemsPanel}" />

Wasn't that easy?