Lets begin with pw.com. The first thing we should do is to run pw.
So now you know that it displays:
Enter Password:
Switch to Softice and examine the memory by using the "MAP" command. Look for seg:offset where Pw dwells. In my computer it dwells at 10f2:0 and ends at 10f2:8F0E.
Write that adress down and switch back to pw. Type in your name and switch to softice and search for your inputs in the segment where pw dwells.
S 10F2:0 l ffff 'your input'
Softice will give you an adress where your input is stored.
10F2:010B (In my computer).
Remeber segment adresses are always diffrent but the offset adress is always the same.
Lets display that memory location and see that our inputs are really there.
D 10F2:010B
You should see your input at that adress. Now, we know that our input is not the correct password (unless we are lucky as hell) and that pw compares our input with the correct password. To do that it has to read our characters from the memory location where our input is stored and compare them with the correct password chars. So lets put a breakpoint on our chars in memory.
BPR 10F2:010B 10F2:010b +6(# of chars you typed) RW
Now switch back to pw and press enter. Softice will pop up as soon as pw reads from the memory locations where our input is stored. You'll pop up in this routine:
MOV BX,DX ;DX is the sixth char user pw MOV AX,DI MOV [BX],AL RET ------ XOR CH,CH MOV CL,[0103] ;What is at adress 0103? MOV CX,BX MOV AL,[BX+103] ; CMP AL,[BX+010A] ;[BX+10A]= The sixth char of user pw JNZ 01BF ;Bad jumpNow you should know what you have found (if you have read the preceeding lessons). If you dump adress 0103 you'll see the correct password. So the JNZ is "Bad Password" jump. How should we crack it? Well there are at least two ways. One way is to change the JNZ into a JZ. That way we will get the "correct password" everytime we type in a FALSe Password. The second way is to make the program compare the correct password with the correct password instead of comparing correct password with user password. That way it will always print "correct password" no matter what we typed in. To change it that way we simply change the CMP line to.
CMP AL,AL NOP NOP JNZ 01BFIf you view pw.com with a hexeditor you'll be able to see the correct password. If you take a comercial game protected with a manual scheme and hex view it you might see the correct passwords. If you dont, it generally means two things.
FF03:5468 MOV [DI-01],DH INC DH PUSH DS PUSH ES POP DS POP ES MOV SI,01FB ; 01FB is the dos buffer where our ; string is MOV CL,DL REPZ MOVSB ; Move our input to ES:DI (data of RET ; Test1) ----- IRET ;return from InterruptThe Iret means reurning from the interrupt service back to the main programs Here what follows:
MOV SI,01E6 ; Si = encryptet password MOV AL,C3 XOR SI,AL ; Decrypt a char CMP BYTE PTR [SI],00 ; Last char? JZ END OF STRING SUB AL,25 INC SI ; Get next char JMP NEXT CHAR TO DECRYPTIf you dump Si you'll see the correct password appear through out the loop. So this is the decryption mechanism. This encryption is quite easy to understand. So when the password is decrypted we will jump to END OF STRING, Here that is:
MOV SI,01E6 XOR AX,AX MOV SI,01E6 ; Correct password MOV DI,01DD ; User password MOV CL,[SI] ; Put first char of correct pw in CL MOV BL,[DI] ; Put first char of user pw in BL CMP CL,BL ; Compare them JZ FALSE PASSWORDSo Changing the instruction CMP CL,BL into CMP CL,CL will do the trick for this program. It's always good to make the crack at the churn of the protection scheme. If you crack the JZ, it might be a mirror check somewhere and you'll have to find that one and change it. By cracking the CMP any kind of flag etc that could be set if the the check fails/succeds will be set as if we entered the right password.
The BPR 183D:0 183D:6574 W took us to the correct place. We first landed in an interrupt routine and stepped from there to the programs execution place. Now you'll probably know that you can breakpoint on interrupts in Softice with the command
BPINT interrupt number |al|ah|ax=value. If we would have used that breakpoint we would have avoided the bios routine and gone straight to the location the IRET took us. But we dont know the interrupt service number that Test1 is using. Well that is easily changed. Run Test1 but this time use the LDR (DLDR if you are using winice) command to load Test1 and BPINT 21 before you press CTRL-D. Here is the list of Int 21 called from test1.com:
__ | XOR AX,[SI] | CMP BYTE PTR [SI+01],00 ;Here is where you land | JZ 014E | CMP BYTE PTR [SI+01],0D ;check if char is carraige return(0D) | JZ 014E | INC SI | JMP 013D ; run until end of string is reached |__ 014E CMP WORD PTR CS:[0245],00 ;???? what's this??? JNZ 014E ; a loop! for what???? MOV SI,0241 MOV DX,[SI] PUSH AX MOV AX,[SI+02] MOV DS,AX MOV AX,251C INT 21 ;SET VECTORIf you let the program run it will show "Wrong password.." and exit to DOS. So it only reads our input string one time. The XOR AX,[SI] looks suspecious at first look, it looks like a encryption instruction. Its the only thing in the first pieace of code that manipulates our string. The next thing that my eyes see is the CMP WORD PTR CS:[0245],00 The CMP is checking the status at CS:[0245] unti it's zero. What's going on at adress CS:0245? and what changes the 01 into 0?
DEC WORD PTR CS:[0245] ; Here's the toggle from 01/00 IRET --- INT 1C ;So Int 1C is one that is hooked CALL 8CFAINT 1C is the user timer click vector. It runs constantly, just try a BPINT 1C and you'll see. Now we understand the strange CMP WORD PTR CS:[0245],00. We now make a guess that the XOR AX,[SI] instruction encrypts our input letters for a later compare. Since the encryptet string is stored in AX as a number and not as a string we have to look for instructions that moves AX value to a place in memory. The PUSH AX stores our encrypted string on the stack. Step over it and do a D SS:SP and you'll see that the number that was in AX is now on another adress. BPM that adress.
XOR [BP+08],BX JNZ 01B2 ; Evil Jump ---If you scan up alittle in the code you'll se this:
MOV BX,[BP+04] XOR BX,B816 XOR [BP+08],BX ; BP+08 is our encrypted code JNZ 01B2Now we can easily crack this by changing the JNZ into a JZ If you wanna know the correct password you'll have to DECRYPT it. I'll leave that up to you. Here are some hint if you wanna have a try.