March 28, 2024, 02:36:14 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


DLL Exports

Started by Brian, February 21, 2019, 12:20:53 PM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

Brian

No idea who came up with this, but it only needed a slight tidy up for it to show Exported Functions from a DLL

Brian

billhsln

Tried program, works ok in the directory it starts in, but when I click on 'Folder' to switch over to the LIB directory for IWB, it just aborts.  No error, just bombs.

Bill
When all else fails, get a bigger hammer.

Brian

Bill,

I did have some bother with the code, especially round Line 133, but I was able this morning to navigate to the \bin folder, and click through four DLLs there. Anyway, the code is not set up to see any .lib files, so they won't show. If anyone spots anything untoward, please let us all know

As I said, it is not my code, just a refresh of a previously written program by someone

Brian

fasecero

Liked this one. Here's some code amended to check .lib files as well - Can be slow. For instance ntdll.lib with 2000+ exports takes more than 40 seconds to load.

autodefine "off"

$include "windowssdk.inc"
$include "stdio.inc"
$include "stdlib.inc"

CONST BTN_FOLDER = 1000
CONST LB_DLLS    = 1001
CONST LV_1      = 1002

DECLARE EXTERN dup ALIAS _DUP$(path:POINTER),POINTER
DECLARE EXTERN _ibstrcpy(szdest:POINTER,szsrc:POINTER)

DIALOG d1

CREATEDIALOG d1,0,0,640,480,0x80CA0880,0,"Dll Viewer",&d1_handler
 CONTROL d1,@LISTBOX,"",10,30,150,440,0x50B10143|@BORDER,LB_DLLS
 CONTROL d1,@STATIC,"Select a DLL:",10,8,68,13,0x5000010B,2
 CONTROL d1,@LISTVIEW,"",170,6,460,462,0x5081000D|@BORDER,LV_1
 CONTROL d1,@BUTTON,"Folder...",90,4,70,20,0x50010000,BTN_FOLDER

DOMODAL d1
 END

CONST SEM_FAILCRITICALERRORS = 1

SUB d1_handler(),INT
  select @MESSAGE
      case @IDINITDIALOG
 CENTERWINDOW d1
 SETCONTROLCOLOR d1,BTN_FOLDER,RGB(0,0,255),RGB(192,192,192)
        ISTRING path[260]
 
        ' GetSystemDirectory(path,260)
 path = "C:\Program Files (x86)\iwbdev\libs"
 'path = "C:\Program Files (x86)\EBDev\libs"
 
        EnumDLLs(d1,path)
        ControlCmd(d1, LV_1, @LVINSERTCOLUMN,0,"#")
        ControlCmd(d1, LV_1, @LVINSERTCOLUMN,1,"Function Pointer")
        ControlCmd(d1, LV_1, @LVINSERTCOLUMN,2,"Function Name")
        ControlCmd(d1, LV_1, @LVSETCOLWIDTH,0,35)
        ControlCmd(d1, LV_1, @LVSETCOLWIDTH,1,100)
        ControlCmd(d1, LV_1, @LVSETCOLWIDTH,2,-2)
        SendMessage(d1, 0x1000 + 54,0,0x420,LV_1)
 ' if you try to LoadLibrary() with invalid image file the system displays the critical-error-handler message box
        SetErrorMode(SEM_FAILCRITICALERRORS)

      case @IDCLOSEWINDOW
        FreeHeap(GetProp(d1.hWnd, "PATH"))
        RemoveProp(d1.hWnd, "PATH")
        CloseDialog(d1)

      case @IDCONTROL
        if (@CONTROLID = LB_DLLS) and (@NOTIFYCODE=@LBNSELCHANGE)
            ShowDLLExports(d1, GetSelected(d1,LB_DLLS))
        endif

        /*add-on*/
        if (@CONTROLID = BTN_FOLDER) and (@NOTIFYCODE=0)
            _ibstrcpy(path, GetProp(d1.hWnd, "PATH"))
            if FolderRequest(d1.hWnd, "Change Folder", path, path, 0)
              FreeHeap(GetProp(d1.hWnd, "PATH"))
              EnumDLLs(d1,path)
            endif
        endif

        /*add-on*/
        if (@CONTROLID = LV_1) and (@NOTIFYCODE=@LVNCOLUMNCLICK)
            lvSort()
        endif

  endselect
  return 0
ENDSUB

