Log in

View Full Version : Serial fishing


WaxfordSqueers
November 8th, 2012, 18:40
Trying to get a bit if rust out and need some current advice on serial fishing, such as likely techniques of the day. I am still stuck in the day of hmemcpy and setting a BP in softice on dialog in serial entry box.

This app uses a TLS callback for sure and it does various time checks before the entry point. I managed to make progress using getwindowtextA and got to a routine checking my bogus entry with two magic numbers, featuring addition and XORs. I am guessing they have taken the legitimate serial and obfuscated it using boolean logic but I am stymied by a couple of points.

1)they check against 0xA and 0xD, the old linefeed/carriage return combo. There is room in the serial entry box to write a small novel so I am assuming the length of the number is greater than the width of the box, requiring a linefeed/CR. Then again, one should never assume anything.

2)if that is true, then I presume there should be checks for dashes, delineating sets of numbers as well.

Any ideas?

3)wrt to the TLS callback, has anyone simply zeroed the entry in the PE header. I can see all sorts of problems with that if their are further callbacks written into the app.

Kayaker
November 9th, 2012, 00:31
Don't really know how to answer that. If the TLS callback is being used for benign purposes (i.e. to "call constructors and destructors for objects" as the PECOFF file suggests a use for), then ignore it. If it's malicious (read anti-debug), then you might as well be full-on paranoid and assume the timing checks are for anti-tracing, it dynamically modifies code, and it's already detected that it's under a debugger and the serial routine you're chasing is a bogus "fool-the-cracker" routine. How's that for old school?

You might as well figure out what the TLS callback is doing first, just so you know what the score is.

As for the rest, you might also try it in reverse. You've likely done this before, rather than approaching the core algorithm from the serial entry box route, use ProcessMonitor to see if you can find it searching for a registry entry or license file when validly registered. Fake as required to get further along to the algo. You may end up in the exact same code, but it's also possible it may clarify some things, like whether the 0x0A0D or spaces/dashes are relevant.

WaxfordSqueers
November 9th, 2012, 03:22
Quote:
[Originally Posted by Kayaker;93645]You might as well figure out what the TLS callback is doing first, just so you know what the score is.


I spent some time with the TLS code but I am presuming that's what it is. There is a TLS entry that CFF explorer lists with address of callbacks and an index, but I am not quite sure where I should be looking.

Anyway, when it loads in softice, you get the typical Invalid schtick till you do a single step, so I missed out initially on the first program step. After tracing through the entry code and doing a ret, I can see that the first program step is a call to the routine I mentioned. I am not too clear whether the system called that address and softice picked it up as the TLS unfolded, but the address of the call is not the address listed as the entry point by PE header analysis software. The EP is jumped to immediately after this routine.

The routine is plain weird...at least to me. It calls time functions and queryperformancecounter but it's what it does with the returned values that is weird. To begin with, it puts a double word in eax from a particular data address. A few steps later, it produces the same number as a magic, hard-coded into the code, and moves it to edi. Then it compares them by comparing eax to edi. I'll call the data memory location that had the magic number stored, xxxxxxxx, because it shows up later.

Here's where the weirdness begins. It calls GetSystenTimeAsFileTime, which returns values in eax and edx. These values are also at ebp-4 and ebp-8, for some reason (doh!! the ebp values were passed to the func as an esp value). It moves one of them to esi, then it xor's them together and the result is in esi. Just to get that straight, it has xored the MSB and the LSB values of the time returned from the time function. So, esi now has that xored value.

Now it calls GetCurrentProcessId and gets a value...32c. I checked that it is the proc id of my app and it is. It now xor's the pid with esi. Then it calls GetCurrentThreadId, which is d6c, and xor's esi with that. To summarize, it has gotten system time, xored the msb and lsb, called for the proc and thread ids, and xored the xored time values with each of those values.

Don't go away, it gets better. It now calls GetTickCount and xor's esi with the msb stored in eax of the returned value. It discards the lsb value from edx. Now it calls QueryPerformanceCounter but it switches things up a bit. It moves a value from the stack into eax which is 0. Then it xors 0 with a value retrieved from QPF, then it xors that value in eax with esi. Then it compares esi with eax and, of course, they are not equal.

