r00t0 KeygenMe v2 [Source] solution:
Described here. x64dbg & scylla are your friends.
Using cross-references to strings "Registration name:", "Registration Serial:", "\nRegistration Succeeded", "\nRegistration Failed" i located print function(VA 0x007d6f40) and all calls to it. Single stepping between print("Registration name:") and print("Registration Serial:")
i have empirically defined wrapper function that get input from terminal(VA 0x007D7C70). Ok, we have narrow range to analyze :
from call to get input name at 0x0061641C to call of print("_\nRegistration Failed_") at 0x006FF521 or call of print("\nRegistrationSucceeded") at 0x006EFCE1.
Lets go.
Code analysis is hardened with innumerable unconditional jump instructions, that interleave code, so called "spaghetti-code".

Between each asm instruction, there are 30-80 trash jump instructions.
x64dbg trace command TraceIntoConditional 1:[cip]!=0xe9 && 1:[cip]!=0xeb, which trace until meet not jump instruction save us tons of hours.
Tracing such way, we stop only at useful instructions and set software breakpoints on them. Now we can switch to x32dbg 'Breakpoints' tab, and overview all instructions that validate name:serial pair without trash jumps.

Validation algorithm:
0 step: get name and serial from input
char name[0x22+1] = {0};
char input_serial[32+1+8+1] = {0};
puts("Registration name:")
fgets (name, 0x22+1, stdin);
puts("Registration Serial:")
fgets (name, 41+1, stdin);1st step: check name length
2 < name <= 0x222nd step: get CPUID
uint32_t cpuid[4] = {0};
__cpuid(cpuid, 0);3d step: get 4-byte hash from name
uint32_t Nhash = 0;
for (size_t i = 0; i < strlen(name); i++) {
Nhash += name[i];
Nhash ^= 0x00ABCDEF;
Nhash = Nhash + (cpuid[0] ^ Nhash);
}4th step: get valid serial from name and CPUID
char derived_serial[32 + 1 + 8] = {0};
sprintf(derived_serial, "%X%X%X%X-%X", cpuid[0], cpuid[1], cpuid[2], cpuid[3], Nhash);5th step: compare input serial and serial derived from name and CPUID
if (strcmp(input_serial, derived_serial) == 0){
puts("\nRegistration Succeeded");
} else {
puts("\nRegistration Failed");
}Keygen is simply made from above code:
#include <stdio.h>
#include <string.h>
#include <stdint.h>
char * name;
uint32_t Nhash = 0;
uint32_t cpuid[4];
char serial[2*16 + 1 + 2*4];
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("[!] Usage: keygen.exe name\n");
return 1;
}
name = argv[1];
if (strlen(name) <= 2) {
printf("[!] Name is too short. It`s length should be minimum 3 chars.\n");
return 2;
}
if (strlen(name) > 0x22) {
printf("[!] Name is too long. It`s length should be maximum 34 chars.\n");
return 2;
}
printf("Provided name : %s\n", name);
__cpuid(cpuid, 0);
for (size_t i = 0; i < strlen(name); i++) {
Nhash += name[i];
Nhash ^= 0x00ABCDEF;
Nhash = Nhash + (cpuid[0] ^ Nhash);
}
sprintf(serial, "%X%X%X%X-%X", cpuid[0], cpuid[1], cpuid[2], cpuid[3], Nhash);
printf("Your serial : %s\n", serial);
return 0;
}Also posted on Tuts 4 You [link].