PDA

View Full Version : How to view OllDbg plugin API names instead of import ordinals?


5aLIVE
August 5th, 2013, 14:37
Just for fun I wanted to disassemble the plugin called OllyFlow v0.71 by Henryouly.

First I tried loading it into IDA and prompted to supply the path for the ollydbg.dll module which doesn't exist.
kao on the tuts4you forum showed me a neat trick and renamed ollydbg.exe to ollydbg.dll to make IDA correctly display the used imported OllyDbg plugin API names instead of the ordinals.

By creating a .map file and importing it into Olly using the MapConv plugin let me see the missing API names.

I want to know if it is possible to display these API names in Olly without the assistance of IDA?

edit: if I hit Ctrl-N I get:
http://i41.tinypic.com/2rp5g5w.jpg

Hitting Enter on a selected import to find its references I get:
http://i41.tinypic.com/10oh9vs.png

Then following a reference in the disassembler shows:
http://i41.tinypic.com/30jmona.jpg

So the names are there but they aren't available for searching using Ctrl-N.
Is the any way to resolve the import API names?


Thanks in advance,
5aLIVE.

blabberer
August 11th, 2013, 05:03
your attachments are not visible

i am not sure what names are shown as ordinals in ollyflow

i just loaded ollydbg on ollydbg and in the debugger ollydbg
went to executable modules (alt+e) -> right click -> view names (ctrl+N)

all imports by ollydflow seems to be visible for me

Code:

Names in OllyFlow, item 0
Address=100080F8
Section=.rdata
Type=Import
Name=OLLYDBG.#101__Readmemory


Names in OllyFlow, item 5
Address=10008108
Section=.rdata
Type=Import
Name=OLLYDBG.#172__Sendshortcut

5aLIVE
August 11th, 2013, 09:59
Hi Blabberer, thank you for taking the time to look at this. I've fixed the image links in my initial post now.

I am now able to see the OllyFlow plugin API names using the method you describe.

Here are the API names:
http://i43.tinypic.com/nmymgn.png

I didn't make it clear that I wanted to know if it there is a way to view the imported plugin API names when loading the plugin on its own using loaddll.exe. Is it possible to do this?

blabberer
August 12th, 2013, 19:10
well you made me finish an unfinished project that's been breathing dust for 6 years now
i started this when someone asked a similar question somewhere else but never got to finish this

tested on ollyflow.dll only may have bugs use with caution and report back if you find this plugin erased your ollydbg directory
use ctrl+n again to view modified import names

Code:


#include <windows.h>
#include <stdio.h>
#include "plugin.h"

HINSTANCE hinst;
HWND hwmain;

void ord2name(void) {
char buffer[0x10],label[TEXTLEN];
ulong importpointer,thunkpointer,address,seladdr;
t_module *dllwithord = NULL;
t_dump *dump = (t_dump *)Plugingetvalue(VAL_CPUDASM);
seladdr = dump->sel0;
dllwithord = Findmodule(seladdr);
for(address = dllwithord->codebase; address < dllwithord->codebase+dllwithord->codesize; address++)
{
Readmemory(buffer,address, 16, MM_SILENT|MM_RESTORE);
if ((*buffer == 0xFF) && (*(buffer+1) == 0x25))
{
memset(label,0,256);
importpointer = 0;
thunkpointer = 0;
Readmemory((void *)&importpointer, address+2, 4, MM_SILENT|MM_RESTORE);
if ((importpointer > dllwithord->codebase) && (importpointer < dllwithord->base+dllwithord->size))
{
Readmemory((void *)&thunkpointer, importpointer, 4, MM_SILENT|MM_RESTORE);
if (Findname(thunkpointer, NM_EXPORT, label) != 0)
{
Insertname(importpointer,NM_IMPORT,label);
}
}
}
}
Redrawdisassembler();
};

BOOL WINAPI DllMain( HINSTANCE hi, DWORD reason, LPVOID reserved )
{
UNREFERENCED_PARAMETER( reserved );
if (reason==DLL_PROCESS_ATTACH)
hinst=hi;
return 1;
};

