As @Igor Skochinsky has already commented, the software is indeed written in Visual Basic 6 compiled in native mode (VB6 also supports P-mode). You can verify this with a PE Info tool like Detect It Easy (but before that you need to unpack the ASPack wrapper).
The cause of the bug is due to multiple reasons.
The software uses an WinApi Function GlobalMemoryStatus
to retrieve the System Memory currently in use. Now there are a couple of quirks of this function:
First
On computers with more than 4 GB of memory, the GlobalMemoryStatus
function can return incorrect information, reporting a value of –1 to
indicate an overflow. For this reason, applications should use the
GlobalMemoryStatusEx function instead.
Hence if your system has more than 4 GB of memory, the output from this function is not reliable, and hence may display erroneous values. Fixing this is difficult.
Second
On Intel x86 computers with more than 2 GB and less than 4 GB of
memory, the GlobalMemoryStatus function will always return 2 GB in the
dwTotalPhys member of the MEMORYSTATUS structure. Similarly, if the
total available memory is between 2 and 4 GB, the dwAvailPhys member
of the MEMORYSTATUS structure will be rounded down to 2 GB. If the
executable is linked using the /LARGEADDRESSAWARE linker option, then
the GlobalMemoryStatus function will return the correct amount of
physical memory in both members
To fix this bug, you need to make the application Large Address Aware. This can be done by loading it in CFF Explorer and check the flag App can handle > 2GB address space under
Nt Headers -> File headers -> Characteristics.
Now, to convert the integer memory value obtained from GlobalMemoryStatus
to a string the app uses the CStr
function.
VB6 has no unsigned 32 bit integer data type. The only unsigned data type is an 8 bit Byte
.
Suppose your system has more than 2GB but less than 4GB memory and that you have already fixed the second bug as mentioned above.
Let's assume your system has 3GB memory. This is equivalent to 3,22,12,25,472
bytes in decimal or 1100 0000 0000 0000 0000 0000 0000 0000
bytes in binary.
Since the MSB of this value is 1, it will be treated as negative when passed to CStr
. Thus the resultant string would be - 1GB
instead of 3GB
. There is also no easy fix for this.
So all-in-all the software is only usable when your system has less than 2GB memory.
UPDATE (Signed Integer Bug Fix)
The signed integer bug can be patched to make the application usable to 4GB.
Patch the binary so as to convert theSAR
(signed shift) to SHR
(unsigned shift) instruction.
Original Code
00092DCD and edx,000FFFFF
00092DD3 add eax,edx
00092DD5 sar eax,14 ; <<<<<<<<<<<
00092DD8 mov dword ptr [ebp-28],eax
00092DDB mov eax,dword ptr [ebp-54]
00092DDE cdq
00092DDF and edx,000FFFFF
00092DE5 add eax,edx
00092DE7 sar eax,14 ; <<<<<<<<<<<
00092DEA mov dword ptr [ebp-30],eax
Patched Code
00092DCD and edx,000FFFFF
00092DD3 add eax,edx
00092DD5 shr eax,14 ; <<<<<<<<<<<
00092DD8 mov dword ptr [ebp-28],eax
00092DDB mov eax,dword ptr [ebp-54]
00092DDE cdq
00092DDF and edx,000FFFFF
00092DE5 add eax,edx
00092DE7 shr eax,14 ; <<<<<<<<<<<
00092DEA mov dword ptr [ebp-30],eax
Incorporating the large address aware and signed integer patch, the application can be made usable to 4 GB of memory.
ThunderRT6
sounds like VB6, not Delphi.