【安全健行】(3):Shellcode基础

2015/5/15 16:04:49

前面我们简单介绍了Hacker的编程基础,然后讲解了Linux下缓冲区漏洞的基本原理,从中我们了解到一个典型的缓冲区漏洞攻击总是由下面三个部分组成:

具体的实现可能会有变化,但是“万变不离其宗”,基本原理还是不变的。我们注意到攻击功能的实现由shellcode来体现,可以说shellcode也是一个缓冲区攻击的核心部分。今天我们来了解下shellcode的知识,首先是一个入门,来介绍下shellcode的使用策略。本节要点如下:

  • 什么是shellcode?
  • 用户空间的shellcode
  1. 基本shellcode
  2. 端口绑定shellcode
  3. 反向shellcode
  4. 查找套接字shellcode
  5. shellcode的变化

内核空间的shellcode

一、什么是shellcode?

shellcode就是上图缓冲区溢出攻击中的实际攻击代码,由于最早的时候Hacker攻击的结果是控制EIP执行攻击指令返回一个目标系统的交互shell,因此这段攻击代码就被称作shellcode。随着时代的演变,shellcode的功能也逐渐丰富,最早的时候shellcode用于从一个没有攻击者账户的计算机上返回一个登录shell,或者已有一个账户,则用来提升shell的操作权限,最理想的情况就是获得root特权或者管理员权限;现在还有一些shellcode加入了内存进程操作、网络通信等功能,但是其名称却一直沿用下来。shellcode的名称也提醒着人们攻击最初的形式。

二、用户空间的shellcode

这个部分我们会分别介绍下实际使用中shellcode的使用策略,即shellcode一般实现什么样的功能。我们会着重介绍下shellcode的基本模式、端口绑定模式以及套架子查找模式,然后对剩下的使用方式简要地说明。

1. 基本shellcode

shellcode用于执行一段攻击者希望的代码,一般的功能如建立账户、文件操作、建立新进程等,而无论是哪个操作,都需要系统底层内核的配合。

这里我们来简单介绍下操作系统的结构。出于安全性和稳定性的考虑,一般操作系统会将内存空间分成用户态和内核态,也可以称作用户空间和内核空间。用户态主要负责数据的数据存储、运行程序的跟功能,而这些操作真的落实到计算机的实际资源(如内存、硬盘)则需要内核态的代码来代理执行。这样操作系统向用户提供了一个封装的操作核心函数接口,用户只需要使用就可以,即使用户程序崩溃,也不会影响系统的整体稳定。

不同的系统有不同的机制进入内核态。类Unix中一般使用软中断来实现,即发送给CPU一个0x80命令,然后系统会陷入内核空间。而Windows中则必须使用标准的API来实现。

在了解了用户态与内核态的区别后,我们来看看基本的shellcode模式,一般来说,shellcode会在目标机器上建立一个新的shell进程,然后同攻击者进行通信,接受攻击者的指令,返回结果。这里有两个关键的问题:

  1. 如何建立新的shell进程?这个问题是比较容易理解的,类Unix下使用execve命令,Windows下可以使用CreateProcess API;
  2. 如何实现shell与攻击者的通信?这个没有那么好理解了,首先我们要知道的是,无论什么操作系统,每建立一个进程就会为其绑定三个文件描述符作为输入输出的指定资源,即stdin(标准输入)、stdout(标准输出)、stderr(标准错误提示) 三个文件描述符,一般默认都是屏幕或终端。这里我们需要在新建shell进程前设置好这三个文件描述符,从而可以建立shell进程同攻击者的通信。

大家可以将基本的shellcode模式理解成本地漏洞攻击,此时返回shell后可以直接在终端中进行通信。

2. 端口绑定shellcode

在上面的模式中,迁移到一个网络远程环境下,那么现在需要建立攻击者和shell进程间一个网络连接,我们的想法是shell进程建立一个TCP套接字,然后绑定一个预先指定的端口(如6666),然后开启监听模式;同时攻击者发起连接到目标的6666端口,建立与shell进程的通信。关键步骤如下:

  1. 创建一个TCP套接字;
  2. 将套接字绑定到攻击者指定的端口(硬编码到shellcode中);
  3. 开启该套接字的监听模式;
  4. 接受新连接;
  5. 将新接受的套接字复制到stdin、stdout、stderr上;
  6. 创建一个新的shell进程,通过这个新套接字收发数据;

具体如图:

一般此时攻击者可以使用Netcat之类的工具来实现通信。但是这种模式存在缺点,比如如果网络不允许外部进入的连接,则shell无法建立通信;并且细心的管理员会发现可疑的shell进程和监听模式的套接字。

3. 反向shellcode

为了解决上面提到的第一个问题,即外部连接禁止的情况,我们可以转换思路,使得shellcode进程主动发起连接,由网络内部来连接我们,故而称作“反向shellcode”。 关键步骤是:

  1. 创建一个TCP套接字;
  2. 配置该套接字,连接到攻击者预先指定的IP和Port;
  3. 连接到指定的IP和Port;
  4. 将建立连接的套接字复制到stdin、stdout、stderr;
  5. 创建新的shell进程进行通信;

具体如图:

这里的问题同样是如果不允许内部80端口以外的端口发起连接,则shell通信也无法建立。另外,可疑的shell进程和套接字依旧容易引起细心管理员的怀疑,有一定的暴露风险。

4. 查找套接字shellcode

我们的第三种建立shell的方法就是复用已有的连接,既然已经有了80端口的网络连接,何苦自己再建立一条呢?如果可以复用80端口的连接,不仅节省了代码开支,而且还具有很好的隐蔽性。这里的关键问题是获取当前连接的套接字,这也是“查找套接字shellcode”的来由,一般的方法是遍历0-255的描述符,来确定到底当前使用的是哪一个。这里的关键步骤是:

  1. 对于256个可能的文件描述符判断每个描述符是否表示一个有效的网络连接,如果是,判断远程端口是否是我们已经在用的端口(这个远程端口提前硬编码到shellcode中);
  2. 一旦找到期望的套接字描述符后,将其复制到stdin、stdout、stderr;
  3. 创建一个新的shell进程通过原始套接字来收发数据;

具体如图:

5. shellcode的变化

除了以上几种最初的shellcode模式外,现在还存在多种功能的shellcode,比如:

  • 命令执行代码:shellcode用于执行特定的命令,如将SSH的公钥复制到目标计算机上便于日后SSH连接访问;比如修改配置文件允许后门shell进行访问等;
  • 文件传输代码:这种代码用于在目标机器上下载一个文件,功能类似于下载器,或者wget;
  • 多级shellcode:为了突破缓冲区的一些限制(比如大小、权限),采用多层shellcode,第一级shellcode的唯一作用是读取更多的shellcode,然后将控制权传给第二级shellcode,以此类推;
  • 系统调用代理shellcode:这种模式不需要在目标机器上下载代码,只需要在进程的上下文中运行着shellcode,然后攻击者输入一个单纯的系统调用指令,shellcode执行后返回结果,可以开发出方便的代理库同shellcode通信;
  • 进程注入shellcode:这类的典型应用是MSF的meterpreter,在一个进程的独立线程下面运行整个代码库的加载任务。这部分可以参考http://www.metasploit.cn/thread-736-1-1.html

三、内核空间的shellcode

内核空间也存在漏洞利用的可能,但是由于公开信息很少,因此研究并不多,但是现在越来越多的人正在研究内核中的漏洞利用。这里编写shellcode特别需要注意的就是稳定性,在用户态中,shellcode崩溃仅仅导致用户进程中止,但是内核态中却会引起系统崩溃。所以要特别小心的调试。

另外,内核态中没有了系统调用的概念,只能使用由内核导出的函数,而这些函数的资料和说明也并不丰富。

因此,更为稳妥的方法是,将内核态的shellcode运行后加载到一个用户态中较高进程的空间中运行。

ReferGray Hat Hacking: The Ethical Hacker‘s Handbook, Third Edition

时间: 2024-10-17 16:01:41

【安全健行】(3):Shellcode基础的相关文章

【安全健行】(2):Linux漏洞基础

2015/5/12 18:36:42 时隔这么久,自己终于重新开始了安全之路,虽然每天的工作和研读的论文也都是安全领域的技术,但是自己心里真正的安全还是漏洞的研究.因此,自己决定业余来自学这部分,今天算是一个正式的开始吧! 今天来简单介绍下Linux漏洞,因为Linux给予了用户更大的自由度和操控性,因此更加适合进行安全研究,我们也从Linux开始.这部分主要分为以下小节: 栈的操作 缓冲区溢出的基本原理 本地缓冲区溢出漏洞攻击框架 小缓冲区的漏洞攻击框架 一.栈的操作 栈是操作系统进程内存中特

