Use wireshark to analyze raw stream without frame seperator - wireshark

My wifi sniff device can output data to a raw file. But it may begin with the middle of a frame, and each frame starts right after another. A pcap file must contain packet headers, which I don't have. So I tried to discard the half complete frame at the beginning of the file, and put the rest into a pcap file with one packet. Then wireshark can analyze the first frame, even with wrong packet size.
My question is how to make wireshark analyze the remaining frames ?
Edit: This is a sample pcap with 2 frame, but without the second packet header
00000000 D4 C3 B2 A1 02 00 04 00 00 00 00 00 00 00 00 00 Ôò¡............
00000010 FF FF 00 00 69 00 00 00 05 00 00 00 00 00 00 00 ÿÿ..i...........
00000020 80 00 00 00 80 00 00 00 08 02 00 00 01 00 5E 00 €...€.........^.
00000030 00 FC E8 94 F6 3C 5F 40 20 68 9D 9A 4B D7 70 73 .üèâ€Ã¶<_# h.Å¡K×ps
00000040 AA AA 03 00 00 00 08 00 46 00 00 20 38 F8 00 00 ªª......F.. 8ø..
00000050 01 02 48 D5 C0 A8 01 66 E0 00 00 FC 94 04 00 00 ..HÕÀ¨.fà..üâ€...
00000060 16 00 09 03 E0 00 00 FC 08 02 00 00 01 00 5E 7F ....à..ü......^.
00000070 FF FA E8 94 F6 3C 5F 40 20 68 9D 9A 4B D7 F0 75 ÿúèâ€Ã¶<_# h.Å¡K×ðu
00000080 AA AA 03 00 00 00 08 00 46 00 00 20 38 F9 00 00 ªª......F.. 8ù..
00000090 01 02 39 D6 C0 A8 01 66 EF FF FF FA 94 04 00 00 ..9ÖÀ¨.fïÿÿúâ€...
000000A0 16 00 FA 04 EF FF FF FA ..ú.ïÿÿú

My question is how to make wireshark analyze the remaining frames ?
Detect the beginnings and ends of frames in your bit sequence, and put each frame into a separate record in the pcap file.
If there's nothing in the bit sequence to allow your software to determine where one frame ends and another frame begins, there's nothing in the bit sequence to allow Wireshark to do so, so if you want to have Wireshark analyzer frames past the first frame, you are FORCED to ensure that there's something in the bit stream to determine frame boundaries, and you might as well have your software break the bit stream into frames.

Related

Parsing/converting Nokia "Smart Feature OS" backup .ib files?

