头歌网络安全(11.12)

头歌禁止复制解决

必须先下篡改猴!!!!

头歌复制助手 Educoder Copy Helpericon-default.png?t=O83Ahttps://scriptcat.org/zh-CN/script-show-page/1860

Java生成验证码

第1关:使用Servlet生成验证码

任务描述
本关任务:使用servlet生成验证码。

相关知识
验证码在我们登陆、注册网站,火车票买票的时候经常会见到的,为什么要有验证码呢?可能很多人都会有这个疑问。


但是作为开发者,可能我们更多的就会关注怎么生成验证码了。

要了解如何生成验证码,我们首先要知道什么是验证码,网站为什么需要它。

为什么要有验证码,什么是验证码
我们经常需要在网站或者应用程序中填写验证码,不过作为用户而言其实我们一点都不喜欢验证码,因为有时候老容易填错。

为什么这个影响用户体验的东西还是一直存在呢?

肯定是有道理的。

一个网站除了我们人操作电脑可以登录之外,使用JavaScript代码和一些脚本语言也是可以登录的,但是我们开发网站是给人用的而不是给机器使用的,我们想象一个网站如果没有验证码,我们只需要编写一段脚本就可以无限次数的登陆某个网站,这样无数次的尝试就可以暴力破解用户的密码,如果是注册行为那就会给网站制造很多垃圾信息,这个就会对该网站造成极大的资源浪费,严重的可能会让这个网站崩溃,所以就有了验证码。

说白了,验证码就是用来判断是人在操作还是机器在操作。

如何使用Servlet生成验证码
在Java中我们可以在Web项目中使用Servlet来生成验证码,流程是:前端请求验证码servlet对应的地址,后端servlet收到请求,生成一串字符作为验证码,存入到Session中,最后将验证码作为一张图片返回给前端。前端填写了验证码提交到服务器来验证。

我们看一个示例,你也可以根据这个示例在右侧编辑器中一步一步实现验证码的功能。

项目和servlet已经创建好了,我们首先在web.xml文件中注册servlet。

如下:


在servlet的doGet()方法中编写代码实现生成图片验证码:

分为如下步骤:

定义图像数据缓冲区(BufferedImage);

创建图片对象;

创建绘制工具(Graphics);

生成随机数,存入到session中;

使用Graphics绘制图形;

将验证码通过图像输出流(ImageIO)输出到客户端;

最后输入验证码地址即可访问单验证码。

具体代码如下:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 使用验证码的步骤
    // 定义图片的宽高
    int height = 20;
    int width = 60;
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    // 绘图工具
    Graphics graphics = image.getGraphics();
    // 绘制矩形
    graphics.setColor(getRandColor());
    // 绘制矩形背景 前两个参数 是 x y的坐标
    graphics.fillRect(0, 0, width, height);
    // 设置文字的颜色 为白色
    graphics.setColor(Color.WHITE);
    String yzm = "";
    // 生成四个随机数字并且画在图片上
    for (int i = 1; i <= 4; i++) {
        // 生成随机数字并且显示到页面上
        int number = new Random().nextInt(10);
        yzm += number;
        graphics.drawString(number + "", 10 * i, 10);
    }
    // 将验证码放入Httpsession中
    HttpSession session = req.getSession();
    session.setAttribute("sessionYzm", yzm);
    // 将验证码图片输出到客户端
    ImageIO.write(image, "jpg", resp.getOutputStream());
}
// 获取随机颜色
private Color getRandColor() {
    int red = new Random().nextInt(255);
    int green = new Random().nextInt(255);
    int blue = new Random().nextInt(255);
    return new Color(red, green, blue);
}
编程要求
web.xml中的代码已经添加,按照上述步骤编写servlet代码,点击测评即可。

效果图:


测试说明
因为需要部署服务器,并且运行测试代码,所以评测时间较长,需要30秒左右。

开始你的任务吧,祝你成功!

package com.servlet;import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class CodeServlet extends HttpServlet {protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {/********* Begin *********///请在此编写生成验证码的代码int height = 20;int width = 60;BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);Graphics graphics = image.getGraphics();graphics.setColor(getRandColor());graphics.fillRect(0,0,width,height);graphics.setColor(Color.WHITE);String yzm = "";for(int i=1;i<=4;i++){int number = new Random().nextInt(10);yzm += number;graphics.drawString(number + "",10*i,10);HttpSession session = req.getSession();session.setAttribute("sessionYzm",yzm);ImageIO.write(image,"jpg",resp.getOutputStream());}/********* End *********/}// 获取随机颜色private Color getRandColor() {int red = new Random().nextInt(255);int green = new Random().nextInt(255);int blue = new Random().nextInt(255);return new Color(red, green, blue);}
}

第2关:用户登录时校验验证码是否正确

任务描述
本关任务:编写程序验证验证码是否正确。

相关知识
上一关我们已经学习如何生成验证码了,为了完成一整套的验证码使用流程我们还需要知道如何验证用户提交的验证码是否正确。

登录功能
我们经常在登录注册的时候填写验证码,本关我们就来实现登录功能。

首先我们来理解验证码校验的基本流程:


上图展示了一个用户填写验证码的基本流程,用户打开网页显示服务端生成的验证码,点击“看不清楚”标签可以重新生成,这个时候会从新请求服务端数据,服务端用Session来保存验证码信息。

当用户点击确认按钮的时候,我们就需要对用户通过表单提交的验证码进行校验了,这个时候服务端获取Session保存的验证码信息和用户提交的验证码数据进行校验如果两者一致则校验通过。

这就是一个完整的验证码流程了。

我们可以将验证码的流程总结为:前端表单登陆 => 后端获取到验证码校验 => 前端收到后端的响应。

借下来我们来实现这个过程。

前端实现
我们创建一个登录表单,代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
</head>
<body>
    <form action="loginServlet">
        用户名:
        <input type="text" name="username">
        <br>
        密 码:
        <input type="text" name="password">
        <br>
        验证码:
        <input type="text" name="verifycode" id="yzm">
        <!-- src填servlet的地址就能显示网络上的图片 -->
        <a href="javascript:reload()"><img id="yzmImg" src="code"/> </a>
        <br>
        <input type="submit" value="提交">
    </form>
</body>
<script type="text/javascript">
    //重新加载验证码
    function reload() {
        var img = document.getElementById("yzmImg");
        img.src = "code?" + new Date().getTime();
    }
</script>
</html>

package com.servlet;import java.io.IOException;
import java.io.PrintWriter;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");/********* Begin *********///请在此进行登录校验PrintWriter writer = resp.getWriter();String username = req.getParameter("username");String password = req.getParameter("password");String verifycode = req.getParameter("verifycode");HttpSession session = req.getSession();String realCode = (String) session.getAttribute("sessionYzm");if(!verifycode.equals(realCode)){writer.write("验证码错误");}else{if("admin".equals(username)&&"admin123".equals(password)){writer.write("登录成功");}}/********* Begin *********/}protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

第3关:使用Kaptcha组件生成验证码

任务描述
本关任务:使用Kaptcha组件生成验证码,并校验验证码是否正确。

相关知识
之前两关我们已经了解了验证码的制作流程,不过我们在开发中一般不会去自己从零开始编写验证码,而是会使用到开源的组件,本关我们就来使用Kaptcha来生成验证码,并且编写一个页面校验用户的验证码是否输入正确。

Kaptcha 组件的使用
先来看要实现的效果:


首先制作用户填写验证码的页面captchacode.jsp

<script type="text/javascript">
    function reloadCode() {
        var date = new Date().getTime();
        document.getElementById("code").src = "<%=request.getContextPath() %>/imageKaptcha?d="+date;
    }
</script>
<form action="checkCaptcha.jsp" method = "post">
     <img alt="验证码" src="imageKaptcha" id = "code"><a href = "javascript:reloadCode();">看不清</a>
     <input type = "text" name = "captcha">
     <input type = "submit" value = "submit">
</form>
接着我们写一个检查验证码输入是否正确的类checkCaptchaServlet.java

request.setCha\fracterEncoding("utf-8");
// 获取Kaptcha jar包里面的KAPTCHA_SESSION_KEY
String trueCaptcha = (String)session.getAttribute(Constants.KAPTCHA_SESSION_KEY);
String inputCaptcha = request.getParameter("captcha");
if(trueCaptcha.toLowerCase().equals(inputCaptcha.toLowerCase())) {
out.write("验证码输入正确");
} else {
out.write("验证码输入错误");
}
然后配置好web.xml就ok了。下面我们来看看怎么配置web.xml

<servlet>
    <servlet-name>myCaptcha</servlet-name>
    <!-- jar中的 KaptchaServlet的路径-->
    <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<!--配置kaptcha 校验验证码是否正确的 servlet-->
<servlet>
    <servlet-name>CheckCaptcha</servlet-name>
    <servlet-class>com.servlet.CheckCaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>myCaptcha</servlet-name>
    <!-- 对于index.jsp中img的src -->
    <url-pattern>/imageKaptcha</url-pattern>
</servlet-mapping>
<!--第三关:配置kaptcha 校验验证码的 servlet-->
<servlet-mapping>
    <servlet-name>CheckCaptcha</servlet-name>
    <url-pattern>/checkCaptcha</url-pattern>
</servlet-mapping>
做完上述步骤之后,运行项目,打开网页,即可查看验证码。


输入正确的验证码点击submit:


经过上述步骤我们就使用Kaptcha组件生成验证码了。

扩展:Kaptcha还有很多其他的设置可以实现图片边框,边框颜色,中文验证码等操作,限于篇幅在这里就不在赘述。

编程要求
好了,到你啦,来使用Kaptcha生成验证码并校验输入的验证码是否正确吧。

补全captchacode.jsp,实现验证码表单的页面效果;

补全CheckCaptchaServlet,实现验证码的校验功能,验证码正确返回:验证码输入正确,否则返回:验证码输入错误。

开始你的任务吧,祝你成功!

checkCaptchaServlet.java

package com.servlet;import com.google.code.kaptcha.Constants;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;/*** Created by 63194 on 2018/9/14.*/
public class CheckCaptchaServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");PrintWriter out = resp.getWriter(); // 初始化 out 变量HttpSession session = req.getSession(); // 初始化 session 变量//校验kaptcha 验证码是否正确//获取Kaptcha jar包里面的KAPTCHA_SESSION_KEYString trueCaptcha = (String) session.getAttribute(Constants.KAPTCHA_SESSION_KEY);String inputCaptcha = req.getParameter("captcha"); // 使用 req 参数if (trueCaptcha != null && inputCaptcha != null && trueCaptcha.toLowerCase().equals(inputCaptcha.toLowerCase())) {out.write("验证码输入正确");} else {out.write("验证码输入错误");}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

 captchacode.jsp

<%--Created by IntelliJ IDEA.User: 63194Date: 2018/9/14Time: 19:14To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<!--------- Begin ---------><script type="text/javascript">function reloadCode() {var date = new Date().getTime();document.getElementById("code").src = "<%=request.getContextPath() %>/imageKaptcha?d="+date;}
</script>
<form action="checkCaptcha.jsp" method = "post"><img alt="验证码" src="imageKaptcha" id = "code"><a href = "javascript:reloadCode();">看不清</a><input type = "text" name = "captcha"><input type = "submit" value = "submit">
</form><!--------- End --------->
</body>
</html>

动态分析技术

任务描述
本关任务:

  使用 qira 拿到属于你的 flag !!!

相关知识
为了完成本关任务,你需要掌握:

  1、正确的程序分析思路
  2、动态调试器 qira 的使用

程序分析
  在本关学习新知识之前,我们需要先知道如何分析一个程序,即拿到一个二进制程序文件后应当如何入手。
  对一个程序的分析应当从以下三步入手:运行程序 --> 静态分析 --> 动态分析。运行程序,即在本机上直接和程序进行交互,观察程序的输入和输出,作为分析人员的我们应当尽可能的执行完所有的功能。静态分析,即利用静态分析软件,如:IDA Pro,尝试对程序进行反汇编、反编译,分析伪代码,结合上一步程序运行的输入和输出快速定位有问题的代码段。动态分析,即利用动态分析软件,如:qira ,尝试观察程序动态运行的结果,能够直接观察到程序运行过程中寄存器、栈、堆等数据的变化。
  接下来我们将用一个例子来完整的走一遍程序分析的流程,示例文件为 demo ,可以在目录/home/headless/Desktop/workspace/myshixun/pwnPro/step2/下找到。
  首先,打开终端,如下终端命令所示,进入到程序所在目录,查看程序信息,发现程序没有可执行权限,添加可执行权限,然后执行程序。

cd /home/headless/Desktop/workspace/myshixun/pwnPro/step2/
ls -all demo
chmod +x demo
./demo
  如下截图所示,发现程序运行后,只打印了No flag here!!!,难道真的没有 flag ,我肯定是不信的,接着我们用 IDA 来分析。

  按照上一关所学的内容,我们在 IDA 中打开 demo 文件,然后在反汇编界面按下 F5 ,直接观察伪代码。如下截图所示,是 demo 程序的主逻辑,最外层是一个 for 循环,将会执行18次,每次都对 false_flag 数组中的值进行了判断,根据判断的结果对 false_flag 数组元素的值进行变化,然后再将其赋值给 true_flag ,最后调用 puts 打印了No flag here!!!。根据题目逻辑,false_flag 是待变换的数组,true_flag 才是存储真正 flag 的地方,程序通过对 false_flag 进行变化然后得到 true_flag ,所以我们需要的是 true_flag 的值,然而这里并没有打印该值。

  我们继续分析,在 IDA 中我们可以通过点击直接跳转到对应变量所在位置,这里我们点击 false_flag 将会跳转到其位置所在。如下截图所示,可以发现 false_flag 位于 data 段,表明其是一个全局变量,后面的箭头所指dq offset aXdsyIkwHz3Eajs表明其是一个指针变量,指向的内容我们可以看后面的方框,这是 IDA 给的注释,表明其指向的字符串是xdsy{Ikw_Hz3_Eajs}。  

  我们再点击 true_flag ,如下截图所示,发现其位于 bss 段,表明其是未初始化的全局变量。箭头指向的位置标注了_BYTE_true_flag[19]表明其是一个长为19的字符数组。当然这里并不能看到其值是啥,因为需要程序运行结束后才能观察到。如果我们想要得到这里的 true_flag ,有两种办法:一是根据程序的逻辑,自己编写求解脚本来得到 flag ,编写脚本的方式也很简单,直接复现程序的逻辑即可;二是使用动态调试,因为 true_flag 是程序的一个变量,在程序运行到某一时刻,该变量中一定存储着正确的 flag 。因此在下一小节,我们将会使用 qira 动态调试来直接得到 true_flag。

动态调试器 qira
什么是 qira
  qira
  在学习动态调试之前,我们先来了解下 qira 。qira 是 github 上的一个开源项目,在上方已经给出了其链接,点击即可跳转到 github ,github 中有详细的介绍和其安装方式。当然在本实验平台中,我们已经安装好了。qira 被誉为超越时空的调试器,即可以在时间中任意穿梭的动态调试器,实质上是一个 trace 工具,将程序整个执行流全部记录下来,然后给予用户回溯、查看命中断点的所有指令(即交叉引用)等。

qira 的基本使用
  打开实验环境的终端,切换到 demo 文件所在的目录下,使用 qira 启动程序,整个过程如下命令所示。

cd /home/headless/Desktop/wordspace/myshixun/pwnPro/step2/
qira demo
  启动后,终端输出如下截图所示,可以看到箭头所指的地方,分别是程序所在路径(这里运行时的环境和实验平台不一样,请用自己在平台的输出进行验证),监听的 ip+port ,以及程序自身的运行输出。值得说明的是,qira 采用 web 页面来展示整个程序的执行过程,后端使用 python flask 框架实现。

  之后,我们打开浏览器,输入127.0.0.1:3002即可看到 qira 的界面,如下截图所示。序号1指示的是 qira 的一条时间线( vtimeline ),在调试复杂程序的时候程序并不会一次执行完,我们每次步入都需要在 web 页面进行刷新,此时就会出现新的时间线。序号2指示的是 qira 的一些控制数据,前三个盒子中展示的内容分别是:第几条指令、第几条时间线、指令地址,我们可以直接修改盒子中的数据来实现跳转。序号3指示的是程序的汇编指令,这里展示的指令和 IDA 中的没有什么区别,当然地址会有所不同,这是因为程序动态运行加上了基地址所导致的。序号4指示的是寄存器的值,序号5指示的是程序运行过程中的函数堆栈,从这里我们可以看到程序的函数调用关系。

 接下来,我们再看看 qira 的强大之处,在 qira 的主界面上,我们可以通过点击位于内存中的地址查看当前内存的数据信息。如下截图所示,我们点击寄存器中的 RSP 栈顶指针寄存器,此时最下方就会展示当前栈帧的内存数据信息,图中方框和箭头圈出的地方刚好是 RSP 指向的8个字节内存数据,后面显示的乱码就是对应字节的 ascii 编码信息,转换不出来就显示 . 号。

使用 qira 找到 flag
  在之前的介绍中,我们知道了 qira 是一个 trace 工具,它会记录程序运行过程中所有寄存器和内存数据的变化,因此通过它,我们就可以在内存中找到 true_flag ,从而无需编写脚本就能获得 flag 。
  在实践之前,这里我们先引入基址这个概念。如下截图所示,我们同时打开 IDA 和 qira ,将 IDA 汇编代码定位到 start 函数,将 qira 指令定位到第0条。我们知道 c 语言中 main 函数是程序的入口点,其实在 main 函数之前还会调用 start 函数,做二进制分析的时候我们应当认为这才是程序真正的入口点。通过对比汇编指令,我们可以看到 qira 就是从 start 开始执行的,但是我们也会发现 IDA 显示的地址是0x0000000000001060,而 qira 显示的却是0x4000001060。 我们知道64位程序的地址都是 64bit ,十六进制表示的话就是16个十六进制数,高位为0可以省略。因此这里 qira 的地址比 IDA 多了0x4000000000,这个地址我们就称为基址,所有汇编指令在运行时的地址都是基址 + 偏移,而 IDA 是静态分析,所以只显示偏移,没有加上这个基址。

  在弄清楚基址这个概念后,寻找 flag 就方便多了,首先我们在 IDA 中找到 true_flag 的地址,如下截图所示,为4030,然后我们将基址加上就是0x4000004030,之后我们将其输入到 qira 最上控制面板的第四个盒子中,截图如下。

  之前并没有介绍这第四个盒子的作用,其实该盒子的作用就是用于展示对应地址的内存数据信息。按照上面的步骤,我们在 qira 中输入 true_flag 的地址后,直接回车,此时可以看到最下方已经出现了对应地址的内存数据信息,如下截图所示,可以看到程序运行后的 flag 了。

  好了,到这里我们已经基本掌握了程序的分析步骤,qira 动态调试器的使用,接下来就用学到的知识去完成本关挑战吧。

编程要求
  本课程采用了 CTF 比赛获取 flag 的方式来进行实践练习,你的目标是拿到一个 flag ,形式为flag{xxxxxxxxxxxxxxx},本关目标文件为/home/headless/Desktop/workspace/myshixun/pwnPro/step2/目录下的 level2 。
  本关没有编程要求,但需要你通过静态分析 + 动态调试拿到隐藏在二进制程序中的 flag ,后面的课程将需要你利用程序漏洞进行编程获取到 shell ,进一步拿到 flag 。

测试说明
  将你拿到的 flag 写入到实验环境提供的 flag.txt 文件中,然后点击评测即可。

开始你的任务吧,祝你成功!

flag{Y0u_Are_Great}

静态分析技术

任务描述
本关任务:

  使用 IDA pro 拿到属于你的 flag !!!

相关知识
为了完成本关任务,你需要掌握:

  1、反编译器 IDA pro 的使用
  2、基本的汇编指令
  3、基本的 ELF 文件格式

IDA pro
什么是 IDA pro
  交互式反汇编器专业版( Interactive Disassembler Professional ),人们常称其为 IDA Pro ,或简称为 IDA 。是目前最棒的一个静态反编译软件,为众多 0day 世界的成员和 ShellCode 安全分析人士不可缺少的利器!IDA Pro 是一款交互式的,可编程的,可扩展的,多处理器的,交叉 Windows 或 Linux WinCE MacOS 平台主机来分析程序, 被公认为最好的花钱可以买到的逆向工程利器。IDA Pro 已经成为事实上的分析敌意代码的标准并让其自身迅速成为攻击研究领域的重要工具。它支持数十种 CPU 指令集其中包括 Intel x86,x64,MIPS,PowerPC,ARM,Z80,68000,c8051 等等。
  IDA 是 Hex-Rays 公司的旗舰产品,作为一款致力于软件逆向和破解的工具,IDA 所属公司却特别痛恨盗版软件。因此,他们对于未经授权就使用 IDA 的做法深恶痛绝。这里特别介绍其反盗版措施,非常值得借鉴和学习。
  第一种反盗技术:每一份 IDA 都带有水印,以将它与购买者一对一地对应起来。如果一份 IDA 出现在盗版软件站中,Hex-Rays 就能够通过水印追踪到购买者,并将其列入销售黑名单。我们常常可以在 Hex-Rays 的 IDA 支持论坛上发现有关 IDA 的“泄露”版本的讨论。
  第二种反盗技术:扫描在局域网中运行的其他IDA程序。例如,Windows 版本的 IDA 启动后,它会在端口23945上广播一个 UDP 包,并等待响应,看相同子网中是否有其他使用相同许可证密钥的 IDA 实例在运行。然后,IDA 会将得到的响应数量与使用该许可证的用户数量进行比较,如果发现网络中存在过多的 IDA 实例,IDA 会拒绝启动,但是要注意,用户可以在一台计算机上使用相同的许可证运行多个 IDA 实例。
  第三种反盗技术:使用密钥文件将每一名购买者与产品联系起来。在启动时,IDA 会搜索一个有效的 ida.key 文件。如果无法定位有效地密钥文件,IDA 就会立即关闭。密钥文件还用于用户升级 IDA 的资格。基本上,ida.key 文件就像是用户的购买收据,要想在将来获得升级资格,用户必须保管好这个文件。

IDA pro的基本使用
  经过上面 IDA 背景知识的学习,我们可以猜想到 IDA 这款软件价值不菲,具体的费用因插件的完备性而不同,感兴趣的同学可以上网搜索了解一下。在本实验平台中,我们已经准备好了该实验环境,使用 IDA Pro 7.5 全插件版本,也就是说所有功能俱全。
  首先,我们打开桌面上命名为 IDA_Pro_v7.5 的文件夹,如下截图所示,其中ida.exe和ida64.exe就是对应的 IDA 应用程序,分别用于逆向分析32位和64位的可执行程序。这里大家可能会有个疑问,为啥 ubuntu 下可以运行.exe程序?这是因为 linux 下的 IDA 本身版本少且不如 Windows 平台下的功能强大,所以这里采用了 Windows 平台下的 IDA 软件。其次之所以这里可以运行 Windows 平台下的程序,是因为平台实验环境已经配置了相应的环境,可以参考 wine 的配置,具体细节此处不详述,不是我们学习的重点。

  这里我们以一个具体程序的为例介绍 IDA 的使用,待分析二进制程序为 demo ,如下截图所示,我们可以在/home/headless/Desktop/workspace/myshixun/pwnPro/step1/目录下找到该二进制程序。该文件为64位可执行程序,接下来我们将使用ida64.exe对其进行分析。

  点击ida64.exe,首先会出现一个版本许可证的界面,下方会存在确认按钮,无论我们是否确认,之后都会进入到如下截图所示的页面。选择New或者Go开启 IDA 其实本身都没有啥区别。选择New会打开文件浏览窗口,我们可以在这里寻找 demo 文件,然后用 IDA 打开它。选择Go会直接打开一个空白的 IDA 界面,之后我们可以通过拖动的方式将 demo 文件拖到 IDA 中,这和第一种操作的结果是一样的。至于第三种选择Previous会直接打开下方方框中排在最上面的对应路径的二进制程序文件,这其实就是历史记录,当然我们也可以直接点击方框中的其它条目来打开之前分析过的二进制文件。

  

  这里我们选择Go,然后将 demo 文件拖到 IDA 中,之后会出现如下截图所示的界面,其中高亮的地方表明了 IDA 会将其作为一个 ELF64 格式的文件来进行分析,其余配置我们默认即可,选择 OK 进入到 IDA 界面。

  在进入正式认识 IDA 分析界面之前,我们来看下 IDA 启动后对文件做了啥更改。如下截图所示,我们发现原程序目录下出现了和待分析程序命名相同,但后缀不同的文件,这是 IDA 生成的数据库文件,值得一提的是,我们在 IDA 中对文件进行修改的话是不会影响原二进制程序文件本身的,改变的是这些数据库文件。

  同样的,我们现在来尝试退出 IDA ,会出现如下截图所示的界面,其目的就是让我们选择是否打包存储 IDA 生成的数据库文件,默认选择如下,确认后会将原来的五个文件打包为后缀为.i64的数据库文件,该文件记录了我们在 IDA 所做的操作和更改。当然我们也可以选择最下面的 Don't save ,该操作在 IDA 关闭后将不会留下任何文件。

  

  好了,经过前面的学习,我们已经掌握了一些基本的操作,接下来我们将会学习 IDA 的几个重要分析界面。

  整体界面
  如下截图所示,待 IDA 将二进制程序分析完毕后,IDA 整体界面可以大致切割为五个部分,我们从上往下依次介绍,序号1指示的是 IDA 的工具栏窗口,这里集合了所有功能选项和操作,具体操作细节我们会在后面实践课程中进一步学习。序号2指示的是Functions window,即函数窗口,这里会显示该程序中所有逆向出来的函数,可以看到其中有我们熟悉的 main 函数、printf 函数,当然还有以 sub 开头命名的函数,这些都是没有识别出具体名字的函数,将会以 sub+ 函数地址的方式命名。序号3指示的是view窗口,截图中是处于IDA View-A反汇编界面的状态,当然该视图还有string window字符串窗口,Hex View-1十六进制窗口等等。序号4指示的是Graph overview,即图表化概览,这里展示的是程序所有函数的流程图,可以看到其流程图和右边的反汇编界面展示的流程是一致的。序号5指示的是Output window,即输出窗口,这里会打印 IDA 在执行过程中的提示信息,最下面的 python 一栏还能执行 python 脚本。

  反汇编界面
  如下截图所示,分别是反汇编界面的两种代码展示方式。第一种是函数控制流程分支展示,这也是 IDA 默认的展示方式。通过这种方式,我们可以清晰的观察到函数的跳转分支情况,以下面的第一张图为例,红色箭头指示的是语句失败的分支,可以是 if 语句,当然具体的话还要根据汇编代码具体分析。第二种是汇编代码的文本视图,以下面的第二张图为例,我们可以看到汇编代码所属的段( segment )、对应地址等。上述两种视图的切换可以通过在 IDA View-A 视图中按下空格键快速切换。

  伪代码界面
  IDA 最强大之处在于提供了极好的反编译功能,如下截图所示,我们选中反汇编界面,按下F5将会执行反编译,此时出现了Pseudocode-A伪代码界面。可以看到,除了个别变量名无法还原外,这里的伪代码已经非常清晰的展示了程序流程。相比较于看汇编代码,通过阅读伪代码可以帮助我们更好的定位程序漏洞,这也是 IDA 为啥如此受欢迎的原因。

  关于 IDA 的基本使用将会介绍到这里,在后面的实践操作中,我们将会进一步熟悉和介绍 IDA 的其它操作。

汇编指令学习
  接下来,我们将以一道例题的方式来学习一下基本的汇编指令,熟悉在汇编下一个函数的功能是如何实现的,使用文件为 demo ,我们在 IDA 中打开它,软件会自动定位到 main 函数。
  如下截图所示,红框圈起来的部分展示的是函数序言和函数尾声,也就是所有函数的开头和结尾都会使用的指令。在汇编层面,所有函数调用都会先开辟栈帧,push rbp会将 rbp 寄存器压栈,rbp 是栈帧寄存器,这里是保存上一个函数的栈帧;mov rbp, rsp,rsp 是栈顶指针寄存器,此时将 rsp 指向 rbp ,也就以为着该函数栈帧正式开始。leave相当于mov rsp, rbp; pop rbp,我们可以发现这和函数序言是完全相反的操作,不难理解,一个函数结束后需要清空自己的栈帧,所以采用相反的操作。最后retn相当于pop rip,rip 是程序指令寄存器也就是下一条要执行的指令,所以这里的retn会弹出之前压入栈中的返回地址到 rip 中继续运行,保证程序流程的完整运行。

  如下截图所示,我们来分析下 scanf 函数的汇编指令执行过程,这里 IDA 会将 scanf 函数识别为__isoc99_scanf,命名中指明了 c 语言版本。先看第一个红框,这里是函数的局部变量,var_12代表距离 rbp 栈帧寄存器的偏移,单位为 byte ,可以看到后面函数调用中就是用 rbp 来定位局部变量的。第二个红框包含了 scanf 调用的完整汇编指令,首先lea rax, [rbp+var_12]将变量地址传到 rax 寄存器中,然后mov rsi, rax将 rax 寄存器的值传递给了 rsi ,之所以这么麻烦是因为 linux 下64位程序规定了前6个参数使用寄存器传参的顺序,即: rdi --> rsi --> rdx --> rcx --> r8 --> r9 ,所以这里 var12 是 scanf 函数的第二个参数。接着lea rdi, a10s将"%10s"也就是我们的格式化字符串传给了 rdi ,也就是 scanf 函数的第一个参数。最后再call ___isoc99_scanf实现函数调用,以上步骤就是实现了源代码的scanf("%10s", &var12)功能。当然在源代码层面,我们并不关心 scanf 的返回值,但是在汇编指令默认会用 rax 寄存器( eax 是 rax 的32位表达方式)来存储函数的返回值,如果函数没有返回值就会将0存放到 rax 寄存器中,这就是mov eax, 0汇编指令的功能。

  好了,这里我们对汇编层面下函数流程的执行进行了一定的分析,其中对 printf 函数的分析,大家可以自己分析一波,比较简单。在分析完汇编后,我们再来看看反编译后的伪代码,相信你一定对二进制程序逆向分析有了更深入的感受和认识。

ELF文件格式
  ELF 是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件,是 UNIX 系统实验室( USL )作为应用程序二进制接口( Application Binary Interface,ABI )而开发和发布的,也是 Linux 的主要可执行文件格式。
  打开 IDA ,在其任意界面按下ctrl+s,会弹出如下截图所示的界面,一个 ELF 文件会根据文件内容将文件分为很多个段( segment ),接下来我们就根据其展示的内容来简单介绍下 ELF 文件格式。该界面展示的内容,从左往右依次是:段名、起始地址、结束地址、内存权限、对齐方式。

  这里我将根据重要性着重介绍几个段:

.plt  实现程序函数链接 lazy 加载的段,里面存储的是跳转到 .got 表地址的代码;
.text  之前我们介绍的汇编指令都处于该段中,也就是说 .text 对应程序真正的代码指令;
.got 存储真正函数地址的段;
.data 程序已经初始化的全局变量;
.bss  程序未初始化的全局变量;
  如下截图所示,在 segment 界面,我们可以通过点击的方式直接进入到程序的相应段中,在该段中我们可以发现一个名为 flag 全局变量,该变量是一个字符串。

  当然除了上面的方式,我们要寻找程序中的字符串,也可以使用快捷键shift+f12,如下截图所示,会跳转到字符串界面,我们可以在最下面找到该字符串,同样点击它也会跳转到对应段。

编程要求
  本课程采用了 CTF 比赛获取 flag 的方式来进行实践练习,你的目标是拿到一个 flag ,形式为flag{xxxxxxxxxxxxxxx},目标文件为/home/headless/Desktop/workspace/myshixun/pwnPro/step1/目录下的 level1 。
  本关没有编程要求,但需要你通过逆向分析拿到隐藏在二进制程序中的 flag ,后面的课程将需要你利用程序漏洞进行编程获取到 shell ,进一步拿到 flag 。

测试说明
  将你拿到的 flag 写入到实验环境提供的 flag.txt 文件中,然后点击评测即可。

开始你的任务吧,祝你成功!

flag{you_g0t_m3}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/469606.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ROM修改进阶教程------安卓14 安卓15去除app签名验证的几种操作步骤 详细图文解析

在安卓14 安卓15的固件中。如果修改了系统级别的app。那么就会触发安卓14 15的应用签名验证。要么会导致修改的固件会进不去系统,或者进入系统有bug。博文将从几方面来解析去除安卓14 15应用签名验证的几种方法。 💝💝💝通过博文了解: 1💝💝💝-----安卓14去除…

第七部分:2. STM32之ADC实验--AD多通道(AD采集三路传感器模块实验:光敏传感器、热敏传感器、反射式传感器附赠温湿度传感器教程)

这个多通道采用非扫描模式--单次转换模式 1.代码配置链路图 2. ADC的输入通道 3.ADC的非扫描模式的转换模式&#xff08;单次和连续&#xff09; 4.ADC的扫描模式的转换模式&#xff08;单次和连续&#xff09; 5.采集校准 代码实验&#xff1a; 代码部分&#xff1a; #inclu…

crond 任务调度 (Linux相关指令:crontab)

相关视频链接 crontab 进行 定时任务 的设置 概述 任务调度&#xff1a;是指系统在某个时间执行的特定的命令或程序 任务调度的分类&#xff1a; 1.系统工作&#xff1a;有些重要的工作必须周而复始地执行。如病毒扫描等。 2.个别用户可能希望执行某些程序&#xff0c;比如…

基于python 的opencv 使用GrabCut算法分割图像代码

#利用grabcut算法分割图像import numpy as np import cv2 from matplotlib import pyplot as plt import warningswarnings.filterwarnings("ignore", module "matplotlib")imgpath E:/code/image_opencv_test/lena.jpg img cv2.imread(imgpath)Coords1x…

AndroidStudio-文本显示

一、设置文本的内容 1.方式&#xff1a; &#xff08;1&#xff09;在XML文件中通过属性&#xff1a;android:text设置文本 例如&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.andr…

css:没错又是我

背景 给元素添加背景样式 还可以设置背景颜色、背景图片&#xff08;教练我要学这个&#xff09;、背景平铺、背景图片位置、背景图像固定 背景颜色 这个我们用过&#xff0c;就是&#xff1a; a {background-color: hotpink; } 一般默认值是transparent&#xff0c;也就…

使用Git工具在GitHub的仓库中上传文件夹(超详细)

如何使用Git工具在GitHub的仓库中上传文件夹&#xff1f; 如果觉得博主写的还可以&#xff0c;点赞收藏关注噢~ 第一步&#xff1a;拥有一个本地的仓库 可以fork别人的仓库或者自己新创建 fork别人的仓库 或者自己创建一个仓库 按照要求填写完成后&#xff0c;点击按钮创建…

uniapp的基本使用(easycom规范和条件编译)和uview组件的安装和使用

文章目录 1、uniapp1.uview组件安装2.uview-plus组件安装 2、条件编译3、easycom规范1.组件路径符合规范2.自定义easycom配置的示例 总结 1、uniapp UniApp的UI组件库&#xff0c;如TMUI、uViewUI、FirstUI、TuniaoUI、ThorUI等&#xff0c;这些组件库适用于Vue3和TypeScript&…

攻防世界37-unseping-CTFWeb

攻防世界37-unseping-CTFWeb <?php highlight_file(__FILE__);class ease{private $method;private $args;function __construct($method, $args) {$this->method $method;$this->args $args;}function __destruct(){if (in_array($this->method, array("…

【大数据学习 | HBASE高级】region split机制和策略

1. region split机制 ​ HRegionServer拆分region的步骤是&#xff0c;先将该region下线&#xff0c;然后拆分&#xff0c;将其子region加入到hbase:meta表中&#xff0c;再将他们加入到原本的HRegionServer中&#xff0c;最后汇报Master。 split前&#xff1a;hbase:meta表有…

FMC 扩展子卡6 路 422,8 组 LVDS,8 路 GPIO

FMC 扩展子卡6 路 422,8 组 LVDS,8 路 GPIO 卡是一款支持多路 LVCMOS 和 LVDS 信号互转的 FMC 扩展子板。它能支持 6 路 422 信号的输入 / 输出 ,8 组 LVDS 信号的输入 / 输出和 8 路 GPIO 信号的输入 / 输出。本产品基于一些逻辑转换芯片而设计&#xff0c;能实现差分信号转单…

old-cms(原生PHP开发的企业网站管理系统)

old-cms是一个使用原生PHP开发的实用的PHP企业网站管理系统&#xff0c;包括企业网站常用的功能板块&#xff0c;如&#xff1a;产品管理、新闻管理、栏目管理、模板标签管理、分类管理、诚聘英才、在线留言反馈、关于我们&#xff08;公司简介&#xff09;等等&#xff0c;也有…

IPv4与IPv6的优缺点

IPv4 和 IPv6 都是 TCP/IP 协议的版本。IP 是指互联网协议&#xff0c;是传输控制协议/互联网协议套件&#xff08;TCP/IP&#xff09;的主要部分。 TCP/IP 是一套标准和规则&#xff0c;用于规范不同网络上的设备之间打包数据&#xff08;数据报&#xff09;的传输和交换。互…

git命令及原理

git: 目录则被称之为“树” 文件被称作 Blob 对象. git help <command>: 获取 git 命令的帮助信息 git init: 创建一个新的 git 仓库&#xff0c;其数据会存放在一个名为 .git 的目录下 git status: 显示当前的仓库状态 git add <filename>: 添加文件到暂存区 git …

aws xray通过设置采样规则对请求进行过滤

参考资料 https://github.com/aws/aws-xray-sdk-pythonpython api reference&#xff0c;https://docs.aws.amazon.com/xray-sdk-for-python/latest/reference/node api reference&#xff0c;https://docs.aws.amazon.com/xray-sdk-for-nodejs/latest/reference/ 初始化环境…

《硬件架构的艺术》笔记(一):亚稳态

同步系统中如果数据和时钟满足建立保持时间的要求&#xff0c;不会发生亚稳态&#xff08;meastable&#xff09;。 异步系统中数据和时钟关系不固定&#xff0c;可能违反建立保持时间&#xff0c;就会输出介于两个有效状态之间的中间级电平&#xff0c;且无法确定停留在中间状…

统信UOS开发环境支持Electron

全面支持Electron开发环境,同时还提供了丰富的开发工具和开发资源,进一步提升工作效率。 文章目录 一、环境部署1. Electron应用开发介绍2. Electron开发环境安装安装Node.js和npm安装electron环境配置二、代码示例Electron开发案例三、常见问题一、环境部署 1. Electron应用…

动手学深度学习68 Transformer

1. Transformer 2. 多头注意力代码 通过不断地reshape&#xff0c;避免forloop操作。 什么样的shape进去&#xff0c;怎样的shape出来。 #save class MultiHeadAttention(nn.Module):"""多头注意力"""def __init__(self, key_size, query_size…

晨控RFID技术助力半导体制造业革新之路

晨控RFID技术助力半导体制造业革新之路 应用背景 随着信息技术的快速发展&#xff0c;无线射频识别技术逐渐成为连接物理世界与数字世界的桥梁。尤其在半导体产业中&#xff0c;RFID技术的应用不仅提升了生产效率&#xff0c;还加强了产品追踪与管理能力&#xff0c;对推动产…

ReactPress:构建高效、灵活、可扩展的开源发布平台

ReactPress Github项目地址&#xff1a;https://github.com/fecommunity/reactpress 欢迎Star。 在当今数字化时代&#xff0c;内容管理系统&#xff08;CMS&#xff09;已成为各类网站和应用的核心组成部分。ReactPress&#xff0c;作为一款融合了现代Web开发多项先进技术的开…