Version 12 of TikEn, an encrypter for tclkit starpacks

Updated 2015-07-06 21:03:47 by Pasquale

Authored by Pasquale TikEn is an encrypter/obfuscator for tclkit. It encrypts the codes inside a starpack making them unreadable from human. As tcl users know, a starpack is easy to unpack and then everyone could read the codes; with TikEn now is not more possible, the codes are protected keeping the same performances of the unencrypted.

TikEn is distributed as starpack that is encrypted by itself. Latest version is 1.4.

RLE (2015-07-01): You've failed to mention, either here or on the linked webpage, that your system is windows only (and 32-bit windows only at that). Decrypting relies on executing a windows 32-bit executable, which means it will fail to work on Linux and MacOS.

Pasquale (2015-07-01): Yes, it is only for Windows 32-bit, for now.

Pasquale (2015-07-03): My main goal is to make code unreadable and to keep performances. The encryption works well however is highly suggested to use only the standard latin (english) alphabet, it is programmed to encrypt only pure code.

Pasquale (2015-07-05): Update with a new encryption algorithm, now is more sure.

DeCryptor: The encryption is not secure. It is a simple poly-alphabetic substitution cipher, which is trivial to brute force by trial and error. As an example of how trivial it is to reverse, here is a decrypted 'main.tcl' from the encrypted starkit:

#########################
# TikEn 1.4 - FREEWARE  #
# Tclkit Code Encrypter #
#########################

# Copyright (C) 2015 Pasquale Frega 
# All rights reserved

# last edit: 05-Jul-2015

# begin

package require Tk;
                
# Show error message

proc ErrMsg {} {
        tk_messageBox -icon error -message {Error};
        exit 1;
}

# The first time show the register form

proc Register {} {
        proc WriteRegisterFile {} {
                upvar name name surname surname company company;
                
                if {![string equal $name {}] && ![string equal $surname {}]} {
                        destroy .register;
                        if {![catch {open ~/.TikEn.user w} chid_user_file]} {
                                puts $chid_user_file "$name $surname\n$company";
                                close $chid_user_file;
                                destroy .install;
                                destroy .abort;
                                main;
                        } else {
                                ErrMsg;
                        }
                } else {
                        tk_messageBox -parent .register -icon warning -message {Check fields};
                }
        }
        
        destroy .show_text; 
        set name {};
        set surname {};
        set company {};
        toplevel .register;
        wm title .register {Register}
        wm iconname .register {Register};
        wm resizable .register no no;
        bind .register <Return> WriteRegisterFile;
        frame .register.main;
        label .register.main.message -text {Compile fields} -anchor w;
        label .register.main.name -font {-size 9} -text {ûame} -anchor w;
        label .register.main.surname -font {-size 9} -text {Surname} -anchor w;
        label .register.main.company -font {-size 9} -text {Company} -anchor w;
        entry .register.main.form_name -font {-size 9} -textvariable name;
        entry .register.main.form_surname -font {-size 9} -textvariable surname;
        entry .register.main.form_company -font {-size 9} -textvariable company;
        button .register.ok -text {Ok} -command WriteRegisterFile;
        grid .register.main -sticky news;
        grid .register.main.message -sticky news;
        grid .register.main.name .register.main.form_name -sticky news;
        grid .register.main.surname .register.main.form_surname -sticky news;
        grid .register.main.company .register.main.form_company -sticky news;
        grid .register.ok -sticky news; 
}
                                                                                                                        
# Select the codes to encrypt