I have already written a bit on this in https://superuser.com/questions/1389657/backup-access-sms-on-nokia-3310-3g-2017-from-linux-pc ; basically, I'm trying to back up SMS messages on a Nokia 3310 3G onto a Ubuntu 18.04 PC; note that hardware system-on-chip and OS differs by version for a Nokia 3310 (2017):
System on chip / Operating system:
MediaTek MT6260 / Nokia Series 30+ (2G)
Spreadtrum SC7701B / Java-powered Smart Feature OS (3G)
Spreadtrum SC9820A / Yun OS (4G, CMCC)
I have the 3G, so I have a "Smart Feature OS" which apparently is a version of KaiOS (Is there any difference between KaiOS and 'Smart Feature OS'? : KaiOS), which apparently (KaiOS – A Smartphone Operating System | Hacker News) is a fork of Firefox OS.
When you hit Menu > Storage > Create backup (https://www.nokia.com/phones/en_int/support/nokia-3310-3g-user-guide/create-a-backup) on this phone, it generates a folder with files in it, named like this:
$ tree All-backup_01-01-2019_20-18-54
All-backup_01-01-2019_20-18-54
├── ibphone_head.in
├── phonebook.ib
└── sms.ib
I've never heard of .ib files before, and I was hoping someone here knew what they are. A quick look suggests IB File Extension - Open .IB File (InterBase Database), however I tried using these .ib files with http://fbexport.sourceforge.net/fbexport.php "Tool for exporting and importing data with Firebird and InterBase databases", and I get:
Engine Code : 335544323
Engine Message :
file ./All-backup_01-01-2019_20-18-54/phonebook.ib is not a valid database
So, that's not it.
Here is a hexdump of ibphone_head.in - looks like there is no personal identifying info here:
$ hexdump -C All-backup_01-01-2019_20-18-54/ibphone_head.in
00000000 00 00 00 00 41 00 6c 00 6c 00 2d 00 62 00 61 00 |....A.l.l.-.b.a.|
00000010 63 00 6b 00 75 00 70 00 5f 00 30 00 31 00 2d 00 |c.k.u.p._.0.1.-.|
00000020 30 00 31 00 2d 00 32 00 30 00 31 00 39 00 5f 00 |0.1.-.2.0.1.9._.|
00000030 32 00 30 00 2d 00 31 00 38 00 2d 00 35 00 34 00 |2.0.-.1.8.-.5.4.|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000100 00 00 00 00 45 00 3a 00 5c 00 42 00 61 00 63 00 |....E.:.\.B.a.c.|
00000110 6b 00 75 00 70 00 73 00 5c 00 41 00 6c 00 6c 00 |k.u.p.s.\.A.l.l.|
00000120 2d 00 62 00 61 00 63 00 6b 00 75 00 70 00 5f 00 |-.b.a.c.k.u.p._.|
00000130 30 00 31 00 2d 00 30 00 31 00 2d 00 32 00 30 00 |0.1.-.0.1.-.2.0.|
00000140 31 00 39 00 5f 00 32 00 30 00 2d 00 31 00 38 00 |1.9._.2.0.-.1.8.|
00000150 2d 00 35 00 34 00 00 00 00 00 00 00 00 00 00 00 |-.5.4...........|
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000200 00 00 00 00 30 30 30 31 2e 30 30 30 30 33 00 00 |....0001.00003..|
00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000230 00 00 00 00 00 00 6d 6d 69 6b 65 79 62 61 63 6b |......mmikeyback|
00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000250 00 00 00 00 00 00 03 00 00 00 00 00 b0 cd 09 00 |................|
00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000270 00 00 00 00 00 00 00 00 f3 dd 00 00 7e 2f 00 00 |............~/..|
00000280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000002c4
So, it seems that strings are encoded with 2 bytes, "wide char"; and for the most part, ibphone_head.in seems to just encode the name of its containing/parent folder, All-backup_01-01-2019_20-18-54.
Here is a hexdump of phone book, where I've anonymized names to AAAAAAAAA and BBB:
$ hexdump -C -n 1900 All-backup_01-01-2019_20-18-54/phonebook.ib
00000000 70 00 68 00 6f 00 6e 00 65 00 62 00 6f 00 6f 00 |p.h.o.n.e.b.o.o.|
00000010 6b 00 2e 00 69 00 62 00 00 00 00 00 00 00 00 00 |k...i.b.........|
00000020 00 00 00 00 01 00 00 00 30 f8 04 00 62 01 00 00 |........0...b...|
00000030 62 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |b...............|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000240 00 00 00 00 98 03 00 00 01 00 00 00 ff ff ff ff |................|
00000250 ff ff ff ff 01 00 01 00 00 00 00 00 00 00 00 00 |................|
00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000360 d9 d4 37 46 00 00 00 00 00 00 01 02 00 00 04 01 |..7F............|
00000370 07 12 80 88 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000003b0 09 00 41 00 41 00 41 00 41 00 41 00 41 00 41 00 |..A.A.A.A.A.A.A.|
000003c0 41 00 41 00 00 00 00 00 00 00 00 00 00 00 00 00 |A.A.............|
000003d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000005e0 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff |................|
000005f0 ff ff ff ff 98 03 00 00 01 00 00 00 ff ff ff ff |................|
00000600 ff ff ff ff 04 00 01 00 00 00 00 00 00 00 00 00 |................|
00000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000710 d9 d4 37 46 00 00 00 00 00 00 01 02 00 00 06 11 |..7F............|
00000720 83 29 23 13 58 f9 00 00 00 00 00 00 00 00 00 00 |.)#.X...........|
00000730 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000760 03 00 42 00 42 00 42 00 00 00 00 00 |..B.B.B.....|
0000076c
Here it seems d9 d4 37 46 is a delimiter for entries, and entries seem to be 0x3b0 = 944 bytes apart; cannot tell where the actual phone number is stored, though.
I won't be pasting the hexdump contents of sms.ib, because I fear to reveal more personal info than I intend to.
However, maybe what has been posted already, will help someone see if this is an already established file format? In any case, I'd like to convert the contents of these files to plain text ...
The phonebook.ib is a proprietary file format. I did some analysis and got to the point where I am able to extract names and phones numbers from it.
Header is 580 bytes and doesn't seem to contain anything interesting.
Entries appear to begin with the entry length, encoded as 3 4-bit decimal nibbles followed by another digit (version number maybe?).
In my sample file all entries were 940 bytes and therefore had 94 03 as their first two bytes. Other field entries I identified at different offsets:
entry+0x12a [1 byte]: Number of bytes representing phone number.
entry+0x12b [1 byte]: Seems like a two-digit decimal coded flag. If high nibble is set (e.g. 10) then phone number begins with +.
entry+0x12c: Phone number, decimal coded. For example, 123456 would appear as 21 43 65. Special digits:
a is *
b is #
f is ignored (seen as a last digit when the number of digits is not even).
entry+0x16c [1 byte]: Name length.
entry+0x16e: Name in UTF-16 (i.e. 2 bytes per char).
Taking your snippet as an example:
0x36e is the phone length, 4 bytes.
0x36f is the extra flag, high nibble is 0 so no + prefix.
0x370 is where the phone number begins, 07 12 80 88 translates to 70210888.
A simple reference parser can be found at my repo: https://github.com/yossigo/phonebook_ib_export
I was about to make the opposite script than Yossi's to convert .vcf files back into the .is format when I found a workaround to backup and restore all contacts to and from the vcf file format with the Nokia 3310 3G :
BACKUP CONTACTS TO VCF FILE: in your contacts, click the left button to share, select all of them using the option in the left button menu, send via Bluetooth to any device, you can then retrieve the vcf file from the other Bluetooth device OR from the /vCard/ folder at the root of your phone (sd card if one is plugged)
RESTORE CONTACTS FROM VCF FILE: copy the file anywhere on the phone or sd card, unplug the phone and use the embedded file browser to find the file, then follow Nokia’s engineer logic by not using the Open button but instead click on the left button and use the option Save vCard

