blabberer
July 22nd, 2013, 13:29
WinApiHelp plugin for ollydbg 1.10
I had been a big fan of compiled html help (*.chm) and with its demise i used to resort to various methods
to create help files (basically for ollydbg usage) as Microsoft's latest help thingies never matched the ease
that chm file offered especially for offline mode usage
chm was simple you download the package double click and there you have everything in front of you
but the hhx hhc were never standalone
they required monstrous packages accompanying them to run and weren't adaptable even then
recently out of sheer circumstances
(i had ~ 600 mb data left on a prepaid and expiry date was closing in had to keep awake few nights
soothing a little bundle of frayed nerves and i ended up downloading the offline content for visual studio 2010 express
(win32 and com development and windows driver kit)
help -> manage help settings -> settings -> i want to use local help
install content from online add add update
and once it was there i clicked F1 on MessageBoxA in editor
a few seconds elapsed one tray icon popped up (help library agent ) and Firefox opened with the help file
now curiosity always kills the cat it is said
wtf is help lib agent ? why should i keep it open ? why it complains links will die and all help will cease to exist for me if i close it ?
what is the queer protocol in Firefox 127.0.0.1:\\ no http:\\ / ftp:\\ ?? Local-host ??
who is looking for that ? the big daddy at ms wants to know how i am helping myself ??
and last but not least of the question can i use it in a standalone mode without having to run umpteen components in the background ?
ollydbg by default used winhelp.chm (circa 19XX) for resolving symbolic help and it is damn outdated though quiet useful still
never saw a good substitute for it (there is a plugin by iirc mario vilas but it patched ollydbg and sort of leeched online help when i saw it )
no good offline substitute
thus this plugin was born
if you have installed any ms products (vs2010 express etc etc it installs help library for context sensitive help (F1 help))
use the help library manger to install contents locally (cute manager can update the content to latest version of the page on MSDN )
provide the path of the HelpLibraryAgent.exe to this plugin
provide the path of your default browser to this plugin
and simply hit F1 voila api help will be on screen in a jiffy
and surprise surprise surprise
you can even add your own help file to the local store and get it back with F1
i have tested this plugin on v1.0 (vs2010 express MS-HELP) on xp sp3 vm only
if anyone having vs2012 / vs2013 v1 . v2 . v3 etc and facing a few features leave back comments it will be appreciated.
SURPRISE DETAILS
supposing you are working on a ollydbg 2.10 h plugin and for all api help you are forced to visit ollydbg.de online everytime
(more surprise once you have the contents locally it will show up in both ollydbg with this plugin and visual-studio directly )
highlight and F1 in vs2010 on say Absolutizepath and you have it in screen
select the line with Absolutizepath in ollydbg and F1 you have it on screen
by adding all the help files to your local store you can have all the api details offline
wget the help files from ollydbg.de
wget -c -np -mirror http://www.ollydbg.de/Help/Absolutizepath.htm
this wilL fetch around ~175 files navigate the downloaded tree to HELP folder and
run this bat file (should be self explanatory ) you would need gnuwin32 sed / 7zip and html tidy in path
html tidy to convert the html files to be xml compliant
sed to delete the <DOCTYPE declaration insert xml header and add meta tags in <head> </head>
7zip to zip the converted files (zip is renamed to mshc )
create an msha file which help library manager recognizes for installing local content)
update and you have all the F1 help for available apis
mshc created thus have one wrinkle still left behind
the relative links do not work
the problem is each html help file needs an unique id for which i provide the file name
but relative links needs to be fixed in each file to a valid ms-xhelp:// protocol
i got bored hacking sed to look for <a href ="t_disasm.htm">t_disasm</a>
and convert it to <a href="ms-xhelp://<uniqueid><text></a> in each and every file
anyone wishing to contribute
are welcome
the source code for the plugin is shown below
a compiled binary and src also attached at the end
winapihelp_plugin_odbg110.rar (223.5 KB)
I had been a big fan of compiled html help (*.chm) and with its demise i used to resort to various methods
to create help files (basically for ollydbg usage) as Microsoft's latest help thingies never matched the ease
that chm file offered especially for offline mode usage
chm was simple you download the package double click and there you have everything in front of you
but the hhx hhc were never standalone
they required monstrous packages accompanying them to run and weren't adaptable even then
recently out of sheer circumstances
(i had ~ 600 mb data left on a prepaid and expiry date was closing in had to keep awake few nights
soothing a little bundle of frayed nerves and i ended up downloading the offline content for visual studio 2010 express
(win32 and com development and windows driver kit)
help -> manage help settings -> settings -> i want to use local help
install content from online add add update
and once it was there i clicked F1 on MessageBoxA in editor
a few seconds elapsed one tray icon popped up (help library agent ) and Firefox opened with the help file
now curiosity always kills the cat it is said
wtf is help lib agent ? why should i keep it open ? why it complains links will die and all help will cease to exist for me if i close it ?
what is the queer protocol in Firefox 127.0.0.1:\\ no http:\\ / ftp:\\ ?? Local-host ??
who is looking for that ? the big daddy at ms wants to know how i am helping myself ??
and last but not least of the question can i use it in a standalone mode without having to run umpteen components in the background ?
ollydbg by default used winhelp.chm (circa 19XX) for resolving symbolic help and it is damn outdated though quiet useful still
never saw a good substitute for it (there is a plugin by iirc mario vilas but it patched ollydbg and sort of leeched online help when i saw it )
no good offline substitute
thus this plugin was born
if you have installed any ms products (vs2010 express etc etc it installs help library for context sensitive help (F1 help))
use the help library manger to install contents locally (cute manager can update the content to latest version of the page on MSDN )
provide the path of the HelpLibraryAgent.exe to this plugin
provide the path of your default browser to this plugin
and simply hit F1 voila api help will be on screen in a jiffy
and surprise surprise surprise
you can even add your own help file to the local store and get it back with F1
i have tested this plugin on v1.0 (vs2010 express MS-HELP) on xp sp3 vm only
if anyone having vs2012 / vs2013 v1 . v2 . v3 etc and facing a few features leave back comments it will be appreciated.
SURPRISE DETAILS
supposing you are working on a ollydbg 2.10 h plugin and for all api help you are forced to visit ollydbg.de online everytime
(more surprise once you have the contents locally it will show up in both ollydbg with this plugin and visual-studio directly )
highlight and F1 in vs2010 on say Absolutizepath and you have it in screen
select the line with Absolutizepath in ollydbg and F1 you have it on screen
by adding all the help files to your local store you can have all the api details offline
wget the help files from ollydbg.de
wget -c -np -mirror http://www.ollydbg.de/Help/Absolutizepath.htm
this wilL fetch around ~175 files navigate the downloaded tree to HELP folder and
run this bat file (should be self explanatory ) you would need gnuwin32 sed / 7zip and html tidy in path
html tidy to convert the html files to be xml compliant
sed to delete the <DOCTYPE declaration insert xml header and add meta tags in <head> </head>
7zip to zip the converted files (zip is renamed to mshc )
create an msha file which help library manager recognizes for installing local content)
update and you have all the F1 help for available apis
mshc created thus have one wrinkle still left behind
the relative links do not work
the problem is each html help file needs an unique id for which i provide the file name
but relative links needs to be fixed in each file to a valid ms-xhelp:// protocol
i got bored hacking sed to look for <a href ="t_disasm.htm">t_disasm</a>
and convert it to <a href="ms-xhelp://<uniqueid><text></a> in each and every file
anyone wishing to contribute

