我想采取的方法是强制所有可能的密钥(种子),直到找到正确的密钥。我知道tex文件中的第一个字符,所以这些是我正在测试的。当我找到正确的序列时,我会停止程序并输出密钥。
/* The ISO/IEC 9899:1990 edition of the C standard */
#include <stdio.h>
#include <time.h>
#include <iostream>
//#define RAND_MAX 32767
static unsigned long int next = 1;
int rand(void) // RAND_MAX assumed to be 32767
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
void srand(unsigned int seed)
{
next = seed;
}
using namespace std;
//Return a byte at a time of the rand() keystream
char randchar() {
static int key;
static int i = 0;
i = i % 4;
if (i == 0) key = rand();
return ((char *)(&key))[i++];
}
int main(int argc, const char* argv[]) {
for (unsigned int i = time(NULL); i >= 0; i--) //Try all possible return values of time(NULL) since today
{
srand(i);
cout << "Trying with time(NULL) = " << i << endl;
FILE *input, *output;
input = fopen("Homework1b-Windows.tex.enc", "r");
output = fopen("Homework1b.tex", "w");
int c,rc, test;
int pos;
pos = 0;
bool pos0, pos1, pos2, pos3, pos4, pos5;
pos0 = pos1 = pos2 = pos3 = pos4 = pos5 = false;
char temp1, temp2;
while ((c = fgetc(input)) != EOF) {
rc=randchar();
fputc(c^rc,output);
test = c^rc;
temp1 = (char)test;
temp2 = '\\';
if ((pos == 0) && (temp1 == temp2))
{
pos0 = true;
}
temp2 = 'd';
if ((pos == 1) && (temp1 == temp2))
{
pos1 = true;
}
/*
temp2 = 'o';
if ((pos == 2) && (temp1 == temp2))
{
pos2 = true;
}
temp2 = 'c';
if ((pos == 3) && (temp1 == temp2))
{
pos3 = true;
}
*/
temp2 = 'u';
if ((pos == 4) && (temp1 == temp2))
{
pos4 = true;
}
temp2 = 'm';
if ((pos == 5) && (temp1 == temp2))
{
pos5 = true;
}
pos++;
}
fclose(input);
fclose(output);
if (pos0 && pos1 && pos4 && pos5)
{
cout << endl << "Cracked. The seed is time(NULL) = " << i << endl;
break;
}
}
system("pause");
}
我知道解密的tex文件以“\ document”开头。
我面临的问题是代码永远不会终止。它永远找不到正确的密钥(种子)。
任何帮助?
谢谢。
答案 0 :(得分:2)
你的想法是合理的(蛮力从“现在”回来并寻找匹配的纯文本),但你的实现可以改进。 例如,您不应该打开和关闭循环内的文件。
如果您查看<template lang="pug">
el-dialog( width="600px", title="Users", :visible.sync="dialogVisible")
el-form.demo-ruleForm(:model="editedItem", status-icon, :rules="formRules", ref="userForm", label-width="140px")
el-form-item(label="Name", prop="firstName")
el-input(v-model="editedItem.name", auto-complete="off")
template(v-if="!changePassword")
el-form-item
el-button(@click="changePassword = true") Change Password?
template(v-else)
el-form-item(label="Password", prop="password")
el-input(type="password", v-model="editedItem.password", auto-complete="off")
el-form-item(label="Confirm Password", prop="confirmPassword")
el-input(type="password", v-model="editedItem.confirmPassword", auto-complete="off")
.dialog-footer(slot="footer")
el-button(type="primary", @click="submitForm('userForm')") Save
</template>
<script>
export default {
name: 'dialog-add-edit-user',
props: {
editedItem: Object,
},
data () {
const validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('Please input the password'))
} else {
if (this.confirmPassword !== '') {
this.$refs.userForm.validateField('confirmPassword')
}
callback()
}
}
const validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('Please input the password again'))
} else if (value !== this.editedItem.password) {
callback(new Error('Two inputs don\'t match!'))
} else {
callback()
}
}
return {
formRules: {
password: [
{
validator: validatePass,
trigger: 'blur'
}
],
confirmPassword: [
{
validator: validatePass2,
trigger: 'blur'
}
]
},
dialogVisible: false,
changePassword: false,
editedItem: {
name: '',
password: '',
confirmPassword: ''
}
}
},
methods: {
submitForm (formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$emit('save-item')
console.log('submit!')
} else {
console.log('error submit!!')
return false
}
})
}
}
}
</script>
的实施方式,直接调用randchar()
可能会更有效,并且一次比较四个字符。
实际上,您可以计算一次加密和纯文本的rand()
,并简单地将xor
返回的值与其进行比较。
为了加快速度,您可以直接在源文件中编写加密和纯文本的前8个字符,使用一个简单的函数将四个rand()
打包到char
:
int
和int to_int(const char buffer[4]) {
return (static_cast<int>(buffer[0])) +
(static_cast<int>(buffer[1]) << 8) +
(static_cast<int>(buffer[2]) << 16) +
(static_cast<int>(buffer[3]) << 24);
}
main()
现在剩下的就是循环遍历所有可能的键并寻找匹配(并且正如@Raxvan指出的那样,你不应该检查 const int crypt1 = to_int("\x57\x12\x6f\x63");
const int crypt2 = to_int("\x51\x59\x65\x6e");
const int plain1 = to_int("\\doc");
const int plain2 = to_int("umen");
const int target1 = plain1 ^ crypt1;
const int target2 = plain2 ^ crypt2;
或者循环永远不会完成):
key >= 0