当前位置: 首页 > news >正文

头歌网络安全(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}

相关文章:

头歌网络安全(11.12)

头歌禁止复制解决 必须先下篡改猴&#xff01;&#xff01;&#xff01;&#xff01; 头歌复制助手 Educoder Copy Helperhttps://scriptcat.org/zh-CN/script-show-page/1860 Java生成验证码 第1关&#xff1a;使用Servlet生成验证码 任务描述 本关任务&#xff1a;使用se…...

洛谷 P1725 琪露诺(线段树优化dp)

题目链接 https://www.luogu.com.cn/problem/P1725 思路 我们令 d p [ i ] dp[i] dp[i]表示琪露诺移动到第 i i i个格子时能够获得的最大冰冻指数。 显然&#xff0c;状态转移方程为&#xff1a; d p [ i ] m a x ( d p [ i ] , d p [ k ] a [ i ] ) dp[i] max(dp[i],dp…...

【LeetCode】【算法】19. 删除链表的倒数第N个结点

LeetCode 19. 删除链表的倒数第N个结点 题目描述 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 思路 思路&#xff1a;快慢指针&#xff0c;快指针先移动n步&#xff0c;快慢指针再同时移动直到快指针到达链表末尾&#xff0c;此…...

Python爬虫 | 爬取豆瓣电影Top250的数据

简单记录一下&#xff0c;实现爬取豆瓣电影Top 250的数据。 这里我使用requests库来发送HTTP请求&#xff0c;以及BeautifulSoup库来解析HTML页面。 1.安装requests和BeautifulSoup库。 如果没有安装&#xff0c;可以通过以下命令安装&#xff1a; pip install requests bea…...

mac 中python 安装mysqlclient 出现 ld: library ‘ssl‘ not found错误

1. 出现报错 2. 获取openssl位置 brew info openssl 3. 配置环境变量&#xff08;我的是在~/.bash.profile&#xff09; export LDFLAGS"-L/opt/homebrew/Cellar/openssl3/3.4.0/lib" export CPPFLAGS"-I/opt/homebrew/Cellar/openssl3/…...

完全清除:苹果手机照片怎么彻底删除

在使用iPhone的过程中&#xff0c;由于拍摄积累的照片往往会占用大量存储空间。有时候&#xff0c;我们需要彻底删除这些照片以释放空间或保护隐私。苹果手机照片怎么彻底删除&#xff1f;在此&#xff0c;本文将与你分享一些实用的技巧。 彻底删除的重要性 彻底删除照片不仅涉…...

高德地图多个图片组成标点(自定义点标记内容)

图标的实现自定义点标记内容...

02-1_MVCC版本链清理

MVCC-版本链清理 文章目录 MVCC-版本链清理简介依赖机制Purge 操作的触发时机版本链清理的详细过程示例操作流程延迟清理配置和监控总结 简介 MySQL 中的 MVCC 机制通过版本链来管理数据的多版本存储&#xff0c;以支持高并发的读写操作。然而&#xff0c;随着事务的进行&…...

探索Python视频处理的瑞士军刀:ffmpeg-python库

文章目录 **探索Python视频处理的瑞士军刀&#xff1a;ffmpeg-python库**第一部分&#xff1a;背景介绍第二部分&#xff1a;ffmpeg-python库是什么&#xff1f;第三部分&#xff1a;如何安装ffmpeg-python库&#xff1f;第四部分&#xff1a;简单库函数使用方法1. 视频转码2. …...

进程间通信 - 通道

进程间通信 - 通道 什么是管道&#xff1f; 进程间的通信方式有五种&#xff0c;分别为:管道、信号量、共享内存、消息队列和套接字。 管道:本质上就是一个文件&#xff0c;前面的进程以写方式打开文件&#xff0c;后面的进程以读方式打开。这样前面写完后面读&#xff0c;于…...

华为数通HCIA系列第5次考试-【2024-46周-周一】

文章目录 1、子网掩码有什么作用&#xff0c;和IP地址是什么关系&#xff0c;利用子网掩码可以获取哪些信息&#xff1f;2、已知一个IP地址是192.168.1.1&#xff0c;子网掩码是255.255.255.0&#xff0c;求其网络地址3、已知某主机的IP地址是192.168.100.200&#xff0c;子网掩…...

【Linux】如何通过终端命令查看当前可用网络 WIFI + 设置已配置网络的连接优先级 + 连接/断连网络

