Last updated on 5 months ago
go进阶 time包 1 2 3 4 5 6 7 8 time.Now() t2:=time.Date(2004 ,1 ,15 ,8 ,26 ,22 ,0 ,time.Local) fmt.Println(t2) h, m, s := time.Now().Clock() fmt.Println(h, m, s)
file操作 都用os包
权限 r w x
读 写 可执行
如果没有的话就是-
-文件 d目录 |连接符
-rwx r-x r-x
-代表文件 rwx代表可读可写可执行 两个r-x分别代表所属组和其它人的权限
八进制表现
r–>004
w–>002
x–>001
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 chomd +x 777 中的777的7就是4+2+1,可读可写可执行 ```go package main import ( "fmt" "os" ) func main() { err := os.Mkdir("./testss", 0777) if err != nil { fmt.Println(err) } fmt.Println("创建成功") file, err := os.Create("123.txt") if err != nil { fmt.Println(err) } fmt.Println(file) //&{0xc00011c780} //open是打开文件并建立连接的操作,open打开的文件的权限是只读 file2, err := os.Open("D:/桌面/hack/if_open.txt") if err != nil { fmt.Println(err) } fmt.Println(file2) //打开文件地址 &{0xc00011ca00} //关闭文件 err = file2.Close() if err != nil { fmt.Println(err) return } fmt.Println("关闭成功") //删除目录或文件 (不放入回收站,慎用) err = os.Remove("D:/桌面/hack/if_open.txt") if err != nil { fmt.Println(err) return } fmt.Println("删除成功") }
IO操作 input output
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 package mainimport ( "fmt" "io" "os" )func main () { fn := "D:/桌面/hack/test.txt" file, err := os.Open(fn) if err != nil { fmt.Println(err) } bs := make ([]byte , 10 ) n, err := file.Read(bs) fmt.Println("这是err" , err) fmt.Println(n) fmt.Println(bs) fmt.Println(string (bs)) i := -1 for { i, err = file.Read(bs) if i == 0 || err == io.EOF { fmt.Println("文件读取结束" ) break } fmt.Println("i现在是" , i, string (bs[:i])) } }
ioutil包 现在新版本golang里ioutil包已经被os和io包吞并了
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 package mainimport ( "fmt" "os" )func main () { filename := "D:/桌面/hack/test.txt" data, err := os.ReadFile(filename) fmt.Println(string (data)) fmt.Println(err) fmt.Printf("%T %T" , data, err) s := "这是测试还是覆盖" err = os.WriteFile(filename, []byte (s), os.ModePerm) if err != nil { fmt.Println(err) return } fmt.Println("成功写入" ) dirname := "D:/桌面/hack" dirinfo, err := os.ReadDir(dirname) if err != nil { fmt.Println(err) return } fmt.Printf("类型是%T" , dirinfo) for i := 0 ; i < len (dirinfo); i++ { fmt.Printf("第%d项是%s,是否是目录%t\n" , i, dirinfo[i].Name(), dirinfo[i].IsDir()) } }
并发并行
进程线程携程 进程是正在运行的程序
操作系统以进程为单位,进程以线程为单位,一个进程可能包含多个线程
比如打开word文档,word文档是正在运行的一个进程
在word里随便敲一行字,会自动触发开头首字母是否大写和整段话是否有拼写错误的检查,这是两个线程
携程是轻线程
goroutine 携程,封装main函数的是主goroutine
用go
标识要用的函数,函数不能有返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package mainimport ( "fmt" )func main () { go print_num() for j := 101 ; j < 200 ; j++ { fmt.Println(j) } }func print_num () { for i := 0 ; i < 100 ; i++ { fmt.Printf("这是第%d个子线程,i" ) } }
net 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 ### 扫描器 #### 端口 ```go package main import ( "fmt" "net" ) func main() { for i := 1; i <= 1024; i++ { go func(j int) { addr := fmt.Sprintf("127.0.0.1:%d", j) con, err := net.Dial("tcp", addr) if err != nil { return } con.Close() fmt.Println(j, "端口是打开的") }(i) } }
稍微进阶一点
就是用了goroutine之后,可能有些携程没加载完,但主进程已经加载完了,这个的作用就是每一次循环就记一次数,循环完成之后记的数就是总的携程数,在用wait()函数等待所有携程完成,在结束进程
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 package mainimport ( "fmt" "net" "sync" )func main () { var ab sync.WaitGroup for i := 0 ; i < 1025 ; i++ { ab.Add(1 ) go func (j int ) { defer ab.Done() addr := fmt.Sprintf("127.0.0.1:%d" , j) con, err := net.Dial("tcp" , addr) if err != nil { return } con.Close() fmt.Printf("%d is open\n" , j) }(i) } ab.Wait() }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package mainimport ( "fmt" "net" "sync" )func worker (ports chan int ,wg *sync.WaitGroup) { for p:=range ports{ fmt.Println(p) wg.Done() } }func main () { ports:=make (chan int ,100 ) var wg sync.WaitGroup for i:=0 ;i<cap (ports);i++{ wg.Add(1 ) ports<-i } wg.Wait() close (ports) }
等待组初步 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package mainimport ( "fmt" "sync" "time" )func pro (i int , wg *sync.WaitGroup) { fmt.Printf("进程%d开始\n" , i) time.Sleep(2 * time.Second) fmt.Printf("进程%d结束\n" , i) wg.Done() }func main () { cou := 3 var wg sync.WaitGroup for i := 0 ; i < cou; i++ { wg.Add(1 ) go pro(i, &wg) } wg.Wait() fmt.Println("main stop" ) }
工人池
一个理论上能用的扫描器 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 package mainimport ( "fmt" "net" "sort" )func main () { ports := make (chan int , 100 ) results := make (chan int ) var openports []int for i := 0 ; i < cap (ports); i++ { go worker(ports, results) } go func () { for i := 1 ; i <= 1024 ; i++ { ports <- i } }() for i := 0 ; i < 1024 ; i++ { port := <-results if port != 0 { openports = append (openports, port) } } close (ports) close (results) sort.Ints(openports) for _, port := range openports { fmt.Printf("%d is open\n" , port) } }func worker (ports, results chan int ) { for p := range ports { addr := fmt.Sprintf("127.0.0.1:%d" , p) conn, err := net.Dial("tcp" , addr) if err != nil { results <- 0 continue } conn.Close() results <- p } }
年轻人的第一款自制扫描器 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 package mainimport ( "fmt" "net" "sort" "sync" )func main () { fmt.Print("请输入要扫描的IP地址: " ) var ip string fmt.Scanln(&ip) fmt.Println("给你一点加载时间,你才知道是真的扫描而不是面向结果编程" ) var wg sync.WaitGroup ops := []int {} ports := make (chan int , 5000 ) for i := 1 ; i <= 5000 ; i++ { wg.Add(1 ) go func (j int ) { defer wg.Done() addr := fmt.Sprintf("%s:%d" , ip, j) conn, err := net.Dial("tcp" , addr) if err != nil { return } ports <- j conn.Close() }(i) } fmt.Println("正在检测" ) wg.Wait() close (ports) for v := range ports { ops = append (ops, v) } sort.Ints(ops) for _, v := range ops { fmt.Printf("%d port is open\n" , v) } fmt.Println("按下回车键以退出程序..." ) fmt.Scanln() }
worker pool的实现 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 package mainimport ( "fmt" "net" "sort" )func worker (ports_chan, results_chan chan int ) { for port := range ports_chan { addr := fmt.Sprintf(":%d" , port) con, err := net.Dial("tcp" , addr) if err != nil { results_chan <- 0 continue } results_chan <- port con.Close() } }func main () { ports_chan := make (chan int , 5000 ) results_chan := make (chan int ) open_ports := make ([]int , 0 , 30 ) for i := 1 ; i <= cap (ports_chan); i++ { go worker(ports_chan, results_chan) } go func () { for i := 1 ; i <= 5000 ; i++ { ports_chan <- i } }() for i := 1 ; i <= 5000 ; i++ { port := <-results_chan if port != 0 { open_ports = append (open_ports, port) } } close (ports_chan) close (results_chan) sort.Ints(open_ports) for _, p := range open_ports { fmt.Printf("%d port is open\n" , p) } }
tcp代理 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 package mainimport ( "io" "log" "net" )func main () { listener, err := net.Listen("tcp" , ":20080" ) if err != nil { log.Fatalln("绑不了端口" ) } log.Println("监听端口20080" ) for { c, err := listener.Accept() log.Println("接收连接" ) if err != nil { log.Fatalln("连不上" ) } go echo(c) } }func echo (c net.Conn) { defer c.Close() b := make ([]byte , 512 ) for { size, err := c.Read(b[0 :]) if err == io.EOF { log.Println("未知错误" ) break } log.Printf("接收到了%d byte的数据,数据是:%s\n" , size, string (b)) log.Println("写数据" ) if _, err := c.Write(b[0 :size]); err != nil { log.Fatalln("写不了" ) } } }
缓冲
端口转发器 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 package mainimport ( "io" "log" "net" )func main () { listener, err := net.Listen("tcp" , ":80" ) if err != nil { log.Fatalln("unable to bind port" ) } for { conn, err := listener.Accept() if err != nil { log.Fatal("unable to accept connection" ) } go handle(conn) } }func handle (src net.Conn) { dst, err := net.Dial("tcp" , "joescatcam.website:80" ) if err != nil { log.Fatalln("unable to connect our unreachable host" ) } defer dst.Close() go func () { if _, err := io.Copy(src, dst); err != nil { log.Fatalln(err) } }() if _, err := io.Copy(src, dst); err != nil { log.Fatalln(err) } }
反向shell(不是反弹shell)
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 package mainimport ( "io" "log" "net" "os/exec" )func handle (c net.Conn) { cmd := exec.Command("cmd.exe" ) rp, wp := io.Pipe() cmd.Stdin = c cmd.Stdout = wp go io.Copy(c, rp) cmd.Run() c.Close() }func main () { listener, err := net.Listen("tcp" , ":1234" ) if err != nil { log.Fatalln(err) } conn, err := listener.Accept() if err != nil { log.Fatalln(err) } go handle(conn) }
http请求 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package mainimport ( "fmt" "io" "net/http" "log" )func main () { resp,err:=http.Get("https://blog.yblue.top" ) if err!=nil { log.Fatalln(err) } defer resp.Body.Close() body,err:=io.ReadAll(resp.Body) if err!=nil { log.Fatalln(err) } fmt.Println(string (body)) fmt.Println(resp.Status) if resp.StatusCode ==200 { fmt.Println("OK" ) } }
如果将请求放到内容里而不是直接在url路径里
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 package mainimport ( "fmt" "log" "net/http" "io" "net/url" )func main () { url_object:=url.Value{} Url,err:=url.Parse("https://baidu.com" ) if err!=nil { log.Fatalln(err) } url_object.Set("name" ,"xiaoming" ) url_object.Set("age" ,"12" ) url_object.Set("name" ,"taosu" ) url_object.Add("age" ,"13" ) Url.RawQuery=url_object.Encode() urlPath:=Url.String() fmt.Println("请求的路径是:" ,urlPath) resp,err:=http.Get(urlPath) defer resp.Body.Close() if err!=nil { log.Fatalln(err) } body,err:=io.ReadAll(resp.Body) if err!=nil { log.Fatalln(err) } fmt.Println(string (body)) }
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 url.Values{} 是 Go 语言中 net/url 包提供的一个类型,用于表示 URL 查询参数的集合。 url.Values 是一个类似于字典的结构,它可以存储一系列的键值对,其中键和值都是字符串类型。它提供了一组方法来设置、获取和操作查询参数。 以下是一些常用的 url.Values 方法: Set(key, value):设置指定键的查询参数值。如果该键已存在,则会用新的值覆盖旧的值。如果该键不存在,则会将键值对添加到查询参数中。 Add(key, value):向查询参数中添加一个新的键值对,不管该键是否已存在。如果该键已存在,则会将新的值追加到已有值的末尾,用 & 符号分隔。 Get(key):获取指定键的查询参数值。如果该键不存在,则返回空字符串。 Del(key):删除指定键的查询参数。 Encode():将 url.Values 对象编码为查询参数字符串。package mainimport ( "fmt" "io" "log" "net/http" "net/url" )func main () { url_object := url.Values{} Url, err := url.Parse("https://blog.yblue.top" ) if err != nil { log.Fatalln(err) } url_object.Set("username" , "admin" ) Url.RawQuery = url_object.Encode() UrlPath := Url.String() resp, err := http.Get(UrlPath) if err != nil { log.Fatalln(err) } defer resp.Body.Close() Body, _ := io.ReadAll(resp.Body) fmt.Println(Body) fmt.Println("utl的路径是:" , UrlPath, "\n" , "查询语句是:" , Url.RawQuery) }
http请求且写入请求头内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport ( "fmt" "io" "net/http" )func main () { client := http.Client{} req, _ := http.NewRequest("GET" , "http://blog.yblue.top" , nil ) req.Header.Add("name" , "Paul_Chan" ) req.Header.Add("age" , "26" ) resp, _ := client.Do(req) body, _ := io.ReadAll(resp.Body) fmt.Println(string (body)) }
打印http请求头 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package mainimport ( "fmt" "net/http" "net/http/httputil" )func main () { req, _ := http.NewRequest("GET" , "http://blog.yblue.top" , nil ) req.Header.Add("name" , "Paul_Chan" ) req.Header.Add("age" , "26" ) req.Header.Add("x-forwarded-for" , "127.0.0.1" ) requestDump, _ := httputil.DumpRequestOut(req, true ) fmt.Println(string (requestDump)) client := http.DefaultClient _,_ = client.Do(req) }