mstik13 on 7:05 PM 11/14/2022: The Program generated a mutated array of 20 digits fully at runtime, based on time, each second you have a new array set, this array set is used to check the inputs, also the first number you input, is used to do mutation n time, the actual check happends with the second number, in order to make a keygen you must save the context, otherwise each second will be generated a new set, making all your previous convinations trys pointless
WhatsUp on 7:13 AM 11/15/2022: mstik13, thanks for trying! As you have pointed out, there are some randomness based on time. However, that is exactly the puzzling point. It is possible to win the game every time without knowing the runtime context.
umpani on 8:42 PM 11/29/2022: Perhaps I need a little hint.
I pointed out, that you are using a PRG twice in the code. At first you fill a 20byte long array with pseudo random values. Then you add to each array entry the second number an a newly generated PR value. With &7FFF you cut Bit 15.
But I have no idea, to set this calculation always to zero to avoid the if condition fail:
if (((PRNArray[extraout_EDX] + PRN) - PRN2 & 0x7fff) != 0)
WhatsUp on 8:12 AM 11/30/2022: Here are two hints:
hint 1: a pseudo random number generator is not really random, it is a deterministic procedure.
hint 2: the only true randomness comes from a call to time(), but with a clever choice of the two numbers, one can pass the test regardless of the return value of time().
dnsy on 1:56 PM 12/29/2022: The only numbers I found that would pass the checks are
Num1: 2147483628
Num2: 0
ONLY if you ignore the check of Num1
dnsy on 1:58 PM 12/29/2022: The only numbers I found that would pass the checks are
Num1: 2147483628
Num2: 0
ONLY if you ignore the check of Num1 less or equal to 999999999, so of course these won't work. Another set of numbers I found that would almost pass the checks most of the time is
Num1: 536870892
Num2: -8192
but because Num2 is negative, being an unsigned 32b-bit int, it will be greater than 0x7FFF.
What I've figured out so far is that in this check:
if ( ((num2 + list_random_nums[counter] - gen_number_based_on_time) & 0x7FFF) != 0 )
break;
(list_random_nums[counter] - number_based_on_time) must be the same in all 20 checks, since num2 is static. I tried making a script for this but failed terribly.
So I'm currently stuck on how to solve this, is it even possible in the first place? Any new hint would be appreciated.
WhatsUp on 5:16 PM 12/29/2022: You are actually very close! Instead of using the negative number -8192, you can & it with 0x7FFF (note that only the last 15 bits are useful). It then becomes 24576.
dnsy on 2:44 AM 12/30/2022: I had the answer right in front of me hahaha. This was a pretty fun crackme, would definitely love to see more like this!
WhatsUp on 4:25 PM 12/31/2022: Thanks for solving! When I have time, I'll create some more puzzles of this type.
natitati on 7:57 PM 03/26/2023: Hey, can someone explain to me why 536870892 and 24576 work?
Quite new to this.
What I dont get it:
v10 = random_time_num();
if ( ((num2_copy + random_nums[v11] - v10) & 0x7FFF) != 0 )
break;
How do these numbers make the expression always 10?
num2_copy is just a copy of num2. and it's static.
but random_nums[v11] is a random number... so is v10 if i understood correctly.
How do we make it 0 again and again 20 times, with randomness taking place?
Any help appreciated :}
natitati on 7:58 PM 03/26/2023: always 0*** sorry
billbob on 8:07 PM 05/12/2023: I used the answer provided above to prove to myself that my brute-force method is correct to find valid inputs.
However, actually running the brute-force would take longer than the existence of the known universe, thanks to what I believe is an O(n^2) algorithm.
Is the solution to this crackme a simple static set of points (or maybe just the single point) which fulfill the requirements regardless of the _time64(0) seed? Or is there an algorithm which can generate time-dependent answers as well, assuming one can open the keygen and crackme at the same second so the context is identical.
I too would be very interested to know which algorithm or deduction method is used to identify PRNG weaknesses like this in general, it would be very helpful.
Despite my failure: interesting crackme, thanks!
WhatsUp on 6:21 PM 06/15/2023: @billbob There are some maths behind this stuff. You don't have to run a bruteforce algorithm to find out the numbers, and they should work no matter what time seed you get at run time. Here are some hints which one can search for: "linear congruential generator", "Euler's totient function", "Fermat–Euler theorem".