【Linux】通过命令行&#xff0c;查看当前可用网络 WIFI 设置已配置网络的连接优先级 连接网络 列出所有可连接网络 nmcli device wifi list这个命令会列出所有可连接 wifi&#xff0c;*表示当前连接。 IN-USE BSSID SSID MODE CHAN …...

华为路由策略配置

一、AS_Path过滤 要求&#xff1a; AR1与AR2、AR2与AR3之间建立EBGP连接 AS10的设备和AS30的设备无法相互通信 1.启动设备 2.配置IP地址 3.配置路由器的EBGP对等体连接&#xff0c;引入直连路由 [AR1]bgp 10 [AR1-bgp]router-id 1.1.1.1 [AR1-bgp]peer 200.1.2.2 as-nu…...

Debezium日常分享系列之:异步 Debezium 嵌入式引擎

Debezium日常分享系列之&#xff1a;异步 Debezium 嵌入式引擎 动机目标非目标保留Kafka Connect模型计划的更改线程池并行运行源任务存储偏移量并发处理CDC事件禁用CDC事件的完全排序自定义记录处理器并行处理记录的选项存储偏移量引擎状态和生命周期防止资源泄漏异常处理退出…...

leetcode206. Reverse Linked List

Given the head of a singly linked list, reverse the list, and return the reversed list. 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 思路一:双指针 class Solu…...

【MATLAB源码-第291期】基于matlab的AMI编码解码系统仿真,输出各个节点波形。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 AMI&#xff08;Alternate Mark Inversion&#xff0c;交替极性反转&#xff09;是一种广泛使用的编码方法&#xff0c;尤其是在通信系统中&#xff0c;用于传输二进制数据。AMI编码的特点是在传输过程中&#xff0c;对于0信…...

springboot苍穹外卖实战:十一:复盘总结

近期在整理草稿区&#xff0c;故放出此贴。 server模块需要导入对common模块的依赖 <dependency><groupId>org.example</groupId><artifactId>sky-common</artifactId><version>1.0-SNAPSHOT</version></dependency>我现在有个…...

基于Python的药房管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…...

chat2db数据库图形化工具

数据库图形化工具 DataGrip&#xff1a;由 JetBrains 公司开发&#xff0c;是开发者中广为人知的数据库管理工具&#xff0c;功能强大且支持多种数据库。DBeaver&#xff1a;一款开源的数据库管理工具&#xff0c;虽然相对 DataGrip 知名度稍低&#xff0c;但在开发者社区中也…...

弱口令整改方案:借助双因子认证加强账号密码安全

弱口令整改方案可借助宁盾 2FA双因子身份认证来解决。双因子认证&#xff08;也称双因素身份认证&#xff09;是一种安全认证机制&#xff0c;通过结合两个及以上不同的身份验证因子&#xff0c;提高企业用户在办公、研发、生产、运维场景下的的账号密码安全性。它可以有效防止…...

动态代理的优势是什么?

在数据采集的世界里&#xff0c;效率和稳定性是衡量代理IP服务优劣的关键指标。动态代理&#xff0c;作为一种高效的网络工具&#xff0c;正逐渐成为企业和开发者的首选。今天&#xff0c;我们就来聊聊动态代理的优势&#xff0c;以及它如何成为数据采集的高效之选。 动态代理…...

将大型语言模型(如GPT-4)微调用于文本续写任务

要将大型语言模型&#xff08;如GPT-4&#xff09;微调用于文本续写任务&#xff0c;构造高质量的训练数据至关重要。以下是如何构造训练数据的详细步骤&#xff1a; 1. 数据收集&#xff1a; 多样性&#xff1a; 收集多种类型的文本&#xff0c;包括小说、新闻、论文、博客等…...

引入了JUnit框架 却报错找不到:java.lang.ClassNotFoundException

完整报错如下&#xff1a; Internal Error occurred. org.junit.platform.commons.JUnitException: TestEngine with ID junit-jupiter failed to discover tests at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrc…...

深度学习:tensor的定义与维度

tensor的定义与维度 Tensor的定义与维度 Tensor是一个多维数组&#xff0c;用于在一般化的n维空间中表示数据和操作。在深度学习框架中&#xff0c;如TensorFlow或PyTorch&#xff0c;Tensor是基础数据结构&#xff0c;用来存储输入、输出、权重等信息。下面是Tensor不同维度…...

