Ghidra + MSDN Offline Library = ❤️



A while back [I blawgd about how to get the MSDN library for offline use](https://blag.nullteilerfrei.de/2017/12/21/get-the-msdn-library-for-offline-use/). However, the Help Viewer has its problems. I won't list all of its problems, but it was certainly a bad candidate to integrate Win32 API documentation support to Ghidra. There is [a pretty neat project by Laurence Jackson](http://laurencejackson.com/win32/), but I think I just found something a little better even: Microsoft provides [a download of the MSDN Library for Visual Studio 2008 SP1, stand-alone, offline, as an ISO](https://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=20955) - smell this, Help Viewer: So this is nice, but the main point of this exercise was to integrate this into Ghidra. If that's something you care about, read on. ## Integrating this into Ghidra After installing the MSDN for VS2008 to the default location, I took a [neat script](https://github.com/0x6d696368/ghidra_scripts/blob/master/GoogleSearch.py) by _mich_ (I take him for a big Endian kinda guy) and modified it as follows:
# Attempt to look up currently higlighted Windows API calls in the MSDN Library.
#@category Search
#@keybinding F2

import shlex
import os
import subprocess

from ghidra.program.model.symbol import FlowType


def searchMSDN(topic):
    def getViewerPath(*commonFilesPathCandidates):
        for baseDir in commonFilesPathCandidates:
            path = os.path.join(baseDir, 'microsoft shared', 'Help 9', 'dexplore.exe')
            if os.path.exists(path):
                return path
    viewer = getViewerPath(
        os.environ.get('CommonProgramFiles(x86)', ''),
        os.environ.get('CommonProgramFiles', ''),
        R'C:\Program Files (x86)\Common Files',
        R'C:\Program Files\Common Files'
    )
    command = '"{}" /helpcol ms-help://MS.MSDNQTR.v90.en /LaunchFKeywordTopic {}'.format(viewer, topic)
    return subprocess.call(shlex.split(command))

def searchAddress(address):
    try:
        search = getFunctionAt(address).getName()
    except AttributeError:
        raise Exception('No reference found for address {}'.format(address))
    if search.startswith('FID_conflict:'):
        search = search[13:]
    return search

def getReferenceName(address, level=0):
    assert level < 5
    for reference in getReferencesFrom(address):
        if reference.isExternalReference():
            return reference.getLabel()
        if reference.getReferenceType() == FlowType.UNCONDITIONAL_CALL:
            try:
                return searchAddress(reference.getToAddress())
            except Exception:
                pass
        if reference.getReferenceType() == FlowType.INDIRECTION:
            return getReferenceName(reference.getToAddress(), level + 1)
    else:
        return searchAddress(address)

try:
    searchMSDN(getReferenceName(currentAddress))
except Exception as E:
    print 'ERROR: Help lookup failed: {}'.format(E)
I put this into %USERPROFILE%\ghidra_scripts, and sure enough, I could bind this to the F2 key: Using it is a painfully slow process, but it works. This is me testing it on a [Phorpiex](https://malpedia.caad.fkie.fraunhofer.de/details/win.phorpiex) sample: MSDN Lookup from Ghidra ### Conclusion I can't believe I am going to say this, but here it goes: > _"Maybe I should rewrite this in Java for better performance."_

Tags: - - -

2 Replies to “Ghidra + MSDN Offline Library = ❤️”

  1. Oh nice, very glad to hear it! I only checked comments just now to say that I updated the script slightly to accommodate FlowType.INDIRECTION.

Leave a Reply

Your email address will not be published. Required fields are marked *