bodgit / sevenzip

Golang library for dealing with 7-zip archives
https://godoc.org/github.com/bodgit/sevenzip
BSD 3-Clause "New" or "Revised" License
166 stars 14 forks source link

Extract files from a self-extracting exe #142

Closed chmaha closed 9 months ago

chmaha commented 9 months ago

Should it be as simple as replacing an existing function which starts with r, err := zip.OpenReader(archive) with r, err := sevenzip.OpenReader(archive)and then being able to use existing f.Open() and io.Copy() lines? I am successful with a test.7z I made but I don't seem to be able to get it to work with this self-extracting exe file: https://www.reaper.fm/files/6.x/reaper683_x64-install.exe. The PE file is definitely valid:

reaper683_x64-install.exe: PE32 executable (GUI) Intel 80386, for MS Windows, Nullsoft Installer self-extracting archive, 5 sections

Plus, I'm able to open this using 7-zip and Gnome archive manager. What am I missing?

bodgit commented 9 months ago

It should work, in theory. The code currently expects the 7z archive signature either immediately at the beginning of the file, or within the first 1 MiB. I limited it to that to prevent it unnecessarily trawling through the whole file especially if it's was a large archive and this worked fine with the test archives I had available.

I'll check this Nullsoft installer you've linked and see where the signature is hiding.

chmaha commented 9 months ago

Many thanks! Here's the initial output from the 7z extraction command if it's useful:

Click to expand Extracting archive: reaper683_x64-install.exe -- Path = reaper683_x64-install.exe Type = PE Physical Size = 15573512 CPU = x86 Characteristics = Executable 32-bit NoRelocs NoLineNums NoLocalSyms Created = 2016-04-02 03:20:09 Headers Size = 1024 Checksum = 15631276 Image Size = 495616 Section Alignment = 4096 File Alignment = 512 Code Size = 24064 Initialized Data Size = 120320 Uninitialized Data Size = 1024 Linker Version = 6.0 OS Version = 4.0 Image Version = 6.0 Subsystem Version = 4.0 Subsystem = Windows GUI DLL Characteristics = TerminalServerAware Stack Reserve = 1048576 Stack Commit = 4096 Heap Reserve = 1048576 Heap Commit = 4096 Image Base = 4194304 ---- Path = [0] Size = 15238320 Packed Size = 15238320 Virtual Size = 15238320 Offset = 325120 -- Path = [0] Type = Nsis Physical Size = 15238313 Tail Size = 7 Method = LZMA:26 Solid = + Headers Size = 141969 Embedded Stub Size = 0 SubType = NSIS-2 BadCmd=11
bodgit commented 9 months ago

So this isn't the same format as the self-extracting format created by 7zip itself, the archive signature isn't anywhere in the file so my package won't open this currently.

This Nullsoft installer appears to have its own file format that I would need to parse to get to the right offset in the file where I presume there's some regular 7zip archive data.

chmaha commented 9 months ago

Ah, I think I found the answer via the command 7z i. For NSIS it says: offset=4 EF BE AD DE N u l l s o f t I n s t

Is that useful?

bodgit commented 9 months ago

I've found the source here https://salsa.debian.org/debian/p7zip/-/tree/master/CPP/7zip/Archive/Nsis

7z i lists all the formats that are supported by the official tool, this package just supports the first one listed:

Formats:
 0 C   F         7z       7z            7 z BC AF ' 1C

The same as I don't support RAR, or RPM, or VMDK, etc. I think this NSIS format is beyond the scope of this package. The original self-extracting format that I've added support for is just a regular .7z archive with a stripped-down executable prepended to the front of it, whereas this Nullsoft installer is something else entirely.

chmaha commented 9 months ago

Thanks. Can I maybe persuade you to support it or at least show me how I could add this unofficially assuming it is a relatively simple case of locating via the offset? At present as part of my ReaClassical installer I'm having to also pull 7zip exe and dll which is something I'm trying to eliminate for obvious reasons...

AFAIK, there's no NSIS extractor library for golang...

bodgit commented 9 months ago

Can I maybe persuade you to support it or at least show me how I could add this unofficially assuming it is a relatively simple case of locating via the offset?

It isn't, that's my point. It doesn't appear to be a .7z archive, it's an entirely different format that just happens to be supported by the 7zip tool, (same as it supports a bunch of other archive formats). However it does seem to use some of the same compression algorithms; deflate, bzip2, lzma, etc.

You could use the source I referenced in my last comment to parse the format coupled with the same packages I use for the compression algorithms to write an NSIS extractor.

chmaha commented 9 months ago

Thanks for clarifying!