基于Python的膳食健康系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…...

FFmpeg 4.3 音视频-多路H265监控录放C++开发十三:将AVFrame转换成AVPacket。视频编码原理.编码相关api

前提&#xff1a; 从前面的学习我们知道 AVFrame中是最原始的 视频数据&#xff0c;这一节开始我们需要将这个最原始的视频数据 压缩成 AVPacket数据&#xff0c; 我们前面&#xff0c;将YUV数据或者 RGBA 数据装进入了 AVFrame里面&#xff0c;并且在SDL中显示。 也就是说&…...

算法——移除元素(leetcode27)

对于移除元素这道题来讲,我首先想到的还是双指针&#xff0c;根据题目要求我们需要在给定的一组数组中找出与目标值不同的元素数量并且将与目标值不同的元素全部移至数组左边右边则不需关注数组元素的大小&#xff0c;我们利用两个指针一个指向数组首部位置&#xff08;左指针&…...

『OpenCV-Python』安装以及图像的读取、显示、保存

点赞 + 关注 + 收藏 = 学会了 OpenCV 是一个开源的计算机视觉库,广泛应用于图像处理、机器学习和实时计算机视觉应用。比如图像和视频的滤镜和降噪、物体检测、人脸识别、证件号识别、车牌识别等应用。当然,也有其他工具可以对这些领域做支持,但本专栏是介绍 OpenCV 的,所…...

python开发桌面应用(跨平台) 全流程

前言 之前开发一些软件,亚马逊商品分析相关软件,但是基本上是通过程序猿控制台命令启动,同时在启动之前,还要进行程序依赖包,这对于非开发人员而言,简直是一种灾难, 为了让软件对于小白更加易用, 打算将其封装成应用程序(跨平台), 下面带大家一起完成python开发桌面应用的三步…...

el-table-column prop值根据数组获取

方法一&#xff1a; 可以给el-table-column添加一个属性&#xff1a;formatter&#xff0c;代码如下&#xff1a; 这里是因为多个列都需要同样的计算&#xff0c;所以使用column.property获取属性&#xff0c;不然可以直接row.属性 方法二&#xff1a; 直接在template scope …...

宜宾seo网站建设/网络推广优化是干啥的

2019独角兽企业重金招聘Python工程师标准>>> 我之前发布了关于java.lang.Object类及其方法的一系列文章。在介绍了Object之后&#xff0c;我们又探究了clone()和euqals()方法。在这篇文章中&#xff0c;我们将继续讨论Object中的finalize()、getClass()和hashCode()…...

可以做策略回测的网站/网络推广与推广

前期更新笔记内容&#xff1a; Web API 基本认知 / 获取DOM元素 / 设置/修改DOM元素内容和元素属性 / 定时器-间歇函数 / 事件基础 / 高阶函数/环境对象 学过了以上内容&#xff0c;今天我们来做一个综合的案例&#xff1a;Tab栏切换需求&#xff1a;点击不同的选项卡&…...

wordpress隐藏图片链接/市场营销八大营销模式

关闭:autocomplete“off” 打开:autocomplete“on”...

有那种做拼贴的网站吗/行业关键词搜索量排名

每个孩子都曾撒过谎&#xff01;面对撒谎的孩子&#xff0c;家长常说&#xff1a;说实话&#xff0c;这件事就不怪你。而当孩子说出真相&#xff0c;家长又会说&#xff1a;我就知道你刚刚在撒谎&#xff01;不得不说&#xff0c;面对孩子撒谎的问题&#xff0c;家长不管是在认…...

啥十小企业网站建设/网站测试的内容有哪些

丁基胺氢溴酸盐名称 中文名 丁基胺氢溴酸盐 英文名 butan-1-amine,hydrobromide 英文别名 n-butylamine hydrobromide 3-bromopropan-1-amine hydrobromide butylamine hydrobromide n-butylammonium bromide n-butylammonium hydrobromide 丁基胺氢溴酸盐物理化学性质 分子式 …...

酒店房产网站建设/企业关键词优化最新报价

2019独角兽企业重金招聘Python工程师标准>>> 《无缘社会》读书笔记及读后感范文2100字&#xff1a; 前几天又看了一本超级丧的书&#xff1a;《无缘社会》&#xff0c;这书到底有多丧呢&#xff0c;这么说吧。我和一个在日本生活多年的大学同学聊这事儿&#xff0c;…...