2023浙江省大学生信息安全竞赛初赛RE:AndriodELF

查看字符串,找到wrong,交叉引用找到关键函数
在这里插入图片描述
可知:flag长度为64,分4个块分别进行加密(即每次加密16个字节)。加密结束后与byte_292C80进行比对

查看主要加密函数
在这里插入图片描述
可知:每次加密会进行16次循环,加密细节又分为4个部分。
分别查看这4个部分。

sub_218D5C
在这里插入图片描述
该函数的作用的就是将块中的每一个字节进行反转,例如:使 11010010 转变为 01001011

sub_218DF8在这里插入图片描述
这个看起来比较复杂,但实际的功能就是对加密的一个块(16个字节)中的字节进行交换,打乱顺序。

其中两个for语句实现的功能类似于:

void swap(int result[]) {
    int temp[16];
    for (int i = 0; i <= 15; ++i ){
        temp[i + v4[i]] = result[i];
    }
    for (int j = 0; j <= 15; ++j ){
        result[i] = temp[i];
    }
}

就是通过一个存放在v4中的索引来进行交换。而v4[4]的仅仅只是起一个暂存的作用。

sub_218EF4在这里插入图片描述该函数的作用的就是将块中的每一个字节的高3位与低5位的位置进行互换。

sub_218F54
在这里插入图片描述
简单异或

那么现在就可以编写逆向脚本了

#include <iostream>

using namespace std;

void dec_4(unsigned char block[],unsigned char num)
{
	for (int i = 0; i < 16; ++ i )
		block[i] ^= 120 * num;
}

void dec_3(unsigned char block[])
{
	for (int i = 0; i < 16; ++i )
		block[i] = block[i] << 5 | block[i] >> 3;
}

void dec_2(unsigned char block[])
{
	unsigned int v4[16] = {
    0x0000000D, 0x00000004, 0x00000000, 0x00000005, 0x00000002, 0x0000000C, 0x0000000B, 0x00000008, 
    0x0000000A, 0x00000006, 0x00000001, 0x00000009, 0x00000003, 0x0000000F, 0x00000007, 0x0000000E, 
	};
	
	unsigned char temp[16];
	
	for (int i = 0; i < 16; ++i )
		temp[i] = block[i];
	
	for (int i = 0; i < 16; ++ i )
		block[i] = temp[v4[i]];
}

void dec_1(unsigned char block[])
{
	char v1;
	for (int i = 0; i < 16; ++ i )
	{
		v1 = 0; 
		for (int j = 0; j < 8; ++ j )
			v1 |= ((block[i] >> j) & 1) << (7-j);
		block[i] = v1; 
	}
}

int main()
{
	unsigned char enc[65] = {
    0x3D, 0x45, 0x38, 0x7E, 0x78, 0x4B, 0x6A, 0x5C, 0x5B, 0x52, 0x4C, 0x73, 0x4E, 0x39, 0x49, 0x5F, 
    0x49, 0x40, 0x38, 0x5E, 0x74, 0x40, 0x66, 0x44, 0x46, 0x7A, 0x39, 0x3B, 0x67, 0x39, 0x70, 0x6C, 
    0x71, 0x5E, 0x6D, 0x4D, 0x5A, 0x4C, 0x7F, 0x3B, 0x4D, 0x63, 0x5E, 0x4E, 0x44, 0x5A, 0x7B, 0x51, 
    0x38, 0x61, 0x29, 0x63, 0x75, 0x5B, 0x67, 0x46, 0x4E, 0x5D, 0x79, 0x29, 0x4D, 0x29, 0x6D, 0x71,
	};
	
	unsigned char block[4][16];
	for (int i = 0; i < 4; ++ i )
		for (int j = 0; j < 16; ++ j )
			block[i][j] = enc[i*16+j];
	
	for (int i = 0; i < 4; ++ i )
	{
		for (char j = 0x10-1; j >= 0; j --)
		{
			dec_4(block[i], j);
			dec_3(block[i]);
			dec_2(block[i]);
			dec_1(block[i]);
		}
	}
	
	for (int i = 0; i < 4; ++ i )
		for (int j = 0; j < 16; ++ j )
			printf("%c", block[i][j]);

	return 0;
}
# DASCTF{51bWZvM0p1xNHLo3A1ndrVH0|VsED3LFyRwYkEVeRqeFSNE!0!oyUki!}

在这里插入图片描述

得到flag

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
全国青少年信息学奥林匹克竞赛初赛是中国的一项面向青少年的计算机竞赛活动。该竞赛旨在培养和选拔具有优秀计算机科学与编程能力的青少年,并为他们提供展示才华的平台。 以下是一些关于全国青少年信息学奥林匹克竞赛初赛的介绍和演示: 1. 竞赛内容:初赛主要包括计算机编程题目,涵盖算法、数据结构、编程语言等方面的知识。参赛选手需要在规定时间内解决一系列编程问题。 2. 参赛资格:初赛面向全国各地的中小学生,一般是高中及以下年级的学生。参赛选手需要通过学校或地区选拔赛获得参赛资格。 3. 竞赛形式:初赛一般采用在线编程的形式进行,选手需要在规定时间内完成编程题目,并提交代码进行评测。 4. 评分标准:初赛的评分主要根据选手的代码正确性、效率和编程风格等方面进行评判。评委会根据选手的代码运行结果和代码质量给出相应的分数。 5. 奖项设置:初赛根据选手的成绩进行排名,根据成绩高低颁发一、二、三等奖和优秀奖等奖项。获奖选手有机会晋级到全国决赛。 6. 意义和影响:全国青少年信息学奥林匹克竞赛初赛为青少年提供了锻炼编程能力和展示才华的机会,对于培养青少年的计算机科学素养和创新能力具有重要意义。 希望以上介绍对您有所帮助!如果您还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值