【安全健行】(5):shellcode编码

2015/5/19 18:08:45 上一节我们介绍了基本shellcode的编写,采用的是exit().setreuid()和execve()三个系统调用,实际中当然是根据自己的需要来选择合适的系统调用了,系统调用号需要查看syscalltable,参数的压入也是采取类似的方式,处理好堆栈,编写汇编代码并不十分困难. 这一节我们要来介绍下shellcode的编码,那么为什么要对shellcode进行编码呢?大致原因有以下几个: 避免出现Bad字符,如\x00.\xa9等: 避开IDS或其他网络

【安全健行】(4):揭开shellcode的神秘面纱

2015/5/18 16:20:18 前面我们介绍了shellcode使用的基本策略,包括基本的shellcode.反向连接的shellcode以及查找套接字的shellcode.在宏观上了解了shellcode之后,今天我们来深入一步,看看shellcode到底是什么.也许大家和我一样,从接触安全领域就听说shellcode,也模糊地知道shellcode基本就是那个攻击载荷,但是shellcode到底长什么样,却一直遮遮掩掩,难睹真容.趁今天这个机会,我们一起来揭开shellcode的神秘面

【安全健行】(1):Hacker编程技能

接触安全领域也算四年了,大大小小的方向都看过一些,却都未能精通,日渐感到自己实力的匮乏,因此自己决定今天开始来学习下Hack技术最为核心的知识和技能:漏 洞挖掘与恶意代码分析.由于主要涉及这个领域,因此所谈与WEB安全脚本之类的关联不大,凡事须追本,根深才能叶茂,希望可以利用近两年的时间,小有所 成.   今天要讲的是Hack技术的编程基础,谈到基础,大家都会给出一些有见解的意见,主流推荐就有C/C++.Java.Perl.Python.VB等: 进一步地还有SOCKET编程.系统编程等.自己当

行测(基础篇)之汉语语法与阅读习惯梳理

一.词性和语法结构 1.词性 实词(具有实际意义的词):名词.动词.形容词.数词.量词.代词. 虚词(没有具体意义的词):副词(很.非常).连词.介词(在.于).助词(的).叹词.拟声词. 2.语法结构 主语(状语)谓语 (补语) (定语) 宾语    傅园慧使出洪荒之力.(主谓宾)    "傅园慧(真的)使出(了)(自己的)洪荒之力" 主语:名词.代词 谓语:动词.形容词 宾语:名词.代词 定语:形容词.名词.代词.数量词 状语:副词.形容词 补语:形容词.动词 3.例题 二.易混淆

【安全健行】(6):Windows漏洞保护机制

2015/5/21 11:07:55 之前我们一直在Linux平台上分析漏洞,那是因为对于绝大多数Hacker获得一个Linux平台更加容易,而且主流的服务器系统基本也都是Linux/Unix的:另外一个好处就是Linux提供了用户自定义的强大功能,我们可以根据需要编译汇编程序代码,关闭相应的安全保护机制,便于我们的研究学习. 然而现实中有影响力的漏洞大多是基于Windows系统,因此这节我们来介绍下Winodws系统上是安全保护机制,至于Windows上的漏洞分析,我们会在之后的恶意代码分析章

2000行之C++基础练习

#include<iostream> using namespace std; enum GameResult{WIN,LOSE,TIE,CANCEL}; int main(){ GameResult result; enum GameResult omit = CANCEL; for(int count = WIN;count <= CANCEL;count++){ result = GameResult(count); if(result = omit) cout<<&q

easyui 处理多行的操作基础

singleSelect="true" 在tabble中不能存在此句 var rows = $('#ttt').datagrid('getSelections'); 获得所有行 for(var index=0; index<rows.length; index++){ var dataInfo={}; dataInfo.id = rows[index].id; dataInfo.name=rows[index].name; 分别对所有行进行操作.

2、链接数据库+mongodb基础命令行+小demo

链接数据库并且打印出数据的流程:1.在CMD里面输入 mongod 2.在CMD里面输入 mongo 3.在输入mongodb命令行里面进行操作,首先输入 show dbs 来查看是否能够链接得上库4.定义db var db = connect('log'); //链接数据库 链接的是哪一个数据库?5.插入数据:db.login.insert(jsonData); //插入数据 5.命令行一:基础命令行(1).查看存在数据库命令 : show dbs (2).查看数据库版本命令 : db.ver