Announcement

Collapse
No announcement yet.

hexdump goes dynamic!

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • hexdump goes dynamic!

    After 3 days off with concussion I decided to break my brain in gently by improving my hexdump utility. The result is - rufff! - but functional and may help you if you want to follow 32-bit addresses at run time. It lets you click on an address, check that the memory thus referenced is readable, and a double-click moves the hexdump window to the address identified. There is a back button. I'm posting it here in anticipation of improvements (hopefully by someone else), one day it may be clean enough for the Source Code Forum.

    Just #include the code below and call it like hexdump address, count.

    This could develop in various ways, if you are interested please post changes or let me know your ideas.

    Thanks.

    Code:
    '
    ' hexdump.inc
    ' dump data to screen in hex and character
    '   in 256-byte chuncks
    '   starting at a given address, or via a register (ESP or EBX, add more as required)
    '
    ' Chris Holbrook 6 Jul 2008
    '
    'dsply first 256 from a memory address as a block of hex digits with a character map on the right
    ' param 1 is byte ptr to memory to view,
    ' param 2 is max number of bytes to view
    ' param 3 is a register name. If param 1 is zero then
    ' the register will be used to point to the data to be dumped to the screen.
    ' example of calling: 1) hexdump (byval varptr(x), 1024) 2) hexdump ( 0, 256, "ESP")
    ' return handle to dialog
    '
    ' changes 5-sep-2008
    ' a left mouse click in the hexdump area will highlight the 32-bit address at the
    ' click location and display it "right way round", in pink if there is no readable
    ' memory there and in green if there is. double-click the highlighted address
    ' to move the hexdump window to that address.
    ' Added BACK button to return from above excursion to the previous page
    '---------------------------------------------------------------------------
    %idc_base_lab = 1004
    %idc_ofs_lab  = 1005
    %idc_cur_lab  = 1006
    %idc_data_lab = 1001
    %idc_prev_bn  = 1002
    %idc_next_bn  = 1003
    %idc_box_lab  = 1007
    %idc_back_bn  = 1008
    GLOBAL gstack() AS LONG
    GLOBAL gstackptr AS LONG
    '----------------------------------------------------------------------------------
    FUNCTION MakeFont(BYVAL fName AS STRING, BYVAL ptSize AS LONG, _
                      OPT BYVAL attr AS STRING) AS DWORD
       '--------------------------------------------------------------------
       ' Create a desired font and return its handle.
       ' attr = "biu" for bold, italic, and underlined (any order)
       '--------------------------------------------------------------------
       LOCAL hDC AS DWORD, CharSet AS LONG, CyPixels AS LONG
       LOCAL BOLD, italic, uLine AS LONG
       IF LEN(attr) THEN
          IF INSTR(LCASE$(attr), "b") THEN BOLD = %FW_BOLD
          IF INSTR(LCASE$(attr), "i") THEN italic = 1
          IF INSTR(LCASE$(attr), "u") THEN uLine = 1
       END IF
       hDC = GetDC(%HWND_DESKTOP)
       CyPixels  = GetDeviceCaps(hDC, %LOGPIXELSY)
       ReleaseDC %HWND_DESKTOP, hDC
       PtSize = 0 - (ptSize * CyPixels) \ 72
       FUNCTION = CreateFont(ptSize, 0, 0, 0, BOLD, italic, uLine, _
                 %FALSE, CharSet, %OUT_TT_PRECIS, _
                 %CLIP_DEFAULT_PRECIS, %DEFAULT_QUALITY, _
                 %FF_DONTCARE , BYCOPY fName)
    END FUNCTION
    '---------------------------------------------------------------------------
    SUB pop ( BYREF l AS LONG)
        l = gstack(gstackptr)
        DECR gstackptr
    END SUB
    '---------------------------------------------------------------------------
    SUB push ( l AS LONG)
        INCR gstackptr
        gstack(gstackptr) = l
    END SUB
    
    '---------------------------------------------------------------------------
    CALLBACK FUNCTION hexdumpCB AS LONG
        LOCAL s AS STRING
        LOCAL COUNT, i, j, l AS LONG
        STATIC ppage, pbase, q AS BYTE PTR
        STATIC startofchunk, maxlength AS LONG
        LOCAL X, Y AS LONG
        LOCAL row, col AS LONG
        LOCAL hfont AS DWORD
        LOCAL pt AS pointapi
        STATIC trget AS LONG
        STATIC  lMaxReadableMem, lcolor AS LONG
    
        SELECT CASE CBMSG
            CASE %WM_INITDIALOG
                DIALOG GET USER CBHNDL, 0 TO pbase
                ppage = pbase
                DIALOG GET USER CBHNDL, 1 TO maxlength
                GOSUB dsply
                CONTROL DISABLE CBHNDL, %IDC_BACK_BN
                '
            CASE %WM_COMMAND
                SELECT CASE CBCTL
                    CASE %idc_prev_bn  ' prev
                        ppage = ppage - 256
                        GOSUB dsply
                    CASE 1003  ' next
                        ppage = ppage + 256
                        GOSUB dsply
                    CASE %IDC_BOX_LAB
                        IF CBCTLMSG = %STN_DBLCLK THEN
                            IF (lmaxreadablemem > 0 ) AND iswindow ( getdlgitem(CBHNDL, %IDC_BOX_LAB) )THEN
                                push pbase
                                push ppage
                                push maxlength
                                CONTROL ENABLE CBHNDL, %IDC_BACK_BN
                                ppage = trget
                                pbase = trget
                                maxlength = lmaxreadablemem
                                deleteobject hfont
                                CONTROL KILL CBHNDL, %IDC_BOX_LAB
                                GOSUB dsply
                            END IF
                        END IF
                    CASE %IDC_BACK_BN
                        IF CBCTLMSG = %BN_CLICKED THEN
                            pop maxlength
                            pop ppage
                            pop pbase
                            IF gstackptr = 0 THEN CONTROL DISABLE CBHNDL, %IDC_BACK_BN
                            GOSUB dsply
                        END IF
                END SELECT
                '
            CASE %WM_LBUTTONDOWN
                pt.X = LO(WORD,CBLPARAM): pt.Y = HI(WORD,CBLPARAM)
                IF getdlgitem(CBHNDL, %IDC_BOX_LAB) <> 0 THEN
                    deleteobject hfont
                    CONTROL KILL CBHNDL, %IDC_BOX_LAB
                END IF
                IF childwindowfrompoint(CBHNDL, pt.x, pt.y) = getdlgitem(CBHNDL, %IDC_BOX_LAB) THEN EXIT SELECT
                DIALOG PIXELS CBHNDL, pt.x, pt.y TO UNITS X, Y
                row = (Y - 40)\10: col = (x -17)\16 ': ? str$(row) + str$(col)
                IF (row < 0) OR (row > 15) THEN EXIT SELECT
                IF (col < 0) OR (col > 15) THEN EXIT SELECT
    
                CONTROL ADD LABEL, CBHNDL, %IDC_BOX_LAB, "", X-2, Y-2, 64, 12, %SS_SUNKEN OR %SS_NOTIFY, %WS_EX_TOPMOST
                hfont = makefont ( "Courier New", 10)
                CONTROL SEND CBHNDL, %IDC_BOX_LAB, %WM_SETFONT, hFont, 0
                ' invert the number in the current + suceeding 3 byte
                s = ""'                        "
                trget = 0
                FOR i = 3 TO 0 STEP -1
                    q = ppage + (row*16) + col + i
                    s = s + HEX$(@q,2) + " "
                NEXT
                trget = VAL ( "&H" + REMOVE$(s,ANY $SPC))
    
                FOR i = 0 TO 5
                    IF isbadreadptr(trget,4^i) THEN
                        IF i = 0 THEN
                            lMaxReadableMem = 0
                            lcolor =  %RED
                        END IF
                    ELSE
                        lMaxReadableMem = 4^i
                        lcolor = %GREEN
                    END IF
                NEXT
                CONTROL SET COLOR CBHNDL, %IDC_BOX_LAB, 0, lcolor
                CONTROL SET TEXT CBHNDL, %IDC_BOX_LAB, s 'remove$(s, $SPC)
                DIALOG REDRAW CBHNDL 'sleep 500
    
        END SELECT
        EXIT FUNCTION
    
    dsply:
        s = STRING$(80 * 16, $SPC)
        FOR i = 0 TO 15
            FOR j = 0 TO 15
                'IF (i * 16) + j + startofchunk > maxlength THEN ITERATE
                q = ppage + (i*16) + j
                MID$(s, (i * 80) + (j*3)+3, 2) = HEX$(@q,2)
                IF INSTR ( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"" £$%^&*()_+{}[]:@~;'#,./<>?`¬",CHR$(@q)) <> 0 THEN
                    MID$(s, (i * 80) + 52 + j, 1) = CHR$(@q)
                ELSE
                    MID$(s, (i * 80) + 52 + j, 1) = "."
                END IF
            NEXT
            MID$(s, ((i) * 80)+1, 1) = HEX$(i)
            MID$(s, ((i+1) * 80) - 2, 2) = $CRLF
        NEXT
        s = "    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F" + _
            $CRLF + STRING$(51,"-") + " " + STRING$(16,"-") + $CRLF + " " + s
        CONTROL SET TEXT CBHNDL, %idc_data_lab,  s
        IF ppage <= pbase THEN
            CONTROL DISABLE CBHNDL, %idc_prev_bn
        ELSE
            CONTROL ENABLE CBHNDL, %idc_prev_bn
        END IF
        IF ppage + 256 >= pbase + maxlength THEN
            CONTROL DISABLE CBHNDL, 1003
        ELSE
            CONTROL ENABLE CBHNDL, 1003
        END IF
        CONTROL SET TEXT CBHNDL, %idc_base_lab, "BASE ADDRESS: " + HEX$(pbase) + "(" + STR$(pbase) + ")"
        CONTROL SET TEXT CBHNDL, %idc_ofs_lab,  "MAX BYTES: " + HEX$(maxlength) + "(" + STR$(maxlength) + ")"
        CONTROL SET TEXT CBHNDL, %idc_cur_lab,  "PAGE OFFSET: " + HEX$(ppage - pbase) + "(" + STR$(ppage- pbase) + ")"
        RETURN
    
    END FUNCTION
    '-------------------------------------------------------------------------------
    FUNCTION hexdump ( BYVAL pb AS BYTE PTR, n AS LONG, OPT reg AS STRING) AS DWORD
        LOCAL hdlg AS DWORD
        LOCAL hfont AS LONG
    
        DIM gstack (0 TO 100) AS GLOBAL LONG
    
        DIALOG NEW 0, "hex memory dump", 0, 0, 390, 245, %WS_POPUP OR %WS_BORDER OR _
            %WS_DLGFRAME OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
            %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
        CONTROL ADD LABEL, hdlg, %idc_data_lab, "",0, 20, 390, 195, %WS_CHILD OR %WS_VISIBLE OR %SS_NOWORDWRAP
        CONTROL ADD LABEL, hdlg, %idc_base_lab, "Base:",5,5, 130, 15, %WS_CHILD OR %WS_VISIBLE OR %SS_NOWORDWRAP
        CONTROL ADD LABEL, hdlg, %idc_ofs_lab, "Max Length:",145,5, 100,15, %WS_CHILD OR %WS_VISIBLE OR %SS_NOWORDWRAP
        CONTROL ADD LABEL, hdlg, %idc_cur_lab, "Curent ofs:",255,5, 100,15, %WS_CHILD OR %WS_VISIBLE OR %SS_NOWORDWRAP
        CONTROL ADD BUTTON, hdlg, %idc_prev_bn, "<", 5, 225, 10, 15, _
                %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %BS_TEXT OR %BS_CENTER OR %BS_VCENTER
        CONTROL ADD BUTTON, hdlg, %idc_next_bn, ">", 25, 225, 10, 15, _
                %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %BS_TEXT OR %BS_CENTER OR %BS_VCENTER
        CONTROL ADD BUTTON, hdlg, %idc_back_bn, "BACK", 45, 225, 30, 15, _
                %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %BS_TEXT OR %BS_CENTER OR %BS_VCENTER
        IF pb = 0 THEN
            SELECT CASE reg
            CASE "EBX"
                !mov  pb, ebx
            CASE "ESP"
                !mov pb, esp
            END SELECT
        END IF
        DIALOG SET USER hdlg, 0, pb
        DIALOG SET USER hdlg, 1, n
        hfont = makefont ( "Courier New", 10)
        CONTROL SEND hDlg, 1001, %WM_SETFONT, hFont, 0
        DIALOG SHOW MODAL hdlg CALL hexdumpCB
        DeleteObject hFont
    END FUNCTION

  • #2
    prettier using seperate controls for each address - this screen has > 300 controls but you wouldn't know it!
    Attached Files

    Comment

    Working...
    X