I like to extract a .jar file in Go. I tried different approaches with the build in libraries but with no success. In buff is a little part of the JAR I try to analyze. The errors also occur on the full byte array.
flate:
buff := []byte{80, 75, 3, 4, 10, 0, 8, 8, 8, 0, 239, 77, 77, 78,
147,
98, 6, 159, 116, 0, 0, 0, 132, 0, 0, 0, 20, 0, 0, 0, 77, 69, 84, 65,
45, 73, 78, 70, 47, 77, 65, 78, 73, 70, 69, 83, 84, 46, 77, 70, 37,
140, 49, 14, 194, 48, 12, 0, 247, 72, 249, 131, 63, 16, 43, 128, 88,
178, 181, 221, 144, 178, 178, 91, 196, 64, 32, 184, 81, 28, 42, 248,
61,5, 214, 187, 211, 69, 146, 124, 102, 237}
b := bytes.NewReader(buff)
zr := flate.NewReader(b)
if _, err := io.Copy(os.Stdout, zr); err != nil {
log.Fatal(err)
}
if err := zr.Close(); err != nil {
log.Fatal(err)
}
fmt.Println()
Error: flate: corrupt input before offset 5
zlib:
b := bytes.NewReader(buff)
r, err := zlib.NewReader(b)
if err != nil {
panic(err)
}
io.Copy(os.Stdout, r)
r.Close()
Error: zlib: invalid header
Wikipedia says JAR is a extension of zip and normal compression programs can unzip them. Any ideas how to get this working? Like adding a working header or is my code wrong?
JAR files are zip archives, not just zlib or flate compressed data.
So use the archive/zip
package to properly process them. For example, to list the files inside the JAR file:
r, err := zip.NewReader(bytes.NewReader(buff), int64(len(buff)))
if err != nil {
panic(err)
}
for _, f := range r.File {
fmt.Println("Found in jar:", f.Name)
}
Of course you have to provide the full file content, else you will most likely get an error when obtaining the zip.Reader
.
If you also want to print the contents of the files inside the archive, this is how you could do it:
for _, f := range r.File {
fmt.Printf("Found in jar: %s, contents:\n", f.Name)
rc, err := f.Open()
if err != nil {
log.Fatal(err)
}
_, err = io.CopyN(os.Stdout, rc, int64(f.UncompressedSize64))
if err != nil {
log.Fatal(err)
}
rc.Close()
fmt.Println()
}
Here's a JAR file which contains a single file named a.txt
, with contents "Hello Gopher"
:
buff := []byte{80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 91, 109, 103, 78, 132, 225, 60, 127, 13, 0, 0, 0, 13, 0, 0, 0, 5, 0, 28, 0, 97, 46, 116, 120, 116, 85, 84, 9, 0, 3, 206, 17, 129, 92, 219, 17, 129, 92, 117, 120, 11, 0, 1, 4, 232, 3, 0, 0, 4, 232, 3, 0, 0, 72, 101, 108, 108, 111, 32, 71, 111, 112, 104, 101, 114, 10, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 91, 109, 103, 78, 132, 225, 60, 127, 13, 0, 0, 0, 13, 0, 0, 0, 5, 0, 24, 0, 0, 0, 0, 0, 1, 0, 0, 0, 164, 129, 0, 0, 0, 0, 97, 46, 116, 120, 116, 85, 84, 5, 0, 3, 206, 17, 129, 92, 117, 120, 11, 0, 1, 4, 232, 3, 0, 0, 4, 232, 3, 0, 0, 80, 75, 5, 6, 0, 0, 0, 0, 1, 0, 1, 0, 75, 0, 0, 0, 76, 0, 0, 0, 0, 0}
Running the above code on this buffer, the output is (try it on the Go Playground):
Found in jar: a.txt, contents:
Hello Gopher