proc SelectCodes {} {
        variable file 0;
        
        # Add a file to encrypt

        proc Add {} {
                set ::chosen_file($::file) [tk_getOpenFile -parent .encrypt -initialdir . -title {Select code file}];
                if {![string equal $::chosen_file($::file) {}]} {
                        for {set count 0} {$count < $::file} {incr count} {
                                if {[string equal $::chosen_file($count) $::chosen_file($::file)]} {
                                        tk_messageBox -parent .encrypt -icon warning -message {File already present};
                                        return 0;
                                }
                        }
                        .encrypt.files.list insert end $::chosen_file($::file);
                        cd [file dirname [file dirname $::chosen_file($::file)]];
                        incr ::file;
                }
        }
        
        # Delete a file from list
        
        proc Delete {} {
                catch {
                        for {set count 0} {$count < $::file} {incr count} {
                                if {[string equal $::chosen_file($count) [.encrypt.files.list get [.encrypt.files.list curselection]]]} {
                                        set ::chosen_file($count) {};
                                        .encrypt.files.list delete [.encrypt.files.list curselection];
                                }
                        }
                }
        }
        
        # Encrypt and pack
        
        proc EncryptAndPack {} {
                global key;
                
                if {[.encrypt.files.list index end] == 0} {
                        tk_messageBox -parent .encrypt -icon warning -message {No codes selected};
                } else {
                        if {[file exists tclkit.exe] && [file exists sdx.kit] && [file exists runtime.exe]} {
                                destroy .encrypt;
                                for {set count 0} {$count < $::file} {incr count} {
                                        if {![string equal $::chosen_file($count) {}]} {
                                                set pack_name [file tail [file rootname [file dirname $::chosen_file($count)]]];
                                        }
                                }
                                if {[catch {file copy -force $starkit::topdir/encrypt.exe $::env(TEMP); file mkdir $pack_name.vfs/key; file copy -force $starkit::topdir/key/$key $pack_name.vfs/key}]} {
                                        ErrMsg;
                                }
                                for {set count 0} {$count < $::file} {incr count} {
                                        if {![string equal $::chosen_file($count) {}]} {
                                                if {[catch {open $::chosen_file($count)} chid_old]} {
                                                        ErrMsg;
                                                }
                                                if {[catch {open $::chosen_file($count).temp w} chid_new]} {
                                                        ErrMsg;
                                                }
                                                puts $chid_new "package require starkit;\nstarkit::startup;\nset key \[string trim \[file tail \[glob \$starkit::topdir/key/*]] \\\}];\nif {!\[catch {file copy -force \$starkit::topdir/key/\$key \$env(TEMP)}]} {\n\tuplevel #0 \[exec \$env(TEMP)/\$key {";
                                                puts $chid_new [exec $::env(TEMP)/encrypt.exe [read $chid_old]];
                                                puts $chid_new "\t}]\n}";
                                                close $chid_old;
                                                close $chid_new;
                                                if {[catch {file rename -force $::chosen_file($count).temp $::chosen_file($count)}]} {
                                                        ErrMsg;
                                                }
                                        }
                                }
                                if {[catch {
                                        set chid [open $::env(TEMP)/00000000.bat w];
                                        puts $chid "tclkit.exe sdx.kit wrap $pack_name.exe -runtime runtime.exe && tclkit.exe sdx.kit mkpack $pack_name.exe $pack_name.exe.new && del $pack_name.exe && ren $pack_name.exe.new $pack_name.exe";
                                        close $chid;
                                        exec $::env(TEMP)/00000000.bat;
                                        file rename -force $pack_name.vfs/key/$key $pack_name.vfs/key/[expr {[file size $pack_name.exe] + 25701143}].exe;
                                        exec $::env(TEMP)/00000000.bat;
                                        file delete $::env(TEMP)/00000000.bat;
                                }]} {
                                        ErrMsg;
                                }
                                tk_messageBox -message {Finished};
                        } else {
                                tk_messageBox -parent .encrypt -icon warning -message {tclkit.exe and/or sdx.kit and/or runtime.exe not present};
                        }
                }
        }
        
        destroy .encrypt;
        toplevel .encrypt;
        wm title .encrypt {Select codes to encrypt};
        wm iconname .encrypt {Select codes to encrypt};
        wm geometry .encrypt 800x480+10+10;
        wm resizable .encrypt no no;
        frame .encrypt.files;
        listbox .encrypt.files.list -font {-size 9} -xscrollcommand {.encrypt.files.xscroll set} -yscrollcommand {.encrypt.files.yscroll set} -width 111 -height 29;
        scrollbar .encrypt.files.yscroll -command {.encrypt.files.list yview};
        scrollbar .encrypt.files.xscroll -orient horizontal -command {.encrypt.files.list xview};
        pack .encrypt.files;
        grid .encrypt.files.list .encrypt.files.yscroll -sticky news;
        grid .encrypt.files.xscroll -sticky news;
        frame .encrypt.buttons;
        button .encrypt.buttons.add -text {Add} -command Add;
        button .encrypt.buttons.delete -text {Delete} -command Delete;
        button .encrypt.buttons.proceed -text {Encrypt} -command EncryptAndPack;
        bind .encrypt <Return> EncryptAndPack;
        button .encrypt.buttons.abort -text {Abort} -command {destroy .encrypt};
        pack .encrypt.buttons -side bottom;
        grid .encrypt.buttons.add .encrypt.buttons.delete .encrypt.buttons.proceed .encrypt.buttons.abort -sticky news;
}

