i have written a go commandline tool to extract the exe from the gif file as used by this malware.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"bytes" | |
"container/ring" | |
"encoding/hex" | |
"flag" | |
"fmt" | |
"io/ioutil" | |
"log" | |
"os" | |
) | |
var inFile string | |
func init() { | |
flag.StringVar(&inFile, "in", "", "path to input file") | |
} | |
func check(err error) { | |
if err != nil { | |
log.Fatal(err) | |
} | |
} | |
func main() { | |
// parse flags | |
flag.Parse() | |
// check if inputFile is given | |
if inFile == "" { | |
err := fmt.Errorf("no input file given") | |
check(err) | |
} | |
// determine fileSize of inputFile | |
var fileSize int64 | |
file, err := os.Open(inFile) | |
check(err) | |
fi, err := file.Stat() | |
check(err) | |
fileSize = fi.Size() | |
var offset int64 | |
var bytesRead int | |
// extract XOR key | |
keyBuf := make([]byte, 256) | |
offset, err = file.Seek(10, 0) | |
check(err) | |
bytesRead, err = file.Read(keyBuf) | |
check(err) | |
log.Printf("read %d at offset %d into keyBuf\n", bytesRead, offset) | |
log.Println("Key extracted is:") | |
d := hex.Dumper(os.Stdout) | |
defer d.Close() | |
d.Write(keyBuf) | |
err = ioutil.WriteFile("key", keyBuf, 0755) | |
check(err) | |
log.Printf("key was written to the file 'key'\n") | |
// extract encrypted EXE from inFile | |
encBlockSize := fileSize - 10 - 256 - 266 | |
encBlockBuf := make([]byte, encBlockSize) | |
offset, err = file.Seek(266, 0) | |
check(err) | |
bytesRead, err = file.Read(encBlockBuf) | |
check(err) | |
log.Printf("read %d at offset %d into encBlockBuf\n", bytesRead, offset) | |
// extract last block from inFile | |
lastBlockBuf := make([]byte, 266) | |
offset, err = file.Seek(-532, 2) | |
check(err) | |
bytesRead, err = file.Read(lastBlockBuf) | |
check(err) | |
log.Printf("read %d at offset %d into lastBlock\n", bytesRead, offset) | |
// xor encBlockBuf with XOR key | |
decBlock := XOR(encBlockBuf, keyBuf) | |
// decBlock = append(decBlock, lastBlockBuf) | |
var exeBuf bytes.Buffer | |
w := bufio.NewWriter(&exeBuf) | |
w.Write(decBlock) | |
w.Write(lastBlockBuf) | |
w.Flush() | |
// write exe file out | |
err = ioutil.WriteFile("exe", exeBuf.Bytes(), 0755) | |
check(err) | |
log.Printf("wrote output to file 'exe'\n") | |
} | |
// XOR implements a rolling xor where the key size is allowed not to be the same size as the data | |
func XOR(data, key []byte) []byte { | |
// setup ring buffer with key data | |
r := ring.New(len(key)) | |
for i := 0; i < r.Len(); i++ { | |
r.Value = key[i] | |
r = r.Next() | |
} | |
// do the actual xor operation | |
for i := 0; i < len(data); i++ { // foreach byte of data | |
data[i] = r.Value.(byte) ^ data[i] // xor data byte with current ring element | |
r = r.Next() // move ring forward | |
} | |
return data | |
} |
As a sample input file you can use SHA1:724fa6b4a6a9cff08cae34cc079ef70d80378b32 the resulting exe file should be SHA1:83f7ce3f6c0a7a92d9b225eb6a2953b761601c58. Both files are available from VirusTotal.
You can download the sample gif with the hidden exe also locally. Use infected
as a password for the zip file.