1/27/2020

Write Metasploit Module in Golang

In Metasploit, support for the gran module began in December 2018. I didn't know much, but only recently.
Metaploit에서 2018년 12월부터 golang module 지원이 시작되었습니다. 저도 잘 모르고 있다가 최근에서야 알게되었네요.

Contributing modules in GO can be achieved in a few simple steps as outlined below. As for supported GO version, we have tested with 1.11.2, no promised for version 2.

Today I'm write a little bit about how to make metasploit modules with golang.
오늘은 go로 metasploit 모듈 만드는 방법에 대해 가볍게 이야기하려고 합니다.


Supports feature

Not all functions are supported, only the module below can use go. In fact, if only the expansion and scanner sides can be used, the attack modules can be easily created with the majority of the PoC codes, so there won't be any major impediments to using them.
모든 기능을 지원하진 않고 아래 모듈에 한정해서만 go 사용이 가능합니다. 사실상 exploit쪽과 scanner 쪽만 사용할 수 있다면 대다수의 PoC코드를 가지고 공격 모듈을 쉽게 만들 수 있으니 사용하는데 있어 크게 지장은 없을 것 같습니다.

remote_exploit
remote_exploit_cmd_stager
capture_server
dos
single_scanner
single_host_login_scanner
multi_scanner

Format

Execution

Execution is a part of the format that is aligned to execute cross-language behavior.
Execution은 cross-language 간 동작 실행을 위해서 맞추는 format 중 실행에 관련된 부분입니다.

2. Execution
Include this line at the top of your module: //usr/bin/env go run "$0" "$@"; exit "$?"
Ensure your file is an executable file

Because metasploit is ruby based and golang code execution requires information about the execution path or environment, you must insert the syntax above the top of the file with annotation.
metasploit은 루비 기반이고, go쪽 코드 실행을 위해선 실행 경로나 환경에 대한 정보가 필요하기 때문에 파일 맨 상단에 주석으로 위에 구문을 넣어줘야합니다.

e.g
//usr/bin/env go run "$0" "$@"; exit "$?"

package main

import (
 "crypto/tls"
 "metasploit/module"
 "msmail"
 "net/http"
 "sort"
 "strconv"
 "sync"
 "time"
)

Metadata

This part is the same as Ruby. When created in accordance with the format below, Metasploit can read, search, and use that information.
이 부분은 Ruby와 동일합니다. 아래 포맷에 맞춰서 작성하면 Metasploit에서 해당 정보를 기반으로 읽고 검색하고 사용할 수 있습니다.

import "metasploit/module"
func main() {
  metadata := &module.Metadata{
    Name: "<module name",
    Description: "<describe>",
    Authors: []string{"<author 1>", "<author 2>"},
    Date: "<date module written",
    Type:"<module type>",
    Privileged:  <true|false>,
    References:  []module.Reference{},
    Options: map[string]module.Option{ 
      "<option 1":     {Type: "<type>", Description: "<description>", Required: <true|false>, Default: "<default>"},  
      "<option 2":     {Type: "<type>", Description: "<description>", Required: <true|false>, Default: "<default>"},
  }}

  module.Init(metadata, <the entry method to your module>)
}
Running on the main() function is the method specified during module.Init. This is what the real example code looks like.
여기서 main() 함수에 실행되는건 module.Init 시 지정한 메소드입니다. 실제 예시 코드로 보면 이렇습니다.

func main() {
 metadata := &module.Metadata{
  Name:        "On premise user enumeration",
  Description: "On premise enumeration of valid exchange users",
  Authors:     []string{"poptart", "jlarose", "Vincent Yiu", "grimhacker", "Nate Power", "Nick Powers", "clee-r7"},
  Date:        "2018-11-06",
  Type:        "single_scanner",
  Privileged:  false,
  References:  []module.Reference{},
  Options: map[string]module.Option{
   "USERNAME":   {Type: "string", Description: "Single user name to do identity test against", Required: false, Default: ""},
   "USER_FILE":  {Type: "string", Description: "Path to file containing list of users", Required: false, Default: ""},
  }}

 module.Init(metadata, run_onprem_enum)
}
When this module runs, it executes 'run_onprem_enum' and returns 'msmail.ReportValidUsers' (host, validUsers)'. In the ReportValidUsers, you can send and receive data with Metasploit by calling the method LogInfo() and ReportCredentialLogin().
이 모듈이 실행되면 run_onprem_enum 를 실행하고, 리턴으로 msmail.ReportValidUsers(host, validUsers) 를 반환합니다. ReportValidUsers를 보면 module의 LogInfo() 와 ReportCredentialLogin() 등의 메소드를 호출하는데 이를 통해서 Metasploit 과 데이터를 주고받을 수 있습니다.

func ReportValidUsers(ip string, validUsers []string) {
 port := "443"
 service := "owa"
 protocol := "tcp"
 for _, user := range validUsers {
  opts := map[string]string{
   "port":         port,
   "service_name": service,
   "address":      ip,
   "protocol":     protocol,
  }
  module.LogInfo("Loging user: " + user)
  module.ReportCredentialLogin(user, "", opts)
 }
}

Go Module method

func Init(metadata *Metadata, callback RunCallback) 
func parseParams(passedParams interface{}) (map[string]interface{}, error) 
func rpcSend(res interface{}) error 
func LogError(message string)
func LogWarning(message string) 
func LogGood(message string) 
func LogInfo(message string) 
func LogDebug(message string) 
func msfLog(message string, level string) 
https://github.com/rapid7/metasploit-framework/blob/df76521100d5d88f994f23316cedcc7d83e3b597/lib/msf/core/modules/external/go/src/metasploit/module/core.go

Golang base module at now

얼마 없긴합니다.. 공식적으론 msmail에 3개정도임..
https://github.com/rapid7/metasploit-framework/search?l=Go&q=go&type=

요거 3개인 것 같습니다 :)


References

https://github.com/rapid7/metasploit-framework/wiki/Writing-External-GoLang-Modules
https://github.com/rapid7/metasploit-framework/blob/master/modules/auxiliary/scanner/msmail/shared/src/msmail/msmail.go
https://github.com/rapid7/metasploit-framework/search?l=Go&q=go&type=


HAHWUL

Security engineer, Rubyist, Gopher and H4cker!

Share: | Coffee Me: