写在前面的话

理解恶意软件的真实代码对恶意软件分析人员来说是非常有优势的,因为这样才能够真正了解恶意软件所要做的事情。但不幸的是,我们并不总是能够得到“真实”的代码,有时恶意软件分析人员可能需要类似反汇编工具或调试器之类的东西才能“推测”出恶意软件的真实行为。不过,当恶意软件使用的是“解释型语言”开发的话,例如Java、JavaScript、VBS或.NET等等,我们就有很多种方法来查看它们真正的原始代码了。

不幸的是,攻击者同样知道这些分析技术,而且为了规避安全分析,他们还会采用很多混淆技术来干扰研究人员的分析过程。攻击者可以利用反分析技术来判断恶意代码是否在虚拟机环境中运行,或者让自己的代码只在特定环境中运行以避免调试以及逆向分析环境(包括反混淆),而今天我们要讨论了就是一种基于JavaScript的新型反逆向分析技术。

JavaScript正邪对垒

对于攻击者来说,JavaScript已经变成一种非常重要的攻击向量了。它一般用于攻击的Payload感染阶段,它的使用非常多样化,编码形式也不像其他语言那样受到各种限制,而且几乎所有的恶意JavaScript代码都会进行混淆处理。下图显示的是一个经过了混淆处理的JavaScriptPayload样本:

对于恶意软件分析人员来说,第一步就是要对这种代码进行反混淆处理。从最简单的复制粘贴,到更强大一点的“脚本替换”(涉及函数和变量的重命名),研究人员需要想方设法让代码更加清晰。但是在JavaScript中,我们可以根据函数名的调用情况来了解函数的运行机制。比如说函数arguments.callee.caller(),在这个函数的帮助下,我们可以创建一个堆栈跟踪,并将执行过的函数按照顺序存储在列表中。获取到函数名之后,我们就可以将它们当作密钥来对处理过的JavaScript代码进行动态“解密”了。这项技术可以让我们得到隐式的控制流完整性,因为如果一个函数被重命名或者函数运行顺序发生了变化,那么“结果哈希”肯定是不同的。如果哈希不同,生成的密钥也就不同,这样就可以进行解密并运行经过特殊加密的代码了。

为了让大家更清楚地了解我在说什么,请大家看看下面这段没有经过混淆处理的样本代码【查看原始代码】:

var _= require("underscore");
 
function keyCharAt(key, i) {
    return key.charCodeAt( Math.floor(i %key.length) );
  }
 
  function xor_encrypt(key, data) {
    return _.map(data, function(c, i) {
      return c.charCodeAt(0) ^ keyCharAt(key,i);
    });
  }
 
  function xor_decrypt(key, data) {
    return _.map(data, function(c, i) {
      return String.fromCharCode( c ^keyCharAt(key, i) );
    }).join("");
  }
 
 
function cow001(){
eval(xor_decrypt(arguments.callee.name,[0,0,25,67,95,93,6,65,27,95,87,25,68,34,22,92,89,82,10,0,2,67,16,114,12,1,3,85,94,69,67,59,5,89,87,86,6,29,4,16,120,84,17,10,87,17,23,24]));
}
 
function pyth001(){
eval(xor_decrypt(arguments.callee.name,[19,22,3,88,0,1,25,89,66]));
}
 
function pippo(){
pyth001();
}
 
pippo();

代码运行过程中会对“特定内容”进行计算(eval()函数),在代码的第21和25行,函数cow001()和pyth001()会计算XOR后的解密内容。xor_decrypt函数可以接收两个参数:decoding_key和需要解密的Payload。接下来,代码会使用arguments.callee.name()函数来将内部阶段的每一个函数名当作解密密钥来使用,如果函数名是“原始函数名”(攻击者用来解密Payload的函数名),那么加密后的代码就会正常运行,不会报错。换句话说,如果函数名经过了重命名,那么eval()函数将得到错误的结果,并导致攻击者转换代码运行路径(使用简单的try catch语句)。

在使用JavaScript代码实施攻击之前,攻击者需要开发恶意JavaScript代码并对其进行混淆处理,这样才能准备好所谓的“攻击路径”。代码混淆的过程中,攻击者需要使用额外的脚本(比如说下面这段代码-【查看原始代码】)并根据混淆后的函数名来加密Payload,然后用新加密的Payload替换之前的代码(加密后的Payload就是加密函数名所使用的密钥)。

"use strict";  
 
var _= require("underscore");
 
function keyCharAt(key, i) {
    return key.charCodeAt( Math.floor(i %key.length) );
  }
 
  function xor_encrypt(key, data) {
    return _.map(data, function(c, i) {
      return c.charCodeAt(0) ^ keyCharAt(key,i);
    });
  }
 
  function xor_decrypt(key, data) {
    return _.map(data, function(c, i) {
      return String.fromCharCode( c ^ keyCharAt(key,i) );
    }).join("");
  }
 
var final_payload = "console.log('Malicious Content Triggers Here !')";
var k_final = "cow001";
var encrypted_final = xor_encrypt(k_final,final_payload);
var decrypted_final = xor_decrypt(k_final, encrypted_final);
console.log(encrypted_final.toString());
console.log(decrypted_final);
 
var _1_payload = "cow001();";
var k_1 = "pyth001";
var encrypted_1 = xor_encrypt(k_1,_1_payload);
var decrypted_1 = xor_decrypt(k_1, encrypted_1);
console.log(encrypted_1.toString());
console.log(decrypted_1);

总结

现在,攻击者就可以使用自己设计的控制流来编写JavaScript代码了。如果攻击者不停地迭代实现这种技术,他基本上就可以完全规避逆向工程分析技术了。