Display NAL H.264 UDP Stream (in VLC)

I am trying to display the video my (PAUL) drone is sending to my over a UDP connection.
Frames look like (hexdump):
00 00 01 a1 00 1d 00 03
90 1a 00 00 a0 8a dc 0c
00 00 00 00 03 00 00 00
d0 02 40 02 00 04 00 00
90 1a 00 00 19 00 ......
Frames always start (trough my observation) with:
00 00 01 a
Are these NAL units?
I am want to display this in VLC player but don't know how to stream it to the VLC media player.
It looks a lot like a valid h.264 bitstream, but its not. 00 00 01 does look like a start code, But after a start code the first bit MUST be 0. a in binary is 1010 hence not valid.

==44088==ERROR: AddressSanitizer: stack-buffer-overflow

My project is swift-only (for the code I wrote, at least). At the start of the app, I download some json to show content. I deserialize this content with swift 4 Coder protocol. This has worked for some time, but just now I got an unexpected stack-buffer-overflow error:
==44088==ERROR: AddressSanitizer: stack-buffer-overflow
while deserializing one of the objects, in one of the background threads.
Based on this, I have 2 questions:
How can I ensure this doesn't happen again?
Is there a way to reproduce it?
More info:
I have this summary, but I'm not sure what to make of it:
SUMMARY: AddressSanitizer: stack-buffer-overflow JsonClass.swift in _T06MyApp11JsonClassVACs7Decoder_p4from_tKcfC
Shadow bytes around the buggy address:
0x100026a904d0: 00 02 f2 f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00
0x100026a904e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026a904f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026a90500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026a90510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100026a90520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[f2]f2
0x100026a90530: f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 00 00
0x100026a90540: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026a90550: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026a90560: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026a90570: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
EDIT:
It reproduced every time (in the simulator). Then I cleaned the build and deleted the derived data folder and it didn't happen since. I'd still like to know if I need to worry for a bug in production...
First I'll briefly answer your questions
How can I ensure this doesn't happen again?
This specific defect you can fix and write unit tests for to prevent having a regression. In general, however, mistakes happen; you cannot prevent them, only mitigate them. Use tools and warnings to try and identify them early on. You are already doing a good thing by employing Address Sanitizer (you should also check out Undefined Behavior Sanitizer and Thread Sanitizer).
Is there a way to reproduce it?
Address Sanitizer will report it 100% of the time it happens. Unfortunately, it sounds like it depends on what data you are working with. Maybe try some malformed data to try and coax it into happening. You can write Unit Tests (be sure to build your tests with Asan enabled) with various types of data. Can't say more without seeing code.
What is the problem?
You definitely have a bug. Asan does not report false positives. It sounds like it might only happen for bad data, but you should never trust you will always have good data.
It is not easy to help you fix your problem without seeing code. Asan reporting a stack buffer overflow is usually one of these things (in my experience):
Allocating a variable on the stack and keeping a reference to it. When the stack frame it was allocated in is destroyed the reference is no longer valid.
Having an array on the stack and going out of bounds.
(rarely) An improper cast of a stack object to an object larger size and accessing a "member" that is beyond the stack top.
If you are running though Xcode it should break when Asan aborts. you should be able to see the stack trace and find where in your code this is happening.
Additional tools to help identify the problem
Compiler warnings
Turn these on and up as much as possible. Often when you do things like take a reference to something with automatic storage duration the compiler can warn you about it.
Clang Static Analyzer
This is also built into Xcode and can be ran by the Product -> Analyize menu. This should populate issues it find in the "issue navigator" on the left column of Xcode. Clang is pretty good at identifying memory errors
31==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcfa87e770
at pc 0x000000344049 bp 0x7ffcfa87e6b0 sp 0x7ffcfa87e6a8
READ of size 1 at 0x7ffcfa87e770 thread T0
#3 0x7f35b846e0b2 (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
Address 0x7ffcfa87e770 is located in stack of thread T0 at offset 80 in frame
This frame has 3 object(s):
[32, 33) 'ref.tmp'
[48, 80) 'agg.tmp' <== Memory access at offset 80 overflows this variable
[112, 144) 'agg.tmp8'
HINT: this may be a false positive if your program uses some custom stack, unwind mechanism, swapcontext or vfork.
(longjmp and C++ exceptions *are* supported)
Shadow bytes around the buggy address:
0x10001f507c90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10001f507ca0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10001f507cb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10001f507cc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10001f507cd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10001f507ce0: 00 00 00 00 f1 f1 f1 f1 01 f2 00 00 00 00[f2]f2
0x10001f507cf0: f2 f2 00 00 00 00 f3 f3 f3 f3 f3 f3 00 00 00 00
0x10001f507d00: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
0x10001f507d10: 04 f2 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10001f507d20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10001f507d30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==31==ABORTING
i am also suffering from the same problem in leet code.

