-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
FadCrypt.py
2599 lines (1864 loc) · 103 KB
/
FadCrypt.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import os
import json
import threading
import subprocess
import time
import getpass
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.exceptions import InvalidTag
import psutil
import tkinter as tk
from tkinter import ttk, simpledialog, messagebox, filedialog, PhotoImage
import winreg
import signal
from PIL import Image, ImageDraw
from pystray import Icon, Menu, MenuItem
import sys
import base64
from cryptography.fernet import Fernet
import shutil
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from tkinterdnd2 import TkinterDnD, DND_FILES # Import the tkinterdnd2 module
import ctypes
from ttkbootstrap import Style
from PIL import Image, ImageTk
import webbrowser
import random
import requests
import pygame
from ctypes import wintypes
# App Version Information
__version__ = "0.1.0"
__version_code__ = 1 # Increment this for each release
# Embedded configuration and state data
embedded_config = {
"applications": []
}
embedded_state = {
"unlocked_apps": []
}
class AppLockerGUI:
def __init__(self, master):
self.master = master
self.master.title("FadCrypt")
# Center the dialog on the screen
screen_width = self.master.winfo_screenwidth()
screen_height = self.master.winfo_screenheight()
dialog_width = 700 # Adjust width as needed
dialog_height = 550 # Adjust height as needed
position_x = (screen_width // 2) - (dialog_width // 2)
position_y = (screen_height // 2) - (dialog_height // 2)
self.master.geometry(f"{dialog_width}x{dialog_height}+{position_x}+{position_y}")
# self.master.geometry("700x450") # Adjusted size to accommodate new tabs
# Prevent resizing
self.master.resizable(False, False)
self.app_locker = AppLocker(self)
# Ensure the settings file is correctly initialized
self.settings_file = os.path.join(self.app_locker.get_fadcrypt_folder(), 'settings.json')
self.lock_tools_var = tk.BooleanVar(value=True) # Default value is True
self.password_dialog_style = tk.StringVar(value="simple")
self.wallpaper_choice = tk.StringVar(value="default")
self.set_app_icon() # Set the custom app icon
self.create_widgets()
self.load_settings()
# Automatically start monitoring if launched with the --auto-monitor flag
if '--auto-monitor' in sys.argv:
self.start_monitoring(auto_start=True)
def resource_path(self, relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
def open_add_application_dialog(self):
self.add_dialog = tk.Toplevel(self.master) # Store reference to the dialog
self.add_dialog.title("Add Application to Encrypt")
# Set the same icon for the dialog
# if hasattr(self, 'icon_img'):
# self.add_dialog.iconphoto(False, self.icon_img)
# self.add_dialog.update_idletasks() # Force update the dialog to ensure the icon is set
# Center the dialog on the screen
screen_width = self.add_dialog.winfo_screenwidth()
screen_height = self.add_dialog.winfo_screenheight()
dialog_width = 400 # Adjust width as needed
dialog_height = 500 # Adjust height as needed
# position_x = (screen_width // 2) - (dialog_width // 2)
position_x = 50 # Position the dialog on the left edge of the screen
position_y = (screen_height // 2) - (dialog_height // 2)
self.add_dialog.geometry(f"{dialog_width}x{dialog_height}+{position_x}+{position_y}")
# Prevent resizing
self.add_dialog.resizable(False, False)
# Ensure the dialog is focused
self.add_dialog.attributes('-topmost', True)
self.add_dialog.focus_set()
# Drag and Drop Area
drop_frame = tk.LabelFrame(self.add_dialog, text="Drag and Drop .exe Here")
drop_frame.pack(padx=10, pady=10, fill="both", expand=True)
# Use TkinterDnD for drag-and-drop functionality
drop_area = tk.Canvas(drop_frame, height=100, bg="lightgray")
drop_area.pack(padx=10, pady=10, fill="both", expand=True)
def update_text_position():
drop_area.delete("all") # Clear previous text
drop_area.create_text(
drop_area.winfo_width() // 2,
drop_area.winfo_height() // 2,
text="Just drop it in—I'll sort out the name and path,\nno worries",
fill="lightgreen",
font=("Arial", 9),
anchor="center"
)
# Update text position after the canvas is rendered
drop_area.after(100, update_text_position) # Adjust delay if needed
# Enable the canvas for drag-and-drop
drop_area.drop_target_register(DND_FILES)
drop_area.dnd_bind('<<Drop>>', self.on_drop)
# Manual Input Area
manual_frame = tk.LabelFrame(self.add_dialog, text="Or Manually Add Application")
manual_frame.pack(padx=10, pady=10, fill="both", expand=True)
tk.Label(manual_frame, text="Name:").pack(pady=5)
self.name_entry = tk.Entry(manual_frame)
self.name_entry.pack(padx=10, pady=5, fill="x")
tk.Label(manual_frame, text="Path:").pack(pady=5)
self.path_entry = tk.Entry(manual_frame)
self.path_entry.pack(padx=10, pady=5, fill="x")
browse_button = ttk.Button(manual_frame, text="Browse", command=self.browse_for_file, style="navy.TButton")
browse_button.pack(pady=5)
# Save Button
save_button = ttk.Button(self.add_dialog, text="Save", command=self.save_application, width=11, style="green.TButton")
save_button.pack(pady=10)
# Bind the Enter key to the Save button
self.add_dialog.bind('<Return>', lambda event: save_button.invoke())
def on_drop(self, event):
file_path = event.data.strip('{}') # Strip curly braces if present
if file_path.endswith('.exe'):
self.path_entry.delete(0, tk.END)
self.path_entry.insert(0, file_path)
app_name = os.path.basename(file_path)
self.name_entry.delete(0, tk.END)
self.name_entry.insert(0, app_name)
else:
self.show_message("Invalid File", "Please drop a valid .exe file.")
def browse_for_file(self):
file_path = filedialog.askopenfilename(filetypes=[("Executable Files", "*.exe")])
if file_path:
self.path_entry.delete(0, tk.END)
self.path_entry.insert(0, file_path)
app_name = os.path.basename(file_path)
self.name_entry.delete(0, tk.END)
self.name_entry.insert(0, app_name)
def save_application(self):
app_name = self.name_entry.get().strip()
app_path = self.path_entry.get().strip()
if not app_name or not app_path:
self.show_message("Error", "Both name and path are required.")
return
# Call the add_application method from AppLocker instance
self.app_locker.add_application(app_name, app_path)
self.update_apps_listbox()
self.update_config_display() # Update config tab
# Close the dialog
self.add_dialog.destroy()
self.show_message("Success", f"Application '{app_name}'\nadded successfully!")
def set_app_icon(self):
try:
# Load the .ico icon image for the taskbar (Windows)
# Image for the main tab's logo above the start monitoring button
ico_path = self.resource_path('img/1.ico') # Update this path to your .ico file
if os.path.exists(ico_path):
self.master.iconbitmap(ico_path)
else:
print(f"Icon file {ico_path} not found, skipping .ico icon.")
# Load the .png icon image for the window icon
# taskbar and topbar image
png_path = self.resource_path('img/icon.png') # Update this path to your .png file to set the app icon which appears in startbar and in the topbar
if os.path.exists(png_path):
icon_img = PhotoImage(file=png_path)
self.master.iconphoto(False, icon_img)
else:
print(f"Icon file {png_path} not found, skipping .png icon.")
except Exception as e:
print(f"Failed to set application icon: {e}")
def create_widgets(self):
self.notebook = ttk.Notebook(self.master)
self.notebook.pack(expand=True, fill="both")
# Main Tab
self.main_frame = ttk.Frame(self.notebook)
self.notebook.add(self.main_frame, text="Main")
try:
# Load and display image
self.load_image()
self.image_label = tk.Label(self.main_frame, image=self.img)
self.image_label.pack(pady=20)
except:
print("create_widget: Failed to load logo image...")
# Frame for centered buttons
center_buttons_frame = ttk.Frame(self.main_frame)
center_buttons_frame.pack(pady=10)
# Add Start Monitoring and Read Me buttons (centered)
self.start_button = ttk.Button(center_buttons_frame, text="Start Monitoring", command=self.start_monitoring, style='red.TButton')
self.start_button.pack(side=tk.LEFT, padx=10)
readme_button = ttk.Button(center_buttons_frame, text="Read Me", command=self.show_readme, style='navy.TButton')
readme_button.pack(side=tk.LEFT, padx=10)
# Create a frame for the left side buttons and separator
left_frame = ttk.Frame(self.main_frame)
left_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=0)
# Create a frame for the buttons
left_button_frame = ttk.Frame(left_frame)
left_button_frame.pack(side=tk.LEFT, fill=tk.Y)
# Add buttons to the left button frame
ttk.Button(left_button_frame, text="Stop Monitoring", command=self.stop_monitoring).pack(pady=5, fill=tk.X)
ttk.Button(left_button_frame, text="Create Password", command=self.create_password).pack(pady=5, fill=tk.X)
ttk.Button(left_button_frame, text="Change Password", command=self.change_password).pack(pady=5, fill=tk.X)
ttk.Button(left_button_frame, text="Snake 🪱", command=self.start_snake_game, style='navy.TButton').pack(pady=5, fill=tk.X)
# Add vertical separator, fill x for shorter separator in middle or y for full height
ttk.Separator(left_frame, orient=tk.VERTICAL).pack(side=tk.LEFT, fill=tk.X, padx=10)
# Add a separator before the footer
ttk.Separator(self.main_frame, orient=tk.HORIZONTAL).pack(fill=tk.X, pady=10, padx=20)
# Create a frame for the footer
footer_frame = ttk.Frame(self.main_frame)
footer_frame.pack(fill=tk.X, padx=10, pady=5)
# Load and scale the main tab's footer logo image
logo_image = Image.open(self.resource_path('img/fadsec-main-footer.png')) # Ensure 'fadsec.png' is in the 'img' directory
scale_factor = 0.4 # Scale to 40% of the original size
logo_image = logo_image.resize((int(logo_image.width * scale_factor),
int(logo_image.height * scale_factor)),
Image.LANCZOS)
logo_photo = ImageTk.PhotoImage(logo_image)
# Add branding logo (left side)
logo_label = tk.Label(footer_frame, image=logo_photo)
logo_label.image = logo_photo # Keep a reference to avoid garbage collection
logo_label.pack(side=tk.LEFT, padx=(0, 0)) # Add padding to the right of the logo
# Add remaining branding and license info (right side)
branding_text = " \u00A9 2024 | fadedhood.com | Licensed under GPL 3.0"
branding_label = ttk.Label(footer_frame, text=branding_text, foreground="gray", font=("Helvetica", 10))
branding_label.pack(side=tk.LEFT)
# Add GitHub link with star emoji (right side)
github_link = ttk.Label(footer_frame, text="⭐ Sponsor on GitHub", foreground="#FFD700", cursor="hand2", font=("Helvetica", 10))
github_link.pack(side=tk.RIGHT)
github_link.bind("<Button-1>", lambda e: webbrowser.open("https://github.com/anonfaded/FadCrypt"))
# Applications Tab
self.apps_frame = ttk.Frame(self.notebook)
self.notebook.add(self.apps_frame, text="Applications")
# Create a frame to hold the listbox and scrollbar
list_frame = ttk.Frame(self.apps_frame)
list_frame.pack(pady=5, padx=5, fill=tk.BOTH, expand=True)
# Create the listbox with a scrollbar
self.apps_listbox = tk.Listbox(list_frame, width=50, font=("Helvetica", 10), selectmode=tk.SINGLE)
self.apps_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.apps_listbox.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.apps_listbox.config(yscrollcommand=scrollbar.set)
self.update_apps_listbox()
# Buttons frame
button_frame = ttk.Frame(self.apps_frame)
button_frame.pack(pady=10, padx=5, fill=tk.X)
# Modify the Add button to open the new dialog
ttk.Button(button_frame, text="Add", command=self.open_add_application_dialog, style="green.TButton").pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="Remove", command=self.remove_application, style="red.TButton").pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="Rename", command=self.rename_application).pack(side=tk.LEFT, padx=5)
# State Tab
# self.state_frame = ttk.Frame(self.notebook)
# self.notebook.add(self.state_frame, text="State")
# self.state_text = tk.Text(self.state_frame, width=60, height=10)
# self.state_text.pack(pady=5)
# self.update_state_display()
# Config Tab
self.config_frame = ttk.Frame(self.notebook)
self.notebook.add(self.config_frame, text="Config")
# Title for the config section
config_title = ttk.Label(self.config_frame, text="Config File", font=("TkDefaultFont", 16, "bold"))
config_title.pack(anchor="w", padx=10, pady=(10, 0))
# Separator before textbox section
ttk.Separator(self.config_frame, orient='horizontal').pack(fill=tk.X, padx=10, pady=5)
# Config text box to display the config file content
self.config_text = tk.Text(self.config_frame, width=99, height=17)
self.config_text.pack(pady=5, padx=10)
self.update_config_display()
# Description below the config text box
config_description = ttk.Label(self.config_frame, text=(
"This is the list of applications currently locked by FadCrypt.\n"
"It is displayed in plain text here for your convenience, "
"but rest assured, the data is encrypted when saved on your computer,\n"
"keeping your locked apps confidential."
))
config_description.pack(anchor="w", padx=10, pady=(10, 10))
# Separator before export section
ttk.Separator(self.config_frame, orient='horizontal').pack(fill=tk.X, pady=10)
# Export config data section
export_frame = ttk.Frame(self.config_frame)
export_frame.pack(fill=tk.X, pady=10, padx=15)
export_title = ttk.Label(export_frame, text="Export Configurations", font=("TkDefaultFont", 10, "bold"))
export_title.pack(anchor="w", padx=10)
export_description = ttk.Label(export_frame, text="Export the list of applications added to the lock list.")
export_description.pack(anchor="w", pady=(0, 5), padx=10)
export_button = ttk.Button(export_frame, text="Export Config", command=self.export_config, style="green.TButton")
export_button.pack(anchor="w", padx=12)
# Settings Tab
self.settings_frame = ttk.Frame(self.notebook)
self.notebook.add(self.settings_frame, text="Settings")
# Create a canvas with scrollbar
self.canvas = tk.Canvas(self.settings_frame)
self.scrollbar = ttk.Scrollbar(self.settings_frame, orient="vertical", command=self.canvas.yview)
self.scrollable_frame = ttk.Frame(self.canvas)
self.scrollable_frame.bind(
"<Configure>",
lambda e: self.canvas.configure(
scrollregion=self.canvas.bbox("all")
)
)
self.canvas_frame = self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
# Configure canvas to expand with window
self.canvas.bind('<Configure>', self.configure_canvas)
self.canvas.configure(yscrollcommand=self.scrollbar.set)
# Enable mousewheel scrolling
self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
# Title
title_label = ttk.Label(self.scrollable_frame, text="Preferences", font=("TkDefaultFont", 16, "bold"))
title_label.pack(anchor="w", padx=10, pady=(10, 20))
# Separator after top frame
ttk.Separator(self.scrollable_frame, orient='horizontal').pack(fill=tk.X, padx=10, pady=5)
# Top frame for radio buttons and preview
top_frame = ttk.Frame(self.scrollable_frame)
top_frame.pack(fill=tk.X, padx=10, pady=10)
# Left frame for radio buttons
left_frame = ttk.Frame(top_frame)
left_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(3, 10))
# Right frame for preview
right_frame = ttk.Frame(top_frame)
right_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)
# Separator after preview section in settings tab
ttk.Separator(self.scrollable_frame, orient='horizontal').pack(fill=tk.X, pady=10)
# Bottom frame for checkboxes and export section
bottom_frame = ttk.Frame(self.scrollable_frame)
bottom_frame.pack(fill=tk.X, padx=10, pady=10)
# Radio buttons
ttk.Label(left_frame, text="Password Dialog Style:", font=("TkDefaultFont", 10, "bold")).pack(anchor="w", pady=10)
ttk.Radiobutton(left_frame, text="Simple Dialog", variable=self.password_dialog_style, value="simple", command=self.save_and_update_preview).pack(anchor="w", padx=20, pady=0)
ttk.Radiobutton(left_frame, text="Full Screen", variable=self.password_dialog_style, value="fullscreen", command=self.save_and_update_preview).pack(anchor="w", padx=20, pady=20)
ttk.Label(left_frame, text="Full Screen Wallpaper:", font=("TkDefaultFont", 10, "bold")).pack(anchor="w", pady=5)
ttk.Radiobutton(left_frame, text="Lab (Default)", variable=self.wallpaper_choice, value="default", command=self.save_and_update_wallpaper).pack(anchor="w", padx=20, pady=0)
ttk.Radiobutton(left_frame, text="H4ck3r", variable=self.wallpaper_choice, value="H4ck3r", command=self.save_and_update_wallpaper).pack(anchor="w", padx=20, pady=20)
ttk.Radiobutton(left_frame, text="Binary", variable=self.wallpaper_choice, value="Binary", command=self.save_and_update_wallpaper).pack(anchor="w", padx=20, pady=0)
ttk.Radiobutton(left_frame, text="Encryptedddddd", variable=self.wallpaper_choice, value="encrypted", command=self.save_and_update_wallpaper).pack(anchor="w", padx=20, pady=20)
# ttk.Radiobutton(left_frame, text="Lab", variable=self.wallpaper_choice, value="Lab", command=self.save_and_update_wallpaper).pack(anchor="w", padx=20, pady=0)
# Preview area
ttk.Label(right_frame, text="Dialog Preview:", font=("TkDefaultFont", 10, "bold")).pack(anchor="w", pady=10, padx=50)
self.preview_frame = ttk.Frame(right_frame, width=400, height=250) # Set a fixed size
self.preview_frame.pack(pady=10)
self.preview_frame.pack_propagate(False) # Prevent the frame from shrinking
self.preview_label = ttk.Label(self.preview_frame)
self.preview_label.pack(expand=True, fill=tk.BOTH)
# Checkbox (full width)
self.lock_tools_var = tk.BooleanVar(value=True)
lock_tools_checkbox_title = ttk.Label(bottom_frame, text="Disable Main loopholes", font=("TkDefaultFont", 10, "bold"))
lock_tools_checkbox_title.pack(anchor="w", pady=5, padx=27)
lock_tools_checkbox = ttk.Checkbutton(
bottom_frame,
text="Disable Command Prompt, Registry Editor, Control Panel, msconfig, and Task Manager during monitoring.\n"
"(Default: All are disabled for best security. For added security, please disable PowerShell as well; search\n"
"on internet for help. Otherwise, FadCrypt could be terminated via PowerShell.)",
variable=self.lock_tools_var,
command=self.save_settings
)
lock_tools_checkbox.pack(anchor="w", pady=10)
# Pack canvas and scrollbar
self.canvas.pack(side="left", fill="both", expand=True)
self.scrollbar.pack(side="right", fill="y")
# About Tab
self.about_frame = ttk.Frame(self.notebook)
self.notebook.add(self.about_frame, text="About")
# Load App Logo with Error Handling
try:
app_icon = tk.PhotoImage(file=self.resource_path('img/icon.png')).subsample(4, 4) # Resize the logo to 50x50 px
except tk.TclError:
print("Error: App icon 'img/icon.png' not found.")
app_icon = None
if app_icon:
icon_label = ttk.Label(self.about_frame, image=app_icon)
icon_label.image = app_icon # Keep a reference to avoid garbage collection
icon_label.pack(pady=20)
else:
icon_label = ttk.Label(self.about_frame, text="FadCrypt", font=("TkDefaultFont", 18, "bold"))
icon_label.pack(pady=20)
# App Name and Version
app_name_label = ttk.Label(self.about_frame, text="FadCrypt", font=("TkDefaultFont", 18, "bold"))
app_name_label.pack()
app_version_label = ttk.Label(self.about_frame, text=f"Version {__version__}", font=("TkDefaultFont", 10))
app_version_label.pack(pady=(0, 10))
# Check for Updates Button
update_button = ttk.Button(self.about_frame, text="Check for Updates", command=self.check_for_updates, style="green.TButton")
update_button.pack(pady=10)
# Description
description_label = ttk.Label(
self.about_frame,
text="FadCrypt is an open-source app lock/encryption software that prioritizes privacy by not tracking or collecting any data. It is available exclusively on GitHub and through the official links mentioned in the README.",
wraplength=400,
justify="center"
)
description_label.pack(pady=(0, 20))
# FadSec Lab Suite Information with Darker Background
suite_frame = ttk.Frame(self.about_frame, padding=10, style="Dark.TFrame")
suite_frame.pack(pady=10, padx=20)
suite_info_label = ttk.Label(suite_frame, text="FadCrypt is part of the FadSec Lab suite. For more information, click on 'View Source Code' below.", background="black", foreground="green")
suite_info_label.pack(anchor="center")
# Button Frame for Alignment
button_frame = ttk.Frame(self.about_frame)
button_frame.pack(pady=10)
# Source Code Button
source_code_button = ttk.Button(button_frame, text="View Source Code", command=self.open_source_code, style="navy.TButton")
source_code_button.grid(row=0, column=0, padx=(0, 10))
# Buy Me A Coffee Button
coffee_button = ttk.Button(button_frame, text="Buy Me A Coffee", command=lambda: webbrowser.open("https://ko-fi.com/fadedx"), style="yellow.TButton")
coffee_button.grid(row=0, column=1, padx=(0, 10))
# New Button: Join Discord
discord_button = ttk.Button(button_frame, text="Join Discord", command=lambda: webbrowser.open("https://discord.gg/kvAZvdkuuN"), style="blue.TButton")
discord_button.grid(row=0, column=2, padx=(0, 10))
# New Button: Write a Review
review_button = ttk.Button(button_frame, text="Write a Review", command=lambda: webbrowser.open("https://forms.gle/wnthyevjkRD41eTFA"), style="green.TButton")
review_button.grid(row=0, column=3)
# Promotion Section for Another App
separator = ttk.Separator(self.about_frame, orient='horizontal')
separator.pack(fill='x', pady=10)
# Title for Promotion Section
promo_title_label = ttk.Label(self.about_frame, text="Check out FadCam, our Android app from the FadSec Lab suite.", font=("TkDefaultFont", 12, "bold"))
promo_title_label.pack(pady=(0, 10))
# Frame for FadCam Promo and Button
fadcam_promo_frame = ttk.Frame(self.about_frame)
fadcam_promo_frame.pack(pady=10)
# fad cam App Icon and Title
try:
fadcam_icon = tk.PhotoImage(file=self.resource_path('img/fadcam.png')).subsample(12, 12) # Resize the logo to 50x50 px
except tk.TclError:
print("Error: FadCam icon 'fadcam_icon.png' not found.")
fadcam_icon = None
if fadcam_icon:
fadcam_label = ttk.Label(fadcam_promo_frame, image=fadcam_icon, text="FadCam - Open Source Ad-Free Offscreen Video Recorder.",
compound="left", font=("TkDefaultFont", 10, "bold"))
fadcam_label.image = fadcam_icon
fadcam_label.grid(row=0, column=0, padx=(0, 10))
fadcam_label.bind("<Button-1>", lambda e: webbrowser.open("https://github.com/anonfaded/FadCam"))
else:
fadcam_label = ttk.Label(fadcam_promo_frame, text="FadCam - Open Source Ad-Free Offscreen Video Recorder.",
font=("TkDefaultFont", 10, "bold"))
fadcam_label.grid(row=0, column=0, padx=(0, 10))
fadcam_label.bind("<Button-1>", lambda e: webbrowser.open("https://github.com/anonfaded/FadCam"))
# Button to Open FadCam Repo
fadcam_button = ttk.Button(fadcam_promo_frame, text="Get FadCam", command=lambda: webbrowser.open("https://github.com/anonfaded/FadCam"), style="red.TButton")
fadcam_button.grid(row=0, column=1)
self.update_preview()
# Method to open the GitHub page
def open_source_code(self):
webbrowser.open("https://github.com/anonfaded/FadCrypt")
# Method to check for updates
def check_for_updates(self):
try:
response = requests.get("https://api.github.com/repos/anonfaded/FadCrypt/releases/latest")
response.raise_for_status() # Ensure we got a valid response
latest_version = response.json().get("tag_name", None)
current_version = __version__
if latest_version and latest_version != current_version:
self.show_message("Update Available", f"New version {latest_version} is available! Visit GitHub for more details.")
else:
self.show_message("Up to Date", "Your application is up to date.")
except requests.ConnectionError:
self.show_message("Connection Error", "Unable to check for updates. Please check your internet connection.")
except requests.HTTPError as http_err:
self.show_message("HTTP Error", f"HTTP error occurred:\n{http_err}")
except Exception as e:
self.show_message("Error", f"An error occurred while checking for updates: {str(e)}")
def show_readme(self):
# Show the Read Me dialog first
self.fullscreen_readme_dialog()
def fullscreen_readme_dialog(self):
dialog = tk.Toplevel(self.master)
dialog.attributes('-alpha', 0.0) # Start fully transparent
dialog.update_idletasks() # Update geometry-related information
# Set dialog to fullscreen
dialog.attributes('-fullscreen', True)
dialog.geometry(f"{dialog.winfo_screenwidth()}x{dialog.winfo_screenheight()}")
# Center the dialog on the screen
screen_width = dialog.winfo_screenwidth()
screen_height = dialog.winfo_screenheight()
dialog_width = screen_width
dialog_height = screen_height
position_x = 0
position_y = 0
dialog.geometry(f"{dialog_width}x{dialog_height}+{position_x}+{position_y}")
dialog.grab_set()
# Add a frame for the text
text_frame = tk.Frame(dialog, bg='white')
text_frame.pack(expand=True, pady=50)
welcome_text = (
"Welcome to FadCrypt!\n\n"
"Experience top-notch security and sleek design with FadCrypt.\n\n"
"Features:\n"
"- Application Locking: Secure apps with an encrypted password. Save your password safely;\nit can't be recovered if lost!\n"
"- Real-time Monitoring: Detects and auto-recovers critical files if they are deleted.\n"
"- Auto-Startup: After starting monitoring, the app will be automatically enabled for every session.\n"
"- Aesthetic UI: Choose custom wallpapers or a minimal style with smooth animations.\n\n"
"Security:\n"
"- System Tools Disabled: Disables Command Prompt, Task Manager, msconfig, Control Panel, and Registry Editor;\n a real nightmare for attackers trying to bypass it.\n Manual PowerShell disabling is recommended as it's a significant loophole!\n"
"- Encrypted Storage: Passwords and config file data (list of locked apps) are encrypted and backed up.\n\n"
"Testing:\n"
"- Test blocked tools (Command Prompt, Task Manager) via Windows search to confirm effectiveness.\nSearch for Control Panel or Task Manager in Windows+S search and see the disabled message box.\n\n"
"Upcoming Features:\n"
"- Password Recovery: In case of a forgotten password, users will be able to recover their passwords.\n"
"- Logging and Alerts: Includes screenshots, email alerts on wrong password attempts, and detailed logs.\n"
"- Community Input: Integrating feedback for improved security and usability.\n\n"
"Extras:\n"
"- Snake Game: Enjoy the classic Snake game on the main tab or from the tray icon for a bit of fun!\n\n"
"# Join our Discord community via the 'Settings' tab\nfor help, questions, or to share your ideas and feedback."
)
# Create a label to hold the animated text
self.animated_label = tk.Label(text_frame, text="", font=("Arial", 16), bg='white', justify="left", anchor="nw")
self.animated_label.pack(padx=50, pady=50, anchor="n")
# Start the typewriter animation
self.animate_text(welcome_text, dialog)
# Add a button to close the dialog
ok_button = ttk.Button(dialog, text="OK", command=lambda: self.fade_out(dialog), style='red.TButton', width="11")
ok_button.pack(pady=20)
# Bind the Enter key to the OK button
dialog.bind('<Return>', lambda event: dialog.destroy())
# Load and place the image in the bottom left corner
self.load_readme_image(dialog)
# Fade in effect
self.fade_in(dialog)
# Ensure the dialog stays on top
dialog.wait_window()
def animate_text(self, text, dialog, index=0):
if index < len(text):
self.animated_label.config(text=text[:index+1])
dialog.after(2, self.animate_text, text, dialog, index+1) # Adjust the speed here
def load_readme_image(self, dialog):
# Load the image using PIL
img = Image.open(self.resource_path("img/readme.png"))
img = img.resize((400, 400), Image.LANCZOS) # Adjust the size as needed
photo = ImageTk.PhotoImage(img)
# Create a label to display the image
image_label = tk.Label(dialog, image=photo, bg='white')
image_label.image = photo # Keep a reference to avoid garbage collection
# Place the image in the bottom left corner
image_label.place(x=10, y=dialog.winfo_screenheight() - 400)
def fade_in(self, window):
alpha = 0.0
while alpha < 1.0:
alpha += 0.05
window.attributes('-alpha', alpha)
window.update_idletasks()
window.after(50) # Adjust the delay to control the fade-in speed
def fade_out(self, window):
alpha = window.attributes('-alpha')
if alpha > 0:
alpha -= 0.05
window.attributes('-alpha', alpha)
window.after(50, self.fade_out, window)
else:
window.destroy()
def configure_canvas(self, event):
# Update the width of the canvas window to fit the frame
self.canvas.itemconfig(self.canvas_frame, width=event.width)
# Update the initial canvas window height to fit the frame
if self.scrollable_frame.winfo_reqheight() < event.height:
self.canvas.itemconfig(self.canvas_frame, height=event.height)
else:
self.canvas.itemconfig(self.canvas_frame, height=self.scrollable_frame.winfo_reqheight())
def _on_mousewheel(self, event):
self.canvas.yview_scroll(int(-1*(event.delta/120)), "units")
def save_and_update_preview(self):
self.save_password_dialog_style()
self.update_preview()
def save_and_update_wallpaper(self):
self.save_wallpaper_choice()
self.update_preview()
def save_password_dialog_style(self):
self.save_settings()
def save_wallpaper_choice(self):
self.save_settings()
def update_preview(self):
dialog_style = self.password_dialog_style.get()
wallpaper_choice = self.wallpaper_choice.get()
if dialog_style == "simple":
preview_path = self.resource_path("img/preview1.png")
elif dialog_style == "fullscreen":
if wallpaper_choice == "default":
preview_path = self.resource_path("img/wall1.png")
elif wallpaper_choice == "H4ck3r":
preview_path = self.resource_path("img/wall2.png")
elif wallpaper_choice == "Binary":
preview_path = self.resource_path("img/wall3.png")
elif wallpaper_choice == "encrypted":
preview_path = self.resource_path("img/wall4.png")
else:
preview_path = self.resource_path("img/preview2.png") # Fallback to fullscreen preview if no wallpaper selected
else:
preview_path = self.resource_path("img/preview2.png") # Fallback to fullscreen preview if no style selected
try:
preview_image = Image.open(preview_path)
preview_image = preview_image.resize((400, 250), Image.Resampling.LANCZOS)
preview_photo = ImageTk.PhotoImage(preview_image)
self.preview_label.config(image=preview_photo)
self.preview_label.image = preview_photo
except FileNotFoundError:
print(f"Preview image not found: {preview_path}")
# image for the main page above the buttons
def load_image(self):
# Open and prepare the image
try:
image = Image.open(self.resource_path('img/banner.png')) # Update this path
image = image.resize((700, 200), Image.LANCZOS) # Resize using LANCZOS filter
self.img = ImageTk.PhotoImage(image)
except:
print("load_image: unable to load 1.ico")
def update_config_textbox(self):
# Update the content of the config text box with the latest config data
config_json = json.dumps(self.app_locker.config, indent=4)
self.config_textbox.config(state=tk.NORMAL)
self.config_textbox.delete(1.0, tk.END)
self.config_textbox.insert(tk.END, config_json)
self.config_textbox.config(state=tk.DISABLED)