BUUCTF SimpleRev(涉及大小端序存储的问题)

本文通过一道CTF逆向题目,介绍了大端序和小端序的概念,并详细解析了如何利用IDAPro进行分析。作者通过分析汇编代码,理解了字符串处理、加密解密函数,并最终通过编写脚本得到解密后的flag。过程中涉及的关键技术包括字符串操作、ASCII码转换、加密算法逆向及C语言脚本编写。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

**

逆向reverse小白一枚,欢迎各位师傅指出不足之处。

buuctf-SimpleRev

**

考点:大端序,小端序,分析伪代码

做这道题的时候遇到了一个新的知识点,大端序和小端序。
在这里插入图片描述

用Exeinfo PE打开
在这里插入图片描述
发现是64位的,无壳。然后用IDA pro64位打开

shift + F12 查看字符串窗口
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ctrl + X 交叉引用

在这里插入图片描述
F5反汇编。
在这里插入图片描述
将100、68、113、83,R字符转换为ASCLL码。
在这里插入图片描述
看到有一个Decry()函数。
打开之后,代码如下:
在这里插入图片描述

unsigned __int64 Decry()
{
char v1; // [rsp+Fh] [rbp-51h]
int v2; // [rsp+10h] [rbp-50h]
int v3; // [rsp+14h] [rbp-4Ch]
int i; // [rsp+18h] [rbp-48h]
int v5; // [rsp+1Ch] [rbp-44h]
char src[8]; // [rsp+20h] [rbp-40h]
__int64 v7; // [rsp+28h] [rbp-38h]
int v8; // [rsp+30h] [rbp-30h]
__int64 v9; // [rsp+40h] [rbp-20h]
__int64 v10; // [rsp+48h] [rbp-18h]
int v11; // [rsp+50h] [rbp-10h]
unsigned __int64 v12; // [rsp+58h] [rbp-8h]

v12 = __readfsqword(0x28u);
*(_QWORD *)src = 357761762382LL;
v7 = 0LL;
v8 = 0;
v9 = 512969957736LL;
v10 = 0LL;
v11 = 0;
text = (char *)join(key3, &v9);
strcpy(key, key1);
strcat(key, src);
v2 = 0;
v3 = 0;
getchar();
v5 = strlen(key);
for ( i = 0; i < v5; ++i )
{
if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
key[i] = key[v3 % v5] + 32;
++v3;
}
printf(“Please input your flag:”, src);
while ( 1 )
{
v1 = getchar();
if ( v1 == 10 )
break;
if ( v1 == 32 )
{
++v2;
}
else
{
if ( v1 <= 96 || v1 > 122 )
{
if ( v1 > 64 && v1 <= 90 )
str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
}
else
{
str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
}
if ( !(v3 % v5) )
putchar(32);
++v2;
}
}
if ( !strcmp(text, str2) )
puts(“Congratulation!\n”);
else
puts(“Try again!\n”);
return __readfsqword(0x28u) ^ v12;
}
在这里插入图片描述
将src 和 v9 的数据转为十六进制,快捷键H。
在这里插入图片描述
可以看到这里的两个十六进制是大端序,但是数据在内存中都是小端序,所以要将其,反转一下。一般在CPU,x86都是小端序,但是IDA将之转换为了大端序。
在这里插入图片描述
先快捷键R 将其转为字符。再反转,所以src = NDCLS , v9 = hadow 。
在这里插入图片描述
key3已经告诉,key3 = kills 。
再看这有一个join函数,它的作用是以指定的字符连接成一个新的字符串。此处是将key3 和 v9 连接成一个新的字符串。
在这里插入图片描述

即text = killshadow。
在这里插入图片描述
strcpy(key, key1); //复制函数,将key1的字符串复制给key,
在这里插入图片描述
key1 = ADSFK, 所以key = ADSFK
strcat函数,是将key 和 src 拼接在一起的函数, 所以key = ADSFKNDCLS。
在这里插入图片描述
看到v5 = strlen(key),strlen是计算字符串的长度,所以v5 = 10 。
再看这个for循环语句,先将64,90变为字符。为
在这里插入图片描述
再对照ASCLL码表,
在这里插入图片描述
如果key3【v3 % v5】是大写字母,则把它变为小写字母。大小写字母的ASCLL码,相差32。
在这里插入图片描述
再将下面的数字变为ASCLL码字符。
在这里插入图片描述
看到最下面的if语句,如果!strcmp(text ,str2),则正确,strcmp函数,是比较函数,如果两个字符串相同,则等于0,所以text = str2才成功。

而得到str2的关键就是:
str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;

接下来,写脚本。

在这里插入图片描述

#include<stdio.h>
int main()
{
char key[] = “adsfkndcls”; //key字符串是adsfkndcls
char text[] = “killshadow”; //text字符串是killshadow
int i; //定义了变量 i
int v2 = 0;
int v3 = 10;//v3的长度为10 ,因为在大写字母变小写的时候,v3会++,而字符串变了10次。
int v5 = 10;
for (int i = 0; i < v5; i++)//开始循环
{
for (int j = 0; j < 123; j++)//开始第二重循环 j = v1;
{
if ((j < ‘A’ || j > ‘Z’) || (j < ‘z’ && j > ‘a’))//|| 和 && 交换 > 和 < 交换 ,让j不再那个范围之内
{
continue;//如果不在范围之内,就跳过本次循环。
}
if ((j - 39 - key[v3 % 10] + 97) % 26 + 97 == text[i])//执行这个算法,跟text字符串相比,如果相等就输出
//这个字符
{
printf("%c",j);
v3++;//注意算法里面 v3++,所以这里也要把v3++;
break;
}
}
}
}

总结:这个题目除了基本的IDA pro的一些小小的快捷键之外,还需要知道小端序和大端序的知识,怎么去判断是小端序和大端序,这个我也不知道(百度了一波,可以自己写一个小程序来判断),大概就是在做题的时候,如果碰到我们需要手动去转字符的,应该就是反转一下字符的位置,实在不行大端序和小端序都去试一下。然后并是分析伪代码,知道它是在干什么,我们需要什么,还差了什么。然后写脚本,来运行得出flag。目前这一点,自己还不是很会,还需多多练习啊。

继续学习!!!

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值