So it jumps. Had they been equal, it would have moved the original magic number into esi (as a hard-coded value from the code) then back to the original data memory location I earlier labeled xxxxxxxx. Then it would 'not' that value (invert it) and store the inverse at the next highest data memory location.

Meanwhile, back at the ranch, we have just done a jump because esi and eax were not equal, after having xored them. Now it tests esi with a value in ebx that was ffff0000. It tests them and they are not equal, so it jumps again.

The place it jumps to is the same location I just mentioned where the magic number is moved to esi then into data memory location xxxxxxxxx. Of course, esi is not the same as the magic, but it is notted as well and the inverse is stored at the next highest data memory location to xxxxxxxx. It seems the app has provided a magic number and stored it at xxxxxxxx, and under certain conditions it puts it back there, and under other conditions it stores the xored time values with the pid and tid at xxxxxxxx. It might be an idea to put a bpx on that location and let the app run.

I have probably now lost you completely. I could post this section of code but I don't know if that is still kosher. I should mention that if the last jump had not been made, because esi and eax were equal, esi would have been moved to eax. Then it would have gotten an shl 10, then ored with the original esi.

I know this sounds hopelessly convoluted, but I am trying to think why they would want to do all this. We know that the thread and proc id's will change each time the app is rebooted. I was thinking they might be using this as a way to verify the serial, but not if they use a random variable like the pid and tid. It has also occured to me that they can tell by the way the values change whether or not it is being single-stepped, or even halted at a bpx.

Maybe they can use it to check for single-stepping but I don't see how they could specifically check for a debugger using just that info.

Once this routine finishes, it returns to a jmp that directs it into heap initialization to begin the thread proper. Next up is GetVersion, etc., then a bit further there is a call to winmain.

blabberer
November 9th, 2012, 14:17
sorry i didnt read your post entirely and i need to get off this damn net and do some work
but from what i glanced i assume you are single stepping through the standard WinMainCrt() entry

ps
don't scream at me "Am I a noob dont i know what crtmain is " if i had i assumed wrong

WaxfordSqueers
November 9th, 2012, 14:37
Quote:
[Originally Posted by blabberer;93649]... i assume you are single stepping through the standard WinMainCrt()


If by WinMainCrt() you are refering to the code between the app entry point and the call to winmain(), yes. In either Olly or softice, I am beginning from the very first code instruction called from kernel32. I am not talking about the windows code itself, rather the initialization code that happens before winmain is called.

It's not clear to me how a TLS Callback would appear in Olly/softice. If code was called before the thread code was officially executed, would it show up in olly/softice as code addresses listed under the apps name, coming before the official app entry point?

Even at that, this is peculiar stuff because the very first instruction is to a call with the time-related functions in it. This happens before the heap is created or any other stuff like GetVersion, GetCommandLine, whatever.

Kayaker suggested it could be related to constructors/destructors but why the magic numbers and the xoring using retrieved time, pid's and tid's?

blabberer
November 9th, 2012, 14:41
sorry for replying to my own post
but i cant get rid of this addiction

yes you are talking about a routine that is plain standard
it either has BufferOverflows.h included or is compiled with wdk
so GsCookie is being initialised in that routine (to catch stack based overflow exploits)

doesnt ida recognize this and collapse this ??

does it look like this

Code:

01002EC1 >MOV EDI, EDI
01002EC3 PUSH EBP
01002EC4 MOV EBP, ESP
01002EC6 SUB ESP, 10
01002EC9 MOV EAX, DWORD PTR DS:[__security_cookie]
01002ECE AND DWORD PTR SS:[EBP-8], 0 //dwlow
01002ED2 AND DWORD PTR SS:[EBP-4], 0 // dwhigh
01002ED6 PUSH EBX
01002ED7 PUSH EDI
01002ED8 MOV EDI, BB40E64E
01002EDD MOV EBX, FFFF0000
01002EE2 CMP EAX, EDI
01002EE4 JE SHORT 01002EF3
01002EE6 TEST EBX, EAX
01002EE8 JE SHORT 01002EF3
01002EEA NOT EAX
01002EEC MOV DWORD PTR DS:[__security_cookie_complement], EAX
01002EF1 JMP SHORT 01002F4E
01002EF3 PUSH ESI
01002EF4 LEA EAX, DWORD PTR SS:[EBP-8]
01002EF7 PUSH EAX
01002EF8 CALL NEAR DWORD PTR DS:[<&KERNEL32.GetSystemTimeAsFileTime>]
01002EFE MOV ESI, DWORD PTR SS:[EBP-4]
01002F01 XOR ESI, DWORD PTR SS:[EBP-8]
01002F04 CALL NEAR DWORD PTR DS:[<&KERNEL32.GetCurrentProcessId>]
01002F0A XOR ESI, EAX
01002F0C CALL NEAR DWORD PTR DS:[<&KERNEL32.GetCurrentThreadId>]
01002F12 XOR ESI, EAX
01002F14 CALL NEAR DWORD PTR DS:[<&KERNEL32.GetTickCount>]
01002F1A XOR ESI, EAX
01002F1C LEA EAX, DWORD PTR SS:[EBP-10]
01002F1F PUSH EAX
01002F20 CALL NEAR DWORD PTR DS:[<&KERNEL32.QueryPerformanceCounter>]
01002F26 MOV EAX, DWORD PTR SS:[EBP-C]
01002F29 XOR EAX, DWORD PTR SS:[EBP-10]
01002F2C XOR ESI, EAX
01002F2E CMP ESI, EDI
01002F30 JE SHORT 01002F3A
01002F32 TEST DWORD PTR DS:[__security_cookie], EBX
01002F38 JNZ SHORT 01002F3F
01002F3A MOV ESI, BB40E64F
01002F3F MOV DWORD PTR DS:[__security_cookie], ESI
01002F45 NOT ESI
01002F47 MOV DWORD PTR DS:[__security_cookie_complement], ESI
01002F4D POP ESI
01002F4E POP EDI
01002F4F POP EBX
01002F50 LEAVE
01002F51 RETN


WaxfordSqueers
November 9th, 2012, 15:10
Quote:
[Originally Posted by blabberer;93651]does it look like this
blabberer, you're a genius, or a genii, if you have multiple personalities. That is the exact code, to a tee.

What's with the magic number moved to the EDI early on....BB40E64E?? and where did you accumulate all this knowledge, it's uncanny.

Still, I have TLS callbacks listed as:

address of callbacks: C7DOBC
address of callbacks: FA15D8
raw data: B8A000
virtual address: BA4000

Are these offsets into the executable, or offsets after it is loaded? I don't see anything of interest after loading unless I add 400000 to C7D0BC, then there are a series of dwords. I have spent a couple of hours reading on TLS but so far no one has offered a solution. One article insisted that double-clicking on the TLS callbacks address in cff explorer would lead to the set of callback addresses but that does not work on my version.

WaxfordSqueers
November 9th, 2012, 15:19
Quote:
[Originally Posted by blabberer;93651]doesnt ida recognize this and collapse this ??
I should have looked there first...sorry. IDA listed it as a closed function called __security_init_cookie and that is followed by jmp __tmainCRTStartup. When I jump to __security_init_cookie, the code is laid out as you posted it but not collapsed.

blabberer
November 9th, 2012, 15:36
it is a global that is compiled in the exe

ULONG thiscrap = 0xbbXXXXXX;


01004000 security_cookie BB40E64E Næ@»
01004004 security_cookie_complement 44BF19B1 ±¿D

read this

http://uninformed.org/index.cgi?v=7&a=2

WaxfordSqueers
November 9th, 2012, 15:54
The quotes feature is not working at present.

You said..."read this http://uninformed.org/index.cgi?v=7&a=2"

Thanks. Funny enough, I was just reading about that, I think on Matt Pietrek's article on SEH's. It seems the convoluted xoring was to get a unique cookie based on the present pid and tid. Is that correct?

With regard to TLS, good old IDA provided the answer. Under 'Names' is a reference to TLSCallbacks. That leads to the address I inquired about for the TLS callback address. There are three pointer listed, to __rmtmp, __termcom, and __endstdio. From what I gather those funcs are related to cleanup and destructors, as Kayaker suggested. There are two other pointers I need to identify.

Answering my own question from your article:

"The guts of the __security_init_cookie routine are actually the most critical part to understand. At a high-level, this routine will take an XOR'd combination of the current system time, process identifier, thread identifier, tick count, and performance counter...". At least I can read a disassembly and understand it...to an extent. :-)