CONST LB_RESETCONTENT = 0x184
CONST LB_DIR = 0x18D
CONST DDL_ARCHIVE = 32
CONST DDL_HIDDEN = 2
CONST DDL_SYSTEM = 4
CONST WM_SETREDRAW = 0xB
Const LVM_SORTITEMSEX = 0x1000 + 81
' custom sum
CONST DDL_MY = DDL_ARCHIVE|DDL_HIDDEN|DDL_SYSTEM

SUB EnumDLLs(d1:WINDOW,path:STRING)
  ControlCmd(d1, LV_1, @LVDELETEALL)
  SetProp(d1.hWnd, "PATH", dup(path))
  SendMessage(d1, LB_RESETCONTENT,0,0,LB_DLLS)
  SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.dll", LB_DLLS)
  SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.ax", LB_DLLS)
  SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.cpl", LB_DLLS)
  SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.acm", LB_DLLS)
  SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.ocx", LB_DLLS)
  SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.sys", LB_DLLS)
  SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.tsp", LB_DLLS)
  SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.xvd", LB_DLLS)
  SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.lib", LB_DLLS)
  setcaption d1, path
ENDSUB

SUB ShowDLLExports(d1:WINDOW,index:INT)
' enumerates all exports of kernel32.dll

 POINTER ImageBase
 POINTER OH_pointer /*Optional Header*/
 POINTER PE_pointer /*COFF File Header*/
 POINTER EXP_pointer /*Export Table address*/
 POINTER NamePointerRVA /* pointer to string* pointers array */
 POINTER ExportAddressTableRVA
 POINTER dir
 POINTER pszFile

 INT NumberOfNamePointers

  ControlCmd(d1, LV_1, @LVDELETEALL)

  dir = GetProp(d1.hWnd, "PATH")
  pszFile = *<STRING>dir + "\\" + GetString(d1, LB_DLLS, index)
 
  setcaption d1, *<STRING>pszFile
 
  string extension = RIGHT$(*<string>pszFile, 3)
 
  SELECT LCASE$(extension)
 CASE "lib"
 ShowlibExports(d1, *<STRING>pszFile)
 RETURN
 ENDSELECT
 
 
  ImageBase = LoadLibrary(pszFile)
  FreeHeap(pszFile)

  if (ImageBase = 0)
      SetCaption(d1, "Failed to load DLL")
      return
  endif

  if left$(*<STRING>ImageBase, 2) <> "MZ"
      SetCaption(d1, "Not Executable")
      return
  endif

  PE_pointer = ImageBase + *<WORD>(ImageBase+0x3C)

  if left$(*<STRING>PE_pointer, 4) <> "PE"
      SetCaption(d1, "Not PE")
      return
  endif

  PE_pointer  += 4 /*COFF File Header*/
  OH_pointer  = PE_pointer + 20 /*Optional Header*/
  EXP_pointer = ImageBase + *<UINT>(OH_pointer + 96) /*Export Table address*/

  NumberOfNamePointers =  *<UINT>(EXP_pointer + 24)
  NamePointerRVA = ImageBase + *<UINT>(EXP_pointer + 32)
  ExportAddressTableRVA = ImageBase + *<UINT>(EXP_pointer + 28)

  ShowExports( _
      d1, _
      ImageBase, _
      ExportAddressTableRVA, _
      NamePointerRVA, _
      NumberOfNamePointers)

  FreeLibrary(ImageBase)
ENDSUB

