資料介紹
軟件簡介
我們在做企業安全時,弱口令檢測是系統/網絡安全的最基礎的部分之一,根據經驗,經常會出現弱口令的服務如下:
- FTP
- SSH
- SMB
- MYSQL
- MSSQL
- POSTGRESQL
- REDIS
- MONGODB
- ELASTICSEARCH
那咱們就一起用GO來寫一款常見服務的弱口令掃描器,且支持以插件的形式增加新的服務掃描模塊。我們的教程暫定為只掃以上服務。
給掃描器啟一個屌炸天的名字x-crack,在$GOPATH/src/中建立一個x-crack項目后開始擼碼,不要給我說什么底層原理、框架內核,老夫敲代碼就是一把梭。
?
開工
數據結構定義
- 掃描模塊的輸入內容為為IP、端口及協議的列表,我們需要定義一個IpAddr的數據結構;
- 每個服務的每次掃描需要傳入的參數為IP、端口、協議、用戶名和密碼,需要定義一個Service結構來包括這些內容;
- 每條Service的記錄在掃描模塊進行嘗試后,會得出掃描結果成功與否,我們再定義一個ScanResult數據結構。
按照開發規范,數據結構的定義統一放到models目錄中,全部的數據結構定義如下:
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語言有現成的FTP模塊,我們找一個star數最多的直接go get安裝一下即可使用了:
go get -u github.com/jlaffaye/ftp
我們把所有的掃描模塊放到plugins目錄中,FTP協議的掃描插件如下所示:
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
}
每個連接需要設置超時時間,防止因網絡問題導致的阻塞,我們打算通過程序的命令行來控制超時時間,所以定義了一個全局變量TimeOut。 放在vars模塊中的原因是防止放在這個模塊中后會和其他模塊互相調用導致的循環import
寫代碼雖然可以一把梭,但是不能等著洋洋灑灑地把幾萬行都寫完再運行,比如我們的目標是造一輛豪車,不能等著所有零件設計好,都裝上去再發動車測試,正確的開發流程是把寫邊測,不要等輪子造出來,而是在螺絲、齒輪階段就測試。
以下為FTP掃描插件這個齒輪的測試代碼及結果。
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)) }
測試結果滿足預期,說明我們這個零件不是次品,可以繼續再造其他零件了。
$ 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包,直接調用即可,完整代碼如下:
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))
}
測試結果如下:
$ 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))
}
測試結果:
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來實現,我們這里圖方便用xorm一把梭了。 對于xorm來說,這3個掃描插件的實現方法大同小異,為了節約篇幅,咱們只看mysql掃描插件的實現,其他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
}
眼尖的同學也許發現了,上面?github.com/netxfly/mysql?這個mysql包是放在筆者的github下的,這是為什么呢?
因為直接用mysql這個包的話,在掃描的過程中會遇到[mysql] packets.go:33: unexpected EOF" error的異常輸出,影響了我們程序在掃描過程中輸出UI的美觀性,這對于帥氣的我是無法接受的,通過設置參數的方法無法解決,最后只好直接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))
}
測試結果:
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))
}
測試結果:
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
}
測試結果:
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))
}
測試結果如下:
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
掃描模塊插件化
前面我們寫好的掃描插件的函數原始是一致,我們可以將這組函數放到一個map中,在掃描的過程中自動化根據不同的協議調用不同的掃描插件。
以后新加的掃描插件,可以按這種方法直接注冊。
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
}
掃描任務調度
前面我們寫好了一些常見服務的弱口令掃描插件,也測試通過了。 接下來我們需要實現從命令行參數傳遞iplist、用戶名字典和密碼字典進去,并讀取相應的信息進行掃描調度的功能,細分一下,需要做以下幾件事:
- 讀取iplist列表
- 讀取用戶名字典
- 讀取密碼字典
- 生成掃描任務
- 掃描任務調度
- 掃描任務執行
- 掃描結果保存
- 命令行調用外殼
讀取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
對于標準的端口,程序可以自動判斷其協議,對于非標準端口的協議,需要在后面加一個字段標注一下協議。
為了防止咱們的程序被腳本小子們濫用,老夫就不提供端口掃描、協議識別等功能了,安全工程師們可以把自己公司的端口掃描器產出的結果丟到這個里面來掃。
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))
}
這個模塊的測試結果如下:
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包中定義了,為了避免多個包之間的循環導入,我們把所有的全局變量都集中到了一個獨立的vars包中。
PortNamesmap為標準端口對應的服務,在加了新的掃描插件后,也需要更新這個map的內容。
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鍵盤掃描器數據表
- Android Things I2C地址掃描器
- I2C掃描器開源硬件
- DSP電路板測試中的邊界掃描技術研究綜述 10次下載
- OTP動態口令的詳細資料說明
- OS32C激光掃描器特點及應用 5次下載
- 基于OS32C激光掃描器軟件配置及配線 18次下載
- HR3220的無線掃描器用戶手冊 14次下載
- NLS-HR15XX-30有線式掃描槍用戶手冊 27次下載
- 基于NLS-HR15XX-3E手持式條碼掃描器使用方法 19次下載
- AD9_Crack軟件下載 0次下載
- ADS2013.06 CRACK 1.9k次下載
- LS3408ER堅固耐用的掃描器
- netTAP網關在SICK條碼掃描器通訊上的應用
- 新的口令認證密鑰協商協議
- 如何更好選擇二維碼識別掃描器廠家? 699次閱讀
- 固定式條碼掃描器能在條碼移動情況下掃描嗎? 457次閱讀
- 選購固定式二維影像掃描器需要注意什么?考慮哪些方面? 687次閱讀
- 工業二維碼條碼掃描器流水線條碼掃描 949次閱讀
- 固定式工業級二維碼掃描器選型方法 972次閱讀
- 工業固定式掃描器怎樣用?固定式工業條碼掃描器解決方案 1.1k次閱讀
- 固定式工業條碼掃描器在mes系統中的各個環節應用 1.2k次閱讀
- 介紹一款智能Web弱口令爆破工具 3k次閱讀
- 基于C++的網絡掃描器設計 1.4k次閱讀
- NanoBeacon? BLE掃描器教程(第四部分) 1.1k次閱讀
- NanoBeacon? BLE掃描器教程(第一部分) 1.6k次閱讀
- TPS61376升壓轉換器助力更高集成度條碼掃描器方案 1.5k次閱讀
- 一款支持弱口令爆破的內網資產探測漏洞掃描工具SweetBabyScan 6.9k次閱讀
- 常見服務弱口令爆破工具:crack 2.9k次閱讀
- 條碼掃描器四種技術工作原理解析 2.1w次閱讀
下載排行
本周
- 1山景DSP芯片AP8248A2數據手冊
- 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開發指南
- 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數字電路基礎pdf(下載)
- 未知 | 13750次下載 | 免費
- 7電子制作實例集錦 下載
- 未知 | 8113次下載 | 免費
- 8《LED驅動電路設計》 溫德爾著
- 0.00 MB | 6656次下載 | 免費
總榜
- 1matlab軟件下載入口
- 未知 | 935054次下載 | 免費
- 2protel99se軟件下載(可英文版轉中文版)
- 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次下載 | 免費
電子發燒友App





創作
發文章
發帖
提問
發資料
發視頻
上傳資料賺積分
評論