terça-feira, 18 de outubro de 2011

A crack in Redgate's Reflector

Above all things related to software development, those who get my warmest affection are the protection mechanisms. Almost every application out there (mainly commercial ones) have a different approach that materializes the individual vision of one programmer. Some choose commercial protection oriented software, some choose cryptography, some encode, other use math, etc. What makes them different is what makes me interested in them. This interest took me yesterday to Redgate's Reflector. But before continuing let me state the following: although I don't favor cracking, especially when a program has prices affordable by everyone like Reflector does, I believe that cracking is a necessity. Be it for validating the strength of the protections in place, be it for bypassing those protections and validate that a piece of software we just bought or downloaded it from the Internet does what it acclaims.
With that said let me tell you why I'm posting about a bypass of Redgate's Reflector protection scheme: because it just took me less than one minute to find it. Considering all the obfuscation effort that Redgate put on Reflector, this seems like they cracked open their own safety mechanisms.  Given their great work with Reflector, I think that such an error deserves a public post.

The story begins when I needed to use Reflector and it informed me that I had to buy the full version if I wanted to continue using it.

If you have been following the news, my country -Portugal- is in a huge recession, which means that we don't have money. So, as I only use Reflector a couple of times  a year, I decided to see if I could do anything to convince Reflector to work just one more time. I grabbed my second favorite debugger, Windbg, and run Reflector. As the application initialized, it started dumping some data to the debugger's output window:
Reflector.exe Information: 0 : Retrieving licence for .NET Reflector 7.0 {2447b2f0-fe09-4d98-8e51-93b07466303e}
Reflector.exe Information: 0 : Machine hash is local
Reflector.exe Information: 0 : Local machine hash is XXXX
Reflector.exe Information: 0 : Persisting
Reflector.exe Information: 0 : Product .NET Reflector
Reflector.exe Information: 0 : Activated False
Reflector.exe Information: 0 : Edition
Reflector.exe Information: 0 : Serial Number
Reflector.exe Information: 0 : Blob {2447b2f0-fe09-4d98-8e51-93b07466303e}
Reflector.exe Information: 0 : Hash XXXX
Reflector.exe Information: 0 : Trial Tampered
Reflector.exe Information: 0 : Expires 2011-11-13 02:59:43 UTC
Reflector.exe Information: 0 : Extended False
Reflector.exe Information: 0 : Installed 2011-10-14 02:59:43 UTC
Reflector.exe Information: 0 : First Used 2011-10-14 02:59:43 UTC
Reflector.exe Information: 0 : Last Used 2011-10-17 09:52:05 UTC
Reflector.exe Information: 0 : Stored to registry

I thought the value {2447b2f0-fe09-4d98-8e51-93b07466303e} was a curious one as it resembled a GUID. Also, the phrase "Stored to registry" seemed, hmmm... suspicious? I grabbed that value and searched the registry for it. This value was being used here:

I deleted the key from the registry and rerun Redgate's Reflector, and guess what?  The trial date was reset.


PS: After I found this, I searched the Internet for this trial reset hack and found that it is known for some time. But, I didn't find any reference to this leak of information by Redgate. This is the second reason why I decided to post it.

sexta-feira, 7 de outubro de 2011

Not all bugs are exploitable

Those who are, we call them vulnerabilities. Which is not the case of the bug I found in Notepad++ and it’s the subject of this post. The bug is triggered when setting the parsing Language of an opened document to "User-Defined"; exit Notepad++ while the document is still open, and then, start Notepad++. Every time Notepad++ is run it will crash with a message stating the error:

At the crash point we can observe the thread state:

ChildEBP RetAddr 
WARNING: Stack unwind information not available. Following frames may be wrong.
000df0d8 1001c863 SciLexer!Scintilla_DirectFunction+0x42e65
000df0f4 1001ca7b SciLexer+0x1c863
000e1090 100044fa SciLexer+0x1ca7b
000e10b8 10025c2b SciLexer+0x44fa
000e10dc 100272ec SciLexer+0x25c2b
000e1190 10029ca7 SciLexer+0x272ec
*** WARNING: Unable to verify checksum for npp.exe
*** ERROR: Module load completed but symbols could not be loaded for npp.exe
000e11a0 0047a597 SciLexer+0x29ca7
000e11c0 004811cd npp+0x7a597
000e11d4 0043b88c npp+0x811cd
000e1698 000e1688 npp+0x3b88c
000e169c 000e19ac 0xe1688
000e16a0 004d0ee8 0xe19ac
000e19ac 00400000 npp+0xd0ee8
000e19b0 00040278 npp
000e19b4 000302a8 0x40278
000e19b8 00000000 0x302a8

eax=00000000 ebx=00000000 ecx=00eadc40 edx=003b0608 esi=000df118 edi=00eaddf0
eip=1006cb0d esp=000def10 ebp=000df0d8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00010202
1006cb0d 8b38            mov     edi,dword ptr [eax]  ds:0023:00000000=????????

It seems that we have a null dereferenced pointer in the SciLexer module; with EAX=0, and, as there’s no null page allocated, we get a crash with access denied error. Let’s give it a look. EAX comes from ESI, so let’s see what’s there:

!address 00eaddf0
Failed to map Heaps (error 80004005)
Allocation Base:        00e90000
Base Address:           00e90000
End Address:            00eb6000
Region Size:            00026000
Type:                   00020000  MEM_PRIVATE
State:                  00001000  MEM_COMMIT
Protect:                00000004  PAGE_READWRITE

!heap -x 00eaddf0
Entry     User      Heap      Segment       Size  PrevSize  Unused    Flags
00eadde8  00eaddf0  003b0000  00e90000       428        58        18  busy extra fill

There’s no information of interest from the heap allocator as Notepad++ uses its own allocator. So, I started digging a little more to know if I could somehow influence this null reference to become something else more interesting from security viewpoint. Reversing some code of the application and analyzing the dump, I managed to get to some conclusions.
What is happening is that the document parsing language is saved in the session.xml file. The file is kept by Notepad++ in the AppData\Roaming\Notepad++ profile directory. This configuration file is always updated and saved when Notepad++ is closed by the user.

As there’s no “User-Defined” language defined, Notepad++ will allocate a language object that’s initialized with zeros by the time it is allocated. When parsing the file it will apply this empty object without verifying that there’s no valid data in it.

We got a "use an un-initialized object", and in consequence a crash. Although the object is not initialized, "sadly" it isn’t exploitable because as I said it is zeroed out on allocation.  This conclusions can be validated by doing the following:

1. Create a user defined language file. Menu View, open User-Defined dialog.
2. Name it User-Defined. 
3. Save it.

If you try now to do the same thing as described before, Notepad++ won’t crash anymore. If you go to the Language menu you will see a weird thing, there will be now two “User-Defined” items. Whichever you choose you'll get the same results, it will apply the previously defined "User-Defined" parsing language and no crash.

While the bug is not corrected by the Notepad++ developer team, you can solve this issue just by deleting the session.xml file. It will be recreated next time you start Notepad++.

Again, not all bugs are exploitable. Those who aren't remain just... bugs!

terça-feira, 4 de outubro de 2011

My new Android

I bought my first Android last weekend. It took me a while to get use to, but I managed to get a nice tour thru the whole system. I was pleasantly surprised finding that there's a lot of forensic/reversing info for it out there. But I'd like to post a list of some internal tools as a reminder for myself and for those who are starting reversing stuff on this platform:

getprop, setprop, monkey, pm, radiooptions, sqlite3


logcat, logwrapper, log, getevent

iftop, netcfg, netstat, ifconfig

lsof, dexdump, strace

printenv, ps, wipe, lsmod, run-as, service, svc, uptime, ssh, procrank, procmem, showmap, librank, rawbu, dumpsys, dumpstate

screencap, screenshot

sábado, 1 de outubro de 2011

Unpack me if you can

Profiting from Desktop heap information