wireshark display filter on specific byte in a raw ethernet packet

I am trying to filter packets where the 15th byte (i.e. the 1st payload byte after the 14 byte header) is a specific value, either 0x00 or 0x01.
The packets I am interested in are raw ethernet, i.e. at the logical-link control layer so I also filter on LLC as the protocol
Here is what I tried:
llc && (frame[14:1] == 00 || frame[14:1] == 01)
this comes up green so I'm pretty sure the syntax is correct. Its only displaying packets where Protocol is LLC but its also letting through packets where the 15th byte is 0x02 which I want to avoid
Any ideas how I can succesfully target the 15th byte value, or to put it another way, the 1st byte value of the payload?
example packet (copied from wireshark) where 15th byte is 0x00:
0000 01 01 01 01 01 01 02 02 02 02 02 02 00 0e 00 05 ................
0010 00 00 00 05 00 00 00 00 00 00 00 01 ............
example packet where 15th byte is 0x01:
0000 02 02 02 02 02 02 01 01 01 01 01 01 00 0a 01 05 ................
0010 00 00 00 0d 00 00 00 f1 00 00 00 00 00 00 00 00 ................
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0030 00 00 00 00 00 00 00 00 00 00 00 00 ............
I'd like to have wireshark display both these packets
There is a 3rd type of packet where the 15th byte is 0x02:
0000 02 02 02 02 02 02 01 01 01 01 01 01 00 39 02 ec .............9..
0010 41 61 02 a2 21 44 2b 0c 00 02 00 1c 0c 02 00 00 Aa..!D+.........
0020 00 00 00 00 00 00 00 00 00 00 00 ee 91 20 04 46 ............. .F
0030 22 44 2b cc 01 03 00 00 00 00 00 00 00 00 00 00 "D+.............
0040 00 00 00 00 00 00 00 .......
This type of packet I would like to exclude with the filter. My filter above still displays these 0x02 packets.
Here is the wireshark display filter requested:
llc and (frame[14] == 0 or frame[14] == 1)
Wireshark counts the first byte in each frame as byte 0, so the 15th byte is frame[14]. You do not need the colon for a single byte (as described in the docs). and and && are equivalent. or and || are also equivalent.

