目錄
- 某檔案被加密了
某檔案被加密了
最后修改時間是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@1
DWORD Seed; // ST38_4@1
int v5; // eax@2
signed int v7; // [sp+24h] [bp-34h]@1
v3 = time32(0i64); //0i64表示int64_t型別的0,time3()表示回傳自1970年1月1日午夜起經過的秒數,或者在出現錯誤時回傳-1
Seed = 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:00
tnNormal.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轉化為的秒數:1554991800
printf("開始的時間: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@1
long Seed; // ST38_4@1
int v5; // eax@2
signed int v7; // [sp+24h] [bp-34h]@1
int 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;
///第一個數是0x25
if( v7 ==0 && 0x25 == temp){
v4 = 0x25;
///第一個數不是0x25
}else if(v7 == 0 && temp !=0x25){
v4 = 0;
break ;
}
///第二個數是0x61
if(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@1
long Seed; // ST38_4@1
int v5; // eax@2
signed int v7; // [sp+24h] [bp-34h]@1
int 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;
///第一個數是0x25
if( v7 ==0 && 0x25 == temp){
v4 = 0x25;
///第一個數不是0x25
}else if(v7 == 0 && temp !=0x25){
v4 = 0;
break ;
}
///第二個數是0x61
if(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;
}
運行結果:

這是因為源檔案演算法中異或這個限制條件不夠苛刻,又沒有其他的條件來限制多解,才會出現這樣的情況,題目的主要用意也是讓我們明白以當前系統時間作為隨機種子并不是安全的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/259991.html
標籤:其他
下一篇:打獵