SUB ShowlibExports(WINDOW d1, string fullpath)
  INT item = 0

  ' do not repaint listview every time we add an item
  SendMessage(d1, WM_SETREDRAW, FALSE, 0, LV_1)

 pointer myfile = CreateFile(fullpath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)

 IF myfile <> INVALID_HANDLE_VALUE THEN
 DWORD dwFileSize = GetFileSize(myfile, NULL)
 
 IF dwFileSize <> 0xFFFFFFFF THEN
 LPSTR pszFileText = GlobalAlloc(GPTR, dwFileSize + 2)
 
 IF pszFileText <> NULL THEN
 DWORD dwRead = 0
 
 IF ReadFile(myfile, pszFileText, dwFileSize, &dwRead, NULL) THEN
 pointer p = pszFileText + 0
 INT counter = 0

 WHILE counter < dwRead - 10
 counter++
 p+=1

 IF LEFT$(*<string>p, 6) = "__imp_" THEN
 IF INSTR(lcase$(*<STRING>p), ".dll") = 0 THEN
 IF LEN(*<STRING>p) > 7 THEN
 string _line
 strncpy(_line, *<STRING>p, 255)
 
 'do something with the data
 _line = MID$(_line, 7)
 istring name[1000] = ""
 
 ' avoid duplicates...
 INT count = CONTROLCMD(d1, LV_1, @LVGETCOUNT)
 INT j
 INT founded = 0

 FOR j = 1 TO count
 CONTROLCMD(d1, LV_1, @LVGETTEXT, j-1, 2, name, 1000)
 IF INSTR(_line, name) THEN
 founded = 1
 BREAKFOR
 ENDIF
 next j
 
 IF founded = 0 THEN
 ControlCmd(d1, LV_1, @LVINSERTITEM, item, using("  #", item))
 ControlCmd(d1, LV_1, @LVSETTEXT, item, 1, " ")
 ControlCmd(d1, LV_1, @LVSETTEXT, item, 2, RTRIM$(_line))
 item++
 ENDIF
 ENDIF
 ENDIF
 ENDIF
 ENDWHILE
 ENDIF
 
 GlobalFree(pszFileText)
 ENDIF
 ENDIF

 CloseHandle(myfile)
 ENDIF

  ' listview will be always sorted as selected
  SendMessage(d1, LVM_SORTITEMSEX, 0, &LVSortCallback3state, LV_1)
  SendMessage(d1, WM_SETREDRAW, TRUE, 0, LV_1)
ENDSUB

SUB ShowExports(d1:WINDOW, ImageBase:UINT, fntable:POINTER, strtable:POINTER, count:INT)

  INT item
  ' do not repaint listview every time we add an item
  SendMessage(d1, WM_SETREDRAW, FALSE, 0, LV_1)
  item=0
  while count

      if (*<INT>fntable < 0)
        ControlCmd(d1, LV_1, @LVDELETEALL)
        SetCaption(d1, "Error! Invalid Offset")
        SendMessage(d1, WM_SETREDRAW, TRUE, 0, LV_1)
        return
      endif

      ControlCmd(d1, LV_1, @LVINSERTITEM, item, using("  #", item))
      ControlCmd(d1, LV_1, @LVSETTEXT, item, 1, "0x"+hex$(ImageBase + *<UINT>fntable))
      ControlCmd(d1, LV_1, @LVSETTEXT, item, 2, *<STRING>(ImageBase + *<UINT>strtable))

      fntable += 4
      strtable+= 4
      count--
      item++
  wend

  ' listview will be always sorted as selected
  SendMessage(d1, LVM_SORTITEMSEX, 0, &LVSortCallback3state, LV_1)
  SendMessage(d1, WM_SETREDRAW, TRUE, 0, LV_1)
ENDSUB

/* tools */

Declare import, SHBrowseForFolder(lpbi:POINTER),INT
Declare import, SHGetPathFromIDList(pITEMIDLIST:UINT, PATH:POINTER),INT
' fills memory with given character
$command _memset(...) /*(memory, char, count*/

const BFFM_INITIALIZED = 1
const BFFM_SETSELECTION = (0x400 + 102)
const BFFM_VALIDATEFAILED = 3

TYPE BROWSEINFO
  UINT    hOwner
  UINT    pidlRoot
  POINTER pszDisplayName
  POINTER lpszTitle
  UINT    ulFlags
  UINT    lpfn
  UINT    lParam
  UINT    iImage
ENDTYPE

SUB FolderRequest(hWnd:uint, title:pointer, dir:pointer, initial:pointer, flags:uint),int
 INT r
 r = FALSE
 UINT item_list
 BROWSEINFO bi

  _memset(&bi, 0, len(bi))
  bi.hOwner = hWnd
  bi.lpszTitle = title
  bi.ulFlags = flags
  IF flags = 0 Then bi.ulFlags = 9 | 0x42
  bi.lpfn = &BrowseRequestCallback
  bi.lParam = initial
  ' Display the browser
  item_list = SHBrowseForFolder(&bi)

  IF item_list
      r = SHGetPathFromIDList(item_list, dir)
      CoTaskMemFree(item_list)
  Endif
  Return r
EndSub

SUB BrowseRequestCallback(hWnd:uint, uMsg:uint, lParam:uint, lpData:uint),int
'  UINT dwStyle
'  ISTRING szText[261]
  Select uMsg

      Case BFFM_INITIALIZED
        ' Set start directory
        SendMessage hWnd, BFFM_SETSELECTION, TRUE, lpData

      Case BFFM_VALIDATEFAILED
        Return 1

  EndSelect

  Return 0
