Java生成验证码+动态分析技术+【实训10】HTML信息隐藏(信息安全技术作业)

news2025/7/11 15:13:34

Java生成验证码

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

  • 任务要求
  • 参考答案
  • 评论
  • 任务描述
  • 相关知识
    • 为什么要有验证码,什么是验证码
    • 如何使用Servlet生成验证码
  • 编程要求
  • 测试说明

任务描述

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

相关知识

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

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

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

为什么要有验证码,什么是验证码

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

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

肯定是有道理的。

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

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

如何使用Servlet生成验证码

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

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

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

如下:

servletdoGet()方法中编写代码实现生成图片验证码:

分为如下步骤:

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

  2. 创建图片对象;

  3. 创建绘制工具(Graphics);

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

  5. 使用Graphics绘制图形;

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

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

具体代码如下:

 
  1. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  2. // 使用验证码的步骤
  3. // 定义图片的宽高
  4. int height = 20;
  5. int width = 60;
  6. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  7. // 绘图工具
  8. Graphics graphics = image.getGraphics();
  9. // 绘制矩形
  10. graphics.setColor(getRandColor());
  11. // 绘制矩形背景 前两个参数 是 x y的坐标
  12. graphics.fillRect(0, 0, width, height);
  13. // 设置文字的颜色 为白色
  14. graphics.setColor(Color.WHITE);
  15. String yzm = "";
  16. // 生成四个随机数字并且画在图片上
  17. for (int i = 1; i <= 4; i++) {
  18. // 生成随机数字并且显示到页面上
  19. int number = new Random().nextInt(10);
  20. yzm += number;
  21. graphics.drawString(number + "", 10 * i, 10);
  22. }
  23. // 将验证码放入Httpsession中
  24. HttpSession session = req.getSession();
  25. session.setAttribute("sessionYzm", yzm);
  26. // 将验证码图片输出到客户端
  27. ImageIO.write(image, "jpg", resp.getOutputStream());
  28. }
  29. // 获取随机颜色
  30. private Color getRandColor() {
  31. int red = new Random().nextInt(255);
  32. int green = new Random().nextInt(255);
  33. int blue = new Random().nextInt(255);
  34. return new Color(red, green, blue);
  35. }

编程要求

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保存的验证码信息和用户提交的验证码数据进行校验如果两者一致则校验通过。

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

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

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

前端实现

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

 
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>登录</title>
  5. </head>
  6. <body>
  7. <form action="loginServlet">
  8. 用户名:
  9. <input type="text" name="username">
  10. <br>
  11. 密 码:
  12. <input type="text" name="password">
  13. <br>
  14. 验证码:
  15. <input type="text" name="verifycode" id="yzm">
  16. <!-- src填servlet的地址就能显示网络上的图片 -->
  17. <a href="javascript:reload()"><img id="yzmImg" src="code"/> </a>
  18. <br>
  19. <input type="submit" value="提交">
  20. </form>
  21. </body>
  22. <script type="text/javascript">
  23. //重新加载验证码
  24. function reload() {
  25. var img = document.getElementById("yzmImg");
  26. img.src = "code?" + new Date().getTime();
  27. }
  28. </script>
  29. </html>

效果如下:

后端校验

前端页面写好之后我们就可以验证在后端编写代码来验证,表单传递过来的参数是否正确了。

步骤如下:

  1. 接收用户传递的参数:username,password,verifycode

  2. 判断验证码是否正确;

  3. 如果验证码正确则判断用户名和密码是否正确。否则提示客户端验证码错误;

  4. 用户名密码正确,回传给客户端“登录成功”。

校验验证码的核心代码如下:

编程要求

好了,该你啦,使用本关所学内容,完成登录的校验,具体要求如下:

  • 首先实现验证码校验的功能,当验证码填写错误的时候,给前端返回数据“验证码错误”;

  • 当用户名为admin,密码为admin123时可以登录成功,返回“登录成功”,其他情况返回“登录失败”;

  • 前端页面已经编写完成,你需要编写的是后端代码。