Having followed all the late buzz about the Windows graphics and messaging subsystem kernel part, I decided to take a look at it to understand how it worked, and see if I could find anything interesting and useful. Inspired by Alex Ionescu online presentation, I dove into the realms of the desktop heap, and started to understand the richness of information available. This post is about a little game that shows some of the potential behind that data. The game I'm proposing here will be to run a packed application and, from user mode, try to get some critical information from that process without interfering with it. As passive and non-invasive as possible. Without calling the kernel and not touching the packed process in any way.

Note: As always, the full paper is available here

For the setting, I grabbed a notepad.exe executable from a XP machine and packed it with UPX.
If you want to know why I didn't use notepad.exe from Windows 7 read my last post: "MUI hell". I renamed notepad.exe to popo.exe as to avoid any confusion with names and I ran it. Running ProcExp afterwards, one can see that the popo.exe process has high entropy, so it is identified as packed images "purple".

Figure 1: Packed process

Next, as I needed another GUI process and I didn't want to lock explorer.exe, I run another notepad.exe. This time I used the one from Windows 7.

As a side note, I'm going to jump around between kernel and user debuggers. Please try to keep in mind that the kernel debugger is just used to validate some of the demonstration data.

Continuing, find a GUI process, :):

!process 0 0 notepad.exe
PROCESS 85cb7d40  SessionId: 1  Cid: 0a14    Peb: 7ffd4000  ParentCid: 0804
    DirBase: 1be3b000  ObjectTable: 998c05d0  HandleCount:  58.
    Image: notepad.exe

From that process, get a GUI thread.

PROCESS 85cb7d40  SessionId: 1  Cid: 0a14    Peb: 7ffd4000  ParentCid: 0804
    DirBase: 1be3b000  ObjectTable: 998c05d0  HandleCount:  58.
    Image: notepad.exe
    VadRoot 84444c88 Vads 70 Clone 0 Private 1454. Modified 1084. Locked 0.

        THREAD 8458d838  Cid 0a14.0a1c  Teb: 7ffdf000 Win32Thread: ff9ba008 WAIT: (WrUserRequest) UserMode Non-Alertable
            84caaec8  SynchronizationEvent

.thread 8458d838 
Implicit thread is now 8458d838

  *** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr 
96b4eb10 82c9ad75 nt!KiSwapContext+0x26
96b4eb48 82c99bd3 nt!KiSwapThread+0x266
96b4eb70 82c9388f nt!KiCommitThreadWait+0x1df
96b4ebe8 915296d6 nt!KeWaitForSingleObject+0x393
96b4ec44 915294e3 win32k!xxxRealSleepThread+0x1d7
96b4ec60 91526550 win32k!xxxSleepThread+0x2d
96b4ecb8 91529aa2 win32k!xxxRealInternalGetMessage+0x4b2
96b4ed1c 82c7487a win32k!NtUserGetMessage+0x3f
96b4ed1c 779c70c6 nt!KiFastCallEntry+0x12a
000ff998 76d7cde0 ntdll!KiIntSystemCall+0x6
000ff99c 76d7ce13 USER32!NtUserGetMessage+0xc
000ff9b8 0080148a USER32!GetMessageW+0x33
000ff9f8 008016ec notepad!WinMain+0xe6
000ffa88 77473c45 notepad!_initterm_e+0x1a1
000ffa94 779e37f5 kernel32!BaseThreadInitThunk+0xe
000ffad4 779e37c8 ntdll!__RtlUserThreadStart+0x70
000ffaec 00000000 ntdll!_RtlUserThreadStart+0x1b

Ok, now we need to get information from the desktop heap, where it's mapped.

TEB at 7ffdf000

dt nt!_TEB 7ffdf000 win*
   +0x040 Win32ThreadInfo : 0xff9ba008 Void
   +0x6cc Win32ClientInfo : [62] 0x20000188
   +0xf6c WinSockData : (null)

dt win32k!tagCLIENTINFO 0x7ffdf6cc
+0x000 CI_flags         : 0x20000188
   +0x018 pDeskInfo        : 0x01d00578 tagDESKTOPINFO
   +0x01c ulClientDelta    : 0xfcb00000
   +0x028 CallbackWnd      : _CALLBACKWND
   +0x03c pClientThreadInfo : 0x01d0fd68 tagCLIENTTHREADINFO
   +0x064 hKL              : 0x08160816 HKL__
   +0x068 CodePage         : 0x4e4
   +0x06a achDbcsCF        : [2]  ""
   +0x06c msgDbcsCB        : tagMSG
   +0x088 lpdwRegisteredClasses : 0x76dc90d4  -> 0x90

dt win32k!tagDESKTOPINFO 0x01d00578
   +0x000 pvDesktopBase    : 0xfe800000 Void
   +0x004 pvDesktopLimit   : 0xff400000 Void
   +0x008 spwnd            : 0xfe800618 tagWND
   +0x00c fsHooks          : 0x4000
   +0x010 aphkStart        : [16] (null)
   +0x050 spwndShell       : 0xfe8082c0 tagWND
   +0x054 ppiShellProcess  : 0xff9c9608 tagPROCESSINFO
   +0x058 spwndBkGnd       : 0xfe808508 tagWND
   +0x05c spwndTaskman     : 0xfe804428 tagWND
   +0x060 spwndProgman     : (null)
   +0x064 pvwplShellHook   : 0xff919638 VWPL
   +0x068 cntMBox          : 0n0
   +0x06c spwndGestureEngine : (null)
   +0x070 pvwplMessagePPHandler : (null)
   +0x074 fComposited      : 0y0
   +0x074 fIsDwmDesktop    : 0y1

!kvas 0xfe800000
kvas : Show region containing fe800000
### Start    End        Length (  MB)    Count Type   
000 fdc00000 ffbfffff  2400000 (  36)        8 SessionSpace

!ptelist 0xfe800000
ptelist : Using fe800000 as VA
VA       |PDE                                 |PTE                               
FE800000 |Hard Pfn=128E0 Attr=---DA--KWEV     |Hard Pfn=13FE1 Attr=---DA--KWEV

Here, we have the kernel address (0xfe800000) of an executable heap in 32 bits architecture.
According to the help from windbg: "Executable page. For platforms that do not support a hardware execute/noexecute bit, including many x86  systems, the E is always displayed.". Basically where NX is not present - Can anyone out there validate the executability of this heap on 0x64?
A kernel address that we got from user mode and a heap we can iterate and validate, also from user mode.
A heap we can fill with GUI objects. Shellcode anyone? Stack pivoting?
This heap is called the Desktop heap and is shared and mapped read only in the user mode region, between all processes that share the same desktop and session, independently of its integrity level.

!vad 84444c88
VAD     level      start      end    commit
85ccf578 ( 5)         10       1f         0 Mapped       READWRITE          Pagefile-backed section
8458f448 ( 1)        800      82f         4 Mapped  Exe  EXECUTE_WRITECOPY  \Windows\System32\notepad.exe
8518bb90 ( 5)        830     182f        41 Private      READWRITE        
85206270 ( 4)       1830     18f7         0 Mapped       READONLY           Pagefile-backed section
845ed280 ( 5)       1900     19de         0 Mapped       READONLY           Pagefile-backed section
84600e10 ( 3)       19e0     19ef         1 Private      READWRITE        
85935718 ( 5)       19f0     1aef       128 Private      NO_ACCESS        
85cb43e0 ( 4)       1af0     1bef       130 Private      NO_ACCESS        
845770c0 ( 2)       1bf0     1cf0         0 Mapped       READONLY           Pagefile-backed section
85220368 ( 4)       1d00     28ff         0 Mapped       READONLY           Pagefile-backed section
85e32560 ( 3)       2900     29ff         2 Private      NO_ACCESS        

Although this alone might get you interested in this portion of memory, I'm not going, in this post, to talk about the potential of using this heap on privilege escalation exploitation cases.
I'm going to focus only on tagCLS type objects and what we can do with the information they provide from a user mode perspective.

