forked from Nhoya/gOSINT
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pni.go
160 lines (144 loc) · 4.1 KB
/
pni.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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package pni
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/cookiejar"
"net/url"
"os"
"regexp"
"strings"
"github.com/otiai10/gosseract"
)
//SyncMeAnswer contains a (partial) representation of the SyncMe JSON answer
type SyncMeAnswer struct {
ErrorCode int `json:"error_code"`
PremiumType int `json:"premium_type"`
Name string `json:"name"`
}
const (
ua = "Mozilla/5.0 (Linux; Android 8.1.0; LG-D802 Build/OPM6.171019.030.K1) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/67.0.3396.87 Mobile Safari/537.36"
)
//Options contains the options for the syncme module
type Options struct {
PhoneNumber []string
JSONFlag bool
}
//StartPNI is the init function of the module ¯\_(ツ)_/¯
func (opts *Options) StartPNI() {
//TODO: add check on number lenght
for _, num := range opts.PhoneNumber {
if !strings.HasPrefix(num, "+") {
fmt.Println(num + " is invalid, You must specify the country code with +")
os.Exit(1)
}
retrievePhoneOwner(num[1:], opts.JSONFlag)
}
}
func retrievePhoneOwner(target string, jsonFlag bool) {
cj, _ := cookiejar.New(nil)
client := &http.Client{
Jar: cj,
}
captchaID, err := sendGETRequest("https://sync.me/search/?number="+target, client)
if err != nil {
fmt.Println("Unable to get info")
os.Exit(1)
}
//extract captcha ID
re := regexp.MustCompile(`var\scaptchaURL\s=\s'(?:\/\.\.){2}/server/simple-php-captcha/simple-php-captcha\.php\?_CAPTCHA&t=(.*)';`)
match := re.FindAllStringSubmatch(string(captchaID), -1)
fmt.Println("https://sync.me/server/simple-php-captcha/simple-php-captcha.php?_CAPTCHA&t=" + match[0][1])
os.Exit(1)
//retrieve captcha
challenge, err := sendGETRequest("https://sync.me/server/simple-php-captcha/simple-php-captcha.php?_CAPTCHA&t="+match[0][1], client)
if err != nil {
panic(err)
}
//solve it
solution := solveCaptcha(challenge)
//send solution
data := url.Values{}
data.Set("action", "captcha")
data.Add("data[g-recaptcha]", solution)
data.Add("captchaResult", "")
data.Add("isMobile", "true")
_, err = sendPOSTRequest("https://sync.me/server/main.php", data, client, target)
if err != nil {
panic(err)
}
data = url.Values{}
data.Set("action", "search")
data.Add("number", target)
report, err := sendPOSTRequest("https://sync.me/server/main.php", data, client, target)
if err != nil {
panic(err)
}
//TODO: move this on an indipended function
if len(report) == 0 {
fmt.Println("Unable to complete the challenge correctly. Please retry, if the error persist open an issue.")
} else {
if jsonFlag {
fmt.Println(report)
} else {
var answer SyncMeAnswer
err := json.Unmarshal(report, &answer)
if err != nil {
panic(err)
}
if answer.ErrorCode == 8203 {
fmt.Println("Unable to find owner")
} else if answer.ErrorCode == 0 {
fmt.Println(answer.Name)
} else {
fmt.Println("Unexpected error occured, please open an issue")
fmt.Println(string(report))
os.Exit(1)
}
}
}
}
func sendGETRequest(URL string, client *http.Client) ([]byte, error) {
req, err := http.NewRequest("GET", URL, nil)
if err != nil {
log.Fatalln(err)
}
req.Header.Set("User-Agent", ua)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
func sendPOSTRequest(URL string, data url.Values, client *http.Client, target string) ([]byte, error) {
req, _ := http.NewRequest("POST", URL, bytes.NewBufferString(data.Encode()))
req.Header.Set("User-Agent", ua)
req.Header.Set("Referer", "https://sync.me/search/?number="+target)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return body, nil
}
func solveCaptcha(challenge []byte) string {
//OCR init
ocr := gosseract.NewClient()
ocr.SetWhitelist("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
defer ocr.Close()
ocr.SetImageFromBytes(challenge)
text, _ := ocr.Text()
return text
}