某文件被加密了(基于时间的随机种子破解)

2024-01-20 20:50

本文主要是介绍某文件被加密了(基于时间的随机种子破解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 某文件被加密了

某文件被加密了

最后修改时间是2019/04/11 22:10:34。 猜测大概2019/04/11
22点11分之前,某一刻用户运行了genprik,生成了密钥加密文件。
加密算法已知,通过分析密文,只能得出密钥第1个字节是0x25第2个字节是0x61。 求完整的16个字节的密钥。

刚开始用IDA打开,IDA会提示exe的入口点在其他的位置,应该是有壳,先对它进行查壳脱壳:
在这里插入图片描述

再用IDA打开:
在这里插入图片描述

int __cdecl main(int argc, const char **argv, const char **envp)
{__time32_t v3; // ST40_4@1DWORD Seed; // ST38_4@1int v5; // eax@2signed int v7; // [sp+24h] [bp-34h]@1v3 = time32(0i64);        //0i64表示int64_t类型的0,time3()表示返回自1970年1月1日午夜起经过的秒数,或者在出现错误时返回-1Seed = GetCurrentProcessId() ^ v3;   //获取当前进程的唯一标识srand(Seed);v7 = 0;do{v5 = rand();printf(Format, (v5 >> 7) & 0xFF);++v7;}while ( v7 < 16 );return 0;
}

这就是代码的关键部分,获取当前系统时间和进程号,来进行运算生产16字节的密钥,所以我们将时间调整到2019/04/11 22:10:34之前进行爆破,因为我们是进行爆破,所以时间不用太准确,只要在这之前都行,当然这里的2019/04/11 22:10:34可能是老师给的hint:设置密钥的正确事件。我将当前时间设为了2019/04/11 22:10:00开始,先将它转换成从1970年1月1日以来持续时间的秒数:
源代码:time.c

#include<stdio.h>
#include<time.h>
/**
struct tm {int tm_sec;// 秒 - 取值区间为[0,59] /int tm_min; // 分 - 取值区间为[0,59] /int tm_hour; / 时 - 取值区间为[0,23] /int tm_mday; / 一个月中的日期 - 取值区间为[1,31] /int tm_mon; / 月份 (从一月开始,0代表一月) - 取值区间为[0,11] /int tm_year; / 年份,其值等于实际年份减去1900 /int tm_wday; / 星期 - 取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 /int tm_yday; / 从每年的1月1日开始的天数 - 取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 /int tm_isdst; / 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的时候,tm_isdst为0;不了解情况时,tm_isdst()为负. /
};
*/
int main(void)
{//获取时间差struct tm tnNormal;///开始的时间:2019/04/11 22:10:00tnNormal.tm_year = 2019-1900;tnNormal.tm_mon = 4-1;tnNormal.tm_mday = 11;tnNormal.tm_hour = 22;tnNormal.tm_min = 10;tnNormal.tm_sec = 0;tnNormal.tm_isdst = 0;time_t tmNormal;tmNormal = mktime(&tnNormal);///开始的时间:2019/04/11 22:10:00转化为的秒数:1554991800printf("开始的时间:2019/04/11 22:10:00转化为的秒数:%d\n",tmNormal);return 0;
}

运行结果:
在这里插入图片描述

将2019/04/11 22:10:00转化为的秒数是:1554991800。接下来从1554991800开始递加,当前进程ID从0到100000循环,爆破直到得出的密钥第1个字节是0x25第2个字节是0x61:
下面是源代码:key.c

#include<stdlib.h>
#include <stdio.h>
/**
0~100000和0~500的第一个解
0x25 0x61 0x6c 0xd5 0x1d 0xd3 0x4b 0xcb 0xe7 0x34 0x97 0x93 0xa4 0x92 0x53 0x1f
当前时间:1554991800,当前进程:32375
*/
int main()
{///开始的时间:2019/04/11 22:09:00__time32_t v3 = 1554991800; // ST40_4@1long Seed; // ST38_4@1int v5; // eax@2signed int v7; // [sp+24h] [bp-34h]@1int i;int flag = 0;int id;__time32_t now;///0x25和0x61__int8 v4,v6;///时间递加for(i = 0; i< 500; i++){now = v3+i;///获取当前进程的唯一标识GetCurrentProcessId()for(id = 0 ; id < 100000 ; id++){Seed = id ^ now;///设置时间种子srand(Seed);v7 = 0;__int8 temp = 0;do{///根据时间种子生成随机数v5 = rand();temp = (v5 >> 7) & 0xFF;///第一个数是0x25if( v7 ==0 && 0x25 == temp){v4 = 0x25;///第一个数不是0x25}else if(v7 == 0 && temp !=0x25){v4 = 0;break ;}///第二个数是0x61if(v7 == 1 && 0x61 == temp){v6 = 0x61;printf("0x25 ");///第二个数不是0x61}else if(v7 == 1 && 0x61 != temp){v4 = 0;v6 = 0;break;}///如果找到结果if(v4 == 0x25 && v6 ==0x61){printf("0x%x ",temp & 0xFF);}++v7;}while( v7 < 16 );if(v7 == 16){///输出正确答案printf("\n当前时间:%d,当前进程:%d\n",now,id);flag = 1;break;}}if(flag == 1){printf("flag\n");break;}}return 0;
}

运行结果:
在这里插入图片描述

最后破解的16字节密钥为:0x25 0x61 0x6c 0xd5 0x1d 0xd3 0x4b 0xcb 0xe7 0x34 0x97 0x93 0xa4 0x92 0x53 0x1f。
到这破解的密钥已经得到的,但是我们发现当前时间:1554991800,当前进程:32375,因为随机种子是由当前时间和当前进程异或得到的,所以随着当前时间和当前进程递增,会出现多个时间和进程的异或结果相同,然后它们都最终得到这同一个密钥:0x25 0x61 0x6c 0xd5 0x1d 0xd3 0x4b 0xcb 0xe7 0x34 0x97 0x93 0xa4 0x92 0x53 0x1f。
我们来输出一下增加的时间0500以内和进程ID在0100000以内的所有解:
源代码:

#include<stdlib.h>
#include <stdio.h>int main()
{///开始的时间:2019/04/11 22:10:00__time32_t v3 = 1554991800; // ST40_4@1long Seed; // ST38_4@1int v5; // eax@2signed int v7; // [sp+24h] [bp-34h]@1int i;int flag = 0;int id;__time32_t now;///0x25和0x61__int8 v4,v6;///时间递加for(i = 0; i< 500; i++){now = v3+i;///获取当前进程的唯一标识GetCurrentProcessId()for(id = 0 ; id < 100000 ; id++){Seed = id ^ now;///设置时间种子srand(Seed);v7 = 0;__int8 temp = 0;do{///根据时间种子生成随机数v5 = rand();temp = (v5 >> 7) & 0xff;///第一个数是0x25if( v7 ==0 && 0x25 == temp){v4 = 0x25;///第一个数不是0x25}else if(v7 == 0 && temp !=0x25){v4 = 0;break ;}///第二个数是0x61if(v7 == 1 && 0x61 == temp){v6 = 0x61;printf("0x25 ");///第二个数不是0x61}else if(v7 == 1 && 0x61 != temp){v4 = 0;v6 = 0;break;}///如果找到结果if(v4 == 0x25 && v6 ==0x61){printf("0x%x ",temp & 0xff);}++v7;}while( v7 < 16 );if(v7 == 16){///输出正确答案printf("\n当前时间:%d,当前进程:%d,异或的结果随机种子:%d\n",now,id,now^id);v4 = 0;v6 = 0;}}}return 0;
}

运行结果:
在这里插入图片描述

这是因为源文件算法中异或这个限制条件不够苛刻,又没有其他的条件来限制多解,才会出现这样的情况,题目的主要用意也是让我们明白以当前系统时间作为随机种子并不是安全的。

这篇关于某文件被加密了(基于时间的随机种子破解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/627301

相关文章

golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法

《golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法》:本文主要介绍golang获取当前时间、时间戳和时间字符串及它们之间的相互转换,本文通过实例代码给大家介绍的非常详细,感兴趣... 目录1、获取当前时间2、获取当前时间戳3、获取当前时间的字符串格式4、它们之间的相互转化上篇文章给大家介

Feign Client超时时间设置不生效的解决方法

《FeignClient超时时间设置不生效的解决方法》这篇文章主要为大家详细介绍了FeignClient超时时间设置不生效的原因与解决方法,具有一定的的参考价值,希望对大家有一定的帮助... 在使用Feign Client时,可以通过两种方式来设置超时时间:1.针对整个Feign Client设置超时时间

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

SpringBoot3使用Jasypt实现加密配置文件

《SpringBoot3使用Jasypt实现加密配置文件》这篇文章主要为大家详细介绍了SpringBoot3如何使用Jasypt实现加密配置文件功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编... 目录一. 使用步骤1. 添加依赖2.配置加密密码3. 加密敏感信息4. 将加密信息存储到配置文件中5

SpringBoot整合jasypt实现重要数据加密

《SpringBoot整合jasypt实现重要数据加密》Jasypt是一个专注于简化Java加密操作的开源工具,:本文主要介绍详细介绍了如何使用jasypt实现重要数据加密,感兴趣的小伙伴可... 目录jasypt简介 jasypt的优点SpringBoot使用jasypt创建mapper接口配置文件加密

Java实现MD5加密的四种方式

《Java实现MD5加密的四种方式》MD5是一种广泛使用的哈希算法,其输出结果是一个128位的二进制数,通常以32位十六进制数的形式表示,MD5的底层实现涉及多个复杂的步骤和算法,本文给大家介绍了Ja... 目录MD5介绍Java 中实现 MD5 加密方式方法一:使用 MessageDigest方法二:使用

Python如何获取域名的SSL证书信息和到期时间

《Python如何获取域名的SSL证书信息和到期时间》在当今互联网时代,SSL证书的重要性不言而喻,它不仅为用户提供了安全的连接,还能提高网站的搜索引擎排名,那我们怎么才能通过Python获取域名的S... 目录了解SSL证书的基本概念使用python库来抓取SSL证书信息安装必要的库编写获取SSL证书信息