The tagCLS objects are created by the win32k module, specifically by the ClassAlloc function, that allocates them in the Desktop heap when called by InternalRegisterClassEx. This USER32 system call is invoked whenever the user32.dll counterpart, RegisterClassEx function, is used to register a window class (tagWNDCLASSEX).

typedef struct tagWNDCLASSEX {
  UINT      cbSize;
  UINT      style;
  WNDPROC   lpfnWndProc;
  int       cbClsExtra;
  int       cbWndExtra;
  HINSTANCE hInstance;
  HICON     hIcon;
  HCURSOR   hCursor;
  HBRUSH    hbrBackground;
  LPCTSTR   lpszMenuName;
  LPCTSTR   lpszClassName;
  HICON     hIconSm;

Let's see what the Desktop heap has for us, from user mode. To calculate its address we grab the pDeskInfo member from the TEB's Win32ClientInfo offset, and subtract the size of heap metadata (0x570). Having the heap's base address we can dump it now:

dt nt!_heap 0x01d00000
   +0x000 Entry            : _HEAP_ENTRY
   +0x008 SegmentSignature : 0xffeeffee
   +0x00c SegmentFlags     : 1
   +0x010 SegmentListEntry : _LIST_ENTRY [ 0xfe8000a8 - 0xfe8000a8 ]
   +0x018 Heap             : 0xfe800000 _HEAP
   +0x01c BaseAddress      : 0xfe800000 Void
   +0x020 NumberOfPages    : 0xc00
   +0x024 FirstEntry       : 0xfe800570 _HEAP_ENTRY
   +0x028 LastValidEntry   : 0xff400000 _HEAP_ENTRY
   +0x02c NumberOfUnCommittedPages : 0xbaa
   +0x030 NumberOfUnCommittedRanges : 1
   +0x034 SegmentAllocatorBackTraceIndex : 0
   +0x036 Reserved         : 0
   +0x038 UCRSegmentList   : _LIST_ENTRY [ 0xfe855ff0 - 0xfe855ff0 ]
   +0x064 Signature        : 0xeeffeeff
   +0x0a0 VirtualAllocdBlocks : _LIST_ENTRY [ 0xfe8000a0 - 0xfe8000a0 ]
   +0x0a8 SegmentList      : _LIST_ENTRY [ 0xfe800010 - 0xfe800010 ]
   +0x0b8 BlocksIndex      : 0xfe800138 Void
   +0x0c4 FreeLists        : _LIST_ENTRY [ 0xfe81ef70 - 0xfe8489b8 ]
   +0x0d0 CommitRoutine    : 0x91497343     long  win32k!UserCommitDesktopMemory+0
   +0x0d4 FrontEndHeap     : (null)
   +0x0d8 FrontHeapLockCount : 0
   +0x0da FrontEndHeapType : 0 ''
   +0x0dc Counters         : _HEAP_COUNTERS
   +0x130 TuningParameters : _HEAP_TUNING_PARAMETERS

All this information pertains to kernel mode, but we can easily determine an offset from the kernel mode values to user mode:

Evaluate expression: -55574528 = fcb00000

As we know that the first chunk of memory for a heap allocation is a HEAP_ENTRY, notice that the tagDESKTOPINFO is the first entry of the heap:

Evaluate expression: -25164424 = fe800578

Evaluate expression: 30410104 = 01d00578

Knowing the offset between kernel mode and user mode mappings of the Desktop heap, we can adjust the kernel addresses found and rebase them to user mode addresses. Doing so allows us to iterate through the whole heap, chunk by chunk.

dt nt!_HEAP_ENTRY 01d00570
   +0x000 Size             : 0x10

Evaluate expression: 30410224 = 01d005f0

dt nt!_HEAP_ENTRY 01d005f0
   +0x000 Size             : 4

Evaluate expression: 30410256 = 01d00610

dt nt!_HEAP_ENTRY 01d00610
   +0x000 Size             : 0x17

Etc. But I said we're going to hunt for tagCLS objects. Let's have a look at them. The size of a tagCLS structure is:

Evaluate expression: 100 = 00000064

But as 64 isn't a multiple of eight we need to round it up, giving:

Evaluate expression: 13 = 0000000d

So we need to seek for heap entries of size 0xd.

Recapitulating, the first heap chunk is a tagDESKTOPINFO.

Evaluate expression: 120 = 00000078

Evaluate expression: 30410224 = 01d005f0

So, our first seekable element is at 01d005f0, which is validated by our previous manual heap walking.
Although I could loop through all the heap entries, like before, I just need to find a first valid tagCLS to validate data. Let's then search for hints on objects sized 0xd then:

s -w 01d005f0 l1000 d
01d006c8  000d 0001 0017 0c00 06d0 ff68 8001 8001  ..........h.....
01d00734  000d 0900 3323 3732 3936 fe00 0018 0001  ....#32769......
01d00800  000d 0001 0018 0c00 0808 ff68 c039 c039  ..........h.9.9.

dt nt!_HEAP_ENTRY 01d006c8 
   +0x000 Size             : 0xd
   +0x002 Flags            : 0x1 ''
   +0x003 SmallTagIndex    : 0 ''
   +0x000 SubSegmentCode   : 0x0001000d Void
   +0x004 PreviousSize     : 0x17

This seems a valid entry. Let's dump it as tagCLS:

dt win32k!tagCLS 01d006c8+8 
   +0x000 pclsNext         : 0xff6806d0 tagCLS
   +0x004 atomClassName    : 0x8001
   +0x006 atomNVClassName  : 0x8001
   +0x008 fnid             : 0x29d
   +0x00c rpdeskParent     : 0x8585d678 tagDESKTOP
   +0x010 pdce             : (null)
   +0x014 hTaskWow         : 0
   +0x016 CSF_flags        : 0x41
   +0x018 lpszClientAnsiMenuName : (null)
   +0x01c lpszClientUnicodeMenuName : (null)
   +0x020 spcpdFirst       : (null)
   +0x024 pclsBase         : 0xffb22758 tagCLS
   +0x028 pclsClone        : (null)
   +0x02c cWndReferenceCount : 0n1
   +0x030 style            : 8
   +0x034 lpfnWndProc      : 0x914fcd91     long  win32k!xxxDesktopWndProc+0
   +0x038 cbclsExtra       : 0n0
   +0x03c cbwndExtra       : 0n0
   +0x040 hModule          : 0x91460000 Void
   +0x044 spicn            : (null)
   +0x048 spcur            : 0xffb75608 tagCURSOR
   +0x04c hbrBackground    : 0x00000002 HBRUSH__
   +0x050 lpszMenuName     : (null)
   +0x054 lpszAnsiClassName : 0xfe800738  "#32769"
   +0x058 spicnSm          : (null)

This is what we need. Let's get the tagDESKTOP address and validate it. This time we’ll be using the kernel to verify its address, by grabbing Win32ThreadInfo member from the TEB.

dt win32k!tagTHREADINFO 0xff9ba008 rpdesk
   +0x0c8 rpdesk : 0x8585d678 tagDESKTOP

Yes, it is the same. Now, if we search for all occurrences of this tagDESKTOP address in the Desktop heap, subtract 0xc from the obtained address, we get a list of all tagCLS objects in the heap.

Note that if I were to do a program or script to do this, I'd register a tagWNDCLASSEX with a known lpfnWndProc       like 0xbadecafe, seek for this value to locate my tagCLS object and get my corresponding tagDESKTOP; then, iterate all the heap items grabbing those with the same desktop. But, as I'm using the debugger for the demo, it's easier and simpler to do it this way.

s -d 01d005f0 l1000000 0x8585d678
01d00624  8585d678 fe800618 00040000 82000100  x...............
01d006dc  8585d678 00000000 00410000 00000000  x.........A.....
01d00754  8585d678 fe800748 00040000 80000100  x...H...........
01d00814  8585d678 00000000 00410000 00000000  x.........A.....
01d0088c  8585d678 fe800880 00040000 80000100  x...............
01d0096c  8585d678 00000000 03410000 00000000  x.........A.....
01d009e4  8585d678 fe8009d8 00000000 00000000  x...............
01d00a2c  8585d678 fe800a20 00000000 00000000  x... ...........
01d00a54  8585d678 00000000 00410000 00000000  x.........A........

The most interesting parts of a tagCLS are lpfnWndProc and hModule because these are user mode addresses that we can use and validate from user mode.

.foreach (meuval {s -[1]d 01d005f0 l1000000 0x8585d678 } )  {
   .if ((poi(${meuval}-0x14)&0x0000ffff) >= 0000000d) {
      .printf "ObjAddr=[%08x], hInstance[%08x], WndProc=",
       dds (${meuval}+28) l1;

Note: The search size given in the command above is greater or equal to the size of tagCLS, because the kernel can reserve some extra space if requested by the user, as indicated in the cbclsExtra class member.

ObjAddr=[fe800ac0], hInstance[00800000], WndProc=01d00af4  008072c5 notepad!NpSaveDialogHookProc+0x97
ObjAddr=[fe800b58], hInstance[76d60000], WndProc=01d00b8c  76d70666 USER32!ImeWndProcW
ObjAddr=[fe800dd0], hInstance[77090000], WndProc=01d00e04  770941b5 MSCTF!UIWndProc
ObjAddr=[fe800e38], hInstance[77090000], WndProc=01d00e6c  770fdd77 MSCTF!UIComposition::CompWndProc
ObjAddr=[fe805228], hInstance[749f0000], WndProc=01d0525c  74a1fe38 COMCTL32!CListView::s_WndProc
ObjAddr=[fe805490], hInstance[749f0000], WndProc=01d054c4  74a16022 COMCTL32!Header_WndProc
ObjAddr=[fe807320], hInstance[01000000], WndProc=01d07354  01003429
ObjAddr=[fe814950], hInstance[70830000], WndProc=01d14984  708432bc
ObjAddr=[fe814ba8], hInstance[70830000], WndProc=01d14bdc  708431dc
ObjAddr=[fe814c40], hInstance[70830000], WndProc=01d14c74  70842954
ObjAddr=[fe82b580], hInstance[77820000], WndProc=01d2b5b4  778663e5 ole32!OleMainThreadWndProc
ObjAddr=[fe82cb70], hInstance[00800000], WndProc=01d2cba4  008014de notepad!NPWndProc
ObjAddr=[fe842790], hInstance[77090000], WndProc=01d427c4  770fdd77 MSCTF!UIComposition::CompWndProc
ObjAddr=[fe8428a8], hInstance[76d60000], WndProc=01d428dc  76db3f06 USER32!EditWndProcW
ObjAddr=[fe842910], hInstance[749f0000], WndProc=01d42944  749f99d0 COMCTL32!Edit_WndProc
ObjAddr=[fe842ac8], hInstance[749f0000], WndProc=01d42afc  74a90d49 COMCTL32!StatusWndProc
ObjAddr=[fe843c78], hInstance[01010000], WndProc=01d43cac  01044270

Dumping lpfnWndProc and hModule from all the tagCLS objects found in the desktop heap, we can observe that all the user windows message dispatch handlers registered in the system for the current desktop are available for analysis from user mode. From the dump above I've identified two from notepad: NpSaveDialogHookProc and NPWndProc which is the main window dispatcher function; and module 0x01000000. This entire post is about module 0x01000000.

Module 0x01000000 is popo.exe as can be seen from the procExp.

Figure 2: Packed popo.exe module address.

And the address from WndProc at memory position 0x1d07354, 0x01003429 is the NPWndProc windows message handler dispatcher function from popo.exe as seen in the figure. The figure shows the unpacked version of popo.exe so that symbol resolution is available.
 Figure 3: Window dispatcher registration.

Figure 4: Window dispatcher registration arguments.

So here you have it. A fine simple non-invasive way of getting some information from packed or protected applications.

Other thoughts: Do you think that the same info is available for Protected (Media Path) processes? Those to which we were not supposed to get any info about?
Is there any information available for other desktops windows if in the same session? Can we link this data in any way with the aheList?

Hope you enjoyed it.