网站域名使用费用,天长网站seo,双鸭山seo,建设网站德州头歌禁止复制解决 必须先下篡改猴#xff01;#xff01;#xff01;#xff01;
头歌复制助手 Educoder Copy Helperhttps://scriptcat.org/zh-CN/script-show-page/1860
Java生成验证码
第1关#xff1a;使用Servlet生成验证码
任务描述 本关任务#xff1a;使用se…
头歌禁止复制解决 必须先下篡改猴
头歌复制助手 Educoder Copy Helperhttps://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 i1;i4;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 contentTypetext/html;charsetUTF-8 languagejava % html head title登录/title /head body form actionloginServlet 用户名 input typetext nameusername br 密 码 input typetext namepassword br 验证码 input typetext nameverifycode idyzm !-- src填servlet的地址就能显示网络上的图片 -- a hrefjavascript:reload()img idyzmImg srccode/ /a br input typesubmit value提交 /form /body script typetext/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;charsetutf-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 typetext/javascript function reloadCode() { var date new Date().getTime(); document.getElementById(code).src %request.getContextPath() %/imageKaptcha?ddate; } /script form actioncheckCaptcha.jsp method post img alt验证码 srcimageKaptcha id codea 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-namemyCaptcha/servlet-name !-- jar中的 KaptchaServlet的路径-- servlet-classcom.google.code.kaptcha.servlet.KaptchaServlet/servlet-class /servlet !--配置kaptcha 校验验证码是否正确的 servlet-- servlet servlet-nameCheckCaptcha/servlet-name servlet-classcom.servlet.CheckCaptchaServlet/servlet-class /servlet servlet-mapping servlet-namemyCaptcha/servlet-name !-- 对于index.jsp中img的src -- url-pattern/imageKaptcha/url-pattern /servlet-mapping !--第三关配置kaptcha 校验验证码的 servlet-- servlet-mapping servlet-nameCheckCaptcha/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;charsetutf-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 contentTypetext/html;charsetUTF-8 languagejava %
html
headtitleTitle/title
/head
body
!--------- Begin ---------script typetext/javascriptfunction reloadCode() {var date new Date().getTime();document.getElementById(code).src %request.getContextPath() %/imageKaptcha?ddate;}
/script
form actioncheckCaptcha.jsp method postimg alt验证码 srcimageKaptcha id codea href javascript:reloadCode();看不清/ainput type text name captchainput 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 启动后终端输出如下截图所示可以看到箭头所指的地方分别是程序所在路径这里运行时的环境和实验平台不一样请用自己在平台的输出进行验证监听的 ipport 以及程序自身的运行输出。值得说明的是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 x86x64MIPSPowerPCARMZ8068000c8051 等等。 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 所做的操作和更改。当然我们也可以选择最下面的 Dont 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, rsprsp 是栈顶指针寄存器此时将 rsp 指向 rbp 也就以为着该函数栈帧正式开始。leave相当于mov rsp, rbp; pop rbp我们可以发现这和函数序言是完全相反的操作不难理解一个函数结束后需要清空自己的栈帧所以采用相反的操作。最后retn相当于pop riprip 是程序指令寄存器也就是下一条要执行的指令所以这里的retn会弹出之前压入栈中的返回地址到 rip 中继续运行保证程序流程的完整运行。 如下截图所示我们来分析下 scanf 函数的汇编指令执行过程这里 IDA 会将 scanf 函数识别为__isoc99_scanf命名中指明了 c 语言版本。先看第一个红框这里是函数的局部变量var_12代表距离 rbp 栈帧寄存器的偏移单位为 byte 可以看到后面函数调用中就是用 rbp 来定位局部变量的。第二个红框包含了 scanf 调用的完整汇编指令首先lea rax, [rbpvar_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 InterfaceABI 而开发和发布的也是 Linux 的主要可执行文件格式。 打开 IDA 在其任意界面按下ctrls会弹出如下截图所示的界面一个 ELF 文件会根据文件内容将文件分为很多个段 segment 接下来我们就根据其展示的内容来简单介绍下 ELF 文件格式。该界面展示的内容从左往右依次是段名、起始地址、结束地址、内存权限、对齐方式。 这里我将根据重要性着重介绍几个段
.plt 实现程序函数链接 lazy 加载的段里面存储的是跳转到 .got 表地址的代码 .text 之前我们介绍的汇编指令都处于该段中也就是说 .text 对应程序真正的代码指令 .got 存储真正函数地址的段 .data 程序已经初始化的全局变量 .bss 程序未初始化的全局变量 如下截图所示在 segment 界面我们可以通过点击的方式直接进入到程序的相应段中在该段中我们可以发现一个名为 flag 全局变量该变量是一个字符串。 当然除了上面的方式我们要寻找程序中的字符串也可以使用快捷键shiftf12如下截图所示会跳转到字符串界面我们可以在最下面找到该字符串同样点击它也会跳转到对应段。
编程要求 本课程采用了 CTF 比赛获取 flag 的方式来进行实践练习你的目标是拿到一个 flag 形式为flag{xxxxxxxxxxxxxxx}目标文件为/home/headless/Desktop/workspace/myshixun/pwnPro/step1/目录下的 level1 。 本关没有编程要求但需要你通过逆向分析拿到隐藏在二进制程序中的 flag 后面的课程将需要你利用程序漏洞进行编程获取到 shell 进一步拿到 flag 。
测试说明 将你拿到的 flag 写入到实验环境提供的 flag.txt 文件中然后点击评测即可。
开始你的任务吧祝你成功
flag{you_g0t_m3}