mirror of
https://github.com/Tylous/Mangle
synced 2026-06-06 16:54:32 +00:00
235 lines
7.7 KiB
Go
235 lines
7.7 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"crypto/rand"
|
|
"encoding/binary"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"math/big"
|
|
mrand "math/rand"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/Binject/debug/pe"
|
|
)
|
|
|
|
var hex = "abcef12345678890"
|
|
|
|
func GenerateNumer(min, max int) string {
|
|
mrand.Seed(time.Now().UnixNano())
|
|
num := mrand.Intn(max-min) + min
|
|
n := num
|
|
s := strconv.Itoa(n)
|
|
return s
|
|
|
|
}
|
|
|
|
func RandStringBytes(n int) string {
|
|
b := make([]byte, n)
|
|
for i := range b {
|
|
b[i] = hex[mrand.Intn(len(hex))]
|
|
|
|
}
|
|
return string(b)
|
|
}
|
|
|
|
type FlagOptions struct {
|
|
outFile string
|
|
inputFile string
|
|
CertCloner string
|
|
GoStrip bool
|
|
size int
|
|
}
|
|
|
|
func options() *FlagOptions {
|
|
outFile := flag.String("O", "", "The new file name")
|
|
inputFile := flag.String("I", "", "Path to the orginal file")
|
|
CertCloner := flag.String("C", "", "Path to the file containing the certificate you want to clone")
|
|
GoStrip := flag.Bool("M", false, "Edit the PE file to strip out Go indicators")
|
|
size := flag.Int("S", 0, "How many MBs to increase the file by")
|
|
flag.Parse()
|
|
return &FlagOptions{outFile: *outFile, inputFile: *inputFile, CertCloner: *CertCloner, GoStrip: *GoStrip, size: *size}
|
|
}
|
|
|
|
func main() {
|
|
fmt.Println(`
|
|
_____ .__
|
|
/ \ _____ ____ ____ | | ____
|
|
/ \ / \\__ \ / \ / ___\| | _/ __ \
|
|
/ Y \/ __ \| | \/ /_/ > |_\ ___/
|
|
\____|__ (____ /___| /\___ /|____/\___ >
|
|
\/ \/ \//_____/ \/
|
|
(@Tyl0us)`)
|
|
|
|
opt := options()
|
|
if opt.inputFile == "" {
|
|
log.Fatal("Error: Please provide a path to a file you wish to mangle")
|
|
}
|
|
|
|
if opt.outFile == "" {
|
|
log.Fatal("Error: Please provide a name for the final file")
|
|
}
|
|
InputFileData, err := ioutil.ReadFile(opt.inputFile)
|
|
|
|
if err != nil {
|
|
log.Fatalf("Error: %s", err)
|
|
}
|
|
if opt.CertCloner != "" {
|
|
FiletoCopy, err := ioutil.ReadFile(opt.CertCloner)
|
|
if err != nil {
|
|
log.Fatalf("Error: %s", err)
|
|
}
|
|
InputFileData = Stealer(InputFileData, FiletoCopy)
|
|
}
|
|
if opt.size > 0 {
|
|
InputFileData = Padding(InputFileData, opt.size)
|
|
}
|
|
|
|
if opt.GoStrip == true {
|
|
InputFileData = GoEditor(InputFileData)
|
|
}
|
|
|
|
fmt.Println("[!] Writing to new file " + opt.outFile)
|
|
ioutil.WriteFile(opt.outFile, InputFileData, 0777)
|
|
|
|
}
|
|
|
|
func GoEditor(buff []byte) []byte {
|
|
gostringg1 := "to unallocated span37252902984619140625Arabic Standard TimeAzores Standard"
|
|
gostringg2 := "TimeCertFindChainInStoreCertOpenSystemStoreWChangeServiceConfigWCheckTokenMembershipCreateProcessAsUserWCryptAcquireContextWEgyptian_HieroglyphsEtwReplyNotificationGetAcceptExSockaddrsGetAdaptersAddressesGetCurrentDirectoryWGetFileAttributesExWGetModuleInformationGetProcessMemoryInfoGetWindowsDirectoryWIDS_Trinary_OperatorIsrael Standard TimeJordan Standard TimeMeroitic_Hieroglyphs"
|
|
gostringg3 := "Standard Timebad defer size classbad font file formatbad system page sizebad use of bucket.bpbad use of bucket.mpchan send (nil chan)close of nil channelconnection timed outdodeltimer0: wrong Pfloating point errorforcegc: phase errorgo of nil func valuegopark: bad g statusinconsistent lockedminvalid request"
|
|
gostringg4 := "codeinvalid write resultis a named type filekey has been revokedmalloc during signalnotetsleep not on g0p mcache not flushedpacer: assist ratio=preempt off reason: reflect.Value.SetIntreflect.makeFuncStubruntime: double waitruntime: unknown pc semaRoot rotateRighttime: invalid numbertrace: out of memorywirep: already in goworkbuf is not emptywrite of Go pointer ws2_32.dll not foundzlib: invalid header of unexported method previous allocCount=, levelBits[level] = 186264514923095703125931322574615478515625AdjustTokenPrivilegesAlaskan Standard TimeAnatolian_HieroglyphsArabian Standard TimeBelarus Standard TimeCentral Standard TimeChangeServiceConfig2WDeregisterEventSourceEastern Standard"
|
|
gostringg5 := "0123456789abcdefghijklmnopqrstuvwxyz444089209850062616169452667236328125Go pointer stored into non-Go memory"
|
|
gostringg6 := "buildinf:"
|
|
gostringg7 := " Go build ID:"
|
|
gostringg8 := "gogo"
|
|
gostringg9 := "goid"
|
|
gostringg10 := "go.buildid"
|
|
gostringg11 := "_cgo_dummy_export"
|
|
stringnum := []string{gostringg1, gostringg2, gostringg3, gostringg4, gostringg5, gostringg6, gostringg7, gostringg8, gostringg9, gostringg10, gostringg11}
|
|
|
|
mydata := string(buff)
|
|
for i := range stringnum {
|
|
val := RandStringBytes(len(stringnum[i]))
|
|
mydata = strings.ReplaceAll(string(mydata), stringnum[i], val)
|
|
}
|
|
fmt.Println("[*] Stripped out golang strings")
|
|
return []byte(mydata)
|
|
|
|
}
|
|
|
|
func Padding(buff []byte, size int) []byte {
|
|
str1 := "0"
|
|
res1 := strings.Repeat(str1, (size * 1024 * 1024))
|
|
sourceBytes, err := pe.NewFile(bytes.NewReader(buff))
|
|
if err != nil {
|
|
log.Panic("Error Reading Inputed File")
|
|
}
|
|
//Shoutout to Binject for their project binjection where I borrowed some of the code below.
|
|
var sectionAlignment, fileAlignment, scAddr uint32
|
|
var imageBase uint64
|
|
var shellcode []byte
|
|
lastSection := sourceBytes.Sections[sourceBytes.NumberOfSections-1]
|
|
switch file := (sourceBytes.OptionalHeader).(type) {
|
|
case *pe.OptionalHeader32:
|
|
imageBase = uint64(file.ImageBase)
|
|
sectionAlignment = file.SectionAlignment
|
|
fileAlignment = file.FileAlignment
|
|
scAddr = align(lastSection.Size, fileAlignment, lastSection.Offset)
|
|
break
|
|
case *pe.OptionalHeader64:
|
|
imageBase = file.ImageBase
|
|
sectionAlignment = file.SectionAlignment
|
|
fileAlignment = file.FileAlignment
|
|
scAddr = align(lastSection.Size, fileAlignment, lastSection.Offset)
|
|
break
|
|
}
|
|
|
|
buf := bytes.NewBuffer([]byte(res1))
|
|
w := bufio.NewWriter(buf)
|
|
binary.Write(w, binary.LittleEndian, imageBase)
|
|
w.Flush()
|
|
shellcode = buf.Bytes()
|
|
|
|
shellcodeLen := len(shellcode)
|
|
newsection := new(pe.Section)
|
|
newsection.Name = "." + RandomString(5)
|
|
o := []byte(newsection.Name)
|
|
newsection.OriginalName = [8]byte{o[0], o[1], o[2], o[3], o[4], o[5], 0, 0}
|
|
newsection.VirtualSize = uint32(shellcodeLen)
|
|
newsection.VirtualAddress = align(lastSection.VirtualSize, sectionAlignment, lastSection.VirtualAddress)
|
|
newsection.Size = align(uint32(shellcodeLen), fileAlignment, 0)
|
|
newsection.Offset = align(lastSection.Size, fileAlignment, lastSection.Offset)
|
|
newsection.Characteristics = pe.IMAGE_SCN_CNT_CODE | pe.IMAGE_SCN_MEM_EXECUTE | pe.IMAGE_SCN_MEM_READ
|
|
sourceBytes.InsertionAddr = scAddr
|
|
sourceBytes.InsertionBytes = shellcode
|
|
|
|
switch file := (sourceBytes.OptionalHeader).(type) {
|
|
case *pe.OptionalHeader32:
|
|
v := newsection.VirtualSize
|
|
if v == 0 {
|
|
v = newsection.Size
|
|
}
|
|
file.SizeOfImage = align(v, sectionAlignment, newsection.VirtualAddress)
|
|
file.CheckSum = 0
|
|
break
|
|
case *pe.OptionalHeader64:
|
|
v := newsection.VirtualSize
|
|
if v == 0 {
|
|
v = newsection.Size
|
|
}
|
|
file.SizeOfImage = align(v, sectionAlignment, newsection.VirtualAddress)
|
|
file.CheckSum = 0
|
|
break
|
|
}
|
|
sourceBytes.FileHeader.NumberOfSections++
|
|
sourceBytes.Sections = append(sourceBytes.Sections, newsection)
|
|
Bytes, _ := sourceBytes.Bytes()
|
|
|
|
fmt.Println("[*] Padding has been added to increase size")
|
|
return Bytes
|
|
|
|
}
|
|
|
|
func Stealer(InputFileData, FiletoCopy []byte) []byte {
|
|
signedFileReader := bytes.NewReader(FiletoCopy)
|
|
signedsourceBytes, err := pe.NewFile(signedFileReader)
|
|
if err != nil {
|
|
|
|
}
|
|
|
|
targetFileReader := bytes.NewReader(InputFileData)
|
|
targetsourceBytes, err := pe.NewFile(targetFileReader)
|
|
if err != nil {
|
|
|
|
}
|
|
|
|
targetsourceBytes.CertificateTable = signedsourceBytes.CertificateTable
|
|
Data, err := targetsourceBytes.Bytes()
|
|
if err != nil {
|
|
}
|
|
fmt.Println("[*] Cloned certificate values")
|
|
return Data
|
|
}
|
|
|
|
func align(size, align, addr uint32) uint32 {
|
|
if 0 == (size % align) {
|
|
return addr + size
|
|
}
|
|
return addr + (size/align+1)*align
|
|
}
|
|
|
|
func RandomString(len int) string {
|
|
bytes := make([]byte, len)
|
|
for i := 0; i < len; i++ {
|
|
r, _ := rand.Int(rand.Reader, big.NewInt(25))
|
|
bytes[i] = 97 + byte(r.Int64()) //a=97
|
|
}
|
|
return string(bytes)
|
|
}
|