EndSub

'////////////// listview sorting function ///////////////

' move global variables to window property
INT LastClickedColumn, ClickedColumn, SortAscDesc
UINT LVhWnd
Const LVM_GETITEM = 4101
Const LVIF_TEXT = 1

TYPE NMLISTVIEW /*hacked!*/
    NMHDR hdr
    INT  iItem
    INT  iSubItem[7]
ENDTYPE

TYPE LVITEM /*hacked!*/
    UINT    mask
    INT    iItem
    INT    iSubItem[3]
    POINTER pszText
    INT    cchTextMax[7]
ENDTYPE

SUB lvSort()
  INT ColumnChanged
  ColumnChanged = 0
  LVhWnd = *<NMHDR>@LPARAM.hWndFrom
  ClickedColumn = *<NMLISTVIEW>@LPARAM.iSubItem

  IF  LastClickedColumn <> ClickedColumn
 LastClickedColumn = ClickedColumn
 SortAscDesc = 1
 ColumnChanged = 1
  Endif
IF ColumnChanged=0
      SortAscDesc++
      IF SortAscDesc = 2 Then SortAscDesc= -1
Endif
  SendMessage(LVhWnd, LVM_SORTITEMSEX, 0, &LVSortCallback3state)
EndSub

SUB LVSortCallback3state(lParam1:int, lParam2:int, lParamSort:uint),int
  LVITEM lvi1, lvi2
  ISTRING txt1[260], txt2[260]
  INT CompareResult 
  lvi1.iItem = lParam1
  lvi2.iItem = lParam2
IF (SortAscDesc = 0)
      lvi1.iSubItem = 0 'sort by first column
      lvi2.iSubItem = 0 'else sort by clicked column
else
      lvi1.iSubItem = ClickedColumn 'the last clicked column
      lvi2.iSubItem = ClickedColumn 'the last clicked column
Endif
  lvi1.mask = LVIF_TEXT
  lvi2.mask = LVIF_TEXT
  lvi1.pszText = &txt1
  lvi2.pszText = &txt2
  lvi1.cchTextMax = 260
  lvi2.cchTextMax = 260
  SendMessage(LVhWnd, LVM_GETITEM, 0, &lvi1)
  SendMessage(LVhWnd, LVM_GETITEM, 0, &lvi2)
  IF (SortAscDesc <> 0)
      CompareResult = lstrcmpi(&txt1, &txt2)
      CompareResult *= SortAscDesc
  Else
      CompareResult = val(txt1) > val(txt2) 'the first column is a numeric value
  Endif
  Return CompareResult
EndSub


billhsln

I switched to a directory with only 1 dll in it, the program aborts on me, just basically shuts down after I select a folder.

Bill
When all else fails, get a bigger hammer.

Brian

Compiled Gabriel's listing, and changed directory about six times with no problems

Bill, I will put my compiled exe in Dropbox\cfImages for you

Brian

billhsln

New version works fine on switching directorys, but when going to where I store my IWB source and have a DLL file, it pulls up the files, but not the stuff in them.  Weird....

Bill
When all else fails, get a bigger hammer.

Brian

February 23, 2019, 03:18:16 AM #7 Last Edit: February 23, 2019, 04:26:18 AM by Brian
Gabriel,
When I list the ntdll.lib, it takes my PC about 17 seconds. You will have to get yourself one of those new-fangled PCs that don't run on steam and valves!
Brian

Bill, you are right. I can change from \libs to \bin and it shows the DLL names, but no exported functions

Brian

fasecero

Quote from: undefinedWhen I list the ntdll.lib, it takes my PC about 17 seconds. You will have to get yourself one of those new-fangled PCs that don't run on steam and valves!

Currently, I have a lenovo notebook which never gave me a letdown (until now), it seems the processor is not that good at all! So I'll keep that in mind and I'll use those exact words when the need for a replacement arrives ;D

Quote from: undefinedBill, you are right. I can change from \libs to \bin and it shows the DLL names, but no exported functions

Did you guys by any chance are able to see any error message in the caption? The program seems to format in there some basic info when something goes wrong. Also any difference running the program as administrator?

Brian

Yes, it shows "Not Executable" when clicking on a file in the \bin folder. Running as Administrator makes no difference

Brian

Brian

Seems to be working OK now with this update, based on Fasecero's addition to read .lib files

Brian