-
Sep 11th, 2018, 06:48 AM
#1
Thread Starter
Addicted Member
[RESOLVED] Extract file from Res / Exe
Hi there,
I have some issue extracting files from Resource / Exe file.
I have a project with resource file named Project1.res and it's contents are:
Code:
AAA ICON MOVEABLE PRELOAD MAIN.ICO
STRINGTABLE DISCARDABLE
BEGIN
100 "1.1.0"
END
800 CUSTOM "test1.exe"
900 CUSTOM "test2.exe"
901 CUSTOM "test2.conf"
I can extract the binary exe files from the resource file without any issue, but the one with ID 901 is getting me some trouble while trying to extract it.
Code:
Call ExtractResFile("CUSTOM", 800, AppPath & "test1.exe")
Call ExtractResFile("CUSTOM", 900, AppPath & "test2.exe")
Call ExtractResFile("CUSTOM", 901, AppPath & "test2.conf")
Private Function ExtractResFile(stResType As String, itResID As Integer, stExport2File As String) As Boolean
On Error GoTo errh
Dim byBin() As Byte
Dim lgArray As Long
Dim frFile As Integer
frFile = FreeFile
byBin = LoadResData(itResID, stResType)
Open stExport2File For Output As frFile
Do Until lgArray = UBound(byBin) + 1
Print #frFile, (Chr$(byBin(lgArray)));
lgArray = lgArray + 1
DoEvents
Loop
Close frFile
ExtractResFile = True
Exit Function
errh:
Close frFile
ExtractResFile = False
Exit Function
End Function
For some reason the ID 901 after extracting will be corrupted by additional 2 bytes NULLs.
If I compile the Project EXE and run it from the IDE it will extract it properly from it, but if I run the compiled exe, then it will add NULL string at the end of the extracted file.
Any help would be appreciated!
btw...the ID 901 is 500Kb textual config file, others are Binaries.
Last edited by beic; Sep 11th, 2018 at 06:52 AM.
Reason: typo
-
Sep 11th, 2018, 07:43 AM
#2
Re: Extract file from Res / Exe
Hi Beic,
Yes, this is a known issue with extracting files from resources. Any file that's over 65520 bytes will be rounded up when it's extracted. If it's smaller, the exact file size will be extracted. If it's larger, it will be rounded UP to the nearest 4-byte boundary. In the past, I have looked at this issue in great detail, and have never found a perfect solution. It actually seems to be a problem beyond VB6, which means that using API calls can't even solve the problem.
Here are some possible solutions, all of which involve checking to see how large the file is before deciding what to do. I'm quite confident about that 65520 byte threshold, so you need to decide whether or not your file is larger than that. Then:
1) You might keep a hard-coded list of the size of your files larger than that, trimming them when they're extracted.
or
2) If there's some way to figure out what the size of the file by examining it, do that and then trim it.
or
3) Test and see if those extra one, two, or three bytes actually make any difference to the program opening the file.
In the past, I've used combinations of all of those. Currently, I use either #2 or #3. The only files I stuff into resources where it makes any difference are DOCX and XLSX files. For the older DOC and XLS files, it doesn't matter. I also stuff all kinds of other file types into my resources, and haven't seen where it makes any difference. Therefore, for me, it's just these DOCX and XLSX files, and I figured out how to read those files and figure out the exact size they should be.
Here's a block of code to fix these files. DataArray is my retrieved Byte Array from resources.
Code:
If UBound(DataArray) > 65519 Then ' Zero based.
s = UCase$(Right$(sSaveSpec, 5))
Select Case s
Case ".XLSX", ".XLTX", ".XLSM", ".XLTM", ".DOCX", ".DOTX", ".DOCM", ".DOTM"
Select Case True
Case DataArray(UBound(DataArray) - 21) = CByte(&H50) And _
DataArray(UBound(DataArray) - 20) = CByte(&H4B) And _
DataArray(UBound(DataArray) - 19) = CByte(&H5) And _
DataArray(UBound(DataArray) - 18) = CByte(&H6) ' In this case, we're good to go.
'
Case DataArray(UBound(DataArray) - 22) = CByte(&H50) And _
DataArray(UBound(DataArray) - 21) = CByte(&H4B) And _
DataArray(UBound(DataArray) - 20) = CByte(&H5) And _
DataArray(UBound(DataArray) - 19) = CByte(&H6) ' Crop a byte.
ReDim Preserve DataArray(0 To UBound(DataArray) - 1)
'
Case DataArray(UBound(DataArray) - 23) = CByte(&H50) And _
DataArray(UBound(DataArray) - 22) = CByte(&H4B) And _
DataArray(UBound(DataArray) - 21) = CByte(&H5) And _
DataArray(UBound(DataArray) - 20) = CByte(&H6) ' Crop two bytes.
ReDim Preserve DataArray(0 To UBound(DataArray) - 2)
'
Case DataArray(UBound(DataArray) - 24) = CByte(&H50) And _
DataArray(UBound(DataArray) - 23) = CByte(&H4B) And _
DataArray(UBound(DataArray) - 22) = CByte(&H5) And _
DataArray(UBound(DataArray) - 21) = CByte(&H6) ' Crop three bytes.
ReDim Preserve DataArray(0 To UBound(DataArray) - 3)
'
Case Else
' Just leave it alone and hope for the best.
End Select
End Select
End If
I can provide more details if you like.
Hope That Helps,
Elroy
EDIT1: Just a bit more information ... newer Office files (the ones with the X on the extension) are actually ZIP files. You can see that by opening them with something like 7Zip. They'll open right up. Therefore, as such, they've got a certain footer on them. The &H50, &H4B, &H5, &H6 is part of that footer, and it's ALWAYS a certain number of bytes from the end. Therefore, I use that information to determine the exact file size.
EDIT2: Now, regarding your .CONF file, I've got no idea what type of file that is. Therefore, you may have to resort to option #1 above, which means that, every time it changes, you'll need to remember to alter your hard-coded size. Or, you'll have to figure out if there's some way to read it to determine the size it should be.
EDIT3: Olaf Schmidt also once pointed out that certain ZIP files (but not Office files) may have a string-descriptor as a footer beyond those &H50, &H4B, &H5, &H6 bytes. He came up with the following code to circumvent that, but I haven't tested it:
Code:
' Debug.Print "ByteArray-Size:"; UBound(b) + 1
' For i = UBound(b) - 3 To 0 Step -1
' If b(i) = 80 And b(i + 1) = 75 And b(i + 2) = 5 And b(i + 3) = 6 Then
' Debug.Print "ExpectedZipLen:"; i + 22 + b(i + 20) + 256& * b(i + 21)
' Exit For
' End If
' Next
Last edited by Elroy; Sep 11th, 2018 at 07:57 AM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Sep 11th, 2018, 07:50 AM
#3
Thread Starter
Addicted Member
Re: Extract file from Res / Exe
Hi Elroy,
Thank you for your quick response!
Before I start to answer/comment to your post I will just add this quickly:
The size of that file is exactly:
Code:
Size: 470 KB (481,455 bytes)
Size on disk: 472 KB (483,328 bytes)
-
Sep 11th, 2018, 08:04 AM
#4
Re: Extract file from Res / Exe
Beic,
If you know that'll ALWAYS be the case, just do something similar to the following after you get it into your Byte Array:
Code:
Redim Preserve byBin(481454)
And that'll probably fix your problem. Notice I used 481,454 and not 481,455 because the array is ZERO-based.
Good Luck,
Elroy
EDIT1: Correction, use SIZE, not Size-on-Disk. I fixed it in the above. Sorry about that. The size on disk adds size for your disk sector and/or cluster sizes (those are old FAT terms, but they still apply).
Last edited by Elroy; Sep 11th, 2018 at 08:09 AM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Sep 11th, 2018, 08:15 AM
#5
Thread Starter
Addicted Member
Re: Extract file from Res / Exe
The file sizes are:
Code:
test1.exe 516 KB (528,384 bytes)
test2.exe 36 KB (36,864 bytes)
test2.conf 472 KB (483,328 bytes)
The weird thing is that both EXE files are extracted correctly, only that CONF file has an issue.
-
Sep 11th, 2018, 08:20 AM
#6
Re: Extract file from Res / Exe
Beic,
Please be sure and use the exact size, and not the size on disk!
With respect to EXE files, it often makes no difference if there's an extra byte or two (or three) tagged onto the end. And, maybe their exact size just happens to be on a 4-byte boundary. It happens 1/4th of the time.
Good Luck,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Sep 11th, 2018, 08:30 AM
#7
Thread Starter
Addicted Member
Re: Extract file from Res / Exe
No, no, no, It's fine, I understood you.
I'm talking about the bigger EXE file and afer extraction the size stays the same, that's weird, but also good!
Regarding CONF file, as you proposed I did it like this:
Code:
If itResID = 901 Then
ReDim Preserve byBin(481454)
End If
and it's extracting fine now!
Last edited by beic; Sep 11th, 2018 at 08:32 AM.
Reason: typo
-
Sep 11th, 2018, 05:26 PM
#8
Re: [RESOLVED] Extract file from Res / Exe
The more "dropper" programs (with embedded PE files) people write the more the antivirus scores given because a program is recognized as a VB6 program goes up. Eventually it will become impossible to run VB6 programs any more.
You are engaged in a strongly discouraged activity.
Another trend I have seen is antivirus detection of code that has been "hidden" as String constants in hex or base64 to be injected by a program after it starts. The score given for this is quite high, and will most likely end up being another "strike" against any VB6 program in the near future because such code injection has recently proliferated.
Because of these exploits VB6 now has a very poor name in the security community.
-
Sep 11th, 2018, 05:43 PM
#9
Re: [RESOLVED] Extract file from Res / Exe
Dilettante,
So, from the OS's (Windows) perspective, what's the difference in my program "dropping" a file from my resources, as compared to, say, my program creating an Access database from scratch and "dropping" it out somewhere for me to use?
Best Regards,
Elroy
EDIT1: Or better yet, my program just opening some file as Open ... For Binary, and then saving persistent data I need to save. From the OS's perspective (or even any virus scanner), I don't see how there's any difference.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Sep 11th, 2018, 06:04 PM
#10
Thread Starter
Addicted Member
Re: [RESOLVED] Extract file from Res / Exe
Originally Posted by dilettante
You are engaged in a strongly discouraged activity.
Wow, wow, wow, hold your horses just there!
First of all you can't accuse me for anything, second I developing a front end GUI for AVR microcontroller flasher, so I don't want to make a setup file for it and I decided to embed those EXEs and support files!
Just my two cents.
Regards,
Viktor
-
Sep 11th, 2018, 06:18 PM
#11
Re: [RESOLVED] Extract file from Res / Exe
I wasn't accusing you of anything except poor practices. Practices that are causing VB6 application users more and more grief.
Even if your program is completely innocent, use of malware techniques gives VB6 programs a black eye as a group.
-
Sep 11th, 2018, 06:21 PM
#12
Thread Starter
Addicted Member
Re: [RESOLVED] Extract file from Res / Exe
These kind of things can be achieved in ANY programming language.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|