测试说明

本次实训使用的是junit+cactus框架进行测试,所有测试集通过即算通关。


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

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 {
@Override    
protected 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 verifycode=req.getParameter("verifycode");
String username=req.getParameter("username");
String password=req.getParameter("password");
HttpSession session =req.getSession();
String realCode=(String)session.getAttribute("sessionYzm");
if(username.equals("admin")&&password.equals("admin123")&&verifycode.equals(realCode)){
 writer.write("登录成功");}
else if(!verifycode.equals(realCode)){   
 writer.write("验证码错误");}
else if(verifycode.equals(realCode)){    
writer.write("验证码正确");
}    else{       
 writer.write("登录失败");    }
 /********* Begin *********/    
}     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {       
 doGet(req,resp);    }
}


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

  • 任务要求
  • 参考答案
  • 评论
  • 任务描述
  • 相关知识
    • Kaptcha 组件的使用
  • 编程要求

任务描述

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

相关知识

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

Kaptcha 组件的使用

先来看要实现的效果:

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

 
  1. <script type="text/javascript">
  2. function reloadCode() {
  3. var date = new Date().getTime();
  4. document.getElementById("code").src = "<%=request.getContextPath() %>/imageKaptcha?d="+date;
  5. }
  6. </script>
  7. <form action="checkCaptcha.jsp" method = "post">
  8. <img alt="验证码" src="imageKaptcha" id = "code"><a href = "javascript:reloadCode();">看不清</a>
  9. <input type = "text" name = "captcha">
  10. <input type = "submit" value = "submit">
  11. </form>

接着我们写一个检查验证码输入是否正确的类checkCaptchaServlet.java

 
  1. request.setCha\fracterEncoding("utf-8");
  2. // 获取Kaptcha jar包里面的KAPTCHA_SESSION_KEY
  3. String trueCaptcha = (String)session.getAttribute(Constants.KAPTCHA_SESSION_KEY);
  4. String inputCaptcha = request.getParameter("captcha");
  5. if(trueCaptcha.toLowerCase().equals(inputCaptcha.toLowerCase())) {
  6. out.write("验证码输入正确");
  7. } else {
  8. out.write("验证码输入错误");
  9. }

然后配置好web.xmlok了。下面我们来看看怎么配置web.xml

 
  1. <servlet>
  2. <servlet-name>myCaptcha</servlet-name>
  3. <!-- jar中的 KaptchaServlet的路径-->
  4. <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
  5. </servlet>
  6. <!--配置kaptcha 校验验证码是否正确的 servlet-->
  7. <servlet>
  8. <servlet-name>CheckCaptcha</servlet-name>
  9. <servlet-class>com.servlet.CheckCaptchaServlet</servlet-class>
  10. </servlet>
  11. <servlet-mapping>
  12. <servlet-name>myCaptcha</servlet-name>
  13. <!-- 对于index.jsp中img的src -->
  14. <url-pattern>/imageKaptcha</url-pattern>
  15. </servlet-mapping>
  16. <!--第三关:配置kaptcha 校验验证码的 servlet-->
  17. <servlet-mapping>
  18. <servlet-name>CheckCaptcha</servlet-name>
  19. <url-pattern>/checkCaptcha</url-pattern>
  20. </servlet-mapping>

做完上述步骤之后,运行项目,打开网页,即可查看验证码。

输入正确的验证码点击submit

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

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

编程要求

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

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

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


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

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;
public class CheckCaptchaServlet extends HttpServlet { 
 @Override   
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {      
  req.setCharacterEncoding("utf-8");      
  resp.setContentType("text/html;charset=utf-8");
 /********* Begin *********/      
  //校验kaptcha 验证码是否正确     
   //获取Kaptcha jar包里面的KAPTCHA_SESSION_KEY   
 //    request.setCha\fracterEncoding("utf-8");    
HttpSession session=req.getSession();
String trueCaptcha=(String)session.getAttribute(Constants.KAPTCHA_SESSION_KEY);       PrintWriter out=resp.getWriter();     
  String inputCaptcha=req.getParameter("captcha");
 if(trueCaptcha.toLowerCase().equals(inputCaptcha.toLowerCase())){       
 out.write("验证码输入正确");       
}else{          
 out.write("验证码输入错误");     
  }
  /********* End *********/  
  }
 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException {       
 doGet(req, resp);
 }
 }

