Created
July 12, 2025 11:17
-
-
Save alwashali/d5aa08cb66053ebecb76d9edc5195653 to your computer and use it in GitHub Desktop.
Discover the connected devices in the network via scraping the router devices page
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Vodafone router | |
// Firmware version: 3.6.12-IMS-KDG | |
package main | |
import ( | |
"bytes" | |
"crypto/sha256" | |
"encoding/hex" | |
"encoding/json" | |
"fmt" | |
"io/ioutil" | |
"net/http" | |
"net/http/cookiejar" | |
"net/url" | |
"strconv" | |
"time" | |
"golang.org/x/crypto/pbkdf2" | |
) | |
func pbkdf2Hex(input, salt string, iterations int, length int) string { | |
key := pbkdf2.Key([]byte(input), []byte(salt), iterations, length, sha256.New) | |
hexs := hex.EncodeToString(key) | |
return hexs[:32] | |
} | |
func postForm(client *http.Client, urlstr string, headers map[string]string, data url.Values) ([]byte, error) { | |
req, err := http.NewRequest(http.MethodPost, urlstr, bytes.NewBufferString(data.Encode())) | |
if err != nil { | |
return nil, err | |
} | |
for k, v := range headers { | |
req.Header.Set(k, v) | |
} | |
resp, err := client.Do(req) | |
if err != nil { | |
return nil, err | |
} | |
defer resp.Body.Close() | |
return ioutil.ReadAll(resp.Body) | |
} | |
func getWithTs(client *http.Client, urlstr string, headers map[string]string) ([]byte, error) { | |
now := strconv.FormatInt(time.Now().UnixNano()/1e6, 10) | |
fullUrl := fmt.Sprintf("%s?_=%s", urlstr, now) | |
req, err := http.NewRequest(http.MethodGet, fullUrl, nil) | |
if err != nil { | |
return nil, err | |
} | |
for k, v := range headers { | |
req.Header.Set(k, v) | |
} | |
resp, err := client.Do(req) | |
if err != nil { | |
return nil, err | |
} | |
defer resp.Body.Close() | |
return ioutil.ReadAll(resp.Body) | |
} | |
func main() { | |
router := "http://192.168.0.1" | |
username := "admin" | |
password := "password" | |
headers := map[string]string{ | |
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...", | |
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", | |
"X-Requested-With": "XMLHttpRequest", | |
"Referer": router + "/", | |
} | |
jar, _ := cookiejar.New(nil) | |
client := &http.Client{ | |
Jar: jar, | |
} | |
// Step 1: get salt | |
data := url.Values{} | |
data.Set("username", username) | |
data.Set("password", "seeksalthash") | |
data.Set("logout", "True") | |
body, err := postForm(client, router+"/api/v1/session/login", headers, data) | |
if err != nil { | |
panic(err) | |
} | |
var saltResp struct { | |
Salt string `json:"salt"` | |
SaltWebUI string `json:"saltwebui"` | |
} | |
if err := json.Unmarshal(body, &saltResp); err != nil { | |
panic(err) | |
} | |
a := pbkdf2Hex(password, saltResp.Salt, 1000, 32) | |
b := pbkdf2Hex(a, saltResp.SaltWebUI, 1000, 32) | |
data = url.Values{} | |
data.Set("username", username) | |
data.Set("password", b) | |
_, err = postForm(client, router+"/api/v1/session/login", headers, data) | |
if err != nil { | |
panic(err) | |
} | |
cookieURL, _ := url.Parse(router) | |
client.Jar.SetCookies(cookieURL, append(client.Jar.Cookies(cookieURL), &http.Cookie{ | |
Name: "cwd", | |
Value: "Yes", | |
})) | |
delete(headers, "Content-Type") | |
//There is a protection that detect if bsd_acl_rules.js and menu are not loaded, before any other API call | |
_, err = getWithTs(client, router+"/js/app/bsd_acl_rules.js", headers) | |
if err != nil { | |
panic(err) | |
} | |
_, err = getWithTs(client, router+"/api/v1/session/menu", headers) | |
if err != nil { | |
panic(err) | |
} | |
client.Jar.SetCookies(cookieURL, append(client.Jar.Cookies(cookieURL), &http.Cookie{ | |
Name: "cwd", | |
Value: "No", | |
})) | |
respBody, err := getWithTs(client, router+"/api/v1/sta_lan_status", headers) | |
if err != nil { | |
panic(err) | |
} | |
fmt.Println("sta_lan_status cookies:", client.Jar.Cookies(cookieURL)) | |
fmt.Println("sta_lan_status response:") | |
var obj interface{} | |
if err := json.Unmarshal(respBody, &obj); err != nil { | |
fmt.Println(string(respBody)) | |
} else { | |
pretty, _ := json.MarshalIndent(obj, "", " ") | |
fmt.Println(string(pretty)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment