Welcome to the new Woodmann RCE Messageboards Regroupment
Please be patient while the rest of the site is restored.

To all Members of the old RCE Forums:
In order to log in, it will be necessary to reset your forum login password ("I forgot my password") using the original email address you registered with. You will be sent an email with a link to reset your password for that member account.

The old vBulletin forum was converted to phpBB format, requiring the passwords to be reset. If this is a problem for some because of a forgotten email address, please feel free to re-register with a new username. We are happy to welcome old and new members back to the forums! Thanks.

All new accounts are manually activated before you can post. Any questions can be PM'ed to Kayaker.

OllyScript/ODbgScript: great GPA bug !

Bugs/suggestions/scripts/... for OllyScript plugin

OllyScript/ODbgScript: great GPA bug !

Post by shERis »

BUG in GPA !
There is a great bug in GPA, but I don´t know how to solve this problem. (I posted it long time before, but there is no solution.)

If you have a command GPA "Any_Proc","COMCTL32.DLL", you´ll get a wrong (non existing) address of this "Any_Proc". :(
Why :confused: ?

I tried the following:
1. I loaded notepad.exe in Olly (could be another app using COMCTL32.DLL)
2. I made a little script:
gpa "CreateToolbar","COMCTL32.DLL"
mov addr,$RESULT
gn addr
and loaded it
3. I singlestepped the script and
4. gn addr fails to get the name of CreateToolbar, it results 0! :(

Furthermore I tried the following:
1. I loaded notepad.exe in a first instance of Olly (could be another app using COMCTL32.DLL)
2. I made a little script:
gpa "CreateToolbar","COMCTL32.DLL"
mov addr,$RESULT
gn addr
and loaded it
3. I started another instance of Olly, attached first instance of Olly and run it
4. I set a BP on CALL near kernel32.LoadLibraryA in GPA command in ODbgScript-section in second instance of Olly and run the second instance
5. I singlestepped the script in first instance of Olly with S
6. Olly stopps in second instance at that CALL LoadLibraryA as wanted
7. Wonder :confused:

I found the following:
In second instance of Olly there are all plugins in shown memory, in first instance not.

In first instance there is COMCTL32 in a high memory space. But in second instance of Olly there is at the same place a DLL called COMCTL_1. And there is at another memory place COMCTL32!!! At this address there is nothing in first instance of Olly! GPA now examines the address of CreateToolbar in COMCTL32 in second instance in a lower space and gives it to $RESULT. But in first instance of Olly this address is invalid!!!

GPA results the proc addresses of the named proc in OllyDbg process and NOT in the app process !!!
All other commands seem to be executed in app process.

Does anybody know how to get proc addresses in another loaded process (it is the loaded app process, here in the example notepad.exe) ?

1st instance of Olly debugs app (notepad.exe).
2nd instance of Olly debugs Olly of 1st instance.

ODbgScript is loaded by Olly - it´s loaded in both instances! But only in 2nd instance you can debug ODbgScript and set a BP on CALL kernel32.LoadLibraryA in ODbgScript code.
When you run a script with GPA then 2nd Olly breaks at LoadLibraryA.

But when you look at memory map window in both Olly´s, you´ll find the following (address could vary for you):

1st instance:
71950000 COMCTL32

2nd instance:
71950000 COMCTL_1
77310000 COMCTL32

When you execute GPA, then it results addresses of COMCTL32 in 2nd instance, it doesn´t matter in what instance of Olly you do. You´ll always get 77310000. But this is wrong!
It seems that Olly (1st instance) loads COMCTL32 twice in its process. One for the app and one for Olly itself.
But the right version of COMCTL32 is renamed to COMCTL_1, which has the same address. Therefore you´ll always get the wrong address of 2nd COMCTL32, which does not exist in app process.
So it is necessary to get proc address in app process and not in Olly process.

This ugly behaviour is only with COMCTL32.DLL. All other libs are at the same memory location in 1st and 2nd instance of Olly, therefore reading app process or Olly process doesn´t matter. But GPA always should result app process !!!

I played a little bit with OllyDbg and found the following:
When Olly is loaded, COMCTL32 from windows system32 directory is loaded into memory. It is shown as COMCTL32 in memory map window.
When Olly begins to run, it loads COMCTL32 from windows WinSxS\x86_Microsoft.Windows.Common-Controls..... directory using kernel32.LoadLibraryW/kernel32.LoadLibraryExW/ntdll.LdrLoadDll. With ntdll.RtlDosApplyFileIsolationRedirection_Ustr the WinSxS path is added to filename.
COMCTL32 therefore is loaded twice. The both versions are not identical. (Process Explorer shows it very well.)
To make a difference between the two instances windows changes the owner name to COMCTL_1 of the second COMCTL32.
I don´t know why Olly does this and this is our problem.

I think there should be a simple possibility to get the proc addresses of the loaded modules in the debugged process using
VAL_HPROCESS (HANDLE) Handle of debugged process
VAL_PROCESSID Process ID of debugged process
information of Plugingetvalue(int type).

Sysinternals Process Explorer shows it in a very effective way.

But I am no windows programmer.

Please help me and Epsylon3 if you know the necessary code to get the right proc address. Any ideas are welcome.

User avatar
Posts: 4169
Joined: Thu Oct 26, 2000 11:00 am

Post by Kayaker »


I don't know if this helps at all, I'm just trying to figure out this strange occurrence of two comctl32.dll instances that Olly displays, as you say, one from C:\WINDOWS\system32\COMCTL32.dll and one from C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_..\comctl32.dll.

I noticed the same thing when working on the Conditional Branch Logger (CBL) Plugin with Blabberer and dELTA, we discussed it a bit but didn't really pay it too much mind. So I decided to see what CBL might do with it and it seems that both versions of the dll are actually used, but in slightly different ways. This might have some bearing on your own problem of finding the "correct" API.

I'm not trying to promote the plugin, just using it as a tool here to dig up some info. We just finished writing the darn thing but I don't think any of us have actually *used* it for anything practical, so forgive me for the step by step description that follows, I'm just learning how to use it too ;)

So, I open up notepad in Olly and it breaks on the Entry Point.
In the Executable Modules window (Alt-E) you see both dll versions listed, COMCTL32 and COMCTL_1.
Let's deal with one at a time.

Step 1:

Right click on COMCTL32 and select the menu option
Conditional Branch Logger -> Add code section as Include range for Selected module
The CBL plugin will tell Olly to analyze the module first then it will add the entire COMCTL32 code section as a logged range.
From the main Olly menu select
Plugins -> Conditional Branch Logger -> Configuration
This will open the gui dll dialog and you should see the added logged range. Make sure it's the only one selected and press OK to close the dialog.
In a couple of seconds you should see about 15000 conditional jumps listed in the CBL jump window with conditional breakpoints set.

Now, and this is important, select from the main Olly menu
Debug -> Restart (Ctrl-F2)

What you should see is the COMCTL32 module running in the CPU window and all the conditional breakpoints being logged in the CBL jump table window. It'll go on for ages, so..
- Press the Pause button from the Olly toolbar
- Right click in the CBL jump table window and select Disable All Breakpoints or Delete All Entries
- Press the Run button from the Olly toolbar (F9) to continue execution

Olly should stop once again at the Entry Point (EP) of notepad.

The point of all this was to prove that the "COMCTL32" version is used during the loading of the PE file, even before the EP of the target is reached.

Step 2:

Now we'll repeat the above process with the 2nd loaded version of comctl32.dll that is named COMCTL_1

Right click in the CBL jump table window and select Delete All Entries to clear the previous work
Right click on COMCTL_1 in the Executable Modules window and again select the menu option
Conditional Branch Logger -> Add code section as Include range for Selected module
Again open up the gui dll dialog and make sure ONLY the COMCTL_1 code section is selected in the Logged (included) range edit box. Close the dialog, wait a couple of seconds and note the new set of breakpoints set up in the CBL window.

Once again, start a fresh instance of notepad with
Debug -> Restart (Ctrl-F2)

This time, Olly should stop immediately at the EP of notepad *without* any of the breakpoints that were set in COMCTL_1 being hit. In other words, the "COMCTL_1" version is NOT used while the PE file is being loaded.

You can continue doing some more testing. With the COMCTL_1 breakpoints still set, tell Olly to run the program, notepad should open. Now select File/Open from notepad. The CBL plugin should start logging a whole bunch of COMCTL_1 breakpoints.

This means that this 2nd version of comctl32 IS being used. Try the same thing with the COMCTL32 named version (i.e. run notepad and use it). You may also see this version being used under some conditions.

All I'm trying to point out here, and it has nothing to do with CBL or conditional jumps, is just that it looks like BOTH versions of comctl32.dll are used. I can't explain why or under what conditions, but you'll have to take that into account if you're trying to figure out which version you should be getting your API addresses from.

Hope this all made sense.

Senior Member
Posts: 1535
Joined: Wed Dec 08, 2004 11:12 am

Post by blabberer »

I noticed the same thing when working on the Conditional Branch Logger (CBL) Plugin with Blabberer and dELTA, we discussed it a bit but didn't really pay it too much mind
it has got something to do with uxtheme , manifests and the snazzy ubercool windoze themes

if there is a manifest file indicating thats shared side by side assemblies are used then the second comctl_dll is loaded and used else old comctl_5 in system directory is used

and as far as i can recall shell32.dll has a manifest that states the loader to load this comctl at the later stages

by the way if you want it from horses's mouth
We fully realize that the new ComCtl32 has the potential to break some applications. To prevent this, ComCtl32 version 6 is installed as a shared assembly, side-by-side with ComCtl32 version 5, which is installed in the System32 directory. The new DLL is only available to applications that provide a manifest telling the operating system that they work with the new DLL. If they do not provide a manifest, existing applications continue to use ComCtl32 version 5. Versions 5 and 6 both ship with Windows XP and are installed side-by-side. We'll talk more about manifests in the next section.

Post by shERis »

Hy Kayaker, hi blabberer!
Thanx for your fast answers! :)

I did know that all. OllyDbg uses COMCTL32.DLL from the system32 dir.
But the app (notepad.exe) uses COMCTL32.DLL from C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_..\.

The problem is that OdbgScript has OllyDbg as base and therefore uses COMCTL32.DLL from system32 dir! :(

I read in microsoft msdn library about manifests (http://msdn2.microsoft.com/en-us/librar ... S.80).aspx and so on) using your hint.

The app determines with manifests, which version of COMCTL32.DLL is used by the app. The used version is stored in C:\Windows\WinSxS dir by installation process. So it is possible, that an app loads different versions of COMCTL32.DLL in runtime. :-/

How can OdbgScript evaluate, which version (system32\ dir, WinSxS\{dll version}\ dir should be loaded? :confused:

I think it should be enough to attach the loaded COMCTL32.DLL of the app. But I dont know how. Perhaps somebody has an idea. With kernel32.GetProcAdress of the app it could be possible.

User avatar
Posts: 4169
Joined: Thu Oct 26, 2000 11:00 am

Post by Kayaker »

shERis wrote:OllyDbg uses COMCTL32.DLL from the system32 dir.
From the indications I had assumed that it wasn't Ollydbg using the default version of COMCTL32 but probably other system dlls used by the target which use that version. Else why would breakpoints be hit in the default version when the PE is loading and also when you select some of the menu items of notepad? If you were to trace through the Olly stack window while this is happening you would definitely see references to notepad and the relevant dll functions that were being called because of it. Notepad may use COMCTL_1 for most of the purposes you are interested in, but it also uses COMCTL32, at least indirectly and under Olly, at other times.

You're right though, ProcessExplorer and Depends recognize the WinSxS version as the correct bound dll, so perhaps parsing the PEB.InLoadOrderModuleList is all that you need to do. The full path can be found in LDR_MODULE.FullDllName.

If not, this may be a hack idea, but you could scan for the second instance of comctl32 (COMCTL_1) in the Executable Modules window (Plugingetvalue(VAL_MODULES)). It's normally marked as a non-system dll unless the user changes that setting, (t_module->issystemdll) as Blabberer pointed out to me. If it exists then change the search path to prioritize (t_module->path) by using the SetDllDirectory function before your gpa LoadLibraryEx call along with your LOAD_WITH_ALTERED_SEARCH_PATH flag. This way C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_..\ will be checked before the system directory, according to the docs.
User avatar
Posts: 4169
Joined: Thu Oct 26, 2000 11:00 am

Post by Kayaker »

Well it turns out that parsing the PEB InLoadOrderModuleList won't differentiate between the two comctl32 versions, both are listed as loaded by this method.

However, here is a plugin routine for doing that and could be adapted for finding other PEB items of the debugged target. Accessing the PEB of the debugee requires reading the memory of the target for certain items. This routine can be placed directly in an existing plugin, the project files are attached.

Code: Select all


	Output currently loaded modules as listed by
	PEB InLoadOrderModuleList

BOOL DebugeeModuleList()

	NTSTATUS					ntstatus;
	ULONG						ReturnLength;
	HANDLE					hProcess;
	PPEB					PebBaseAddress;
	PEB						Peb;

	PLIST_ENTRY				pInLoadOrderModuleList;
	PLIST_ENTRY				pInLoadOrderModuleListHead;

	ULONG					pDllBase;
	PUNICODE_STRING			pusBaseDllPath;
	UCHAR					UnicodeStr[512];
	UCHAR					AsciiStr[256];


	HMODULE hNtDll = GetModuleHandle("ntdll.dll");
        return FALSE;

	pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)GetProcAddress(
									hNtDll, "NtQueryInformationProcess");

        return FALSE;

	// Handle of debugged process
	hProcess = (HANDLE)Plugingetvalue(VAL_HPROCESS);

	ntstatus = pNtQueryInformationProcess(hProcess,

	if(ntstatus == STATUS_SUCCESS)
		PebBaseAddress = (PPEB) ProcessInfo.PebBaseAddress;

		// Read PEB in address space of debugee
		ReadProcessMemory(hProcess, (PPEB) PebBaseAddress, 
			&Peb, sizeof (PEB), NULL);

		// Read PEB_LDR_DATA in address space of debugee
		ReadProcessMemory(hProcess, (PPEB_LDR_DATA) Peb.Ldr, 
			&Ldr, sizeof (PEB_LDR_DATA), NULL);

		// Pointer to InLoadOrderModuleList
		pInLoadOrderModuleList = (PLIST_ENTRY) &Ldr.InLoadOrderModuleList;

		// Save the first InLoadOrderModuleList entry
		pInLoadOrderModuleListHead = pInLoadOrderModuleList->Flink;

		Addtolist(0, 1, "Currently loaded modules as listed by PEB InLoadOrderModuleList" );
		Addtolist(0, 1, " Base Address      Name");

		// Walk the list
			// Read in turn each LDR_DATA_TABLE_ENTRY in address space of debugee
			ReadProcessMemory(hProcess, (PLDR_DATA_TABLE_ENTRY) pInLoadOrderModuleList->Flink, 
				&LdrDataTableEntry, sizeof (LDR_DATA_TABLE_ENTRY), NULL);
			// Increment to next LDR_DATA_TABLE_ENTRY in load order
			// This is a duplicate LIST_ENTRY to that contained in PEB_LDR_DATA
			pInLoadOrderModuleList = &LdrDataTableEntry.InLoadOrderModuleList;

			// Exit if we've gone the complete cycle of linked lists
			if(pInLoadOrderModuleList->Flink == pInLoadOrderModuleListHead)

			// Module base address	
			pDllBase = (ULONG) LdrDataTableEntry.DllBase;

			// A pointer to the Module path	
			pusBaseDllPath = (PUNICODE_STRING) &LdrDataTableEntry.FullDllName;

			// Read Module path string in address space of debugee
			ReadProcessMemory(hProcess, pusBaseDllPath->Buffer, 
				&UnicodeStr, pusBaseDllPath->MaximumLength, NULL);
			// Convert Unicode string to ASCII string
			WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)UnicodeStr, -1,
				(LPSTR)AsciiStr, 256, NULL, NULL);			
			// Output to OllyDbg log window
			Addtolist(0, 1, " %.8X      %s", pDllBase,
						(long) AsciiStr	);

		} while(pInLoadOrderModuleList->Flink != pInLoadOrderModuleListHead);

   return TRUE;

Here's the output from the log window. The first part is what Olly reports, the second part is from parsing the PEB.
Notice that there is 1 dll listed through InLoadOrderModuleList that *isn't* listed by OllyDbg - umdmxfrm.dll. Not sure why, a bug? a different method of determining loaded modules? module not really loaded but still listed under InLoadOrderModuleList?

Code: Select all

           File 'C:\OllyDbg\Projects\NOTEPAD.EXE'
           New process with ID 000008A0 created
01006420   Main thread with ID 00000B98 created
01000000   Module C:\OllyDbg\Projects\NOTEPAD.EXE
5D090000   Module C:\WINDOWS\system32\COMCTL32.dll
73000000   Module C:\WINDOWS\system32\WINSPOOL.DRV
763B0000   Module C:\WINDOWS\system32\comdlg32.dll
77C10000   Module C:\WINDOWS\system32\msvcrt.dll
77D40000   Module C:\WINDOWS\system32\USER32.dll
77DD0000   Module C:\WINDOWS\system32\ADVAPI32.dll
77E70000   Module C:\WINDOWS\system32\RPCRT4.dll
77F10000   Module C:\WINDOWS\system32\GDI32.dll
77F60000   Module C:\WINDOWS\system32\SHLWAPI.dll
7C800000   Module C:\WINDOWS\system32\kernel32.dll
7C900000   Module C:\WINDOWS\system32\ntdll.dll
7C9C0000   Module C:\WINDOWS\system32\SHELL32.dll
5CB70000   Module C:\WINDOWS\system32\ShimEng.dll
6F880000   Module C:\WINDOWS\AppPatch\AcGenral.DLL
76B40000   Module C:\WINDOWS\system32\WINMM.dll
774E0000   Module C:\WINDOWS\system32\ole32.dll
77120000   Module C:\WINDOWS\system32\OLEAUT32.dll
77BE0000   Module C:\WINDOWS\system32\MSACM32.dll
77C00000   Module C:\WINDOWS\system32\VERSION.dll
769C0000   Module C:\WINDOWS\system32\USERENV.dll
5AD70000   Module C:\WINDOWS\system32\UxTheme.dll
773D0000   Module C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_
5CD70000   Module C:\WINDOWS\system32\serwvdrv.dll
01006420   Program entry point

           Currently loaded modules as listed by PEB InLoadOrderModuleList
            Base Address      Name
            01000000      C:\OllyDbg\Projects\NOTEPAD.EXE
            7C900000      C:\WINDOWS\system32\ntdll.dll
            7C800000      C:\WINDOWS\system32\kernel32.dll
            763B0000      C:\WINDOWS\system32\comdlg32.dll
            77F60000      C:\WINDOWS\system32\SHLWAPI.dll
            77DD0000      C:\WINDOWS\system32\ADVAPI32.dll
            77E70000      C:\WINDOWS\system32\RPCRT4.dll
            77F10000      C:\WINDOWS\system32\GDI32.dll
            77D40000      C:\WINDOWS\system32\USER32.dll
            77C10000      C:\WINDOWS\system32\msvcrt.dll
            5D090000      C:\WINDOWS\system32\COMCTL32.dll
            7C9C0000      C:\WINDOWS\system32\SHELL32.dll
            73000000      C:\WINDOWS\system32\WINSPOOL.DRV
            5CB70000      C:\WINDOWS\system32\ShimEng.dll
            6F880000      C:\WINDOWS\AppPatch\AcGenral.DLL
            76B40000      C:\WINDOWS\system32\WINMM.dll
            774E0000      C:\WINDOWS\system32\ole32.dll
            77120000      C:\WINDOWS\system32\OLEAUT32.dll
            77BE0000      C:\WINDOWS\system32\MSACM32.dll
            77C00000      C:\WINDOWS\system32\VERSION.dll
            769C0000      C:\WINDOWS\system32\USERENV.dll
            5AD70000      C:\WINDOWS\system32\UxTheme.dll
            773D0000      C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_ 
            5CD70000      C:\WINDOWS\system32\serwvdrv.dll
            5B0A0000      C:\WINDOWS\system32\umdmxfrm.dll
I don't know if this helps your cause, you may have to come up with another way of doing what you need.

(4.12 KiB) Downloaded 279 times

Post by shERis »

Wow! :)
That´s a lot of information, Kayaker! You are really good! Great thanks! :yay:

I think, this could be one way of determining the proc addresses.

But now I cannot do more.

I hope Epsylon3 will read this thread and use your information to create a full working GPA command!

Epsylon3, please help me!

Senior Member
Posts: 129
Joined: Fri May 26, 2006 5:10 pm
Location: France

Post by Epsylon3 »

Yea, i can read it... but have some problems to understand all... i need to test it...

Will try to find time to do that.... but i'm on a new kind of mission since few weeks and have no vacations for the moment...

could you try to force load the module (with full path, or not) in dbg app with the example script from the wiki

This example will call a LoadLibraryEx in dbg app... if the module is already loaded, it does nothing, but with that you can set bp in module before app really load it (dynamically)
Senior Member
Posts: 129
Joined: Fri May 26, 2006 5:10 pm
Location: France

Post by Epsylon3 »

thanks for sources Kayaker, i was also trying to do things with PEB (locally), to replace previous script in one command...