yes it doesnt look like any encryption but some pseudo random generator based on some original password i guessed so when i first saw the second and third charecters are replaced on addition of every charecter to the password because it is generated based on the lenght of the pw
(generated from backwards) so obviously every thing would depend on the lenght of the pw
yes as kayaker pointed out the offsets do change based on various factors like path name , password lenght etc the algo keeps on copy pasting data to different places in the allocated 0x28000 block.
in your screen shot i see the 2 bps hit so you may need to view memory a bit up and down and see where the generated hash is stored
my script wont let windbg break it will simply print the output and keep on continuing and you can watch the passowrd generated as you enter charecters in the edit box (if you loose focus of edit box it will be quiet some time to see them again till WM_PAINT WM_MOUXEXXXX msgs are processed by the windowing system ) keep windbg in background and crackme in top of Z order and enter password to view output in windbg below
i trivially bruteforced it in ollydbg with the ripped algo from sub crackZ hinted but there are further checks and from a fleet glance at comparison algo next to the sub
i think you need a password that is of certain length and 23 is not the right size either add eax,eax or cmp ch.bh should set the zer0 flag ) so that dl is set in sete dl
here is a full password for your test
Code:
CX2g!F%q2FP]$f,B+7,&@G.000000000000
Press any key to continue . . .
here is the shabby shitty bruteforcer for the above password
Code:
// setuppw.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define HARDCODED_HASH_LENGHT 0x17
#define CRYPTED_HASH_LENGTH HARDCODED_HASH_LENGHT + 0xc
BYTE HARDCODED_HASH[HARDCODED_HASH_LENGHT] = //009926A8 PX1QGTTEU<S7?<9T43387M3
{
0x50, 0x58, 0x31, 0x51, 0x47, 0x54, 0x54, 0x45,
0x55, 0x3C, 0x53, 0x37, 0x3F, 0x3C, 0x39, 0x54,
0x34, 0x33, 0x33, 0x38, 0x37, 0x4D, 0x33
};
BYTE CRYPTED_HASH[CRYPTED_HASH_LENGTH] = {0};
BYTE PASSWORD_HASH[CRYPTED_HASH_LENGTH] = {0};
DWORD count = 0;
int _tmain(int argc, _TCHAR* argv[])
{
// i started with '!' filled buffer to brute force but i saw it generating non printable bytes
// so ripped correct printable bytes from ollydbg to the array which made the generation of all printable
// charecters possible the array below generates a correct HARDCODED_HASH but few more checks need to be
// passed in the comaprison algo (add eax,eax or cmp ch.bh one of this should set the zero flag)
// have fun finding how to do it
memset(&CRYPTED_HASH,0x21,sizeof(CRYPTED_HASH));
CRYPTED_HASH[0] = 'C';
CRYPTED_HASH[1] = 'X';
CRYPTED_HASH[2] = '2';
CRYPTED_HASH[3] = 'g';
CRYPTED_HASH[4] = '!';
CRYPTED_HASH[5] = 'F';
CRYPTED_HASH[6] = '%';
CRYPTED_HASH[7] = 'q';
CRYPTED_HASH[8] = '2';
CRYPTED_HASH[9] = 'F';
CRYPTED_HASH[10] = 'P';
CRYPTED_HASH[11] = ']';
CRYPTED_HASH[12] = '$';
CRYPTED_HASH[13] = 'f';
CRYPTED_HASH[14] = ',';
CRYPTED_HASH[15] = 'B';
CRYPTED_HASH[16] = '+';
CRYPTED_HASH[17] = '7';
CRYPTED_HASH[18] = ',';
CRYPTED_HASH[19] = '&';
CRYPTED_HASH[20] = '@';
CRYPTED_HASH[21] = 'G';
CRYPTED_HASH[22] = '.';
__asm
{
pushad
redo:
xor edi,edi
mov ebp,CRYPTED_HASH_LENGTH
mov esi,1
looper:
mov eax, offset CRYPTED_HASH[0]
movzx eax,byte ptr [eax+esi-1]
mov edx,eax
mov ecx,CRYPTED_HASH_LENGTH
sub ecx,esi
imul ecx,edi
add edx,ecx
add edi,edx
mov ebx,eax
imul ebx,edi
add ebx,esi
BACK:
mov eax,ebx
mov ecx,5ah
xor edx,edx
div ecx
imul eax,eax,5ah
sub ebx,eax
cmp ebx,30h
jnb FORWARD
add ebx,30h
FORWARD:
cmp ebx,2fh
jbe BACK
cmp ebx,5bh
jnb BACK
mov eax,offset PASSWORD_HASH[0]
mov byte ptr [eax+esi-1],bl
inc esi
dec ebp
jnz looper
push ebx
mov ebx,offset HARDCODED_HASH[0]
add ebx,count
movzx ebx,byte ptr [ebx]
push eax
add eax,count
cmp byte ptr [eax] , bl
pop eax
pop ebx
je ARGH
push ebx
mov ebx,offset CRYPTED_HASH[0]
add ebx,count
inc Byte ptr [ebx]
pop ebx
jmp redo
ARGH:
cmp count,0x16
je finished
inc count
jmp redo
finished:
popad
}
printf("%s\n",&CRYPTED_HASH);
return 0;
}
the windbg output from script take a look at last output it shows full comaprison
Code:
ModLoad: 77b40000 77b62000 C:\WINDOWS\system32\apphelp.dll
ModLoad: 755c0000 755ee000 C:\WINDOWS\system32\msctfime.ime
Breakpoint 0 hit
Breakpoint 0 hit
ModLoad: 4b400000 4b486000 C:\WINDOWS\system32\msftedit.dll
Breakpoint 0 hit
009b40c4 50 00 00 00 f8 b5 41 00-f8 b5 41 00 34 3f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 P.....A...A.4?..................
009926a8 50 58 31 51 47 54 54 45-55 3c 53 37 3f 3c 39 54 34 33 33 38 37 4d 33 00 12 00 00 00 01 00 00 00 PX1QGTTEU<S7?<9T43387M3.........
009b40c4 50 34 00 00 f8 b5 41 00-f8 b5 41 00 34 3f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 P4....A...A.4?..................
009926a8 50 58 31 51 47 54 54 45-55 3c 53 37 3f 3c 39 54 34 33 33 38 37 4d 33 00 12 00 00 00 01 00 00 00 PX1QGTTEU<S7?<9T43387M3.........
================
009b40c4 50 38 42 00 f8 b5 41 00-f8 b5 41 00 34 3f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 P8B...A...A.4?..................
009926a8 50 58 31 51 47 54 54 45-55 3c 53 37 3f 3c 39 54 34 33 33 38 37 4d 33 00 12 00 00 00 01 00 00 00 PX1QGTTEU<S7?<9T43387M3.........
================
================
009b40f4 50 58 31 51 47 54 54 45-55 3c 53 37 3f 3c 39 54 34 33 33 38 37 4d 33 50 3b 4a 3f 46 4f 36 37 50 PX1QGTTEU<S7?<9T43387M3P;J?FO67P
009926a8 50 58 31 51 47 54 54 45-55 3c 53 37 3f 3c 39 54 34 33 33 38 37 4d 33 00 12 00 00 00 01 00 00 00 PX1QGTTEU<S7?<9T43387M3.........
================
since this post developed a bit more than the usual google and poster disappearing after that without making effort or if he made effort without sharing the results
i took a loook again to complete the brute forcing again in ollydbg with the code above with only one modification that of making both hash length equal viz 0x17
because add eax eax can set the zero flag only if eax is 0 and eax can be zero only when both lengths are equal
this password solves the mystery
Code:
wbd584e'!P"/AX6$s/!L>1+
anyone want to post a neat and clean keygen for this ??
the concept should be the buffer must be filled with say 0x20 (first printable charecter <space> for 0x17 characters
increased one at a time upto 0x7f (last printable charecter viz ~ tilde) till the first character of the hardcoded hash is found viz 'P'.
then second X (if no valid second increase first by one and reset count back to zero so the next valid charecter for P is found
in my case above 'C' produced 'P' with certain sequnce of charecters in first brute session
in the second brute session 'w' produces 'P' with another sequence
and remember to reset the rest of characters back to what it was viz 0x20 before relooping to find the next character
it is fs$%%% easy to brute in this manner in ollydbg manually with the ripped algo no need to even pause the app can be done with just binary edit in dump window
while the exe is running need just one breakpoint at inc count line
i modified the code above a little bit to check for minimum acceptable charecter as PASSWORD for runnning brute session in ollydbg
Code:
// setuppw.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define HARDCODED_HASH_LENGHT 0x17
#define CRYPTED_HASH_LENGTH HARDCODED_HASH_LENGHT
BYTE HARDCODED_HASH[HARDCODED_HASH_LENGHT] = //009926A8 PX1QGTTEU<S7?<9T43387M3
{
0x50, 0x58, 0x31, 0x51, 0x47, 0x54, 0x54, 0x45,
0x55, 0x3C, 0x53, 0x37, 0x3F, 0x3C, 0x39, 0x54,
0x34, 0x33, 0x33, 0x38, 0x37, 0x4D, 0x33
};
BYTE CRYPTED_HASH[CRYPTED_HASH_LENGTH] = {0};
BYTE PASSWORD_HASH[CRYPTED_HASH_LENGTH] = {0};
DWORD count = 0;
int _tmain(int argc, _TCHAR* argv[])
{
// i started with '!' filled buffer to brute force but i saw it generating non printable bytes
// so ripped correct printable bytes from ollydbg to the array which made the generation of all printable
// charecters possible the array below generates a correct HARDCODED_HASH but few more checks need to be
// passed in the comaprison algo (add eax,eax or cmp ch.bh one of this should set the zero flag)
// have fun finding how to do it
memset(&CRYPTED_HASH,0x20,sizeof(CRYPTED_HASH));
//CRYPTED_HASH[0] = 'C';
//CRYPTED_HASH[1] = 'X';
//CRYPTED_HASH[2] = '2';
//CRYPTED_HASH[3] = 'I';
//CRYPTED_HASH[4] = 't';
//CRYPTED_HASH[5] = '\\';
//CRYPTED_HASH[6] = '-';
//CRYPTED_HASH[7] = 'i';
//CRYPTED_HASH[8] = '5';
//CRYPTED_HASH[9] = 'X';
//CRYPTED_HASH[10] = 'h';
//CRYPTED_HASH[11] = '9';
//CRYPTED_HASH[12] = '\\';
//CRYPTED_HASH[13] = '@';
//CRYPTED_HASH[14] = '6';
//CRYPTED_HASH[15] = 'z';
//CRYPTED_HASH[16] = '5';
//CRYPTED_HASH[17] = 'A';
//CRYPTED_HASH[18] = '7';
//CRYPTED_HASH[19] = '^';
//CRYPTED_HASH[20] = '>';
//CRYPTED_HASH[21] = '-';
//CRYPTED_HASH[22] = ':';
// wbd584e'!P"/AX6$s/!L>1+
__asm
{
pushad
redo:
xor edi,edi
mov ebp,CRYPTED_HASH_LENGTH
mov esi,1
looper:
mov eax, offset CRYPTED_HASH[0]
movzx eax,byte ptr [eax+esi-1]
mov edx,eax
mov ecx,CRYPTED_HASH_LENGTH
sub ecx,esi
imul ecx,edi
add edx,ecx
add edi,edx
mov ebx,eax
imul ebx,edi
add ebx,esi
BACK:
mov eax,ebx
mov ecx,5ah
xor edx,edx
div ecx
imul eax,eax,5ah
sub ebx,eax
cmp ebx,30h
jnb FORWARD
add ebx,30h
FORWARD:
cmp ebx,2fh
jbe BACK
cmp ebx,5bh
jnb BACK
mov eax,offset PASSWORD_HASH[0]
mov byte ptr [eax+esi-1],bl
inc esi
dec ebp
jnz looper
push ebx
mov ebx,offset HARDCODED_HASH[0]
add ebx,count
movzx ebx,byte ptr [ebx]
push eax
add eax,count
cmp byte ptr [eax] , bl
pop eax
pop ebx
je ARGH
adder:
push ebx
mov ebx,offset CRYPTED_HASH[0]
add ebx,count
inc Byte ptr [ebx]
pop ebx
jmp redo
ARGH:
push ebx
mov ebx,offset CRYPTED_HASH[0]
add ebx,count
movzx ebx,byte ptr [ebx]
cmp bl, 0x21
pop ebx
jl adder
cmp count,0x16
je finished
inc count
jmp redo
finished:
popad
}
printf("%s\n",&CRYPTED_HASH);
return 0;
}