If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below. |
|
|
Thread Tools | Rate Thread | Display Modes |
#61
|
|||
|
|||
filever?
On 2/2/19 11:26 AM, Frank Slootweg wrote:
T wrote: On 2/1/19 3:57 PM, RBFrank wrote: On Fri, 1 Feb 2019 15:31:29 -0800, T wrote: On 1/31/19 4:03 PM, Mayayana wrote: I assume you're in WINE I am in raw Linux and using Perl 6 (not Perl 5). I have WINE installed, but am not using it for this. That's certainly doable. As I said above, if you want to do it directly then download my icon extractor script and look up the layout of the VS_VERSION_INFO resource. Is that a Windows program? Doesn't Perl have the ability to parse byte data? beyond your wildest imagination. If so then you just need to walk the PE header to the resource section and get the data. Or if you want to use a half-assed hack that wil probably be fine in most cases, look for the string VS_VERSION_INFO Is this is your program or hex edit? , then look ahead from there for the file version string, then get the bytes after that. It should be hard to work out the layout by looking at the FILEVERSIONINFO enum. What do I look for in Hex Edit? Judging by the types of questions you're asking, it seems that you might not be qualified for this task. Mumble. Apparently, no one else is either. I have been googling my ass off looking for the definition of this metadata and where to look for it. I get back a lot of systems calls. Dot Net has a beautiful one. But no one will tell me where to look. In addition to what you've been given already, you could take a target file and check its version info in Windows, then do a byte-level review of the file to find the version string, then back up from there to see what any headers might look like. See if you can find a marker that tells you that you've definitely found the version string. After that, it's off to the races. I have been looking around various exe's with hexedit seeing if I can find some commonality. What I really, really could use if the definition of this metadata so I knew where to look. Once I know where to look, digging out the version is child's play with Perl (6). You seem to have managed to create a basic home-grown solution, but maybe this is still of use: This thread says that ExifTool also handles EXE files and also runs on Linux: https://superuser.com/questions/1060460/how-to-get-from-a-exe-executable-file-the-version-author-publisher-etc-and (Found by doing a 'where is version in exe file' search in Google.) The ExifTool page says that it is platform-independent Perl library 'plus a command-line application', but only has Windows and MacOS *executables*: 'ExifTool by Phil Harvey' https://sno.phy.queensu.ca/~phil/exiftool I don't know much about Perl, but AFAICT, the 'command-line application' "exiftool" is written in Perl (#!/usr/bin/perl -w) and contained in the 'Download Version 11.26' archive file Image-ExifTool-11.26.tar.gz So, as probably most Linux systems have Perl, you should be able to run the exiftool Perl program on most Linux systems. See https://sno.phy.queensu.ca/~phil/exiftool/#supported for the Supported File Types and click on a file type - i.e. EXE - to get details about that file type. HTH. Oh ya, I saw that. Beautiful tool. I just wanted control over it myself |
Ads |
#62
|
|||
|
|||
filever?
On 2/2/19 5:44 AM, Mayayana wrote:
"T" wrote Well, so far so good. It is a bit slow on larger exe's. Will have to work on that. Perl, slow? You could go a lot faster if you first get the pointer in the file header. But if you want to stick with the brute hack of searching for the string "VS_VERSION_INFO", you'll do better if you start from the end. It's typically near the back. The correct version is located under "VERSION_INFO". I traced the slow part down to my conversion from a type Buf to type Str. I am working on doing my own Subroutines to duplicate the string functions I used as Buf functions so as to not have the lag. Other than that it is really fast! I only suck up the first 3MB of the file. So far, I can always find VERSION_INFO without an issue. |
#63
|
|||
|
|||
filever?
On 02/02/2019 04.20, T wrote:
On 2/1/19 7:04 PM, Carlos E.R. wrote: .... Wait. Are you seeking for the version a program reports about itself? Like asking word.exe what version it is? Like in Linux doing: "man --version"? Which is why you are looking at "resources" and strings? Yup. Then there is no universal method. -- Cheers, Carlos. |
#64
|
|||
|
|||
filever?
"T" wrote | So if you look at the docs you've got: | | 4D 5A "magic" | 90 major linker version | 00 | 03 00 00 00 size of code | 04 00 00 00 size of initial data | [I'm not sure those are used. They seem to | always be the same.] | FF FF 00 00 offset of entry point | B8 00 00 00 base of code | 00 00 00 00 base of data | 40 00 00 00 image base | 00 00 00 00 section alignment | 00 00 00 00 file alignment | 00 00 major OS version | 00 00 minor OS version | | Then, of course, there's the task of actually intepreting | what is or isn't stored in those values. But it's impressive | that Perl was able to read 40 bytes. | | | The "FileVersion" is located under "VERSION_INFO". There | are several file version in an exe, so I look only for the one | under VERSION_INFO. | It sounds to me like you're not getting enough sleep. You repeatedly fail to actually read what people are writing. You posted the 1st 40 bytes of the file that you're trying to read. I posted what those bytes mean, to point out how to read the PE file header. Yes, file version info is under VERSION_INFO, but it's actually VS_VERSION_INFO. I must have written that at least 4 times already in other posts. |
#65
|
|||
|
|||
filever?
"T" wrote
| Wine also has their own tool too, but I forgot what it is | called. I would look at it, but C blows my mind. | | But, I want full control over the process myself. | For future reference, I don't know if you know about the Perl Win32 library. If not, you might find it useful. I don't use Perl but used to have a friend who did. He showed me this at one point. Briefly, software in Windows uses the Win32 API, which is a massive collection of documented functions. They're what make Windows a software platform. Whether you want to write a file, change a Registry value, find a file version, copy an image.... it's all in there. And there are also many similar APIs that are not central but are used, for instance, for text-to-speech or advanced graphic functions. The format of the functions is generally similar. A typical one is SendMessage, which is used to do things in controls and windows. For instance, scrolling a text box: Return = SendMessage(window.handle, messageID, param1, param2) The parameters are usually integers or string pointers. Typically only compiled software can call those functions because it requires direct access to memory addresses, and data types that scripting languages don't have. But someone wrote a Win32 library (module?) for Perl that allows you to pass the parameters and data types in and get the result back. So it might be something like: return = PerlMod.CallWin32 SendMessage, Handle[long], ID[long], p1[long], p2[long] That's probably not the right syntax, but you can get the idea from that. The Perl library takes in the request, translates it, and makes the call itself. That would be a very clunky way to write software, but you could use it in Windows or under WINE to accomplish all sorts of things. |
#66
|
|||
|
|||
filever?
"T" wrote
| "VS_VERSION_INFO", you'll do better if you start from | the end. It's typically near the back. | | The correct version is located under "VERSION_INFO". | See my latest post above, then check your EXE. Don't you see "VS_" in front of "VERSION_INFO"? That makes it a more unique string, so you should use it. | I only suck up the first 3MB of the file. So far, I can | always find VERSION_INFO without an issue. | Again you're not reading what I wrote. The resource section is generally at the back. You're getting success only because most EXEs are less than 3 MBs. I just checked one I knew would be bloated. Paint Shop Pro 16. It's a bit over 4 MB. "VS_VERSION_INFO" is found at offset 3,874,438. So your method would fail there. In other words, if you start from the back and only look further if that fails, then the operation will be a lot more efficient. It might also be good to only look for VS_ at first. That alone will be ra x = Find "VS_" If after x is "VERSION_INFO" then.... If you're finding string ops faster than array then you'll probably want to either ucase the string or do a binary search. Perl can probably do the latter. You could also try only getting every second byte, or rather, every first byte of two. That would basically turn your EXE string data from "unicode" to corrupted ANSI. But the version info would be converted to readable ANSI. It would just drop out the nulls. Whether that makes sense would depend on what Perl can do and which operations are faster. With interpreted languages it can sometimes be surprising what will optimize. In general, memory allocation is the worst. But there can be funny quirks. For instance, in VBScript, it's very fast to ucase but relatively slower to do a non-binary search. So I can make multiple non-case-sensitive searches much faster by ucasing a long string first. It's counter-intuitive, but it works. |
#67
|
|||
|
|||
filever?
"T" wrote
| I traced the slow part down to my conversion from a type | Buf to type Str. I am working on doing my own Subroutines | to duplicate the string functions I used as Buf functions | so as to not have the lag. Other than that it is | really fast! | | I only suck up the first 3MB of the file. So far, I can | always find VERSION_INFO without an issue. | Here's an interesting one. We're getting somewhat OT, but I guess at least we're not discussing cold weather in the middle ages, as in the polar vortex thread. '----- begin vbscript---------------------- Dim FSO, TS, s, Arg, oFil, FLen, Pt1, Pt2, sVer, L1, L2 Set FSO = CreateObject("Scripting.FileSystemObject") Arg = WScript.arguments.item(0) L1 = timer Set oFil = FSO.GetFile(Arg) FLen = oFil.Size Set oFil = Nothing Set TS = FSO.OpenTextFile(Arg, 1, False, -1) s = TS.Read(FLen) TS.Close Set TS = Nothing Pt1 = InStrRev(s, "VS_VERSION_INFO", -1, 0) If Pt1 0 Then Pt2 = InStr(Pt1, s, "FileVersion", 0) If Pt2 0 Then sVer = Mid(s, (Pt2 + 13), 15) End If L2 = timer Pt1 = InStr(sVer, chr(0)) If Pt1 0 Then sVer = Left(sVer, Pt1 - 1) MsgBox sVer & vbCrLf & CStr(L2 - L1) Set FSO = Nothing WScript.quit '------------------------------ That's a VBScript. I drop EXEs onto it. It's incredibly inefficient because it has to load the Windows Script Host, then load scrrun.dll for the FileSystemObject, then get the file loaded, then get the bytes converted to pseudo-unicode and put into a string. Nevertheless, it found the version in a 4+ MB EXE in a little under 1/2 second. When I ran it on a small EXE, 30 KB, it was too fast to register on the timer. (I'm not sure, but I think that probably means it was under 15ms. The timer function registers fractions of a ms, but I'm not sure the system timer can.) I would guess Perl is significantly faster than VBS. A couple of notes: VBS can read the file as ASCII or unicode. I set it for unicode, a hack that allowed me to cut the file in half and convert unicode strings to ANSI in one operation. Perl may not have an option to read unicode. This particular definition of unicode is unicode-16, which is the standard in Windows. I think Linux is currently defaulting to utf-8. Also, InStrRev searches a string from the back. Perl may not have a correlate. Lastly, the part near the end that searches for chr(0) is necessary because in Windows a null marks the end of a string and will cause odd behavior if left in. So I needed to snip the nulls. Otherwise I won't get the timer reading in the msgbox because when I concatenate the version string with the timer report, msgbox sees the nulls and snips it there. The only thing I'm not sure of is whether the "FileVersion" string will always start at an even offset. I'm guessing it will because uneven byte arrangements in a file ar very rare. Even when there's something like a 1 byte value in a header, the header will still generally be a multiple of 4 bytes. |
#68
|
|||
|
|||
filever?
On 2/3/19 5:24 AM, Mayayana wrote:
"T" wrote | So if you look at the docs you've got: | | 4D 5A "magic" | 90 major linker version | 00 | 03 00 00 00 size of code | 04 00 00 00 size of initial data | [I'm not sure those are used. They seem to | always be the same.] | FF FF 00 00 offset of entry point | B8 00 00 00 base of code | 00 00 00 00 base of data | 40 00 00 00 image base | 00 00 00 00 section alignment | 00 00 00 00 file alignment | 00 00 major OS version | 00 00 minor OS version | | Then, of course, there's the task of actually intepreting | what is or isn't stored in those values. But it's impressive | that Perl was able to read 40 bytes. | | | The "FileVersion" is located under "VERSION_INFO". There | are several file version in an exe, so I look only for the one | under VERSION_INFO. | It sounds to me like you're not getting enough sleep. I have heard of that concept. You repeatedly fail to actually read what people are writing. You posted the 1st 40 bytes of the file that you're trying to read. I posted what those bytes mean, to point out how to read the PE file header. I am not following you. Here is the fisrt 0x0070 bytes: 00000000 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 MZ.............. 00000010 B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 .........@....... 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................. 00000030 00 00 00 00 00 00 00 00 00 00 00 00 D8 00 00 00 ................. 00000040 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68 .........!..L.!Th 00000050 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F is program canno 00000060 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 t be run in DOS 00000070 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00 mode....$...... Not seeing anything useful. Be nice if I could find a pointer to VS_VERSION_INFO Yes, file version info is under VERSION_INFO, but it's actually VS_VERSION_INFO. I must have written that at least 4 times already in other posts. You are correct. 00002C60 A4 03 34 00 00 00 56 00 53 00 5F 00 56 00 45 00 ...4...V.S._.V.E. 00002C70 52 00 53 00 49 00 4F 00 4E 00 5F 00 49 00 4E 00 R.S.I.O.N._.I.N. 00002C80 46 00 4F 00 00 00 00 00 BD 04 EF FE 00 00 01 00 F.O............. |
#69
|
|||
|
|||
filever?
On 2/3/19 5:41 AM, Mayayana wrote:
"T" wrote | Wine also has their own tool too, but I forgot what it is | called. I would look at it, but C blows my mind. | | But, I want full control over the process myself. | For future reference, I don't know if you know about the Perl Win32 library. If not, you might find it useful. I don't use Perl but used to have a friend who did. He showed me this at one point. Briefly, software in Windows uses the Win32 API, which is a massive collection of documented functions. They're what make Windows a software platform. Whether you want to write a file, change a Registry value, find a file version, copy an image.... it's all in there. And there are also many similar APIs that are not central but are used, for instance, for text-to-speech or advanced graphic functions. The format of the functions is generally similar. A typical one is SendMessage, which is used to do things in controls and windows. For instance, scrolling a text box: Return = SendMessage(window.handle, messageID, param1, param2) The parameters are usually integers or string pointers. Typically only compiled software can call those functions because it requires direct access to memory addresses, and data types that scripting languages don't have. But someone wrote a Win32 library (module?) for Perl that allows you to pass the parameters and data types in and get the result back. So it might be something like: return = PerlMod.CallWin32 SendMessage, Handle[long], ID[long], p1[long], p2[long] That's probably not the right syntax, but you can get the idea from that. The Perl library takes in the request, translates it, and makes the call itself. That would be a very clunky way to write software, but you could use it in Windows or under WINE to accomplish all sorts of things. yes, I have seen all that. I can't read C so it is not of much use. |
#70
|
|||
|
|||
filever?
On 2/3/19 6:09 AM, Mayayana wrote:
"T" wrote | "VS_VERSION_INFO", you'll do better if you start from | the end. It's typically near the back. | | The correct version is located under "VERSION_INFO". | See my latest post above, then check your EXE. Don't you see "VS_" in front of "VERSION_INFO"? That makes it a more unique string, so you should use it. | I only suck up the first 3MB of the file. So far, I can | always find VERSION_INFO without an issue. | Again you're not reading what I wrote. The resource section is generally at the back. You're getting success only because most EXEs are less than 3 MBs. I just checked one I knew would be bloated. Paint Shop Pro 16. It's a bit over 4 MB. "VS_VERSION_INFO" is found at offset 3,874,438. So your method would fail there. I found "VERSION_INFO" to also be a unique sting in everything I tested, but I do get your point and just added the "VS_" into my search. Thank you! In other words, if you start from the back and only look further if that fails, then the operation will be a lot more efficient. It might also be good to only look for VS_ at first. That alone will be ra x = Find "VS_" If after x is "VERSION_INFO" then.... Perl 6 is so bloody fast at finding fragments, that I would take longer to look for "VS_", which may or may not be unique, and then look for the rest of it. If you're finding string ops faster than array then you'll probably want to either ucase the string or do a binary search. Perl can probably do the latter. You could also try only getting every second byte, or rather, every first byte of two. That would basically turn your EXE string data from "unicode" to corrupted ANSI. But the version info would be converted to readable ANSI. It would just drop out the nulls. Whether that makes sense would depend on what Perl can do and which operations are faster. I want it jsut as I read it. Some are using four nuls to terminate and some are using a space to terminate. If I "decode" I lose my nuls and con't tell when the version stops. I do dump any remaining nuls from the version after I cut it out. With interpreted languages it can sometimes be surprising what will optimize. In general, memory allocation is the worst. But there can be funny quirks. For instance, in VBScript, it's very fast to ucase but relatively slower to do a non-binary search. So I can make multiple non-case-sensitive searches much faster by ucasing a long string first. It's counter-intuitive, but it works. Perl 6's "index" search is bloody fast. Where I am slow is converting Buf (Binary) into Str (String). Takes up[ to 15 seconds in some instances. for ( @$BinaryFile ) - $Char { $StrFile ~= chr($Char); } I am looking at doing index searches directly on the binary code, rather than converting to a strig. Thank you for all the tips! -T |
#71
|
|||
|
|||
filever?
"T" wrote
| That's probably not the right syntax, but you can get | the idea from that. The Perl library takes in the request, | translates it, and makes the call itself. That would be a | very clunky way to write software, but you could use it in | Windows or under WINE to accomplish all sorts of things. | | | | yes, I have seen all that. I can't read C so it is not of much use. It has nothing to do with C. You just have to know what to call, which is in the MSDN docs. It might not be of any use to you, but you can do it. The file version functions are an example. But I don't know how complicated it might be for Perl with datatypes. For instance, GetVersionEx returns the Windows version info. It's a very simple call. But it returns a pointer to a data structure. So Perl would need to provide a way for you to access that. |
#72
|
|||
|
|||
filever?
"T" wrote
| Where I am slow is converting Buf (Binary) into | Str (String). Takes up[ to 15 seconds in some | instances. | | for ( @$BinaryFile ) - $Char { $StrFile ~= chr($Char); } | And you can't just read it in as a string in the first place? I don't know much about Perl, so I don't really know what it can do. I'm surprised the conversion is so slow. A byte array is essentially the same as a string except for the frontend marker bytes. For instance, in VB there's a function StrConv that will convert any size array to string almost instantly. There are also fast functions to join array members into a string. But an array search should also be fast. Something like: For i = last to first if i = 79 'O if i - 1 = 0 if i - 2 = 70 'F if i - 3 = 0 if i - 4 = 78 'N.... If you get that far you're 95% sure it's VS_VERSION_INFO, so you could afford to check back for the whole thing at that point. |
#73
|
|||
|
|||
filever?
On 2/3/19 7:20 PM, Mayayana wrote:
"T" wrote | That's probably not the right syntax, but you can get | the idea from that. The Perl library takes in the request, | translates it, and makes the call itself. That would be a | very clunky way to write software, but you could use it in | Windows or under WINE to accomplish all sorts of things. | | | | yes, I have seen all that. I can't read C so it is not of much use. It has nothing to do with C. You just have to know what to call, which is in the MSDN docs. It might not be of any use to you, but you can do it. The file version functions are an example. But I don't know how complicated it might be for Perl with datatypes. For instance, GetVersionEx returns the Windows version info. It's a very simple call. But it returns a pointer to a data structure. So Perl would need to provide a way for you to access that. If I know where to point, I can easily find it with Perl. I just can't find where to point in the docs. Do you know where these docs are? |
#74
|
|||
|
|||
filever?
On 2/3/19 7:43 PM, Mayayana wrote:
And you can't just read it in as a string in the first place? If will, but it "encodes" you, usually UTF8. You lose your nuls, etc. |
#75
|
|||
|
|||
filever?
On 04/02/2019 02.32, T wrote:
On 2/3/19 5:24 AM, Mayayana wrote: "T" wrote Â*Â* It sounds to me like you're not getting enough sleep. I have heard of that concept. You repeatedly fail to actually read what people are writing. You posted the 1st 40 bytes of the file that you're trying to read. I posted what those bytes mean, to point out how to read the PE file header. I am not following you.Â* Here is the fisrt 0x0070 bytes: 00000000Â*Â* 4D 5A 90 00Â* 03 00 00 00Â* 04 00 00 00Â* FF FF 00 00 MZ.............. 00000010Â*Â* B8 00 00 00Â* 00 00 00 00Â* 40 00 00 00Â* 00 00 00 00 ........@....... 00000020Â*Â* 00 00 00 00Â* 00 00 00 00Â* 00 00 00 00Â* 00 00 00 00 ................ 00000030Â*Â* 00 00 00 00Â* 00 00 00 00Â* 00 00 00 00Â* D8 00 00 00 ................ 00000040Â*Â* 0E 1F BA 0EÂ* 00 B4 09 CDÂ* 21 B8 01 4CÂ* CD 21 54 68 ........!..L.!Th 00000050Â*Â* 69 73 20 70Â* 72 6F 67 72Â* 61 6D 20 63Â* 61 6E 6E 6FÂ* is program canno 00000060Â*Â* 74 20 62 65Â* 20 72 75 6EÂ* 20 69 6E 20Â* 44 4F 53 20Â* t be run in DOS 00000070Â*Â* 6D 6F 64 65Â* 2E 0D 0D 0AÂ* 24 00 00 00Â* 00 00 00 00 mode....$...... Not seeing anything useful. That's the MSDOS header and stub, mentioned in the wikipedia links I posted. The new executable header goes after them, but not on a fixed address, I'm afraid. Be nice if I could find a pointer to VS_VERSION_INFO That's a resource, I think. You need to use or develop software to walk the resource data. The first step would be to find resource table start and size, values stored in the PE header. -- Cheers, Carlos. |
Thread Tools | |
Display Modes | Rate This Thread |
|
|