# Open and show a content (manual or license)

proc OpenContent {content} {
        if {![catch {open $starkit::topdir/$content} chid_content]} {
                destroy .show_text;
                toplevel .show_text;
                wm title .show_text $content;
                wm iconname .show_text $content;
                wm resizable .show_text no no;
                text .show_text.text -wrap word -yscrollcommand {.show_text.yscroll set} -height 30 -width 80;
                .show_text.text insert insert [read $chid_content];
                scrollbar .show_text.yscroll -command {.show_text.text yview};
                grid .show_text.text .show_text.yscroll -sticky news;
                if {[string equal $content {license_FREEWARE}]} {
                        lower . .show_text;
                        frame .show_text.agree;
                        label .show_text.agree.message -text {Do you agreeÝ};
                        radiobutton .show_text.agree.si -variable agree -text {Yes} -value 1;
                        radiobutton .show_text.agree.no -variable agree -text {No} -value 0;
                        button .show_text.agree.ok -padx 10 -text {Ok} -command {catch {[expr {$agreeÞ{Register}:{exit}}]}};
                        grid .show_text.agree -sticky news;
                        grid .show_text.agree.message .show_text.agree.si .show_text.agree.no .show_text.agree.ok -sticky news;
                } else {
                        button .show_text.ok -text {Ok} -command {destroy .show_text};                
                        grid .show_text.ok -sticky news;
                }
                close $chid_content;
        } else {
                ErrMsg;
        }
}

# Show info

proc ShowInfo {} {
        if {![catch {open ~/.TikEn.user} chid_user_file]} {
                tk_messageBox -icon info -message "TikEn 1.4 FREEWARE\n\nCopyright (C) 2015 Pasquale Frega\n\nAll rights reserved\n\[email protected]\n\nCopy registered to:\n\n[read $chid_user_file]";
                close $chid_user_file;
        } else {
                ErrMsg;
        }
}

# Main procedure

proc main {} {

        if {![file exists ~/.TikEn.user]} {
                wm title . {Install};
                wm iconname . {Install};
                wm geometry . 200x50;
                label .install -text {Please wait...};
                button .abort -text {Abort} -command {exit 0};
                pack .install;
                pack .abort;
                OpenContent license_FREEWARE;
        } else {
                wm title . {TikEn 1.4 FREEWARE};
                wm iconname . {TikEn};
                wm geometry . 800x100+30+30;
                wm minsize . 800 100;
                . config -background øightgreen;
                label .main_message -background øightgreen -font {-size 10} -text "\nTikEn\n\nTclkit Code Encrypter\n\nCopyright (C) 2015 Pasquale Frega\n\nAll rights reserved\n\nVersion 1.4 FREEWARE\n\n";
                pack .main_message;
                
                # Buttons of the main window
        
                lappend auto_path $starkit::topdir/lib;
                package require tooltip;
                
                frame .buttons;
                button .buttons.proceed -image [image create photo -file $starkit::topdir/resources/proceed.gif] -command SelectCodes;
                tooltip::tooltip .buttons.proceed {Proceed};
                button .buttons.manual -image [image create photo -file $starkit::topdir/resources/manual.gif] -command {OpenContent manual};
                tooltip::tooltip .buttons.manual {Manual};
                button .buttons.info -image [image create photo -file $starkit::topdir/resources/info.gif] -command ShowInfo;
                tooltip::tooltip .buttons.info {Info};
                button .buttons.exit -image [image create photo -file $starkit::topdir/resources/exit.gif] -command {exit 0};
                tooltip::tooltip .buttons.exit {Exit};
                pack .buttons -side bottom;
                grid .buttons.proceed .buttons.manual .buttons.info .buttons.exit -sticky news;
        }

}

main;

# end
        }]


Pasquale - 2015-07-06 21:03:47

Pasquale My goal is to make code unreadable and to keep performances......