希望本文的内容可以给大家的安全研究带来灵感!

控制流程完整性:给大家介绍一种“另类”的Javascript反分析技术的更多相关文章

  1. Linux下几种另类创建文件之方法

    以前我们用编辑器例如vi来新建文件,下面介绍几种另类生成文件的方法,多用在备份和测试上. 创建文件的方法: 1.echo 命令    #echo "set bell"  >& ...

  2. MySQL聚合函数、控制流程函数(含navicat软件的介绍)

    MySQL聚合函数.控制流程函数(含navicat软件的介绍) 一.navicat的引入:(第三方可视化的客户端,方便MySQL数据库的管理和维护) NavicatTM是一套快速.可靠并价格相宜的数据 ...

  3. MySQL数据库学习笔记(四)----MySQL聚合函数、控制流程函数(含navicat软件的介绍)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  4. 【JAVA零基础入门系列】Day8 Java的控制流程

    什么是控制流程?简单来说就是控制程序运行逻辑的,因为程序一般而言不会直接一步运行到底,而是需要加上一些判断,一些循环等等.举个栗子,就好比你准备出门买个苹果,把这个过程当成程序的话,可能需要先判断一下 ...

  5. C#深入浅出之操作符和控制流程

    操作符 操作符简单举例就是生活中的+-*/等等运算符号,下面会详细讨论运算符内容. 一元正负操作符 有时候需要改变数值的正负号.一元操作符(-)可以使得数字的正负号改变. 例如:int a = -11 ...

  6. JavaScript---js语法,数据类型及方法, 数组及方法,JSON对象及方法,日期Date及方法,正则及方法,数据类型转换,运算符, 控制流程(三元运算),函数(匿名函数,自调用函数)

    day46 一丶javascript介绍 JavaScript的基础分为三个       1.ECMAScript:JavaScript的语法标准.包括变量,表达式,运算符,函数,if语句,for语句 ...

  7. 《Android游戏开发详解》一1.7 控制流程第1部分——if和else语句

    本节书摘来异步社区<Android游戏开发详解>一书中的第1章,第1.7节,译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社区"异步社区"公众号查看. 1.7 ...

  8. C# 8.0和.NET Core 3.0高级编程 分享笔记三:控制流程和转换类型

    控制流程和转换类型 本章的内容主要包括编写代码.对变量执行简单的操作.做出决策.重复执行语句块.将变量或表达式值从一种类型转换为另一种类型.处理异常以及在数值变量中检查溢出. 本章涵盖以下主题: 操作 ...

  9. 干货:结合Scikit-learn介绍几种常用的特征选择方法

    原文  http://dataunion.org/14072.html 主题 特征选择 scikit-learn 作者: Edwin Jarvis 特征选择(排序)对于数据科学家.机器学习从业者来说非 ...

随机推荐

  1. 主流 NoSQL 数据库对比

    HBase HBase 是 Apache Hadoop 中的一个子项目,属于 bigtable 的开源版本,所实现的语言为Java(故依赖 Java SDK).HBase 依托于 Hadoop 的 H ...

  2. Java 命令行编译项目

    如果是用Exlipse, 第三方的包可以放在eclipse文件夹的jre包的lib文件夹中! (初学者的一些总结-高手们勿喷哈-) 原因: 以前一直用Eclispe编程环境运行Java.非常舒服,就像 ...

  3. [2018-9-4T2]探索黑暗dark

    题目大意:有一棵树,第$i$个点的点权为$s_i(s_1>0)$.初始有每个点都是亮的.$m$次修改,每次改变一个点的亮暗,回答包含$1$的全亮的连通块中点权和最大的连通块的和的值. 题解:正解 ...

  4. BZOJ2435 [Noi2011]道路修建 【树形Dp 吧。。】

    题目 在 W 星球上有 n 个国家.为了各自国家的经济发展,他们决定在各个国家 之间建设双向道路使得国家之间连通.但是每个国家的国王都很吝啬,他们只愿 意修建恰好 n – 1条双向道路. 每条道路的修 ...

  5. code forces 979C

    C. Kuro and Walking Route time limit per test 2 seconds memory limit per test 256 megabytes input st ...

  6. ASP.NET Identity 使用 RoleManager 进行角色管理 (VS2013RC)

    注:本文系作者原创,但可随意转载. 最近做一个Web平台系统,系统包含3个角色,“管理员, 企业用户, 评审专家”, 分别有不同的功能.一直以来都是使用微软封装好的Microsoft.AspNet.I ...

  7. 从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式

    如何正确使用NIO来构架网络服务器一直是最近思考的一个问题,于是乎分析了一下Jetty.Tomcat和Mina有关NIO的源码,发现大伙都基于类似的方式,我感觉这应该算是NIO构架网络服务器的经典模式 ...

  8. LNMP下安装phpmyadmin的一个小错误解决办法

    环境:ubuntu16.04 + nginx1.10.0 + php7.04 + mysql5.6 安装phpmyadmin之后tail nginx 的错误日志,提示以下: 2016/06/30 15 ...

  9. Html5学习进阶三 Input 类型

    HTML5 新的 Input 类型 HTML5 拥有多个新的表单输入类型.这些新特性提供了更好的输入控制和验证. 本章全面介绍这些新的输入类型: email url number range Date ...

  10. [ CodeVS冲杯之路 ] P3116

    不充钱,你怎么AC? 题目:http://codevs.cn/problem/3116/ 基础的高精度加法,注意一下两个数长短不一和答案第一位的处理即可,当然也可以用压位的方法做 #include&l ...