动态分析技术

第1关:动态分析技术

  • 任务要求
  • 评论
  • 任务描述
  • 相关知识
    • 程序分析
    • 动态调试器 qira
      • 什么是 qira
      • qira 的基本使用
      • 使用 qira 找到 flag
  • 编程要求
  • 测试说明

任务描述

本关任务:

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

相关知识

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

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

程序分析

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

 
  1. cd /home/headless/Desktop/workspace/myshixun/pwnPro/step2/
  2. ls -all demo
  3. chmod +x demo
  4. ./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 启动程序,整个过程如下命令所示。

 
  1. cd /home/headless/Desktop/wordspace/myshixun/pwnPro/step2/
  2. 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 文件中,然后点击评测即可。


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

打开终端 

cd /home/headless/Desktop/workspace/myshixun/pwnPro/step2/
vim flag.txt

按i,输入flag{Y0u_Are_Great},按Esc再:wq保存退出即可

 

第1关:HTML信息隐藏

  • 任务要求

步骤1:

选择载体HTML文件,位于data/workspace/myshixun/xxaqcenter.html 用编辑器打开xxaqcenter.html这个文件

步骤2:

在上述的HTML 文件中隐藏 I LOVE YOU ,将I LOVE YOU 转换成ASCII码二进制形式为:01001001 01001100 01001111 01010110 01000101 01011001 01001111 01010101

步骤3:选择隐藏方法

(1)利用标记中属性赋值号“=”左右添加空格来隐藏信息。以左右都无空格表示00,左无右有空格表示01,左有右无空格表示10,左右均有空格表示11,则一个属性赋值可隐藏2bit信息。 (2)标记名称(除<p></p>外)字母全部大写代表1,全部小写代表0。这样一个标记名称可隐藏1bit信息。 (3)属性字母的大写代表1,小写代表0。这样一个属性名称可隐藏1bit信息。 (4)在网页结束标记</html>后或者在每行的行尾插入空格或Tab键隐藏信息,插入一个空格代表0,插入一个Tab代表1.

步骤4:对比隐藏效果

修改HTML文本内容后

浏览隐写前与隐写后的页面效果

从两幅图可以看出,在视觉上没有任何差别,而实际上已经隐藏了秘密信息。在本实训中,通过设计的信息隐藏方法,成功的将I LOVE YOU隐写在选择的HTML文件中,并且使得页面浏览效果与之前没什么不同。

解:隐写前:

 隐写后:

 ASCII码二进制形式为:01001001 01001100 01001111 01010110 01000101 01011001 01001111 01010101

再结合隐藏信息的方法即可写出

(1)利用标记中属性赋值号“=”左右添加空格来隐藏信息。以左右都无空格表示00,左无右有空格表示01,左有右无空格表示10,左右均有空格表示11,则一个属性赋值可隐藏2bit信息。

(2)标记名称(除<p></p>外)字母全部大写代表1,全部小写代表0。这样一个标记名称可隐藏1bit信息。

(3)属性字母的大写代表1,小写代表0。这样一个属性名称可隐藏1bit信息。

(4)在网页结束标记</html>后或者在每行的行尾插入空格或Tab键隐藏信息,插入一个空格代表0,插入一个Tab代表1.

也不必过于纠结过程,将1.sh中400改为200即可过评测!!!

按i,400改为200,Esc,再:wq保存

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

硬链接及软连接引出的inode

