[NTFS Streams Info program is designed for viewing and editing alternative NTFS streams. Not the most convenient tool, NTFS Stream Explorer is much better by its features and interface, and besides it is free. However, the project ceased to exist long ago, and the information on the offsite is much different. A good reason to practice necromancy and reverse engineering.
Due to development shutdown, download links on the former offsite are gone, but the global Internet Archive still has data on the latest version. Get the distribution from there, install: http://web.archive.org/web/20051124144929/http://www.isgeo.kiev.ua/shareware/NTFSInfoSetup.exe
Registration error message The program will reply with a weird message on the input of an illegal serial number. The executable file is not packed in any way, so let’s send it to the disassembler, and for now let’s look for the message string.
String in file One occurrence is found. All the cross-references to the line about incorrect registration lead to one big function at address 0049550C. You can easily guess that this is the check for the entered serial number. Let’s try to reverse the function of checking the serial number to find out the algorithm of its generation. To do this you should use the debugger to find out what, with what, where and how it is compared.
But I can’t run the program under a debugger in a usual way. It throws unhandled exceptions at every sneeze and crashes with a memory error when trying to run it under the debugger without reaching registration check. This triggers anti-tampering protection. But for every sly ass there’s a dick with a screw, in our case it’s an opportunity to attach a debugger to a running process. Run the program in normal mode, wait for the registration window to pop up. Attach debugger to the process and set breakpoint at the beginning of the check function. Release the program for execution. Now we don’t have any exceptions (for now), after entering serial number breakpoint goes off and we can pass all checks in step by step mode. Here we go.
CODE:0049553D mov eax, [ebp var_8] CODE:00495540 call sub_404B44 CODE:00495545 cmp eax, 13h CODE:00495548 jz short loc_495560 CODE:0049554A mov ecx, offset _str_Invalid_registr.Text CODE:0049554F mov dl, 1 CODE:00495551 mov eax, off_4953F0
First check. The length of serial number must be 13h (19 in decimal system) characters. And then the first surprise from the developer: each field for entering parts of the serial number has 5 characters, while according to this check it should be 4 (4 groups of 4 characters 3 separators = 19).
CODE:0049559F mov [ebp var_1C], 1 CODE:004955A6 loc_4955A6: CODE:004955A6 lea eax, [ebp var_28] CODE:004955A9 push eax CODE:004955AA mov ecx, 1 CODE:004955AF mov edx, [ebp var_1C] CODE:004955B2 mov eax, [ebp var_14] CODE:004955B5 call unknown_libname_592 CODE:004955BA mov eax, [ebp var_28] CODE:004955BD movzx eax, byte ptr [eax] CODE:004955C0 add [ebp var_18], eax CODE:004955C3 inc [ebp var_1C] CODE:004955C6 cmp [ebp var_1C], 5 CODE:004955CA jnz short loc_4955A6
The 4 characters of the first block are added together. In the future, other parts of the serial number will be added to this sum, but all in due time. For convenience, let’s call this sum the accumulator.
CODE:004955E5 mov al, [eax] CODE:004955E7 sub al, 47h CODE:004955E9 jz short loc_49560D CODE:004955EB sub al, 5 CODE:004955ED jz short loc_49560D CODE:004955EF sub al, 6 CODE:004955F1 jz short loc_49560D CODE:004955F3 sub al, 4 CODE:004955F5 jz short loc_49560D CODE:004955F7 mov ecx, offset _str_Invalid_registr.Text CODE:004955FC mov dl, 1 CODE:004955FE mov eax, off_407CF4
The first group check begins. The second character must be coded 47h, (47h 5), (47h 5 6), or (47h 5 6 4), that is, G, L, R, or V.
CODE:00495631 mov eax, [ebp var_30] CODE:00495634 mov al, [eax] CODE:00495636 cmp al, 44h CODE:00495638 jbe short loc_4956A5 CODE:0049563A lea eax, [ebp var_38] CODE:0049563D push eax CODE:0049563E mov ecx, 1 CODE:00495643 mov edx, 4 CODE:00495648 mov eax, [ebp var_14] CODE:0049564B call unknown_libname_592 CODE:00495650 mov eax, [ebp var_38] CODE:00495653 mov al, [eax] CODE:00495655 cmp al, 4Fh CODE:00495657 jnb short loc_4956A5 CODE:00495659 lea eax, [ebp var_3C] CODE:0049565C push eax CODE:0049565D lea eax, [ebp var_40] CODE:00495660 mov edx, [ebp var_14]
The 4th character of the first group must be in the range 45h…4Eh, i.e. from E to N.
CODE:0049567D mov eax, [ebp var_3C] CODE:00495680 mov al, [eax] CODE:00495682 cmp al, 50h CODE:00495684 jb short loc_4956A5 CODE:00495686 lea eax, [ebp var_44] CODE:00495689 push eax CODE:0049568A mov ecx, 1 CODE:0049568F mov edx, 3 CODE:00495694 mov eax, [ebp var_14] CODE:00495697 call unknown_libname_592 CODE:0049569C mov eax, [ebp var_44] CODE:0049569F mov al, [eax] CODE:004956A1 cmp al, 59h CODE:004956A3 jbe short loc_4956BD
The 3rd character of the first group must be in the range 50h…59h, i.e. from P to Y.
CODE:004956EC push offset loc_495929 CODE:004956F1 push dword ptr fs:[eax] CODE:004956F4 mov fs:[eax], esp CODE:004956F7 lea ecx, [ebp var_14] CODE:004956FA mov edx, [ebp var_C] CODE:004956FD sub edx, 42h CODE:00495700 mov eax, [ebp var_10] CODE:00495703 mov ebx, [eax] CODE:00495705 call dword ptr [ebx 0Ch] CODE:00495708 mov [ebp var_1C], 1
The 1st character of serial number is tested in a very intricate way: 42h is subtracted from its code, then some operation like reading from memory is performed, which throws exception when trying to trace under debugger if the value is negative. That is, the code for the first character must be 43h or greater, such as the C character.
CODE:00495750 mov bl, [eax] CODE:00495752 lea eax, [ebp var_58] CODE:00495755 push eax CODE:00495756 mov ecx, 1 CODE:0049575B mov edx, 1 CODE:00495760 mov eax, [ebp var_14] CODE:00495763 call unknown_libname_592 CODE:00495768 mov eax, [ebp var_58] CODE:0049576B movzx eax, byte ptr [eax] CODE:0049576E add eax, 6 CODE:00495771 cmp ebx, eax CODE:00495773 jnz short loc_4957C3 CODE:00495775 lea eax, [ebp var_5C] CODE:00495778 push eax
Check the second group of the serial number. The 3rd character of the second group must equal the first 6.
CODE:0049579C mov dl, [edx 1] CODE:0049579F call unknown_libname_77 CODE:004957A4 mov eax, [ebp var_64] CODE:004957A7 mov ecx, 1 CODE:004957AC mov edx, 1 CODE:004957B1 call unknown_libname_592 CODE:004957B6 mov eax, [ebp var_60] CODE:004957B9 movzx eax, byte ptr [eax] CODE:004957BC add eax, 2 CODE:004957BF cmp ebx, eax CODE:004957C1 jz short loc_4957DB
The 4th character of the second group must equal the second 2.
CODE:00495708 mov [ebp var_1C], 1 CODE:0049570F loc_49570F: CODE:0049570F lea eax, [ebp var_50] CODE:00495712 push eax CODE:00495713 mov ecx, 1 CODE:00495718 mov edx, [ebp var_1C] CODE:0049571B mov eax, [ebp var_14] CODE:0049571E call unknown_libname_592 CODE:00495723 mov eax, [ebp var_50] CODE:00495726 movzx eax, byte ptr [eax] CODE:00495729 add [ebp var_18], eax CODE:0049572C inc [ebp var_1C] CODE:0049572F cmp [ebp var_1C], 5 CODE:00495733 jnz short loc_49570F
The second group of serial characters is added to the drive in turn.
CODE:004957F0 mov [ebp var_1C], 1 CODE:004957F7 loc_4957F7: CODE:004957F7 lea eax, [ebp var_68] CODE:004957FA push eax CODE:004957FB lea eax, [ebp var_6C] CODE:004957FE mov edx, [ebp var_14] CODE:00495801 mov ecx, [ebp var_1C] CODE:00495804 mov dl, [edx ecx-1] CODE:00495808 call unknown_libname_77 CODE:0049580D mov eax, [ebp var_6C] CODE:00495810 mov ecx, 1 CODE:00495815 mov edx, 1 CODE:0049581A call unknown_libname_592 CODE:0049581F mov eax, [ebp var_68] CODE:00495822 movzx eax, byte ptr [eax] CODE:00495825 add [ebp var_18], eax CODE:00495828 inc [ebp var_1C] CODE:0049582B cmp [ebp var_1C], 5 CODE:0049582F jnz short loc_4957F7
The third group is not checked at all, just added to the drive. It can be any characters.
CODE:0049584A mov edx, 3 CODE:0049584F mov eax, [ebp var_14] CODE:00495852 call unknown_libname_592 CODE:00495857 mov eax, [ebp var_70] CODE:0049585A movzx eax, byte ptr [eax] CODE:0049585D add [ebp var_18], eax CODE:00495860 lea eax, [ebp var_74] CODE:00495863 push eax CODE:00495864 mov ecx, 1 CODE:00495869 mov edx, 1 CODE:0049586E mov eax, [ebp var_14] CODE:00495871 call unknown_libname_592 CODE:00495876 mov eax, [ebp var_74] CODE:00495879 movzx eax, byte ptr [eax] CODE:0049587C add [ebp var_18], eax
Go to the fourth and last group of the serial number. The first and third characters of the group are added to the drive.
CODE:0049587F mov eax, [ebp var_18] CODE:00495882 mov ecx, 0Ah CODE:00495887 cdq CODE:00495888 idiv ecx CODE:0049588A mov [ebp var_20], edx CODE:004958BB mov eax, [ebp var_78] CODE:004958BE movzx eax, byte ptr [eax] CODE:004958C1 mov edx, [ebp var_20] CODE:004958C4 add edx, 41h CODE:004958C7 cmp eax, edx CODE:004958C9 jnz short loc_4958F1
The accumulator is divided by 10, 41h is added to the remainder. The fourth character of the last group must equal this result.
CODE:0049588D mov eax, [ebp var_18] CODE:00495890 mov ecx, 64h CODE:00495895 cdq CODE:00495896 idiv ecx CODE:00495898 mov eax, edx CODE:0049589A mov ecx, 0Ah CODE:0049589F cdq CODE:004958A0 idiv ecx CODE:004958A2 mov [ebp var_24], eax CODE:004958E1 mov eax, [ebp var_7C] CODE:004958E4 movzx eax, byte ptr [eax] CODE:004958E7 mov edx, [ebp var_24] CODE:004958EA add edx, 41h CODE:004958ED cmp eax, edx CODE:004958EF jz short loc_495909
The accumulator is divided by 100, the remainder is divided by 10, and 41h is added to the final quotient. The second character of the last group must equal this result.
After each failed check under the debugger the program throws an exception and fatal crashes with a memory reading error. So I have to run it again, attach the debugger, switch to a breakpoint in the check function. The author did a good job showing a really creative approach to the registration check system.
Armed with a calculator, you can calculate the correct serial number using the algorithm described above. For example, a valid serial number should be CGQE-0062-PCLX-MEHI. Check. You will not see any error messages, the main program window will open. Exit. We are running it again. This time we don’t say a word about registration, program is running properly. We have reached our goal. You can write a keygen by yourself.
the dump furniture store hours