Code:
xcopy help odbg2pluginhelp /EVQI
cd odbg2pluginhelp
for /F %%I in ('dir /b *.htm') do tidy -quiet -wrap 0 -modify -numeric -utf8 -asxml %%I
for /F %%I in ('dir /b *.htm') do sed -i "1,2d" %%I
del sed*
for /F %%I in ('dir /b *.htm') do sed -i "1,1s/^/<?xml version=\"1.0\" encoding=\"utf-8\"?>\n/" %%I
del sed*
for /F %%I in ('dir /b *.htm') do sed -i "/<head>/a <meta name=\"Microsoft.Help.F1\" content=\"%%~nI\" />\n<meta name=\"Microsoft.Help.Id\" content=\"%%~nI%%~xI\" />\n" %%I
del sed*
"c:\Program Files\7-Zip\7z.exe" a odbg2pluginhelp.zip
ren odbg2pluginhelp.zip odbg2pluginhelp.mshc
echo ^<html xmlns="http://www.w3.org/1999/xhtml"^> > helpcontentsetup.msha
echo ^<head^> >> helpcontentsetup.msha
echo ^<title^>odbg2pluginhelp^</title^> >> helpcontentsetup.msha
echo ^</head^> >> helpcontentsetup.msha
echo ^<body class="vendor-book"^> >> helpcontentsetup.msha
echo ^<div class="details"^> >> helpcontentsetup.msha
echo ^<span class="vendor"^>odbg^</span^> >> helpcontentsetup.msha
echo ^<span class="locale"^>en-us^</span^> >> helpcontentsetup.msha
echo ^<span class="product"^>ollydbg2.01h^</span^> >> helpcontentsetup.msha
echo ^<span class="name"^>odbgpluginhelp^</span^> >> helpcontentsetup.msha
echo ^</div^> >> helpcontentsetup.msha
echo ^<div class="package-list"^> >> helpcontentsetup.msha
echo ^<div class="package"^> >> helpcontentsetup.msha
echo ^<span class="name"^>odbg2pluginhelp^</span^> >> helpcontentsetup.msha
echo ^<a class="current-link" href="odbg2pluginhelp.mshc"^>Help.mshc^</a^> >> helpcontentsetup.msha
echo ^</div^> >> helpcontentsetup.msha
echo ^</div^> >> helpcontentsetup.msha
echo ^</body^> >> helpcontentsetup.msha
echo ^</html^> >> helpcontentsetup.msha
the source code for the plugin is shown below
a compiled binary and src also attached at the end
Code:
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
#include <iphlpapi.h>
#include "plugin.h"
#pragma warning(disable : 6335)
#pragma comment(lib, "iphlpapi.lib"
#pragma comment(lib, "psapi.lib"
#pragma comment(lib, "ws2_32.lib"
HINSTANCE hinst;
HWND hwmain;
DWORD pid = NULL;
u_short LocalPort = NULL;
char pathtohelplib[MAX_PATH];
char pathtodefbrowser[MAX_PATH];
PMIB_TCPTABLE_OWNER_PID pTcpTable = NULL;
DWORD findhelplibagent(void)
{
DWORD ProcessIds[1024], BytesReturned, TotalProcesses,Status;
unsigned int i;
if ( !EnumProcesses( ProcessIds, sizeof(ProcessIds), &BytesReturned ) )
{
Addtolist(0,1,"Enum Process Failed\n";
Status = 0xffffffff;
return Status;
}
TotalProcesses = BytesReturned / sizeof(DWORD);
for ( i = 0; i < TotalProcesses; i++ )
{
if( ProcessIds[I] != 0 )
{
char ProcessName[MAX_PATH] = {"unknown"};
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessIds[I] );
if (NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeed;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeed) )
{
GetModuleBaseNameA( hProcess, hMod, ProcessName, sizeof(ProcessName)/sizeof(char) );
if (_strnicmp("HelpLibAgent.exe",ProcessName,sizeof("HelpLibAgent.exe") == NULL)
{
pid = ProcessIds[I];
CloseHandle( hProcess );
Status = 1;
return Status;
}
else
{
CloseHandle( hProcess );
}
}
}
}
}
Status = 0;
return Status;
}
int Getlibagentpidandport()
{
struct in_addr LocalIpAddr;
char szLocalAddr[128];
DWORD dwSize = NULL;
DWORD ret , ishlplibagentrunning;
ishlplibagentrunning = findhelplibagent();
if ( ishlplibagentrunning == -1)
{
Addtolist(0,1, "EnumProcess Failed\n";
return FALSE;
}
else if ( ishlplibagentrunning == 0)
{
Addtolist(0,1, "HelpLibraryAgent is Not Running starting it\n";
STARTUPINFOA sinfo;
PROCESS_INFORMATION pinfo;
memset(&sinfo,0,sizeof(sinfo));
memset(&pinfo,0,sizeof(pinfo));
sinfo.cb = sizeof(sinfo);
CreateProcessA(
NULL,pathtohelplib,NULL,NULL,FALSE,NULL,NULL,NULL,&sinfo,&pinfo);
WaitForInputIdle(pinfo.hProcess,INFINITE);
ishlplibagentrunning = findhelplibagent();
if ( ishlplibagentrunning != 1)
{
Addtolist(0,1,"cant start HelpLibAgent.exe\n";
return FALSE;
}
else
{
Sleep(10000);
}
}
ret = GetExtendedTcpTable(pTcpTable,&dwSize,TRUE,AF_INET,TCP_TABLE_OWNER_PID_ALL, NULL);
if(ret == ERROR_INVALID_PARAMETER)
{
Addtolist(0,1,"GetExtendedTcpTable failed\n";
return FALSE;
}
else if (ret == ERROR_INSUFFICIENT_BUFFER )
{
pTcpTable = (PMIB_TCPTABLE_OWNER_PID)malloc(dwSize*sizeof(wchar_t)+10);
memset(pTcpTable,0,dwSize*sizeof(wchar_t)+10);
dwSize = dwSize*sizeof(wchar_t)+10;
ret = GetExtendedTcpTable(pTcpTable,&dwSize,TRUE,AF_INET,TCP_TABLE_OWNER_PID_LISTENER, NULL);
if ( ret!= NO_ERROR)
{
Addtolist(0,1,"GetExtendedTcpTable failed again with %x\n",ret);
free(pTcpTable);
return FALSE;
}
else if (ret == NO_ERROR)
{
for (ULONG i =0; i<pTcpTable->dwNumEntries;i++)
{
if(pTcpTable->table[I].dwOwningPid == pid)
{
LocalIpAddr.S_un.S_addr =pTcpTable->table[I].dwLocalAddr;
strcpy_s(szLocalAddr, sizeof (szLocalAddr), inet_ntoa(LocalIpAddr));
LocalPort = ntohs((u_short)pTcpTable->table[I].dwLocalPort);
}
}
}
}
free(pTcpTable);
return TRUE;
}
void ExecuteQuery(PCHAR symname)
{
char buff [0x300];
Getlibagentpidandport();
_snprintf_s(
buff,
_countof(buff),
sizeof(buff)-10,
"http://127.0.0.1:%d/help/0-%u/ms.help?product=VS&productVersion=100&method=f1&query=%s",
LocalPort,
pid,
symname
);
ShellExecuteA(NULL,"open",pathtodefbrowser,buff,NULL,SW_SHOWNORMAL);
}
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_Plugindata( char shortname[32] )
{
strcpy_s( shortname, 30, "winapihelp" );
return PLUGIN_VERSION;
};
extc int _export _cdecl ODBG_Plugininit( int ollydbgversion, HWND hw, ulong *features )
{
UNREFERENCED_PARAMETER( features );
if (ollydbgversion<PLUGIN_VERSION)
{
return -1;
}
Addtolist(0,0,"WinApiHelp Plugin by blabberer";
hwmain=hw;
Pluginreadstringfromini(hinst,"vs2010helplibagent",pathtohelplib,"helplibagent path not found";
Pluginreadstringfromini(hinst,"defaultbrowser",pathtodefbrowser,"default browser path not found";
if (_strnicmp(pathtohelplib,"helplibagent path not found",sizeof("helplibagent path not found") == 0)
{
memset(&pathtohelplib,0,sizeof(pathtohelplib));
Browsefilename ("CHOOSE PATH TO HELPLIBRARYAGENT.EXE",pathtohelplib,".exe",0);
if(*pathtohelplib !='\0')
{
Pluginwritestringtoini(hinst,"vs2010helplibagent",pathtohelplib);
Addtolist(0,1,"path to HelpLibraryAgent.exe is %s",pathtohelplib);
}
}
if (_strnicmp(pathtodefbrowser,"default browser path not found",sizeof("default browser path not found") == 0)
{
memset(&pathtodefbrowser,0,sizeof(pathtodefbrowser));
Browsefilename ("CHOOSE PATH TO DEFAULT BROWSER",pathtodefbrowser,".exe",0);
if(*pathtodefbrowser !='\0')
{
Pluginwritestringtoini(hinst,"defaultbrowser",pathtodefbrowser);
Addtolist(0,1,"path to default browser is %s",pathtodefbrowser);
}
}
return 0;
};
extc int _export _cdecl ODBG_Pluginshortcut( int origin,int ctrl,int alt,int shift,int key, void *item )
{
t_dump* cpudump = NULL;
t_disasm disas;
uchar *decoderes = NULL;
char cmd[MAXCMDSIZE];
char jmpconst[TEXTLEN];
char jmpaddr[TEXTLEN];
char adrconst[TEXTLEN];
char immconst[TEXTLEN];
if( ( origin == PM_DISASM) && (ctrl == 0) && (alt == 0) && (shift == 0) && (key == VK_F1) )
{
cpudump = (t_dump*)item;
ulong psize;
int jcc,jaddr,adrc,immc;
decoderes = Finddecode(cpudump->sel0,&psize);
Readcommand(cpudump->sel0,cmd);
Disasm((uchar *)cmd,sizeof(cmd),cpudump->sel0,decoderes,&disas,DISASM_ALL,Getcputhreadid());
jcc = Findsymbolicname(disas.jmpconst,jmpconst);
jaddr = Findsymbolicname(disas.jmpaddr,jmpaddr);
adrc = Findsymbolicname(disas.adrconst,adrconst);
immc = Findsymbolicname(disas.immconst,immconst);
if( jcc > 1)
{
ExecuteQuery(jmpconst);
}
else if ( jaddr> 1)
{
ExecuteQuery(jmpaddr);
}
else if( adrc > 1 )
{
ExecuteQuery(adrconst);
}
else if (immc > 1)
{
ExecuteQuery(immconst);
}
return 1;
}
return 0;
}