資料介紹
軟件簡介
我們在做企業(yè)安全時,弱口令檢測是系統(tǒng)/網(wǎng)絡安全的最基礎的部分之一,根據(jù)經(jīng)驗,經(jīng)常會出現(xiàn)弱口令的服務如下:
- FTP
- SSH
- SMB
- MYSQL
- MSSQL
- POSTGRESQL
- REDIS
- MONGODB
- ELASTICSEARCH
那咱們就一起用GO來寫一款常見服務的弱口令掃描器,且支持以插件的形式增加新的服務掃描模塊。我們的教程暫定為只掃以上服務。
給掃描器啟一個屌炸天的名字x-crack
,在$GOPATH/src/中建立一個x-crack項目后開始擼碼,不要給我說什么底層原理、框架內(nèi)核,老夫敲代碼就是一把梭。
?
開工
數(shù)據(jù)結(jié)構(gòu)定義
- 掃描模塊的輸入內(nèi)容為為IP、端口及協(xié)議的列表,我們需要定義一個IpAddr的數(shù)據(jù)結(jié)構(gòu);
- 每個服務的每次掃描需要傳入的參數(shù)為IP、端口、協(xié)議、用戶名和密碼,需要定義一個Service結(jié)構(gòu)來包括這些內(nèi)容;
- 每條Service的記錄在掃描模塊進行嘗試后,會得出掃描結(jié)果成功與否,我們再定義一個ScanResult數(shù)據(jù)結(jié)構(gòu)。
按照開發(fā)規(guī)范,數(shù)據(jù)結(jié)構(gòu)的定義統(tǒng)一放到models目錄中,全部的數(shù)據(jù)結(jié)構(gòu)定義如下:
package models type Service struct { Ip string Port int Protocol string Username string Password string } type ScanResult struct { Service Service Result bool } type IpAddr struct { Ip string Port int Protocol string }
FTP掃描模塊
go語言有現(xiàn)成的FTP模塊,我們找一個star數(shù)最多的直接go get
安裝一下即可使用了:
go get -u github.com/jlaffaye/ftp
我們把所有的掃描模塊放到plugins
目錄中,F(xiàn)TP協(xié)議的掃描插件如下所示:
package plugins import ( "github.com/jlaffaye/ftp" "x-crack/models" "x-crack/vars" "fmt" ) func ScanFtp(s models.Service) (err error, result models.ScanResult) { result.Service = s conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", s.Ip, s.Port), vars.TimeOut) if err == nil { err = conn.Login(s.Username, s.Password) if err == nil { defer conn.Logout() result.Result = true } } return err, result }
每個連接需要設置超時時間,防止因網(wǎng)絡問題導致的阻塞,我們打算通過程序的命令行來控制超時時間,所以定義了一個全局變量TimeOut。 放在vars模塊中的原因是防止放在這個模塊中后會和其他模塊互相調(diào)用導致的循環(huán)import
寫代碼雖然可以一把梭,但是不能等著洋洋灑灑地把幾萬行都寫完再運行,比如我們的目標是造一輛豪車,不能等著所有零件設計好,都裝上去再發(fā)動車測試,正確的開發(fā)流程是把寫邊測,不要等輪子造出來,而是在螺絲、齒輪階段就測試。
以下為FTP掃描插件這個齒輪的測試代碼及結(jié)果。
package plugins_test import ( "x-crack/models" "x-crack/plugins" "testing" ) func TestScanFtp(t *testing.T) { s := models.Service{Ip: "127.0.0.1", Port: 21, Protocol: "ftp", Username: "ftp", Password: "ftp"} t.Log(plugins.ScanFtp(s)) }
測試結(jié)果滿足預期,說明我們這個零件不是次品,可以繼續(xù)再造其他零件了。
$ go test -v plugins/ftp_test.go === RUN TestScanFtp --- PASS: TestScanFtp (0.00s) ftp_test.go:36: dial tcp 127.0.0.1:21: getsockopt: connection refused {{127.0.0.1 21 ftp ftp ftp} false} PASS ok command-line-arguments 0.025s
SSH掃描模塊
go的標準庫中自帶了ssh包,直接調(diào)用即可,完整代碼如下:
package plugins import ( "golang.org/x/crypto/ssh" "x-crack/models" "x-crack/vars" "fmt" "net" ) func ScanSsh(s models.Service) (err error, result models.ScanResult) { result.Service = s config := &ssh.ClientConfig{ User: s.Username, Auth: []ssh.AuthMethod{ ssh.Password(s.Password), }, Timeout: vars.TimeOut, HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }, } client, err := ssh.Dial("tcp", fmt.Sprintf("%v:%v", s.Ip, s.Port), config) if err == nil { defer client.Close() session, err := client.NewSession() errRet := session.Run("echo xsec") if err == nil && errRet == nil { defer session.Close() result.Result = true } } return err, result }
同樣,每個子模塊寫好后都需要先用go test跑一下看是否滿足預期,測試代碼如下:
package plugins_test import ( "x-crack/models" "x-crack/plugins" "testing" ) func TestScanSsh(t *testing.T) { s := models.Service{Ip: "127.0.0.1", Port: 22, Username: "root", Password: "123456", Protocol: "ssh"} t.Log(plugins.ScanSsh(s)) }
測試結(jié)果如下:
$ go test -v plugins/ssh_test.go === RUN TestScanSsh --- PASS: TestScanSsh (0.00s) ssh_test.go:36: dial tcp 127.0.0.1:22: getsockopt: connection refused {{127.0.0.1 22 ssh root 123456} false} PASS ok command-line-arguments 0.026s
SMB掃描模塊
SMB弱口令的掃描插件,我們使用了github.com/stacktitan/smb/smb
包,同樣直接go get
安裝一下即可拿來使用。 代碼如下:
package plugins import ( "github.com/stacktitan/smb/smb" "x-crack/models" ) func ScanSmb(s models.Service) (err error, result models.ScanResult) { result.Service = s options := smb.Options{ Host: s.Ip, Port: s.Port, User: s.Username, Password: s.Password, Domain: "", Workstation: "", } session, err := smb.NewSession(options, false) if err == nil { session.Close() if session.IsAuthenticated { result.Result = true } } return err, result }
同樣也先寫測試用例來測試一下,測試代碼如下:
package plugins_test import ( "x-crack/models" "x-crack/plugins" "testing" ) func TestScanSmb(t *testing.T) { s := models.Service{Ip: "share.xsec.io", Port: 445, Protocol: "smb", Username: "xsec", Password: "fsafffdsfdsa"} t.Log(plugins.ScanSmb(s)) }
測試結(jié)果:
hartnett at hartnettdeMacBook-Pro in /data/code/golang/src/x-crack (master) $ go test -v plugins/smb_test.go === RUN TestScanSmb --- PASS: TestScanSmb (0.04s) smb_test.go:36: NT Status Error: Logon failed {{share.xsec.io 445 smb xsec fsafffdsfdsa} false} PASS ok command-line-arguments 0.069s
MYSQL、MSSQL和POSTGRESQL掃描模塊
MYSQL、MSSQL和POSTGRESQL的掃描模塊,我使用了第三方的ORM?xorm
,當然也可以直接使用原生的sql driver來實現(xiàn),我們這里圖方便用xorm
一把梭了。 對于xorm
來說,這3個掃描插件的實現(xiàn)方法大同小異,為了節(jié)約篇幅,咱們只看mysql掃描插件的實現(xiàn),其他2個插件可以參考github中的完整源碼。 首先還是先go get
要用到的包:
go get github.com/netxfly/mysql go get github.com/go-xorm/xorm github.com/go-xorm/core
接下來我們把需要驗證的IP、port、username、password組成datasource傳遞給xorm,完整代碼如下:
package plugins import ( _ "github.com/netxfly/mysql" "github.com/go-xorm/xorm" "github.com/go-xorm/core" "x-crack/models" "fmt" ) func ScanMysql(service models.Service) (err error, result models.ScanResult) { result.Service = service dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8", service.Username, service.Password, service.Ip, service.Port, "mysql") Engine, err := xorm.NewEngine("mysql", dataSourceName) if err == nil { Engine.SetLogLevel(core.LOG_OFF) // fix "[mysql] packets.go:33: unexpected EOF" error Engine.SetMaxIdleConns(0) // Engine.SetConnMaxLifetime(time.Second * 30) defer Engine.Close() err = Engine.Ping() if err == nil { result.Result = true } } return err, result }
眼尖的同學也許發(fā)現(xiàn)了,上面?github.com/netxfly/mysql
?這個mysql包是放在筆者的github下的,這是為什么呢?
因為直接用mysql這個包的話,在掃描的過程中會遇到[mysql] packets.go:33: unexpected EOF" error
的異常輸出,影響了我們程序在掃描過程中輸出UI的美觀性,這對于帥氣的我是無法接受的,通過設置參數(shù)的方法無法解決,最后只好直接fork了一份mysql的包,把打印這個異常的語句注釋掉再提交上去直接使用了。
測試代碼:
package plugins_test import ( "testing" "x-crack/plugins" "x-crack/models" ) func TestScanMysql(t *testing.T) { service := models.Service{Ip: "10.10.10.10", Port: 3306, Protocol: "mysql", Username: "root", Password: "123456"} t.Log(plugins.ScanMysql(service)) }
測試結(jié)果:
go test -v plugins/mysql_test.go === RUN TestScanMysql --- PASS: TestScanMysql (0.02s) mysql_test.go:36: Error 1045: Access denied for user 'root'@'10.10.10.100' (using password: YES) {{10.10.10.10 3306 mysql root 123456} false} PASS ok command-line-arguments 0.041s
Redis掃描模塊
go get
安裝第三方包github.com/go-redis/redis
,完整代碼如下:
package plugins import ( "github.com/go-redis/redis" "x-crack/models" "x-crack/vars" "fmt" ) func ScanRedis(s models.Service) (err error, result models.ScanResult) { result.Service = s opt := redis.Options{Addr: fmt.Sprintf("%v:%v", s.Ip, s.Port), Password: s.Password, DB: 0, DialTimeout: vars.TimeOut} client := redis.NewClient(&opt) defer client.Close() _, err = client.Ping().Result() if err == nil { result.Result = true } return err, result }
測試代碼:
package plugins_test import ( "x-crack/models" "x-crack/plugins" "testing" ) func TestScanRedis(t *testing.T) { s := models.Service{Ip: "127.0.0.1", Port: 6379, Password: "test"} t.Log(plugins.ScanRedis(s)) }
測試結(jié)果:
go test -v plugins/redis_test.go === RUN TestScanRedis --- PASS: TestScanRedis (0.00s) redis_test.go:36: dial tcp 127.0.0.1:6379: getsockopt: connection refused {{127.0.0.1 6379 test} false} PASS ok command-line-arguments 0.025s
MONGODB掃描模塊
mongodb掃描模塊依賴mgo包,可用go get
合令直接安裝。
go get gopkg.in/mgo.v2
完整代碼:
package plugins import ( "gopkg.in/mgo.v2" "x-crack/models" "x-crack/vars" "fmt" ) func ScanMongodb(s models.Service) (err error, result models.ScanResult) { result.Service = s url := fmt.Sprintf("mongodb://%v:%v@%v:%v/%v", s.Username, s.Password, s.Ip, s.Port, "test") session, err := mgo.DialWithTimeout(url, vars.TimeOut) if err == nil { defer session.Close() err = session.Ping() if err == nil { result.Result = true } } return err, result }
測試結(jié)果:
go test -v plugins/mongodb_test.go === RUN TestScanMongodb --- PASS: TestScanMongodb (3.53s) mongodb_test.go:36: no reachable servers {{127.0.0.1 27017 mongodb test test} false} PASS ok command-line-arguments 3.558s
ELASTICSEARCH掃描模塊
ELASTICSEARCH掃描插件依賴第三方包gopkg.in/olivere/elastic.v3
,同樣也是直接go get
安裝。 完整代碼如下:
package plugins import ( "gopkg.in/olivere/elastic.v3" "x-crack/models" "fmt" ) func ScanElastic(s models.Service) (err error, result models.ScanResult) { result.Service = s client, err := elastic.NewClient(elastic.SetURL(fmt.Sprintf("http://%v:%v", s.Ip, s.Port)), elastic.SetMaxRetries(3), elastic.SetBasicAuth(s.Username, s.Password), ) if err == nil { _, _, err = client.Ping(fmt.Sprintf("http://%v:%v", s.Ip, s.Port)).Do() if err == nil { result.Result = true } } return err, result }
測試代碼:
package plugins_test import ( "x-crack/models" "x-crack/plugins" "testing" ) func TestScanElastic(t *testing.T) { s := models.Service{Ip: "127.0.0.1", Port: 9200, Protocol: "elastic", Username: "root", Password: "123456"} t.Log(plugins.ScanElastic(s)) }
測試結(jié)果如下:
go test -v plugins/elastic_test.go === RUN TestScanElastic --- PASS: TestScanElastic (5.02s) elastic_test.go:36: no Elasticsearch node available {{127.0.0.1 9200 elastic root 123456} false} PASS ok command-line-arguments 5.061s
掃描模塊插件化
前面我們寫好的掃描插件的函數(shù)原始是一致,我們可以將這組函數(shù)放到一個map中,在掃描的過程中自動化根據(jù)不同的協(xié)議調(diào)用不同的掃描插件。
以后新加的掃描插件,可以按這種方法直接注冊。
package plugins import ( "x-crack/models" ) type ScanFunc func(service models.Service) (err error, result models.ScanResult) var ( ScanFuncMap map[string]ScanFunc ) func init() { ScanFuncMap = make(map[string]ScanFunc) ScanFuncMap["FTP"] = ScanFtp ScanFuncMap["SSH"] = ScanSsh ScanFuncMap["SMB"] = ScanSmb ScanFuncMap["MSSQL"] = ScanMssql ScanFuncMap["MYSQL"] = ScanMysql ScanFuncMap["POSTGRESQL"] = ScanPostgres ScanFuncMap["REDIS"] = ScanRedis ScanFuncMap["ELASTICSEARCH"] = ScanElastic ScanFuncMap["MONGODB"] = ScanMongodb }
掃描任務調(diào)度
前面我們寫好了一些常見服務的弱口令掃描插件,也測試通過了。 接下來我們需要實現(xiàn)從命令行參數(shù)傳遞iplist、用戶名字典和密碼字典進去,并讀取相應的信息進行掃描調(diào)度的功能,細分一下,需要做以下幾件事:
- 讀取iplist列表
- 讀取用戶名字典
- 讀取密碼字典
- 生成掃描任務
- 掃描任務調(diào)度
- 掃描任務執(zhí)行
- 掃描結(jié)果保存
- 命令行調(diào)用外殼
讀取ip\用戶名和密碼字典
該模塊主要用了標準庫中的bufio
包,逐行讀取文件,進行過濾后直接生成相應的slice。其中iplist支持以下格式:
127.0.0.1:3306|mysql 8.8.8.8:22 9.9.9.9:6379 108.61.223.105:2222|ssh
對于標準的端口,程序可以自動判斷其協(xié)議,對于非標準端口的協(xié)議,需要在后面加一個字段標注一下協(xié)議。
為了防止咱們的程序被腳本小子們?yōu)E用,老夫就不提供端口掃描、協(xié)議識別等功能了,安全工程師們可以把自己公司的端口掃描器產(chǎn)出的結(jié)果丟到這個里面來掃。
package util import ( "x-crack/models" "x-crack/logger" "x-crack/vars" "os" "bufio" "strings" "strconv" ) func ReadIpList(fileName string) (ipList []models.IpAddr) { ipListFile, err := os.Open(fileName) if err != nil { logger.Log.Fatalf("Open ip List file err, %v", err) } defer ipListFile.Close() scanner := bufio.NewScanner(ipListFile) scanner.Split(bufio.ScanLines) for scanner.Scan() { ipPort := strings.TrimSpace(scanner.Text()) t := strings.Split(ipPort, ":") ip := t[0] portProtocol := t[1] tmpPort := strings.Split(portProtocol, "|") // ip列表中指定了端口對應的服務 if len(tmpPort) == 2 { port, _ := strconv.Atoi(tmpPort[0]) protocol := strings.ToUpper(tmpPort[1]) if vars.SupportProtocols[protocol] { addr := models.IpAddr{Ip: ip, Port: port, Protocol: protocol} ipList = append(ipList, addr) } else { logger.Log.Infof("Not support %v, ignore: %v:%v", protocol, ip, port) } } else { // 通過端口查服務 port, err := strconv.Atoi(tmpPort[0]) if err == nil { protocol, ok := vars.PortNames[port] if ok && vars.SupportProtocols[protocol] { addr := models.IpAddr{Ip: ip, Port: port, Protocol: protocol} ipList = append(ipList, addr) } } } } return ipList } func ReadUserDict(userDict string) (users []string, err error) { file, err := os.Open(userDict) if err != nil { logger.Log.Fatalf("Open user dict file err, %v", err) } defer file.Close() scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanLines) for scanner.Scan() { user := strings.TrimSpace(scanner.Text()) if user != "" { users = append(users, user) } } return users, err } func ReadPasswordDict(passDict string) (password []string, err error) { file, err := os.Open(passDict) if err != nil { logger.Log.Fatalf("Open password dict file err, %v", err) } defer file.Close() scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanLines) for scanner.Scan() { passwd := strings.TrimSpace(scanner.Text()) if passwd != "" { password = append(password, passwd) } } password = append(password, "") return password, err }
IP列表、用戶名字典與密碼字典讀取的測試代碼:
package util_test import ( "x-crack/util" "testing" ) func TestReadIpList(t *testing.T) { ipList := "/tmp/iplist.txt" t.Log(util.ReadIpList(ipList)) } func TestReadUserDict(t *testing.T) { userDict := "/tmp/user.dic" t.Log(util.ReadUserDict(userDict)) } func TestReadPasswordDict(t *testing.T) { passDict := "/tmp/pass.dic" t.Log(util.ReadPasswordDict(passDict)) }
這個模塊的測試結(jié)果如下:
go test -v util/file_test.go === RUN TestReadIpList --- PASS: TestReadIpList (0.00s) file_test.go:35: [{127.0.0.1 3306 MYSQL} {8.8.8.8 22 SSH} {9.9.9.9 6379 REDIS} {108.61.223.105 2222 SSH}] === RUN TestReadUserDict --- PASS: TestReadUserDict (0.00s) file_test.go:40: [root admin test guest info adm mysql user administrator ftp sa]=== RUN TestReadPasswordDict --- PASS: TestReadPasswordDict (0.00s) file_test.go:45: [1314520520 135246 135246789 135792468 1357924680 147258369 1472583690 1qaz2wsx 5201314 54321 55555 654321 789456123 88888 888888 88888888 987654321 9876543210 ^%$#@~! a123123 a123456 a12345678 a123456789 aa123456 aa123456789 aaa123456 aaaaa aaaaaa aaaaaaaa abc123 abc123456 abc123456789 abcd123 abcd1234 abcd123456 admin admin888 ] PASS ok command-line-arguments 0.022s
其中iplist在加載的過程中不是無腦全部讀進去的,在正式掃描前會先過濾一次,把不通的ip和端口對剔除掉,以免影響掃描效率,代碼如下:
package util import ( "gopkg.in/cheggaaa/pb.v2" "x-crack/models" "x-crack/logger" "x-crack/vars" "net" "sync" "fmt" ) var ( AliveAddr []models.IpAddr mutex sync.Mutex ) func init() { AliveAddr = make([]models.IpAddr, 0) } func CheckAlive(ipList []models.IpAddr) ([]models.IpAddr) { logger.Log.Infoln("checking ip active") var wg sync.WaitGroup wg.Add(len(ipList)) for _, addr := range ipList { go func(addr models.IpAddr) { defer wg.Done() SaveAddr(check(addr)) }(addr) } wg.Wait() vars.ProcessBarActive.Finish() return AliveAddr } func check(ipAddr models.IpAddr) (bool, models.IpAddr) { alive := false _, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", ipAddr.Ip, ipAddr.Port), vars.TimeOut) if err == nil { alive = true } vars.ProcessBarActive.Increment() return alive, ipAddr } func SaveAddr(alive bool, ipAddr models.IpAddr) { if alive { mutex.Lock() AliveAddr = append(AliveAddr, ipAddr) mutex.Unlock() } }
通過標準端口查詢對應服務的功能在vars包中定義了,為了避免多個包之間的循環(huán)導入,我們把所有的全局變量都集中到了一個獨立的vars包中。
PortNames
map為標準端口對應的服務,在加了新的掃描插件后,也需要更新這個map的內(nèi)容。
package vars import ( "github.com/patrickmn/go-cache" "gopkg.in/cheggaaa/pb.v2" "sync" "time" "strings" ) var ( IpList = "iplist.txt" ResultFile = "x_crack.txt" UserDict = "user.dic" PassDict = "pass.dic" TimeOut = 3 * time.Second ScanNum = 5000 DebugMode bool StartTime time.Time ProgressBar *pb.ProgressBar ProcessBarActive *pb.ProgressBar ) var ( CacheService *cache.Cache Mutex sync.Mutex PortNames = map[int]string{ 21: "FTP", 22: "SSH", 445: "SMB", 1433: "MSSQL", 3306: "MYSQL", 5432: "POSTGRESQL", 6379: "REDIS", 9200: "ELASTICSEARCH", 27017: "MONGODB", } // 標記特定服務的特定用戶是否破解成功,成功的話不再嘗試破解該用戶 SuccessHash map[string]bool SupportProtocols map[string]bool ) func init() { SuccessHash = make(map[string]bool) CacheService = cache.New(cache.NoExpiration, cache.DefaultExpiration) SupportProtocols = make(map[string]bool) for _, proto := range PortNames { SupportProtocols[strings.ToUpper(proto)] = true } }
?
- TCA8424低壓8x16鍵盤掃描器數(shù)據(jù)表
- Android Things I2C地址掃描器
- I2C掃描器開源硬件
- DSP電路板測試中的邊界掃描技術研究綜述 9次下載
- OTP動態(tài)口令的詳細資料說明
- OS32C激光掃描器特點及應用 5次下載
- 基于OS32C激光掃描器軟件配置及配線 18次下載
- HR3220的無線掃描器用戶手冊 12次下載
- NLS-HR15XX-30有線式掃描槍用戶手冊 26次下載
- 基于NLS-HR15XX-3E手持式條碼掃描器使用方法 19次下載
- AD9_Crack軟件下載 0次下載
- ADS2013.06 CRACK 1859次下載
- LS3408ER堅固耐用的掃描器
- netTAP網(wǎng)關在SICK條碼掃描器通訊上的應用
- 新的口令認證密鑰協(xié)商協(xié)議
- 固定式工業(yè)條碼掃描器在mes系統(tǒng)中的各個環(huán)節(jié)應用 198次閱讀
- 介紹一款智能Web弱口令爆破工具 1587次閱讀
- 一款網(wǎng)絡攝像頭漏洞掃描工具 3690次閱讀
- 基于C++的網(wǎng)絡掃描器設計 638次閱讀
- NanoBeacon? BLE掃描器教程(第四部分) 479次閱讀
- NanoBeacon? BLE掃描器教程(第二部分) 662次閱讀
- NanoBeacon? BLE掃描器教程(第一部分) 725次閱讀
- TPS61376升壓轉(zhuǎn)換器助力更高集成度條碼掃描器方案 682次閱讀
- 一款支持弱口令爆破的內(nèi)網(wǎng)資產(chǎn)探測漏洞掃描工具SweetBabyScan 4419次閱讀
- 常見服務弱口令爆破工具:crack 2165次閱讀
- 基于mPSD3254BV單片機和MAX604芯片實現(xiàn)無線掃描器的設計 2129次閱讀
- 條碼掃描器四種技術工作原理解析 1.8w次閱讀
- 弱密碼是什么?有什么用?應用在哪? 8887次閱讀
- 一種基于嵌入式系統(tǒng)的語音口令識別系統(tǒng)的設計 1000次閱讀
- 基于PIC16C65單片機的掃描隧道顯微鏡的電子學系統(tǒng) 1779次閱讀
下載排行
本周
- 1山景DSP芯片AP8248A2數(shù)據(jù)手冊
- 1.06 MB | 532次下載 | 免費
- 2RK3399完整板原理圖(支持平板,盒子VR)
- 3.28 MB | 339次下載 | 免費
- 3TC358743XBG評估板參考手冊
- 1.36 MB | 330次下載 | 免費
- 4DFM軟件使用教程
- 0.84 MB | 295次下載 | 免費
- 5元宇宙深度解析—未來的未來-風口還是泡沫
- 6.40 MB | 227次下載 | 免費
- 6迪文DGUS開發(fā)指南
- 31.67 MB | 194次下載 | 免費
- 7元宇宙底層硬件系列報告
- 13.42 MB | 182次下載 | 免費
- 8FP5207XR-G1中文應用手冊
- 1.09 MB | 178次下載 | 免費
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 2555集成電路應用800例(新編版)
- 0.00 MB | 33566次下載 | 免費
- 3接口電路圖大全
- 未知 | 30323次下載 | 免費
- 4開關電源設計實例指南
- 未知 | 21549次下載 | 免費
- 5電氣工程師手冊免費下載(新編第二版pdf電子書)
- 0.00 MB | 15349次下載 | 免費
- 6數(shù)字電路基礎pdf(下載)
- 未知 | 13750次下載 | 免費
- 7電子制作實例集錦 下載
- 未知 | 8113次下載 | 免費
- 8《LED驅(qū)動電路設計》 溫德爾著
- 0.00 MB | 6656次下載 | 免費
總榜
- 1matlab軟件下載入口
- 未知 | 935054次下載 | 免費
- 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
- 78.1 MB | 537798次下載 | 免費
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420027次下載 | 免費
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費
- 6電路仿真軟件multisim 10.0免費下載
- 340992 | 191187次下載 | 免費
- 7十天學會AVR單片機與C語言視頻教程 下載
- 158M | 183279次下載 | 免費
- 8proe5.0野火版下載(中文版免費下載)
- 未知 | 138040次下載 | 免費
評論
查看更多