extc int _export _cdecl ODBG_Plugininit( int ollydbgversion, HWND hw, ulong *features )
{
UNREFERENCED_PARAMETER( features );
if (ollydbgversion<PLUGIN_VERSION)
{
return -1;
}
Addtolist(0,0,"ollydbg 1.10 import ordinal to import name Plugin ord2name by blabberer";
hwmain=hw;
return 0;
};

extc int _export _cdecl ODBG_Plugindata( char shortname[32] )
{
strcpy_s( shortname, 30, "ord2name" );
return PLUGIN_VERSION;
};

extc int _export _cdecl ODBG_Pluginmenu( int origin, char data[4096], void *item )
{
UNREFERENCED_PARAMETER( item );
switch (origin)
{
case PM_MAIN:
strcpy_s( data, 4000, "0 &ord2name" );
return 1;
default:
break;
};
return 0;
};

extc void _export cdecl ODBG_Pluginaction(int origin,int action,void *item)
{
UNREFERENCED_PARAMETER( item );
if (origin==PM_MAIN)
{
switch (action)
{
case 0:
ord2name();
break;
default:
break;
};
};
};



attachement modified with latest correction

Code:


F:\plug110\test\ord2name>fc ord2name.cpp old_ord2name_odbg_plugin\ord2name.cpp
Comparing files ord2name.cpp and OLD_ORD2NAME_ODBG_PLUGIN\ORD2NAME.CPP
***** ord2name.cpp
void ord2name(void) {
char buffer[0x10],label[TEXTLEN],decode[TEXTLEN],comment[TEXTLEN];
ulong importpointer,thunkpointer,address,seladdr;
***** OLD_ORD2NAME_ODBG_PLUGIN\ORD2NAME.CPP
void ord2name(void) {
char buffer[0x10],label[TEXTLEN];
ulong importpointer,thunkpointer,address,seladdr;
*****

***** ord2name.cpp
{
Decodeaddress(thunkpointer,seladdr,ADC_DIFFMOD,decode,
TEXTLEN,comment);
Insertname(importpointer,NM_IMPORT,decode);
}
***** OLD_ORD2NAME_ODBG_PLUGIN\ORD2NAME.CPP
{
Insertname(importpointer,NM_IMPORT,label);
}
*****


F:\plug110\test\ord2name>


modifed code and attachment posted in a later thread

5aLIVE
August 13th, 2013, 02:50
Thank you very much indeed for taking this off the dusty shelf.

It appears to work well, but with one small glitch. If you look at the first three import names in the list you can see that they are missing the prefixed name of the import library, KERNEL32 in this case.

http://i44.tinypic.com/jt9wz8.png

blabberer
August 13th, 2013, 06:02
thanks for report module names should be visible now check earlier post
for modified dll

5aLIVE
August 13th, 2013, 06:47
You're very welcome. The affected module names can now be seen but they are lowercase when all the others are in uppercase.

I also noticed that the module name for RtlUnwind before your ord2name plugin is run is shown as KERNEL32 after running the plugin it changes to "ntdll" as can be seen below.

Code:

Before plugin use:

Names in OllyFlow
Address Section Type ( Name Comment
008780E4 .rdata Import ( KERNEL32.GetACP
008780E8 .rdata Import ( KERNEL32.GetOEMCP
00878034 .rdata Import ( KERNEL32.RtlUnwind


After plugin use:
Names in OllyFlow
Address Section Type ( Name Comment
008780E4 .rdata Import ( kernel32.GetACP
008780E8 .rdata Import ( kernel32.GetOEMCP
00878034 .rdata Import ( ntdll.RtlUnwind


blabberer
August 21st, 2013, 01:08
case was easier just or ADC_UPPERCASE job done
but finding how ollydbg handles forwarded api naming was time consuming

finally think i ironed out both the issues you reported
in the process i also added support for mfc ordinals to names

reversing mfc in ollydbg should be a bit easier with names now instead of #5560

note to all this plugin gets the names in ollyflow because name is available natively

for mfc application the name information do not exist in the dll
so you would need the pdb for each of the mfcXXS.dll where xx can be from 42 to 90 and s can be null and d to indicate mfc version 42 debug dll

to fetch pdb and load it in ollydbg you can look for my symbol loader plugin i posted earlier in this forum

mfc ordinal to name tested on one throwaway box and one exe (google mfc crackme first hit crackme by illitirit in dogs on acid forum)
any bug reports welcome
also in general if name info is available in either pdb or natively this plugin should handle it now.

28012802


Code:

#include <windows.h>
#include <stdio.h>
#include "plugin.h"

// skif 0xff 0x25 jmp <import> opcodes to grab address
#define SKIPBYTES 2

HINSTANCE hinst;
HWND hwmain;

void ord2name(void)
{
unsigned long importpointer = 0;
unsigned long thunkpointer = 0;
unsigned long address = 0;
unsigned long seladdr = 0;
char buffer[TEXTLEN] = {0};
char label[TEXTLEN] = {0};
char decode[TEXTLEN] = {0};
char impname[TEXTLEN] = {0};
char comment[TEXTLEN] = {0};
char strstr_buff[TEXTLEN] = {0};
t_module *dllwithord = NULL;
t_dump *dump = (t_dump *)Plugingetvalue(VAL_CPUDASM);
seladdr = dump->sel0;
dllwithord = Findmodule(seladdr);
for(address = dllwithord->codebase; address < dllwithord->codebase+dllwithord->codesize; address++)
{
Readmemory(buffer,address, MAXCMDSIZE, MM_SILENT|MM_RESTORE);
if ((*buffer == 0xFF) && (*(buffer+1) == 0x25))
{
importpointer = 0;
thunkpointer = 0;
char *pch;
Readmemory((void *)&importpointer, (address + SKIPBYTES ), sizeof(unsigned long), MM_SILENT|MM_RESTORE);
if ((importpointer > dllwithord->codebase) && (importpointer < dllwithord->base+dllwithord->size))
{
Readmemory((void *)&thunkpointer, importpointer, sizeof(unsigned long), MM_SILENT|MM_RESTORE);
if (Findname(thunkpointer, NM_EXPORT, label) != 0)
{

Findname(importpointer, NM_IMPORT, impname);
Decodeaddress(thunkpointer,seladdr,ADC_DIFFMOD | ADC_UPPERCASE ,decode,TEXTLEN,comment);
strncpy_s( strstr_buff, decode,sizeof(decode));
pch = strstr(strstr_buff , label);
*pch = '\0';
if( ( strncmp(strstr_buff,impname,strlen(strstr_buff))) == 0)
{
Insertname(importpointer,NM_IMPORT,decode);
}
}
if (Findname(thunkpointer, NM_LIBRARY, label) != 0)
{
Insertname(importpointer,NM_IMPORT,label);
}
}
}
}
Redrawdisassembler();
};

BOOL WINAPI DllMain( HINSTANCE hi, DWORD reason, LPVOID reserved )
{
UNREFERENCED_PARAMETER( reserved );
if (reason==DLL_PROCESS_ATTACH)
hinst=hi;
return 1;
};

extc int _export _cdecl ODBG_Plugininit( int ollydbgversion, HWND hw, ulong *features )
{
UNREFERENCED_PARAMETER( features );
if (ollydbgversion<PLUGIN_VERSION)
{
return -1;
}
Addtolist(0,0,"ollydbg 1.10 import ordinal to import name Plugin ord2name by blabberer";
hwmain=hw;
return 0;
};

extc int _export _cdecl ODBG_Plugindata( char shortname[32] )
{
strcpy_s( shortname, 30, "ord2name" );
return PLUGIN_VERSION;
};

extc int _export _cdecl ODBG_Pluginmenu( int origin, char data[4096], void *item )
{
UNREFERENCED_PARAMETER( item );
switch (origin)
{
case PM_MAIN:
strcpy_s( data, 4000, "0 &ord2name" );
return 1;
default:
break;
};
return 0;
};

extc void _export cdecl ODBG_Pluginaction(int origin,int action,void *item)
{
UNREFERENCED_PARAMETER( item );
if (origin==PM_MAIN)
{
switch (action)
{
case 0:
ord2name();
break;
default:
break;
};
};
};


attached a vs2010 express project with compiled binary below
2803

5aLIVE
August 21st, 2013, 09:56
Brilliant! The addition of mfc ordinals naming is bound to be a great help. I have a little program in mind that uses MFC to test this on. So I'll report back my findings once I get your winapihelp plugin up and running.

update #1: Well, I'm not entirely sure which symbol loader plugin you mean so I tried using a patched OllyDbg with symsrv.dll copied to a fresh copy of Olly.

A snippet from the Ollys log shows:
C:\WINDOWS\WinSxS\x86_Microsoft.VC80.MFCLOC_1fc8b3b9a1e18e3b_8.0.50727.6195_x-ww_6a5bb789\MFC80ENU.DLL
Debugging information (Microsoft format) available

Viewing the modules names after running the ord2name plug has no effect so presumably I am doing something wrong?

Taking a peek inside mfc80.udd shows ordinals only, by contrast other system .udd files have both ordinals and API names. So it is appears to me that I need a different method of obtaining debug symbols for mfc80.dll. Can you tell me how to grab and load .pdb file please?

Do I use the method you describe in this thread ("t-11946.html")?

update #2:
Well, I can't get patched Olly 1.10 to download symbol files as I had done before. It just seems to halt when loading a system file. So I installed and configured Olly 2.0h and it downloads the .pdb files without a hitch.

Switching back to Olly 1.10 and renaming the symserv.dll allows the system files to load.

From the log, I see:
C:\WINDOWS\WinSxS\x86_Microsoft.VC80.MFC_1fc8b3b9a1e18e3b_8.0.50727.6195_x-ww_150c9e8b\mfc80.dll
Invalid or compressed Image Export Directory
Debugging information (Microsoft format) available

So that looks like what I need.

Next I type into the modified commandline plugin:
loadpdb C:\WINDOWS\WinSxS\x86_Microsoft.VC80.MFC_1fc8b3b9a1e18e3b_8.0.50727.6195_x-ww_150c9e8b\mfc80.dll

The log then shows:

35 C:\SYMSERV*HTTP://MSDL.MICROSOFT.COM/DOWNLOAD/SYMBOLS
dbghelp dll loaded and address retrieved
No Symbols - skipping

Can you tell me where I am going wrong here?

update #3: I restored the name of symsrv.dll and copied the file symsrv.yes from the Olly 2.0h to Olly 1.10 and it no longer stalls at a system file.

So from the log window as before, I see:
C:\WINDOWS\WinSxS\x86_Microsoft.VC80.MFC_1fc8b3b9a1e18e3b_8.0.50727.6195_x-ww_150c9e8b\mfc80.dll
Invalid or compressed Image Export Directory
Debugging information (Microsoft format) available

And again typing into the modified command line plugin:
loadpdb C:\WINDOWS\WinSxS\x86_Microsoft.VC80.MFC_1fc8b3b9a1e18e3b_8.0.50727.6195_x-ww_150c9e8b\mfc80.dll

This time, the log now shows:
35 C:\SYMSERV*HTTP://MSDL.MICROSOFT.COM/DOWNLOAD/SYMBOLS
dbghelp dll loaded and address retrieved

But the ord2name plugin doesn't update the ordinals to API names. Erm... yes it does after I copied your updated plugin to the Olly folder. I'm not sure how that happened, but it did and its fixed now.

All the API names can now be seen, which is great, with the exception of one stray ordinal as shown below.

0042D3D0 Import mfc80.#6283

All the other named ordinals look like this:
0042D4A8 Import CArchive::Write
0042D4AC Import CArchive::WriteCount
0042D47C Import CFileDialog::~CFileDialog
0042D160 Import CWinApp::WriteProfileInt
0042D164 Import CWinApp::WriteProfileStringA

Shouldn't the API names all be prefixed with the module name mfc80? I also notice that all module names remain in lowercase type before and after running the ord2name plugin.

5aLIVE
September 1st, 2013, 12:44
It also works for OLEAUT32.DLL.

Before:
http://i41.tinypic.com/2cddh05.png

And after:
http://i44.tinypic.com/xgacs2.png