Does TMonitor.GetBoundsRect have an access violation bug in Delphi 2007 triggered by VNC?

This is a crash report I get from customers running one of our big products built in Delphi 2007, that I am unable to reproduce and which doesn't even have any non-VCL code directly involved via the call stack.
The VCL Source code for TMonitor in Delphi 2007 is very simple (Forms.pas)
TMonitor.GetBoundsRect calls win32 API GetMonitorInfo after initializing a
struct's cbSize so that the Windows API knows what size to return.
I have been over and over this code and I can't see how this level could crash, unless the Self pointer is invalid, although I suspect it might actually be the THintWindow level malfunctioning, and it is only at the TMonitor.GetBoundsRect that this malfunction becomes a visible crash because somehow it has gotten a pointer to an invalid TMonitor object and invoked a method on it.
function TMonitor.GetBoundsRect: TRect;
var
MonInfo: TMonitorInfo;
begin
MonInfo.cbSize := SizeOf(MonInfo);
GetMonitorInfo(FHandle, #MonInfo); // <----- CRASH.
Result := MonInfo.rcMonitor;
end;
Crash call stack via madExcept is only reproduceable on client systems:
main thread ($70):
004f5004 +010 myapp.exe Forms 6361 +2 TMonitor.GetBoundsRect
004f4fe2 +00a myapp.exe Forms 6352 +1 TMonitor.GetWidth
004e022f +06b myapp.exe Controls 9929 +7 THintWindow.ActivateHint
004e0457 +017 myapp.exe Controls 9970 +1 THintWindow.ActivateHintData
004f95fa +31a myapp.exe Forms 8923 +56 TApplication.ActivateHint
004f8fc1 +02d myapp.exe Forms 8728 +8 TApplication.HintTimerExpired
004f61e6 +022 myapp.exe Forms 7083 +3 HintTimerProc
7e4196c2 +00a USER32.dll DispatchMessageA
004f7f00 +0fc myapp.exe Forms 8105 +23 TApplication.ProcessMessage
004f7f3a +00a myapp.exe Forms 8124 +1 TApplication.HandleMessage
004f822f +0b3 myapp.exe Forms 8223 +20 TApplication.Run
0155cf77 +2f3 myapp.exe myapp 368 +41 initialization
All the code above in the entire call stack is VCL source code, none of it is mine.
Aside from disabling all Hints in the entire application, is there anything I could do to further troubleshoot this or work around it?
Update: Registers and disasm, and exception address:
exception class : EAccessViolation
exception message : Access violation at address 004F5004 in module 'hirepnt.exe'. Read of address 00000004.
cpu registers:
eax = 00000000
ebx = 0012fccc
ecx = 7e42ac2c
edx = 0012fccc
esi = 07b694a8
edi = 0012fd14
eip = 004f5004
esp = 0012fc90
ebp = 0012fd1c
stack dump:
0012fc90 94 fc 12 00 28 00 00 00 - 2c ac 42 7e 70 b3 6f 02 ....(...,.B~p.o.
0012fca0 fc fc 12 00 01 00 00 00 - 70 b3 6f 02 cc 53 4f 00 ........p.o..SO.
0012fcb0 01 00 00 00 01 00 00 00 - 3c 56 4f 00 14 fd 12 00 ........<VO.....
0012fcc0 a8 94 b6 07 00 00 00 00 - e7 4f 4f 00 00 00 00 00 .........OO.....
0012fcd0 4b 64 4f 00 14 fd 12 00 - a8 94 b6 07 00 00 00 00 KdO.............
0012fce0 34 02 4e 00 4c fd 12 00 - c4 5c 40 00 1c fd 12 00 4.N.L....\#.....
0012fcf0 40 fd 12 00 97 fd 12 00 - 0c 23 4d 00 e0 01 00 00 #........#M.....
0012fd00 6d 01 00 00 e0 01 00 00 - 6d 01 00 00 41 02 00 00 m.......m...A...
0012fd10 80 01 00 00 34 fd 12 00 - 10 cc 6e 02 40 fd 12 00 ....4.....n.#...
0012fd20 5d 04 4e 00 d8 fd 12 00 - 0c 23 4d 00 f0 fd 12 00 ].N......#M.....
0012fd30 e0 01 00 00 6d 01 00 00 - 41 02 00 00 7c 01 00 00 ....m...A...|...
0012fd40 f4 fd 12 00 00 96 4f 00 - 00 00 00 00 0c fe 12 00 ......O.........
0012fd50 c4 5c 40 00 f4 fd 12 00 - 8c fe 12 00 c4 61 4f 00 .\#..........aO.
0012fd60 40 41 6f 02 00 00 00 00 - 00 00 00 00 28 05 00 00 #Ao.........(...
0012fd70 15 02 00 00 00 00 00 00 - 00 00 00 00 d9 04 00 00 ................
0012fd80 ac 01 00 00 84 00 00 e0 - 01 00 00 6d 01 00 00 41 ...........m...A
0012fd90 02 00 00 7c 01 00 00 01 - 4f 00 00 00 69 00 00 00 ...|....O...i...
0012fda0 51 00 00 00 6b 00 00 00 - e0 01 00 00 61 01 00 00 Q...k.......a...
0012fdb0 f0 84 22 06 0c 23 4d 00 - e0 01 00 00 6d 01 00 00 .."..#M.....m...
0012fdc0 56 05 00 00 18 00 00 ff - fe ff ff ff fe ff ff ff V...............
disassembling:
[...]
004f4ff6 push edi
004f4ff7 add esp, -$28
004f4ffa mov ebx, edx
004f4ffc 6360 mov dword ptr [esp], $28
004f5003 6361 push esp
004f5004 > mov eax, [eax+4]
004f5007 push eax
004f5008 mov eax, [$1644560]
004f500d mov eax, [eax]
004f500f call eax
004f5011 6362 mov edi, ebx
[...]
It's most likely qc #53932 (also #25466 #57953), and patching Forms.pas does fix it. In my case, using D7, it only got triggered by using remote access, and the problem/fix is the same as for D2007.
Specifically, the patch is to change TScreen.FindMonitor. This is the D7 change, not sure if it needs any edits for D2007.
function TScreen.FindMonitor(Handle: HMONITOR): TMonitor;
var
I: Integer;
begin
Result := nil;
for I := 0 to MonitorCount - 1 do
if Monitors[I].Handle = Handle then
begin
Result := Monitors[I];
// break;
Exit;
end;
//if we get here, the Monitors array has changed, so we need to clear and reinitialize it
for i := 0 to MonitorCount-1 do
TMonitor(Monitors[i]).Free;
fMonitors.Clear;
EnumDisplayMonitors(0, nil, #EnumMonitorsProc, LongInt(FMonitors));
for I := 0 to MonitorCount - 1 do
if Monitors[I].Handle = Handle then
begin
Result := Monitors[I];
Exit;
end;
end;
The problem is quite simple to reproduce as follows:
Create an app with a main form with a panel and set a hint for the panel.
Run the application.
Hover your mouse over the panel to see the hint.
Switch to another user on your computer without closing the app.
Switch back to the original user and hover your mouse over the panel
You get the access violation:
Access violation at address 0048A74 in module 'App.exe'.Read of address 00000004.
My workaround consists in processing the WM_WTSSESSION_CHANGE message.
procedure TITMainForm.WMWTSSESSION_CHANGE(
var msg : TMessage);
begin
// Destroy and recreate screen to trigger call to GetMonitors.
FORMS.screen.Free;
FORMS.screen := TScreen.Create(NIL);
end;

Resources