Correspondence From Casimir On Reversing Turbo Encrypto

Other Essays by Casimir
  • Cracking of Crypt-o-Text v1.21 & v1.24
  • Cracking of Encrypt-It For Windows
  • Cracking of WinXFiles
  • The Cracking of File Locker
  • The Cracking of Keeper
  • The Cracking of Gregory Braun's Crypto v3.5
  • The Cracking of SecurityPlus!
  • The Cracking of MasterKey v1.02/1.05
  • Hi joe!

    Ok, let's have a look at Turbo Encrypto:

    Turbo Encrypto v1.01 by Raymond J. Province
    Web Page:
    http://www.netcom.com/~skylark/support.html
    http://www.netcom.com/~skylark/question.html
    e-mail:
    skylark@ix.netcom.com
    skylark@freeyellow.com
    size ENCRYPTO.EXE : 348672 bytes
    The shareware version i'm using has 4 encryption schemes:

    but you'll see we don't even have to figure out HOW they work to defeat them.

    And So We Begin...Looking For Our Input In Memory

    So write something in Turbo Encrypto' text editor and encrypt it with pwd: "CASIMIR" (as usual). Then try to decrypt it, and when asked for a pwd, enter "JOE", BUT don't press the "OK" button ! Before go into Winice and set a BPX GETDLGITEMTEXT. Now you can return to Turbo Encrypto and press "OK".

    Winice'll pop up in the begining of the USER!GETDLGITEMTEXT subroutine. Press F11 to find out who called it, you'll get: (* here we are)

    :0006.1D66 8D46C8 lea ax, [bp-38]
    :0006.1D69 50 push ax
    :0006.1D6A 6A29 push 0029
    :0006.1D6C 9AFFFF0000 call USER.GETDLGITEMTEXT
    *0006.1D71 16 push ss
    Disable breakpoint, and set a BPX CS:1D6C. Now you can exit Winice. An error window will appear, press Ok, enter "JOE" again, press OK. Winice pops up, dump memory location DS:AX (argument of the call), you will see...nothing. Pass GETDLGITEMTEXT, and "JOE" is copied to DS:AX.

    We found the echo of input in memory, now we must find out who is using it. So we set a BPR DS:57CE DS:57D0 R (because AX=57CE, you may have a different value on your computer). You discover that input'lenght is being calculated in USER!LSTRLEN (CS:1D8B) and stored in DS:[bp-04].

    Why...What Could This String Be?

    Now stop for a time and watch next instructions. An other mysterious lenght is being calculated (CS:1D98) and stored in DS:[bp-06]. Huuummm... Perform a d DS:[bp-62], you will see: ef{`gb~ [65.66.7B.60.67.62.7E]. Yes, you guessed it, this is the good pwd crypted! Have a look at the crypted file, and look for "ef{`gb~": it appears on the beginning of file (i always have HexWorkshop running during cracking session, very useful tool).

    :0006.1D86 16 push ss
    :0006.1D87 8D46C8 lea ax, [bp-38] // input ("JOE")
    :0006.1D8A 50 push ax
    :0006.1D8B 9AFFFF0000 call KERNEL.LSTRLEN
    :0006.1D90 8946FC mov [bp-04], ax // input'lenght (3)
    :0006.1D93 16 push ss
    :0006.1D94 8D469E lea ax, [bp-62] // good pwd crypted
    :0006.1D97 50 push ax
    :0006.1D98 9AFFFF0000 call KERNEL.LSTRLEN
    :0006.1D9D 8946FA mov [bp-06], ax // good pwd'lenght
    :0006.1DA0 837EFC00 cmp word ptr [bp-04], 0000 // input=0 ?
    :0006.1DA4 744A je 1DF0 // Sorry!
    :0006.1DA6 8B46FC mov ax, [bp-04]
    :0006.1DA9 3B46FA cmp ax, [bp-06] // same lenght ?
    :0006.1DAC 7542 jne 1DF0 // Sorry!
    Then prg checks if input = null string (CS:1DA0). If input=0, then you get the Sorry! msg. If input !=0 then you can go on and you reach a second check (CS:1DA9). If good pwd'lenght=input'lenght, ok, you passed the test. Otherwise, you get the Sorry! msg once again.

    Now We Enter The Most Interesting Part: The Third And Last Check...

    Each character of crypted pwd is uncrypted and checked against input. Big mistake, of course... The pwd should NEVER be uncrypted, it sounds obvious, but look! (NB: registered version is sold $49 !!!)

    :0006.1DC4 C45EF2 les bx, [bp-0E] // crypted pwd
    :0006.1DC7 FF46F2 inc word ptr [bp+F2]
    :0006.1DCA 268A07 mov al , es:[bx] // character i from pwd
    :0006.1DCD 98 cbw
    :0006.1DCE 8BD6 mov dx, si
    :0006.1DD0 03D1 add dx, cx
    :0006.1DD2 33C2 xor ax, dx // uncryption
    :0006.1DD4 C45EF6 les bx, [bp-0A]
    :0006.1DD7 FF46F6 inc word ptr [bp+F6]
    :0006.1DDA 50 push ax
    :0006.1DDB 268A07 mov al , es:[bx] // character i from input
    :0006.1DDE 98 cbw
    :0006.1DDF 5A pop dx
    :0006.1DE0 3BD0 cmp dx, ax //DX=pwd'char i AX=input'char i
    :0006.1DE2 7404 je 1DE8
    :0006.1DE4 33FF xor di, di
    :0006.1DE6 EB06 jmp 1DEE
    ... ...
    :0006.1DE8 41 inc cx
    :0006.1DE9 3B4EFA cmp cx, [bp-06]
    :0006.1DEC 7CD6 jl 1DC4
    :0006.1DEE EB02 jmp 1DF2
    You just have to sit on CS:1DE0 and wait to see what correct pwd was. Pwd can be extracted very easily from textfile (this would be a very good exercice for any wannabee-cracker {:-) (did you see my brand-new hair?)).

    Need A Further Elucidation! -- I Did!

    !!!!!!!!!! THE TURBO-ENCRYPTO ADD-ON!!!!!!!!!!


    To be honest, i didn't think this essay would hold your attention so much ! Cracking of Turbo Encrypto (TE) was less difficult -and therefore less interesting- than Crypt-o-Text'cracking. For one main reason: TE extracts good password from crypted file, then it checks if good pwd = input... So you can easily discover what pwd should have been entered in order to uncrypt file (similar to some cases of fake registration) !

    I'll try to give you more information: let's focus on the uncryption scheme.

    Encryption methods only differ by SI'value in CS:1DCE. I found out that:

    CS:1DC4 (loop start) les bx, [bp-0E] // crypted pwd
    :1DC7 inc word ptr [bp+F2]
    :1DCA mov al , es:[bx] // char i from crypted pwd
    :1DCD cbw
    :1DCE mov dx, si // si depends on encryption method
    :1DD0 add dx, cx // cx=0,1,2,...,pwd'lenght
    :1DD2 xor ax, dx // ax=([crypted char i] XOR [si+cx])
    :1DD4 les bx, [bp-0A]
    :1DD7 inc word ptr [bp+F6]
    :1DDA push ax
    :1DDB mov al , es:[bx] // character i from input
    :1DDE cbw
    :1DDF pop dx
    :1DE0 cmp dx, ax // dx=pwd'char i ax=input'char i
    :1DE2 je 1DE8 // dx=ax?
    :1DE4 xor di, di // no, set di=0 and...
    :1DE6 jmp 1DEE // ...exit
    :1DE8 inc cx // yes, increment cx
    :1DE9 cmp cx, [bp-06] // another char to check?
    :1DEC (loop end) jl 1DC4 // yes, go on
    :1DEE jmp 1DF2 // no, exit
    Offset encryption SI=0x20
    Skytale encryption SI=0x22
    Logical encryption SI=0x24
    E-Mail encryption SI=0x26

    To sum up, the asm listing above is equivalent to the following C listing (quite shorter {:-) ):

    for(i=0;i<pwd_lenght;i++) { dx=si+i; pwd_uncrypted[i]=(pwd_crypted[i]^dx); }

    For instance, with E-Mail encryption (encrypt a file with "CASIMIR" as pwd):
    pwd_crypted[0]= e (0x65) = pwd_uncrypted[0]=(0x65^0x26)=0x43 C
    pwd_crypted[1]= f (0x66) = pwd_uncrypted[1]=(0x66^0x27)=0x41 A
    pwd_crypted[2]= { (0x7B) = pwd_uncrypted[2]=(0x7B^0x28)=0x53 S
    pwd_crypted[3]= ` (0x60) = pwd_uncrypted[3]=(0x60^0x29)=0x49 I
    pwd_crypted[4]= g (0x67) = pwd_uncrypted[4]=(0x67^0x2A)=0x4D M
    pwd_crypted[5]= b (0x62) = pwd_uncrypted[5]=(0x62^0x2B)=0x49 I
    pwd_crypted[6]= ~ (0x7E) = pwd_uncrypted[6]=(0x7E^0x2C)=0x52 R

    TE can remember what method was used by writing in crypted file, after crypted pwd: "Enc O", "Enc S", "Enc L" or "Enc E". I hope it will help...

    To Patch Or Not To Patch

    Anyway, you can just patch prg so it will let you in, even if you provide no pwd. To do so, you just have to disable the 3 checks:

    That's all... Hope you enjoyed!

    A la prochaine!

    Copyright 1998 by
    Caz

    An additional note:

    Rather than changing three jump instructions to force TE to allow the use of any password or no password, I achieved the desired effect by changing at :1DF4 the instruction "JNE 1E95" to a JE.

    Joe

    March 27, 1998