逆向(异或)_reverse异或操作-程序员宅基地

技术标签: 学习  CTF混合  

在学习逆向前我们需要掌握一些汇编的基础知识的
同时我们得知道可执行文件的原理
计算机生成可执行文件,我们大致可以简单的这么理解
1.asm源程序文件
2.asm源程序生成obj也就是目标文件
3.由目标文件链接生成可执行文件,Windows的可执行文件通常是EXE,Linux通常是ELF
而在实际的环境中,计算会选择丢弃部分不要重要,或者自己优化一些信息。
逆向就是需要对这些信息进行还原,同时可以进行破译,也就是游戏开外挂,软件正版却有盗版的存在

test1(静态分析)

首先用查壳工具先看看
在这里插入图片描述
64位,ELF文件
查壳的目的:
1.看加了什么保护没
2.看看是多少位的程序,因为IDA有32和64的版本,必须与之分别对应
逆向基本步骤是使用IDA,对源程序进行反汇编,分析其中的代码

IDA

IDA(Interactive Disassembler)是一款强大的逆向工程工具,常用于分析和反汇编计算机程序。它支持各种平台和体系结构,并提供了丰富的功能和工具,可用于深入研究二进制代码的功能、结构和漏洞。
以下是IDA的一些主要特点和功能:
1.反汇编和分析:IDA能够将二进制文件转换为可读的汇编代码,使用户可以更好地理解程序的内部结构和执行逻辑。它提供了丰富的反汇编视图和分析工具,以帮助用户识别代码块、函数、指令和数据。
2.交互式界面:IDA提供了直观且易于使用的图形用户界面,支持用户与反汇编结果进行交互。用户可以浏览代码、跳转到函数或指令,查看和编辑数据以及设置断点等。
3.反编译器:IDA还提供了反编译功能,可以将汇编代码转换为高级语言表示,如C语言。这可以帮助用户更好地理解程序的功能和逻辑,尤其是对于无法获得源代码的情况。
4.插件和脚本支持:IDA支持各种插件和脚本,用户可以根据需要扩展和定制工具。这使得用户可以编写自己的脚本来自动化任务、添加新的功能或与其他工具集成。
总体而言,IDA是一款功能强大且灵活的逆向工程工具。它被广泛用于恶意软件分析、漏洞研究、软件安全评估和逆向工程等领域,并受到安全专家、软件工程师和研究人员的青睐。
同时IDA可以按F5,生成C/C++代码
以Test1为例子
打开IDA左边这一栏代表的是所用到的函数,当然我们知道C语言是从主函数开始的,所以一般我们先会去看看main函数的样子,当函数少的时候,我们可以直接看到,但是当函数多的时候我们就看不到了,此时我们用Ctr+f的方式可以在左边的篮筐进行搜索
在这里插入图片描述由于这题比较简单,突破口就是main函数
这里需要我们有C语言的基础,仔细看好
每一个变量,每一个函数的逻辑关系
当然由于这道题说了考察异或那我们重点观察异或!!(这里其实已经在汇编、离散数学中学过)

什么是异或

异或(XOR)是一种逻辑运算符,常用于计算机科学和电子工程中。异或操作符通常用符号 “^” 表示。
异或操作的定义如下:
当两个操作数的位值不同时,异或结果为1。
当两个操作数的位值相同时,异或结果为0。
例如,对于两个二进制数1和0进行异或操作:
1 XOR 0 = 1
异或操作还具有以下一些重要性质:
1.结合律:(A XOR B) XOR C = A XOR (B XOR C)
2.交换律:A XOR B = B XOR A
3.自反性:A XOR A = 0
4.零元素:A XOR 0 = A
异或操作在计算机科学中广泛应用,包括数据加密、校验和计算、错误检测和纠错编码等领域。在编程中,异或操作也常用于快速交换变量值、判断奇偶性和重复元素的消除等。

为什么要异或?这道题的思路

根据上面我们现在知道,把密码重复异或两次就会出现成本身,那么这道题的思路:
1,找到匹配的数据
2.将匹配的数据进行二次异或
3.最后得到原来的密码,也就是我们所需要的信息

int __cdecl main(int argc, const char **argv, const char **envp)
{
    
  size_t v3; // rbx
  char s[8]; // [rsp+0h] [rbp-40h] BYREF
  __int64 v6; // [rsp+8h] [rbp-38h]
  __int64 v7; // [rsp+10h] [rbp-30h]
  __int64 v8; // [rsp+18h] [rbp-28h]
  char v9; // [rsp+20h] [rbp-20h]
  int i; // [rsp+2Ch] [rbp-14h]

  *(_QWORD *)s = 0LL;
  v6 = 0LL;
  v7 = 0LL;
  v8 = 0LL;
  v9 = 0;
  puts("Welcome to RE world,Can you solve the problem?");
  printf("Now you should input your flag and i'll tell you if it is right:");
  __isoc99_scanf("%s", s);
  for ( i = 0; ; ++i )
  {
    
    v3 = i;
    if ( v3 >= strlen(s) )
      break;
    s[i] ^= i;   **重点!!!
  }
  if ( (unsigned int)compare(s) )
    puts("Well done! You find the secret!");**根据这里的提示我们看到如果(unsigned int)compare(s)
    成立==1那就说梦成功了,那这里我们在IDA里面点进这个函数看看
  else
    puts("The flag is wrong! Maybe something run before main");
  return 0;

在这里插入图片描述

__int64 __fastcall compare(const char *a1)
{
    
  int i; // [rsp+1Ch] [rbp-4h]

  if ( strlen(a1) != 32 )
  {
    
    puts("The length of flag is Wrong!!");
    exit(0);
  }
  for ( i = 0; i <= 31; ++i )
  {
    
    if ( final[i] != a1[i] )**这里我们看到我们输入的字符串被传输进入了a1[]里面,然后与fianl[]里面的数做了
    一个对比,那其实就是final[]就是加密后的密码,点击进入查看数据
      return 0LL;
  }
  return 1LL;
}

在这里插入图片描述

.data是什么?

学逆向我们还需要懂得一些文件结构的基础,这里我之前有讲过可以去看看下面这篇我写的博客
https://blog.csdn.net/m0_72827793/article/details/130231662
里面讲了PE文件结构,当然这道题是ELF文件结构,但他们都是类似的,都在COFF的基础上

至于db是汇编语言的知识

可以在我博客上的汇编框里面找找

回到刚才

这些数据就是我们需要破译的密码
这里我们需要提取出来选中这些数据
shift+e
在这里插入图片描述
我们选择十六进制转换
在这里插入图片描述
我们把数据提取出来(0X)表示十六进制
0x66, 0x6D, 0x63, 0x64, 0x7F, 0x56, 0x69, 0x6A, 0x6D, 0x7D,
0x62, 0x62, 0x62, 0x6A, 0x51, 0x7D, 0x65, 0x7F, 0x4D, 0x71,
0x71, 0x73, 0x79, 0x65, 0x7D, 0x46, 0x77, 0x7A, 0x75, 0x73,
0x21, 0x62

解密

这里我们可以C语言,也可以用python等一些语言写一个破译的脚本
这里是我写的
在这里插入图片描述
运行即可
在这里插入图片描述

Test2(动态)

学了上面这些,我们再加深一下理解,同时做一个提升
看一下同类型的test2这道题
同样的方式先找到main函数
在这里插入图片描述解析这段

 if ( Size != 38 )**这里判断了输入的数必须是38goto LABEL_22;
  v5 = 0i64;
  v3 = &Buf1;
  do
  {
    
    v6 = &Buf1**给数赋值
    v7 = &Buf1;
    if ( (unsigned __int64)qword_7FF7B8B96C68 >= 0x10 )
      v6 = (void **)Buf1;
    if ( (unsigned __int64)qword_7FF7B8B96C68 >= 0x10 )
      v7 = (void **)Buf1;
    *((_BYTE *)v7 + v5) ^= *((_BYTE *)v6 + v5 + 1);**给数组str[i]^=str[i+1],下面的依次类推分析
    v8 = &Buf1;
    v9 = &Buf1;
    if ( (unsigned __int64)qword_7FF7B8B96C68 >= 0x10 )
      v8 = (void **)Buf1;
    if ( (unsigned __int64)qword_7FF7B8B96C68 >= 0x10 )
      v9 = (void **)Buf1;
    *((_BYTE *)v9 + v5 + 1) ^= *((_BYTE *)v8 + v5 + 2);
    v10 = &Buf1;
    v11 = &Buf1;
    if ( (unsigned __int64)qword_7FF7B8B96C68 >= 0x10 )
      v10 = (void **)Buf1;
    if ( (unsigned __int64)qword_7FF7B8B96C68 >= 0x10 )
      v11 = (void **)Buf1;
    *((_BYTE *)v11 + v5 + 2) ^= *((_BYTE *)v10 + v5 + 3);
    ++v5;
    v4 = Size;
  }
  while ( v5 < Size - 3 );

跟上一题的思路类似,那这里我们要怎么去寻找到那个匹配的数呢?看到后面这一段代码

 v12 = &Buf2;**先看明白下面 
 Size != qword_7FF7B8B96C40 || (v13 = memcmp(v3, v12, Size), v14 = "Right!", v13)
 这个判断,再看这个!
 **此时我们我们便可以知道Buf2就是判断的值
  if ( (unsigned __int64)qword_7FF7B8B96C48 >= 0x10 )
    v12 = (void **)Buf2;
  if ( (unsigned __int64)qword_7FF7B8B96C68 >= 0x10 )
    v3 = (void **)Buf1;
  if ( Size != qword_7FF7B8B96C40 || (v13 = memcmp(v3, v12, Size), v14 = "Right!", v13) )
LABEL_22:
    v14 = "Wrong!";
  sub_7FF7B8B62410(v3, v14, v4);
  return 0;

memcmp函数

在这里插入图片描述

Buf2问题

可以当我们点开buf2发现,这里面啥也没有
在这里插入图片描述**所以我们需要动态调试!!**数据节(data section)是程序的一部分,它存储了静态和全局变量的初始化值。在程序执行过程中,这些变量的值可能会被修改或者被其他操作所影响。因此,通过动态调试,在程序运行时可以实时查看这些变量的当前值,而不仅仅是它们的初始化值。
由于动态调试可以在程序运行时观察和修改内存中的数据,因此可能需要使用动态调试来确认 Buf2 的具体值,以便确定判断条件的结果
其实IDA通常不用于动态调试,IDA一般当作地图来使用,我们通常会选用OD或者X64dgb进行动态调试
这里我们还是讲解一些IDA动态调试
设立断点
在这里插入图片描述在这里插入图片描述选择start process
或者直接按F9即可
输入38个字符

在这里插入图片描述
在看到IDA
在这里插入图片描述
F7步入,F8不过
不过这里当我们执行过
v12 = &Buf2;这条语句时,我们会看到这个
在这里插入图片描述
点击小坐标我们进去看看
在这里插入图片描述
会出现这样的画面,同时我们再点击进入下面箭头所指的部分

在这里插入图片描述
跳转到这样的画面
在这里插入图片描述
如果你不清楚,数据是哪里开始的你可以回到刚才上一页的地方
看到这样的画面
在这里插入图片描述
至于结束会出现在这里,也就是0的前面
在这里插入图片描述
我们再次提取数据,用上一道题讲过的方法
0x0A, 0x0B, 0x7D, 0x2F, 0x7F, 0x67, 0x65, 0x30, 0x63, 0x60,
0x37, 0x3F, 0x3C, 0x3F, 0x33, 0x3A, 0x3C, 0x3B, 0x35, 0x3C,
0x3E, 0x6C, 0x64, 0x31, 0x64, 0x6C, 0x3B, 0x68, 0x61, 0x62,
0x65, 0x36, 0x33, 0x60, 0x62, 0x36, 0x1C, 0x7D,

最后进行解密

这里给出了两个语言写的代码,自行研究一下

#include <stdio.h>
#include <stdlib.h>
int  main()
{
    
	int i=0;
	int str[38]={
     0x0A, 0x0B, 0x7D, 0x2F, 0x7F, 0x67, 0x65, 0x30, 0x63, 0x60, 
   0x37, 0x3F, 0x3C, 0x3F, 0x33, 0x3A, 0x3C, 0x3B, 0x35, 0x3C, 
   0x3E, 0x6C, 0x64, 0x31, 0x64, 0x6C, 0x3B, 0x68, 0x61, 0x62, 
   0x65, 0x36, 0x33, 0x60, 0x62, 0x36, 0x1C, 0x7D};
   int str1[38]={
    0};
   int str2[38]={
    0};
   for(i=0;i<38;i++)
   {
    
   	str1[i]=str[37-i];
   }
    for(i=3;i<38;i++)
    {
    
    	str1[i - 2] ^= str1[i - 3];
        str1[i - 1] ^= str1[i - 2];
        str1[i] ^= str1[i - 1];
	}
	for(i=0;i<38;i++)
	{
    
		str2[i]=str1[37-i];
		printf("%c",str2[i]);
	}
	
   return 0;
 } 

Python注意缩进

 k= [
    0x0A, 0x0B, 0x7D, 0x2F, 0x7F, 0x67, 0x65, 0x30, 0x63, 0x60,
    0x37, 0x3F, 0x3C, 0x3F, 0x33, 0x3A, 0x3C, 0x3B, 0x35, 0x3C,
    0x3E, 0x6C, 0x64, 0x31, 0x64, 0x6C, 0x3B, 0x68, 0x61, 0x62,
    0x65, 0x36, 0x33, 0x60, 0x62, 0x36, 0x1C, 0x7D
   ]
s = k[::-1]
for i in range(3, len(s)):
    s[i - 2] ^= s[i - 3]
    s[i - 1] ^= s[i - 2]
    s[i] ^= s[i - 1]

s=s[::-1]
for i in range(len(s)):
    print(chr(s[i]), end='')

结果
在这里插入图片描述
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_72827793/article/details/131475323

智能推荐

JNI编程示例-程序员宅基地

文章浏览阅读681次。源代码地址:链接:百度网盘 请输入提取码提取码:gtlz一、Demo介绍为了更深入的理解Jni编程知识,我们通过一个简单demo把相关知识用实际代码串起来,会有更清晰的认识。在这个demo中,涉及数组处理、字符串处理、类成员变量访问修改等内容,基本涵盖了常见的用法。 相关介绍 涉及文件 (java代码/xml布局文件) demo界面示例 主界面 点击button进入对应示例 s

Struts2之图书管理系统_用spring整合采用struts2开发的登录程序,实现同样的“图书管理系统”登录功能-程序员宅基地

文章浏览阅读666次。趁着周末,梳理一下前几周学的struts2,回顾起struts2,它和springmvc同是action层的解决方案,讲图书系统的同时,先让我们了解一下三层架构,以SSH框架为例。参考来源:http://blog.csdn.net/inter_peng/article/details/410217271.Action/Service/DAO简介:Action是管理业务(Service)..._用spring整合采用struts2开发的登录程序,实现同样的“图书管理系统”登录功能

yolov8的predict使用方法,更改predict.py的输出结果,输出label的真实坐标,保存图片和txt文档,图片中没有异物生成空的txt文档_yolov8 predict-程序员宅基地

文章浏览阅读1.4w次,点赞23次,收藏135次。更改predict.py的输出结果,输出label的真实坐标,保存图片和txt文档,图片中没有异物生成空的txt文档_yolov8 predict

JAVA线程之Thread类详解-程序员宅基地

文章浏览阅读9.7w次,点赞42次,收藏195次。ss_thread

lynis-程序员宅基地

文章浏览阅读89次。 lynis 是个不错的安全审计工具。 常见用法:lynis -c 逐项手动检查,并在最后给出建议lynis -Q 显式自动扫描,并在最后给出建议lynis -q 静默自动扫描,只给出警告 顺便说下另一个问题,在centos 5下安装lynis出错: ERROR with rpm_check_debug vs depsolve:rpmlib(Fil..._languard network scanner 2.0

## 实现MQTT数据在MySQL上的数据持久化实验_用c# 实现emqx 数据持续化到mysql-程序员宅基地

文章浏览阅读663次。一.硬件连接二.软件部分1.云服务器2.安装宝塔面板在腾讯云上安装宝塔面板:安装SSH 连接工具,安装步骤https://www.bt.cn/bbs/thread-1971-1-1.html,挂载磁盘后(查看),根据系统执行框内命令开始安装(这里我选用的是Ubuntu系统)在云服务中打开端口(入站规则和出站规则都要添加)找到腾讯云公网IP地址,在浏览器中输入该IP地址+端口(这里我采用的是8888端口)3.安装EMQX Cloud在云服务器上安装EMQX Cloud,下载链接:htt_用c# 实现emqx 数据持续化到mysql

随便推点

Python使用递归法和函数式编程计算整数各位之和-程序员宅基地

文章浏览阅读1.5k次。问题描述:给定一个正整数,计算其各位数字之和。参考代码:程序运行无任何输出,表示两个函数结果一致。----------相关阅读----------1900页Python系列PPT分享一:基..._python输入一串正整数折半递归求和

信号采集系统的硬件连接笔记_地开信号采集-程序员宅基地

文章浏览阅读2.3k次,点赞2次,收藏6次。在使用差分或者RSE方式时,由于信号负端不与AIGND连接,放大器的输入偏置电流有可能会使信号电压偏离测量设备的量程范围,所以需要在信号两端与AIGND之间分别加一个偏置电阻,从系统平衡角度而言,建议取等值的两电阻,阻值范围一般在10kΩ和100kΩ之间。无参考地单端(NRSE)连接方式的测量系统是对RSE连接方式的一种变形,各路信号共享一个基准点,而仪用放大器负极正是与这个公共基准点相连的,但并不与系统地相连,所以测得信号是以该基准点作为参考点的电压信号。这样可以实现信号地与系统地之间的隔离。_地开信号采集

sublime text python c++_sublime python中如何用 c++-程序员宅基地

文章浏览阅读810次。1.python/c++指定pathctrl+b编译ctrl+shift+b编译运行2.c++实现控制台输出使用批处理文件。本解决方法以C语言程序为例,编译器是gcc,我下载了MINGW直接解压到C盘根目录下,并设置了相应的PATH。其它编程语言可以按照这个思路适当修改批处理文件。新建两个批处理文件,一个名为runp.bat,内容如下:@ec_sublime python中如何用 c++

python基础——matplotlib——scatter和plot方法中的maker参数(点的样式)_python scatter marker-程序员宅基地

文章浏览阅读2w次,点赞15次,收藏66次。一、scatterscatter方法主要用来做散点图展示,而plot方法主要用来做折线图展示,也可以用于散点图的展示。两个方法的参数基本是通用的。以scatter方法为例,常用参数包括:plt.scatter( ['x', 'y', 's=None', 'c=None', 'marker=None', 'cmap=None', 'norm=None', 'vmin=None', 'vmax=None', 'alpha=None', 'linewidths=None', 'verts=&._python scatter marker

【MQTT协议详解】MQTT协议-程序员宅基地

文章浏览阅读3.2w次,点赞39次,收藏399次。MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于 **发布/订阅** 范式的消息协议。它工作在TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议。 *简而言之,MQTT其实就是一个用于TCP通信的消息协议而已。既然消息协议,"消息" 自然是表示MQTT其实本质就是消息,消息在某种理解上,可以理解报文,报文包,数据等等;既然是协议,自然表示它有着自己的规则,什么叫规则?就是规定这个消息该以怎样的**........_mqtt协议

计算机硬盘各分区名称,电脑分区后修改磁盘名称的方法步骤-程序员宅基地

文章浏览阅读9.7k次。我们新安装的磁盘,分区之后想对磁盘命名,直接修改是不行的,那么怎么解决呢,下面就由学习啦小编给你们介绍电脑分区后修改磁盘名称的方法吧,希望能帮到大家哦!电脑分区后修改磁盘名称的方法:首选我们打开桌面上的“这台电脑”或者计算机,小编是win8系统。然后选择需要修改的磁盘右键并“重命名”,就会出来需要管理员身份怎么办,意思是这边是不能修改的。选择任务栏最又左下角处的“桌面图标”右键,然后选择“磁盘管理..._如何修改电脑磁盘名称