Kayaker
November 9th, 2012, 17:06
Quote:
[Originally Posted by WaxfordSqueers;93650]It's not clear to me how a TLS Callback would appear in Olly/softice. If code was called before the thread code was officially executed, would it show up in olly/softice as code addresses listed under the apps name, coming before the official app entry point?


I suspected it was GsCookie code you were looking at, partly from the description and primarily because there is no default way to trace TLS Callbacks with Softice as far as I know. You can with Olly or IDA, perhaps Windbg, but not Softice.

However, as they like to say in the mobile world, I have an App for that. It's a combination of PsSetCreateProcessNotifyRoutine and a redirection of TLS callbacks to injected code, with an option to break into Softice for tracing of the callback(s). If you're ever desperate to trace real TLS callbacks in Softice, let me know. Else just use IDA or the TLSCatch Olly plugin by Waliedassar here.

WaxfordSqueers
November 9th, 2012, 17:52
Quote:
[Originally Posted by Kayaker;93656]If you're ever desperate to trace real TLS callbacks in Softice, let me know.
Thanks K. No desperation, just trying to eliminate the anti-debug stuff.

So far, it's looking like what Ork used to warn about, that I am giving programmers far too much credit for originality. Whereas some are very clever, the average one who writes an app does not seem that up on dirty tricks.

Wrt to softice, why could you not catch the loading process farther back, along the lines of baseprocesstart as a bp? Surely there's a point in ntdll where it calls a function written by the programmer to do tls stuff.

Speaking of which, I had a thread a while back complaining that I could no longer find _baseprocessstart in softice. I used to find it with an addr kernel32 and _baseprocesstart would be listed in the exports, if I had a k32 nms file loaded. I could then bpx on it. More recently, I cannot find it or used the addr command on k32. deroko told me you can't addr k32 because it does not have a process context.

What was it we used to do to find _baseprocessstart? Before loading an app, I would change context into k32 and set a bp on _baseprocesstart. When I booted the app, ice would break at _baseprocessstart. I am not imagining that. It was a technique I used to trap an app with an obfuscated entry point.

The major difference between IceStealth and IceExt just occured to me recently. With IceExt, you can use loader32 to reach the entry point then enable IceExt. You cannot do that with IceStealth. Once it is loaded, you cannot turn it off.

Kayaker
November 9th, 2012, 18:21
Sure, just make sure you've loaded the correct symbol table and grep for what you want. Isn't Softice wonderful?

Code:

:wc // turn code window off so you can dump this output with Loader32 "Save Softice History As"

:table kernel32
:sym _baseprocess*

Address Symbol Name
.text(001B:7C801000, 00081C21 bytes)
001B:7C8171BB _BaseProcessInitPostImport
001B:7C816D2C _BaseProcessStart
001B:7C810867 _BaseProcessStartThunk

:table ntdll
:sym *ldrp*tls*

Address Symbol Name
.text(001B:7C901000, 0007A6FE bytes)
001B:7C918E1D _LdrpAllocateTls
001B:7C9284D9 _LdrpCallTlsInitializers => _LdrpCallInitRoutine // I'd trace this if you want the TLS callbacks
001B:7C919237 _LdrpFreeTls
001B:7C9225DA _LdrpInitializeTls
.data(0023:7C97C000, 000049E0 bytes)
0023:7C97C048 _LdrpImageHasTls
0023:7C97C168 _LdrpNumberOfTlsEntries
0023:7C97C198 _LdrpTlsList

WaxfordSqueers
November 9th, 2012, 19:34
Quote:
[Originally Posted by Kayaker;93658]Sure, just make sure you've loaded the correct symbol table and grep for what you want. Isn't Softice wonderful?

Thanks K., worked like a charm that time. Can't see what I was doing wrong. I tried the table command before with no luck. Must have been a bad hair day.

I think it may have had something to do with me having the exp for k32 turned off in winice.dat. I don't mean the nms file ref in winice.dat, I mean those near the bottom of the dat file that are often commented out.

Would that not be a solution to tracing tls with ice? If you knew where the tls was called from in ntdll, could you not bpx on that, or are there no symbols for ntdll?

blabberer
November 10th, 2012, 00:40
ollydbg 1.10 is wonderfull select the line


