![]() |
![]() |
|
![]() |
Formatted Hexadecimal Memory Dumper © 2002 Rick Kelly www.crooit.com Introduction For the developer working with Win32 structures or other random memory locations, there are times when visually inspecting memory contents may be necessary. Given a memory pointer and a length, our goal is to produce a standard text file that looks like: Memory Address=00EF90E8 Length=32 00EF90E8 0000 1C 02 00 00 41 00 6C 00 61 00 73 00 6B 00 61 00 ....A.l.a.s.k.a. 00EF90F8 0010 6E 00 20 00 53 00 74 00 61 00 6E 00 64 00 61 00 n. .S.t.a.n.d.a.Where we not only show the raw hexadecimal contents but a sanitized ASCII string value as well. Win32 API References The following Win32 API method is used to retrieve a value from memory and save it in a Paradox variable. Uses "kernel32.dll" MoveFromMemory( wDestination cPtr, wSource cLong, wLength cLong) cLong [stdcall "RtlMoveMemory"] endUses Overview A neat trick we will use takes advantage of how Intel® words and double-words are loaded and stored from low byte to high byte. For instance, a stored word or Type SmallInt with value 16 looks like x'1000'. We can fetch one byte from memory, store it in the first byte of a SmallInt and then use normal OPAL for further processing. Our method below will take a LongInt pointer and LongInt length, produce a normal text file with a specified name of the memory contents, and optionally, run the Windows Notepad program so we can see the results. method HexDump(liPointer LongInt, liLength LongInt, stFileName String, loNotePad Logical) var siAny SmallInt stHex String stAny String stASCII String liMemory LongInt ts TextStream liSegments LongInt liIndex LongInt stAlias String endVar switch case ts.open(stFileName,"NW") = False : otherwise : stHex = toHex(liPointer) stAny = "Memory Address=" + upper(stHex.substr(3,8)) + " Length=" + strval(liLength) + chr(13) + chr(10) ts.writeLine(stAny) ; ; Calculate the number of 16 byte segments we are going to process ; liSegments = longInt(ceil(liLength / 16.0)) ; ; Loop through memory and decode ; for liIndex from 1 to liSegments stHex = toHex(liPointer) stAny = upper(stHex.substr(3,8)) + " " stHex = toHex((liIndex * 16) - 16) stAny = stAny + upper(stHex.substr(7,4)) + " " stASCII = " " for liMemory from liPointer to liPointer + iif(liLength < 16,liLength - 1,15) siAny = 0 MoveFromMemory(siAny,liMemory,1) stHex = toHex(siAny) stAny = stAny + upper(stHex.substr(9,2)) + " " ; ; Show only standard ASCII character set ; switch case siAny >= 32 and siAny <= 126 : stASCII = stASCII + chr(siAny) otherwise : stASCII = stASCII + "." endSwitch endFor ; ; If this is the last block and it is not ; an even multiple of 16, pad it with ; some spaces ; switch case liIndex <> liSegments : case liLength >= 16 : otherwise : stAny = stAny + space((16 - liLength) * 3 + 3) endSwitch ts.writeLine(stAny + stASCII) liPointer = liPointer + 16 liLength = liLength - 16 endFor ts.close() endSwitch ; ; Optional launch of Notepad ; switch case loNotePad = True : ; ; Check if alias was used ; switch case stFileName.substr(1,1) = ":" : ; ; Isolate Alias and get path ; stFileName = stFileName.substr(2,stFileName.size() - 1) siAny = stFileName.search(":") stAlias = stFileName.substr(1,siAny - 1) stFileName = getAliasPath(stAlias) + "\\" + stFileName.substr(siAny + 1, stFileName.size() - siAny) endSwitch ; ; Launch Notepad ; execute("notepad.exe " + stFileName,No,ExeShowMaximized) endSwitch endMethod Example The following script (download available here) will retrieve a Windows TimeZone structure and call HexDump. Uses "kernel32.dll" MoveFromMemory(wDestination cPtr, wSource cLong, wLength cLong) cLong [stdcall "RtlMoveMemory"] GlobalAlloc(wFlags cLong, dwBytes cLong) cLong [stdcall] GlobalFree(hMem cLong) cLong [stdcall] GetTimeZoneInformation(wTZI cLong) cLong [stdcall] endUses method run(var eventInfo Event) var liPointer LongInt liLength LongInt liReturn LongInt endVar ; ; TimeZone Structure ; ; + 0 = Bias ; + 4 = Standard Name (32 SmallInt values) ; + 68 = Standard Date Structure ; + 84 = Standard Bias ; + 88 = Daylight Name (32 SmallInt values) ; + 152 = Daylight Date Structure ; + 168 = Daylight Bias ; ; Total Length = 172 bytes ; ; Date Structure (all type SmallInt) ; Year,Month,Day of Week,Day,Hour,Minute,Second,Millisecond ; liLength = 172 liPointer = GlobalAlloc(fromHex("0x40"),liLength) ; ; Retrieve Time Zone Structure ; liReturn = GetTimeZoneInformation(liPointer) HexDump(liPointer,liLength,":PRIV:__mdump.txt",True) liReturn = GlobalFree(liPointer) endMethod Discussion of this article |
![]() Feedback | Paradox Day | Who Uses Paradox | I Use Paradox | Downloads ![]() |
|
![]() The information provided on this Web site is not in any way sponsored or endorsed by Corel Corporation. Paradox is a registered trademark of Corel Corporation. ![]() |
|
![]() Modified: 15 May 2003 Terms of Use / Legal Disclaimer ![]() |
![]() Copyright © 2001- 2003 Paradox Community. All rights reserved. Company and product names are trademarks or registered trademarks of their respective companies. Authors hold the copyrights to their own works. Please contact the author of any article for details. ![]() |
![]() |
|