blabberer

winapihelp plugin for ollydbg 1.10

Rate this Entry
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

a substitute sed one liner added to convert relative links to ms-xhelp protocol

relative links will work properly now

toc and style sheet remains

attachment modfied with latest bat file



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 "s/href=\"/href=\"ms-xhelp:\/\/\/?Id=/g" %%I
del sed*

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;
}
Attached Thumbnails Attached Files

Submit "winapihelp plugin for ollydbg 1.10" to Digg Submit "winapihelp plugin for ollydbg 1.10" to del.icio.us Submit "winapihelp plugin for ollydbg 1.10" to StumbleUpon Submit "winapihelp plugin for ollydbg 1.10" to Google

Updated July 23rd, 2013 at 14:55 by blabberer

Categories
Uncategorized

Comments