7C901176 ntdll.LdrpCallInitRoutine /$ 55 PUSH EBP
and press ctrl+r


References in ntdll:.text to LdrpCallInitRoutine
Address Disassembly Comment
7C901176 ntdll.LdrpCallInitRoutine PUSH EBP (Initial CPU selection)
7C913A3E CALL LdrpCallInitRoutine
7C91B190 CALL LdrpCallInitRoutine
7C91C4F5 CALL LdrpCallInitRoutine
7C91E03F CALL LdrpCallInitRoutine
7C923AD5 CALL LdrpCallInitRoutine
7C93CADB CALL LdrpCallInitRoutine
7C9570EA CALL LdrpCallInitRoutine


it will tell you where this tlsinit is called from
and you can use ntglobalflagplugin by stingduk to catch tls callbacks (uses a primitive mechanism)



windbg is wonderfulls wunderfull
it will tell you where this is called from with symbolic names as well
[CODE]

no selection nothing just type
# call*ntdll!LdrpCallInitRoutine ntdll L?0xb2000
notice regexp * and modname

ntdll!LdrShutdownThread+0xd2:
7c913a3e e833d7feff call ntdll!LdrpCallInitRoutine (7c901176)
ntdll!LdrpInitializeThread+0xbb:
7c91b190 e8e15ffeff call ntdll!LdrpCallInitRoutine (7c901176)
ntdll!LdrpRunInitializeRoutines+0x33f:
7c91c4f5 e87c4cfeff call ntdll!LdrpCallInitRoutine (7c901176)
ntdll!LdrUnloadDll+0x417:
7c91e03f e83231feff call ntdll!LdrpCallInitRoutine (7c901176)
ntdll!LdrShutdownProcess+0x14a:
7c923ad5 e89cd6fdff call ntdll!LdrpCallInitRoutine (7c901176)
ntdll!LdrpCallTlsInitializers+0x7e:
7c93cadb e89646fcff call ntdll!LdrpCallInitRoutine (7c901176)
ntdll!AVrfpLoadAndInitializeProvider+0x111:
7c9570ea e887a0faff call ntdll!LdrpCallInitRoutine (7c901176)


and you can verify addresses match with ollydbg



odbg 2 is even more whateverbull

you can ask it to set bp on tls callbacks using its inbuilt option

and it will break promptly on tls callback

see a stack when it broke in tls call back



CPU Disasm
Address Hex dump Command Comments
00401068 /$ 55 PUSH EBP ; TLS callback function <----auto comment by odbg2
00401069 |. 8BEC MOV EBP, ESP
0040106B |. E8 E0FFFFFF CALL <JMP.&kernel32.IsDebuggerPresent ; [KERNEL32.IsDebuggerPresent




Log data
Address Message
# ChildEBP RetAddr Args to Child
00 0013f9ac 7c90118a 00400000 00000001 00000000 mytls+0x1068
01 0013f9cc 7c93cae0 00401068 00400000 00000001 ntdll!LdrpCallInitRoutine+0x14
02 0013fa18 7c935e80 00400000 00000001 00030000 ntdll!LdrpCallTlsInitializers+0x83
03 0013fb18 7c9211b4 0013fd30 7ffdf000 7ffd8000 ntdll!LdrpRunInitializeRoutines+0x48b
04 0013fc94 7c9210af 0013fd30 7c900000 0013fce0 ntdll!LdrpInitializeProcess+0x1131
05 0013fd1c 7c90e457 0013fd30 7c900000 00000000 ntdll!_LdrpInitialize+0x183
06 00000000 00000000 00000000 00000000 00000000 ntdll!KiUserApcDispatcher+0x7

blabberer
November 10th, 2012, 01:01
Quote:
[Originally Posted by WaxfordSqueers;93655]
Answering my own question from your article:

"The guts of the __security_init_cookie routine are actually the most critical part to understand. At a high-level, this routine will take an XOR'd combination of the current system time, process identifier, thread identifier, tick count, and performance counter...". At least I can read a disassembly and understand it...to an extent. :-)


if reading source is most critical part then i have to say the authors of that article did a great job

iirc the source for gs cookie implementation is/was public right from its inception iirc circa 200X

Code:


C:\Program Files\Microsoft Visual Studio 10.0\VC\crt>dir /s /b gs*
C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\gs_cookie.c
C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\gs_report.c
C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\gs_support.c


Code:

C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src>type gs_cookie.c | grep
-i bb
#define DEFAULT_SECURITY_COOKIE 0xBB40E64E

C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src>


Code:


C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src>type gs_support.c | gre
p -i -A 5 -B 5 Query

cookie ^= GetCurrentProcessId();
cookie ^= GetCurrentThreadId();
cookie ^= GetTickCount();

QueryPerformanceCounter(&perfctr);
#if defined (_WIN64)
cookie ^= perfctr.QuadPart;
#else /* defined (_WIN64) */
cookie ^= perfctr.LowPart;
cookie ^= perfctr.HighPart;

C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src>


Kayaker
November 10th, 2012, 02:29
Quote:
[Originally Posted by blabberer;93660]
odbg 2 is even more whateverbull
you can ask it to set bp on tls callbacks using its inbuilt option
and it will break promptly on tls callback


Olly2 will only break on the first TLS callback apparently.

Here's an old TLS callback in MASM test I had created with 2 callbacks, both of which execute during DLL_PROCESS_ATTACH and DLL_PROCESS_DETACH. Only the first of 4 executions is paused on.

Waliedassar mentions something similar

http://waleedassar.blogspot.ca/2010/10/quick-look-at-tls-callbacks.html
http://waleedassar.blogspot.ca/2012/03/ollydbg-v201-and-tls-callbacks.html

blabberer
November 10th, 2012, 07:24
on odbg 1.10 ntglobalflag plugin seems to catch all the tls callbacks


Code:

7C9484DF Debug string: LDR: Tls Callbacks Found. Imagebase 00400000 Tls 0040212C CallBacks 00402120
7C9484DF Debug string: LDR: Calling Tls Callback Imagebase 00400000 Function 004010B0
7C9484DF Debug string: LDR: Calling Tls Callback Imagebase 00400000 Function 004010DB
7C9484DF Debug string: LDR: Tls Callbacks Found. Imagebase 00400000 Tls 0040212C CallBacks 00402120
7C9484DF Debug string: LDR: Calling Tls Callback Imagebase 00400000 Function 004010B0
7C9484DF Debug string: LDR: Calling Tls Callback Imagebase 00400000 Function 004010DB



walieds prj tls

7C9484DF Debug string: LDR: Calling Tls Callback Imagebase 10000000 Function 10001000
7C9484DF Debug string: LDR: Calling Tls Callback Imagebase 00400000 Function 00401030
7C9484DF Debug string: LDR: Calling Tls Callback Imagebase 00400000 Function 00401000
00401040 Program entry point
7C9484DF Debug string: LDR: PID: 0xab0 finished - '"C:\Documents and Settings\Admin\Desktop\prj\prj\pxm\Debug\pxm.exe"'
7C9484DF Debug string: LDR: Calling Tls Callback Imagebase 10000000 Function 10001000
7C9484DF Debug string: LDR: Calling Tls Callback Imagebase 00400000 Function 00401030
7C9484DF Debug string: LDR: Calling Tls Callback Imagebase 00400000 Function 00401000

fake tls

Log data, item 2
Address=7C9484DF
Message=Debug string: LDR: Tls Callbacks Found. Imagebase 00F00000 Tls 00F12058 CallBacks 01F12200

Log data, item 0
Address=7C9484DF
Message=Debug string: LDR: Calling Tls Callback Imagebase 00F00000 Function 00F010A0




i havent played much with odbg2 thanks for headup

WaxfordSqueers
November 10th, 2012, 21:33
Quote:
[Originally Posted by blabberer;93664]on odbg 1.10 ntglobalflag plugin seems to catch all the tls callbacks

I am still trying to get my head around Olly and have retreated to softice for my current problem.

I loaded several dll plugins for Olly in the 1.10 plugin directory but they do not show up under the plugins menu. I know this sounds trivial but people who write about plugins seem to take for granted that loading them is more than trivial.

Also, wondered if in your exploration of the deep code woods if you have encountered the magic word 0xBEAD? It shows up in one particular routine and I am wondering if its decimal equivalent may be a window reference.

eg. cmp word ptr [esi+28], 0xBEAD