inode定义 inode是linux系统中用作数据索引的标识符。简单来说&#xff0c;inode指示了一个文件的基本信息&#xff0c;如inode编号、修改时间、文件的位置等。 如同一本书的目录&#xff0c;会直接告诉你想看的章节是在第几页。不同的是&#xff0c;书是以页为单位的&#x…

软考 - 数据结构与算法

数据结构 线性结构 线性表 存储结构 顺序存储&#xff1a;用一组地址连续的存储单元 依次存储线性表中的数据元素&#xff0c;使得逻辑上相邻的元素物理上也相邻。 链式存储&#xff1a;存储各数据元素的结点的地址并不要求是连续的&#xff0c;数据元素逻辑上相邻&#xff…

提升Mac运行速度的三大方法

任何一部电子设备在使用多年之后都会出现性能下降的问题&#xff0c;苹果的Mac计算机自然也不例外。当你发现Mac运行缓慢&#xff0c;因为有太多文件或缓存垃圾将Mac的运行速度拖了下来。 要想提高生活和工作效率&#xff0c;必须对Mac进行优化&#xff0c;提升一下Mac 的使用性…

全业务链管理平台Odoo

什么是 Odoo ? Odoo 是一款非常容易使用又完全集成的商业应用&#xff0c;是一站式全业务链管理平台。 docker cli 安装 本项目涉及到 2 个容器&#xff0c;之前我们在下面&#x1f447;这些文章中 开源的看板管理工具Wekan类Trello的看板软件Planka群晖上安装MediaWiki的简…

linux系统java环境变量的下载与安装

由于目前好多工具的安全使用需要安装java环境&#xff0c;所有今天就分享一下java环境变量的安装与配置下载地址&#xff1a; https://download.oracle.com/otn/java/jdk/8u351-b10/10e8cce67c7843478f41411b7003171c/jdk-8u351-linux-i586.tar.gz?AuthParam1668564371_517fa4…

【2022.11.16】Lammps+Python+MATLAB在绘制维诺图时遇到的问题

目录写在前面绘制g6(r)执行步骤问题1&#xff1a;数据导入问题2&#xff1a;利用Python选取想要的数据问题3&#xff1a;如何找到每个点的最近邻问题4&#xff1a;绘制维诺图写在前面 记录一下做毕设时候遇到的问题 大目标是绘制g6的图片 相关文章&#xff1a; [1] Zu M , Li…

艾美捷可电离脂质SM-102解决方案

艾美捷SM-102是一种用于脂质纳米颗粒&#xff08;LNP&#xff09;的可电离脂质。LNP组合物已被证明有效地作为生物活性物质如小分子药物、蛋白质和核酸的运输载体进入细胞和/或细胞内隔室。这是一种试剂级产品&#xff0c;仅供研究使用。 艾美捷SM-102基本参数&#xff1a; 类…

企业管理 - 波司登战略管理解析

波司登战略管理解析 领导人讲话&#xff0c;视频&#xff1a;国家的战略&#xff0c;建设有中国特色的社会主义 这是一个文化大过滤时代&#xff1a;从宏观来讲&#xff0c;大的社会环境&#xff0c;包括现象&#xff0c;反腐&#xff0c;教育改革&#xff0c;把中华民族优秀…

Go(八)函数

目录 1. 函数 1.1 函数定义 1.2 函数的调用 1.3 参数 1.3.1 类型简写 1.3.2 可变参数 1.4 返回值 1.4.1 多返回值 1.4.2 返回值命名 1.4.3 返回值补充 2. 函数进阶 2.1 变量作用域 2.1.1 全局变量 2.1.2 局部变量 2.2 函数类型与变量 2.2.1 定义函数类型 2.2.…

FL Studio21免许可证完整版数字音频工作站(DAW)

如果你一直梦想制作自己的音乐(无论是作为一名制作人还是艺术家)&#xff0c;你可能会想你出生在这个时代是你的幸运星。这个水果圈工作室和上一版之间的改进水平确实令人钦佩。这仅仅是FL Studio 21所提供的皮毛。你的音乐项目的选择真的会让你大吃一惊。你以前从未有过这样的…

K3s离线部署

下载离线镜像包 离线镜像包下载地址 因为我的环境是CentOS 7.7&#xff0c;所以下载红框里的两个 下载部署脚本 部署脚本下载地址&#xff08;https://get.k3s.io&#xff09; 将准备好的文件上传到服务器上后&#xff0c;将k3s二进制文件及镜像包放到指定目录&#xff08;每…

大数据在线实习项目能收获什么呢?

大数据在线实习项目提供在线大数据项目&#xff0c;参与真实企业项目&#xff0c;可提供实习证明。 项目实习过程会根据项目背景、项目目标、项目数据来逐一展开&#xff0c;一个项目的项目周期大概为4周时间&#xff0c;同时也可以根据自身时间条件来调整。 项目涉及多方面知识…

CSC公派|高职院校教师赴澳大利亚大学访学

L老师只是高职院校护理与助产学专业教师&#xff0c;硕士学位&#xff0c;却能在众多申请者中脱颖而出&#xff0c;一举中榜。原因之一是接收学校专门设有护理与助产学院且排名靠前&#xff0c;导师的研究方向和L老师高度相符&#xff0c;在访学的必要性、可行性及应用前景上占…

线路测量通用公式的推导及编程

wyqzm网友&#xff1a; 问几个问题1、点到中线的垂距计算公式是怎么推导出来的&#xff0c;就是那个S&#xff1d;&#xff08;XA-XB&#xff09;SIN....我怎么也看不明白这是一个什么样的公式&#xff1f;别笑话哦&#xff01; 2、假如一条线路有很多的曲线组合&#xff0c;怎…

振弦采集模块UART 通讯协议

振弦采集模块UART 通讯协议 UART 接口支持标准的工业 MODBUS 通讯协议&#xff08; 03、 04、 06、 16 指令码&#xff09;和自定义的简单 AABB协议以及$字符串指令集。 前两种协议均支持基于模块地址和总线连接的一主多从应用结构&#xff0c; 在总线中&#xff0c; VMXXX 模…

记一次攻防演练之vcenter后渗透利用

1. 说明 很早之前的一次攻防演练&#xff0c;主要是从web漏洞入手&#xff0c;逐渐学习vcenter后利用技术。过程由于太长&#xff0c;很多细节都省略了&#xff0c;中间踩坑、磕磕绊绊的地方太多了。。。 由于敏感性&#xff0c;很多地方都是打码或者是没有图&#xff0c;按照…

synchronized关键字

多线程编程中&#xff0c;最让人头疼的问题莫过于线程安全&#xff0c;如果对存在线程安全问题的代码不加以处理&#xff0c;可能会带来严重的后果&#xff0c;例如用两个线程对同一个变量进行增加操作 class Counter {//这个 变量 是两个线程要去自增的变量public int count;…

进程调度算法详解

进程调度算法&#x1f3de;️1. 调度指标&#x1f301;2. 先进先出&#xff08;FIFO&#xff09;&#x1f320;3. 最短作业优先&#xff08;SJF&#xff09;&#x1f30c;4. 最短剩余时间优先&#xff08;STCF&#xff09;&#x1f33f;5. 新度量指标&#xff1a;响应时间&…

linux网络编程(四)多路I/O转接服务器

文章目录1.多路I/O转接服务器2.select 方式的多路I/O转接服务器3.poll 方式的多路I/O转接服务器4.epoll 方式的多路I/O转接服务器1.多路I/O转接服务器 多路IO转接服务器也叫做多任务IO服务器。该类服务器实现的主旨思想是&#xff0c;不再由应用程序自己监视客户端连接&#xf…

利用stream实现行政区域列表转tree树形结构

一、数据结构 CREATE TABLE t_districts (adcode bigint NOT NULL COMMENT 主键(区域编码)\r\n,pid varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT 父级区域编码,name varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci D…