DWORD request_sniffer_capture_stop(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid; CaptureJob *j; DWORD result; check_pssdk(); dprintf("sniffer>> stop_capture()"); ifid = packet_get_tlv_value_uint(packet, TLV_TYPE_SNIFFER_INTERFACE_ID); dprintf("sniffer>> stop_capture(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 is not being captured #ifdef _WIN32 if (!j->adp) #else if (!j->pcap) #endif { result = ERROR_INVALID_PARAMETER; break; } lock_acquire(snifferm); j->active = 0; #ifdef _WIN32 AdpSetMacFilter(j->adp, 0); AdpCloseAdapter(j->adp); AdpDestroy(j->adp); #else thread_sigterm(j->thread); thread_join(j->thread); // should take less than 1 second :p #endif 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); lock_release(snifferm); dprintf("sniffer>> stop_capture() interface %d processed %d packets/%d bytes", j->intf, j->cur_pkts, j->cur_bytes); } while (0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Creates a registry key and returns the associated HKEY to the caller if the * operation succeeds. * * TLVs: * * req: TLV_TYPE_ROOT_KEY - The root key * req: TLV_TYPE_BASE_KEY - The base key * opt: TLV_TYPE_PERMISSION - Permissions with which to create the key */ DWORD request_registry_create_key(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); LPCTSTR baseKey = NULL; HKEY rootKey = NULL, resKey; DWORD permission; DWORD result; rootKey = (HKEY)packet_get_tlv_value_uint(packet, TLV_TYPE_ROOT_KEY); baseKey = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY); permission = packet_get_tlv_value_uint(packet, TLV_TYPE_PERMISSION); // Validate the parameters and then attempt to create the key if ((!rootKey) || (!baseKey)) result = ERROR_INVALID_PARAMETER; else { if (!permission) permission = KEY_ALL_ACCESS; result = RegCreateKeyEx(rootKey, baseKey, 0, NULL, 0, permission, NULL, &resKey, NULL); } // Add the HKEY if we succeeded, but always return a result if (result == ERROR_SUCCESS) packet_add_tlv_uint(response, TLV_TYPE_HKEY, (DWORD)resKey); packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); packet_transmit(remote, response, NULL); return ERROR_SUCCESS; }
/* * Queries a registry value's type and data for a given HKEY. * * TLVs: * * req: TLV_TYPE_HKEY - The HKEY to query the value on * req: TLV_TYPE_VALUE_NAME - The name of the value to query */ DWORD request_registry_query_value(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); LPCSTR valueName = NULL; LPBYTE valueData = NULL; DWORD valueDataSize = 4096; DWORD result = ERROR_SUCCESS; DWORD valueType = 0; HKEY hkey = NULL; // Acquire the standard TLVs hkey = (HKEY)packet_get_tlv_value_uint(packet, TLV_TYPE_HKEY); valueName = packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME); do { // Get the size of the value data if ((result = RegQueryValueEx(hkey, valueName, 0, NULL, NULL, &valueDataSize)) != ERROR_SUCCESS) break; // Allocate storage for the value data if (!(valueData = (LPBYTE)malloc(valueDataSize))) continue; // Query the value's information if ((result = RegQueryValueEx(hkey, valueName, 0, &valueType, valueData, &valueDataSize)) != ERROR_SUCCESS) break; // Add the information about the value to the response packet_add_tlv_uint(response, TLV_TYPE_VALUE_TYPE, valueType); switch (valueType) { case REG_SZ: packet_add_tlv_string(response, TLV_TYPE_VALUE_DATA, (LPCSTR)valueData); break; case REG_DWORD: packet_add_tlv_uint(response, TLV_TYPE_VALUE_DATA, *(LPDWORD)valueData); break; default: packet_add_tlv_raw(response, TLV_TYPE_VALUE_DATA, valueData, valueDataSize); break; } } while (0); // Populate the result code packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); // Transmit the response packet_transmit(remote, response, NULL); return ERROR_SUCCESS; }
/*! * @brief Update the timeouts with the given values * @param remote Pointer to the \c Remote instance. * @param packet Pointer to the request packet. * @returns Indication of success or failure. * @remark If no values are given, no updates are made. The response to * this message is the new/current settings. */ DWORD remote_request_core_transport_set_timeouts(Remote * remote, Packet * packet) { DWORD result = ERROR_SUCCESS; Packet* response = NULL; do { response = packet_create_response(packet); if (!response) { result = ERROR_NOT_ENOUGH_MEMORY; break; } int expirationTimeout = (int)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_SESSION_EXP); int commsTimeout = (int)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_COMM_TIMEOUT); DWORD retryTotal = (DWORD)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_RETRY_TOTAL); DWORD retryWait = (DWORD)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_RETRY_WAIT); // TODO: put this in a helper function that can be used everywhere? // if it's in the past, that's fine, but 0 implies not set if (expirationTimeout != 0) { dprintf("[DISPATCH TIMEOUT] setting expiration time to %d", expirationTimeout); remote->sess_expiry_time = expirationTimeout; remote->sess_expiry_end = current_unix_timestamp() + expirationTimeout; } if (commsTimeout != 0) { dprintf("[DISPATCH TIMEOUT] setting comms timeout to %d", commsTimeout); remote->transport->timeouts.comms = commsTimeout; remote->transport->comms_last_packet = current_unix_timestamp(); } if (retryTotal > 0) { dprintf("[DISPATCH TIMEOUT] setting retry total to %u", retryTotal); remote->transport->timeouts.retry_total = retryTotal; } if (retryWait > 0) { dprintf("[DISPATCH TIMEOUT] setting retry wait to %u", retryWait); remote->transport->timeouts.retry_wait = retryWait; } // for the session expiry, return how many seconds are left before the session actually expires packet_add_tlv_uint(response, TLV_TYPE_TRANS_SESSION_EXP, remote->sess_expiry_end - current_unix_timestamp()); packet_add_tlv_uint(response, TLV_TYPE_TRANS_COMM_TIMEOUT, remote->transport->timeouts.comms); packet_add_tlv_uint(response, TLV_TYPE_TRANS_RETRY_TOTAL, remote->transport->timeouts.retry_total); packet_add_tlv_uint(response, TLV_TYPE_TRANS_RETRY_WAIT, remote->transport->timeouts.retry_wait); } while (0); if (response) { packet_transmit_response(result, remote, response); } return result; }
DWORD request_sniffer_capture_release(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid,i; CaptureJob *j; DWORD result; check_pssdk(); dprintf("sniffer>> release_capture()"); ifid = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_INTERFACE_ID); dprintf("sniffer>> release_capture(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 is not being captured #ifdef _WIN32 if(! j->adp || j->active == 1) #else if(! j->pcap || j->active == 1) #endif { result = ERROR_INVALID_PARAMETER; break; } lock_acquire(snifferm); 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); dprintf("sniffer>> release_capture() interface %d released %d packets/%d bytes", j->intf, j->cur_pkts, j->cur_bytes); for(i=0; i<j->max_pkts; i++) { if(!j->pkts[i]) break; PktDestroy(j->pkts[i]); j->pkts[i] = NULL; } free(j->pkts); memset(j, 0, sizeof(CaptureJob)); lock_release(snifferm); } while(0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Write to the remote end of the channel */ DWORD channel_write(Channel *channel, Remote *remote, Tlv *addend, DWORD addendLength, PUCHAR buffer, ULONG length, ChannelCompletionRoutine *completionRoutine) { PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL; ChannelCompletionRoutine *dupe = NULL; DWORD res = ERROR_SUCCESS; LPCSTR method = "core_channel_write"; Packet *request; Tlv methodTlv; do { // Allocate a request packet if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, NULL))) { res = ERROR_NOT_ENOUGH_MEMORY; break; } // Add the supplied TLVs packet_add_tlvs(request, addend, addendLength); // If no method TLV as added, add the default one. if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS) packet_add_tlv_string(request, TLV_TYPE_METHOD, method); // Add the channel identifier and the length to write packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel)); // if the channel data is ment to be compressed, compress it! if( channel_is_flag( channel, CHANNEL_FLAG_COMPRESS ) ) packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA|TLV_META_TYPE_COMPRESSED, buffer, length); else packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA, buffer, length); packet_add_tlv_uint(request, TLV_TYPE_LENGTH, channel_get_id(channel)); // Initialize the packet completion routine if (completionRoutine) { // Duplicate the completion routine dupe = channel_duplicate_completion_routine(completionRoutine); requestCompletion.context = dupe; requestCompletion.routine = _channel_packet_completion_routine; realRequestCompletion = &requestCompletion; } // Transmit the packet with the supplied completion routine, if any. res = packet_transmit(remote, request, realRequestCompletion); } while (0); return res; }
/* * Read data from the remote end of the channel. */ DWORD channel_read(Channel *channel, Remote *remote, Tlv *addend, DWORD addendLength, ULONG length, ChannelCompletionRoutine *completionRoutine) { PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL; ChannelCompletionRoutine *dupe = NULL; Packet *request; DWORD res = ERROR_SUCCESS; PCHAR method = "core_channel_read"; Tlv methodTlv; do { // Allocate an empty request if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, NULL))) { res = ERROR_NOT_ENOUGH_MEMORY; break; } // Add the supplied TLVs packet_add_tlvs(request, addend, addendLength); // If no method TLV as added, add the default one. if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS) packet_add_tlv_string(request, TLV_TYPE_METHOD, method); // Add the channel identifier and the length to read packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel)); packet_add_tlv_uint(request, TLV_TYPE_LENGTH, length); // Initialize the packet completion routine if (completionRoutine) { // Duplicate the completion routine dupe = channel_duplicate_completion_routine(completionRoutine); requestCompletion.context = dupe; requestCompletion.routine = _channel_packet_completion_routine; realRequestCompletion = &requestCompletion; } // Transmit the packet with the supplied completion routine, if any. res = packet_transmit(remote, request, realRequestCompletion); } while (0); return res; }
static DWORD request_sniffer_capture_dump_read(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid; unsigned int bcnt; CaptureJob *j; DWORD result; check_pssdk(); dprintf("sniffer>> capture_dump_read()"); ifid = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_INTERFACE_ID); bcnt = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_BYTE_COUNT); bcnt = min(bcnt, 32*1024*1024); dprintf("sniffer>> capture_dump_read(0x%.8x, %d)", ifid, bcnt); result = ERROR_SUCCESS; do { // the interface is invalid if(ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) { packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, 0); break; } j = &open_captures[ifid]; if(! j->dbuf) { packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, 0); break; } if(j->didx + bcnt > j->dlen) { bcnt = j->dlen - j->didx; } packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, bcnt); packet_add_tlv_raw(response, TLV_TYPE_SNIFFER_PACKET, (unsigned char *)j->dbuf+j->didx, bcnt); j->didx += bcnt; } while(0); // Free memory if the read is complete if(j->didx >= j->dlen-1) { free(j->dbuf); j->dbuf = NULL; j->didx = 0; j->dlen = 0; } packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Handles the getpid request */ DWORD request_sys_process_getpid(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); #ifdef _WIN32 packet_add_tlv_uint(response, TLV_TYPE_PID, GetCurrentProcessId()); #else packet_add_tlv_uint(response, TLV_TYPE_PID, getpid()); #endif packet_transmit_response(ERROR_SUCCESS, remote, response); return ERROR_SUCCESS; }
DWORD channel_write(Channel *channel, Remote *remote, Tlv *addend, DWORD addendLength, PUCHAR buffer, ULONG length, ChannelCompletionRoutine *completionRoutine) { PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL; ChannelCompletionRoutine *dupe = NULL; DWORD res = ERROR_SUCCESS; LPCSTR method = "core_channel_write"; Packet *request; Tlv methodTlv; do { if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, NULL))) { res = ERROR_NOT_ENOUGH_MEMORY; break; } packet_add_tlvs(request, addend, addendLength); if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS) packet_add_tlv_string(request, TLV_TYPE_METHOD, method); packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel)); if( channel_is_flag( channel, CHANNEL_FLAG_COMPRESS ) ) packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA|TLV_META_TYPE_COMPRESSED, buffer, length); else packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA, buffer, length); packet_add_tlv_uint(request, TLV_TYPE_LENGTH, channel_get_id(channel)); if (completionRoutine) { dupe = channel_duplicate_completion_routine(completionRoutine); requestCompletion.context = dupe; requestCompletion.routine = _channel_packet_completion_routine; realRequestCompletion = &requestCompletion; } res = packet_transmit(remote, request, realRequestCompletion); } while (0); return res; }
/* * Opens a remote registry key and returns the associated HKEY to the caller if the * operation succeeds. * * TLVs: * * req: TLV_TYPE_ROOT_KEY - The root key * req: TLV_TYPE_TARGET_HOST - The target machine name */ DWORD request_registry_open_remote_key(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); LPCTSTR targetHost = NULL; HKEY rootKey = NULL, resKey; DWORD result; targetHost = packet_get_tlv_value_string(packet, TLV_TYPE_TARGET_HOST); rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY); // Validate the parameters and then attempt to create the key if ((!rootKey) || (!targetHost)) result = ERROR_INVALID_PARAMETER; else { result = RegConnectRegistry(targetHost, rootKey, &resKey); } // Add the HKEY if we succeeded, but always return a result if (result == ERROR_SUCCESS) { packet_add_tlv_qword(response, TLV_TYPE_HKEY, (QWORD)resKey); } packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); packet_transmit(remote, response, NULL); 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; char *expanded = NULL; char *regular; regular = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH); if (regular == NULL) { result = ERROR_INVALID_PARAMETER; goto out; } // Allocate storage for the expanded path expanded = fs_expand_path(regular); if (expanded == NULL) { result = ERROR_NOT_ENOUGH_MEMORY; goto out; } packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, expanded); free(expanded); out: packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); return PACKET_TRANSMIT(remote, response, NULL); }
/* * Copies source file path to destination * * req: TLV_TYPE_FILE_PATH - The file path to expand */ DWORD request_fs_file_move(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; LPCSTR oldpath; LPCSTR newpath; oldpath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_NAME); newpath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH); if (!oldpath) result = ERROR_INVALID_PARAMETER; #ifdef _WIN32 else if (!MoveFile(oldpath,newpath)) #else else if (!rename(oldpath,newpath)) #endif result = GetLastError(); packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); packet_transmit(remote, response, NULL); return ERROR_SUCCESS; }
/* * Returns a list of thread identifiers that are running in the context of the * supplied process. * * req: TLV_TYPE_PID - The process identifier to operate on */ DWORD request_sys_process_thread_get_threads(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); THREADENTRY32 entry; HANDLE th32 = NULL; DWORD result = ERROR_SUCCESS; DWORD processId; processId = packet_get_tlv_value_uint(packet, TLV_TYPE_PID); do { // Validate the process identifier if (!processId) { result = ERROR_INVALID_PARAMETER; break; } // Get a snapshot of the threads running in the supplied process if (!(th32 = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, processId))) { result = GetLastError(); break; } entry.dwSize = sizeof(entry); // If the first enumeration fails, see why if (Thread32First(th32, &entry)) { // Keep looping until there are no more threads do { if (entry.th32OwnerProcessID != processId) continue; packet_add_tlv_uint(response, TLV_TYPE_THREAD_ID, entry.th32ThreadID); } while (Thread32Next(th32, &entry)); } // If we did not reach the end of the enumeration cleanly, something // stupid happened if (GetLastError() != ERROR_NO_MORE_FILES) { result = GetLastError(); break; } } while (0); packet_transmit_response(result, remote, response); // Cleanup if (th32) CloseHandle(th32); return ERROR_SUCCESS; }
/* * Queries a registry class for a given HKEY. * * TLVs: * * req: TLV_TYPE_HKEY - The HKEY to query the class on */ DWORD request_registry_query_class(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); LPCSTR valueName = NULL; BYTE valueData[4096]; DWORD valueDataSize = 4096; DWORD result = ERROR_SUCCESS; DWORD valueType = 0; HKEY hkey = NULL; // Acquire the standard TLVs hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY); do { // Get the size of the value data if ((result = RegQueryInfoKey(hkey, valueData, &valueDataSize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) != ERROR_SUCCESS) break; packet_add_tlv_string(response, TLV_TYPE_VALUE_DATA, (LPCSTR)valueData); } while (0); // Populate the result code packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); // Transmit the response packet_transmit(remote, response, NULL); return ERROR_SUCCESS; }
/* * Removes a registry key with the supplied root and base key information. * * TLVs: * * req: TLV_TYPE_ROOT_KEY - The root key handle. * req: TLV_TYPE_BASE_KEY - The base key name. * opt: TLV_TYPE_FLAGS - Zero or more flags that control how the key is * deleted. */ DWORD request_registry_delete_key(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); LPCSTR baseKey = NULL; DWORD result = ERROR_SUCCESS; DWORD flags = 0; HKEY rootKey = NULL; rootKey = (HKEY)packet_get_tlv_value_uint(packet, TLV_TYPE_ROOT_KEY); baseKey = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY); flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS); if ((!rootKey) || (!baseKey)) result = ERROR_INVALID_PARAMETER; else { if (flags & DELETE_KEY_FLAG_RECURSIVE) result = SHDeleteKey(rootKey, baseKey); else result = RegDeleteKey(rootKey, baseKey); } // Set the result and send the response packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); packet_transmit(remote, response, NULL); return ERROR_SUCCESS; }
/* * Returns the SHA1 hash for a specified file path * * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd */ DWORD request_fs_sha1(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); char *filePath; DWORD result = ERROR_SUCCESS; SHA_CTX context; FILE *fd; size_t ret; unsigned char buff[16384]; unsigned char hash[SHA_DIGEST_LENGTH + 1] = {0}; filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH); result = fs_fopen(filePath, "rb", &fd); if (result == ERROR_SUCCESS) { SHA1_Init(&context); while ((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) { SHA1_Update(&context, buff, ret); } fclose(fd); SHA1_Final(hash, &context); packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, sizeof(hash)); } packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); return PACKET_TRANSMIT(remote, response, NULL); }
/* * Returns the number of event records in an event log * * TLVs: * * req: TLV_TYPE_EVENT_HANDLE - The event log handle */ DWORD request_sys_eventlog_numrecords(Remote * remote, Packet * packet) { Packet * response = packet_create_response(packet); HANDLE hEvent = NULL; DWORD numRecords; DWORD result = ERROR_SUCCESS; hEvent = (HANDLE)packet_get_tlv_value_qword(packet, TLV_TYPE_EVENT_HANDLE); if(!hEvent) { result = ERROR_INVALID_PARAMETER; } else { if(GetNumberOfEventLogRecords(hEvent, &numRecords) == 0) { result = GetLastError(); } else { packet_add_tlv_uint(response, TLV_TYPE_EVENT_NUMRECORDS, numRecords); } } packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * sys_getuid * ---------- * * Gets the user information of the user the server is executing as */ DWORD request_getuid(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD res = ERROR_SUCCESS; CHAR username[512]; DWORD size = sizeof(username); memset(username, 0, sizeof(username)); do { // Get the username if (!GetUserName(username, &size)) { res = GetLastError(); break; } packet_add_tlv_string(response, TLV_TYPE_USER_NAME, username); } while (0); // Transmit the response if (response) { packet_add_tlv_uint(response, TLV_TYPE_RESULT, res); packet_transmit(remote, response, NULL); } return res; }
static void set_value(Remote *remote, Packet *packet, HKEY hkey) { Packet *response = packet_create_response(packet); LPCSTR valueName = NULL; DWORD valueType = 0; DWORD result = ERROR_SUCCESS; Tlv valueData; // Acquire the standard TLVs valueName = packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME); valueType = packet_get_tlv_value_uint(packet, TLV_TYPE_VALUE_TYPE); do { // Get the value data TLV if (packet_get_tlv(packet, TLV_TYPE_VALUE_DATA, &valueData) != ERROR_SUCCESS) { result = ERROR_INVALID_PARAMETER; break; } // Now let's rock this shit! result = RegSetValueEx(hkey, valueName, 0, valueType, valueData.buffer, valueData.header.length); } while (0); // Populate the result code packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); // Transmit the response packet_transmit(remote, response, NULL); }
DWORD request_resolve_hosts(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); Tlv hostname = {0}; int index = 0; int iResult; u_short ai_family = packet_get_tlv_value_uint(packet, TLV_TYPE_ADDR_TYPE); while( packet_enum_tlv( packet, index++, TLV_TYPE_HOST_NAME, &hostname ) == ERROR_SUCCESS ) { struct in_addr addr = {0}; struct in6_addr addr6 = {0}; iResult = resolve_host((LPCSTR)hostname.buffer, 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)); } } else { dprintf("Unable to resolve_host %s error: %x", hostname.buffer, iResult); packet_add_tlv_raw(response, TLV_TYPE_IP, NULL, 0); } packet_add_tlv_uint(response, TLV_TYPE_ADDR_TYPE, ai_family); } packet_transmit_response(NO_ERROR, remote, response); return ERROR_SUCCESS; }
/* * Gets information about the file path that is supplied and returns it to the * requestor * * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd */ DWORD request_fs_stat(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); struct meterp_stat buf; char *filePath; char *expanded = NULL; DWORD result = ERROR_SUCCESS; filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH); if (!filePath) { result = ERROR_INVALID_PARAMETER; goto out; } expanded = fs_expand_path(filePath); if (expanded == NULL) { result = ERROR_NOT_ENOUGH_MEMORY; goto out; } result = fs_stat(expanded, &buf); if (0 == result) { packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf, sizeof(buf)); } free(expanded); out: packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); return PACKET_TRANSMIT(remote, response, NULL); }
/* * Allocates a streaming TCP channel * * TLVs: * * req: TLV_TYPE_HOST_NAME - The host to connect to * req: TLV_TYPE_PORT - The port to connect to */ DWORD request_net_tcp_client_channel_open(Remote *remote, Packet *packet) { Channel *channel = NULL; Packet *response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; LPCSTR host; DWORD port; do { // No response packet? if (!response) break; // Extract the hostname and port that we are to connect to host = packet_get_tlv_value_string(packet, TLV_TYPE_PEER_HOST); port = packet_get_tlv_value_uint(packet, TLV_TYPE_PEER_PORT); // Open the TCP channel if ((result = create_tcp_client_channel(remote, host, (USHORT)(port & 0xffff), &channel)) != ERROR_SUCCESS) break; // Set the channel's identifier on the response packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(channel)); } while (0); // Transmit the response packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Open a TCP channel with the remote endpoint */ DWORD network_open_tcp_channel(Remote *remote, LPCSTR remoteHost, USHORT remotePort, PacketRequestCompletion *complete) { Packet *request = packet_create(PACKET_TLV_TYPE_REQUEST, "network_open_tcp_channel"); DWORD res = ERROR_SUCCESS; do { // Verify that the packet was allocated if (!request) { res = ERROR_NOT_ENOUGH_MEMORY; break; } // Add the host/port combination packet_add_tlv_string(request, TLV_TYPE_NETWORK_GENERAL_REMOTE_HOST, remoteHost); packet_add_tlv_uint(request, TLV_TYPE_NETWORK_GENERAL_REMOTE_PORT, remotePort); // Transmit the request res = packet_transmit(remote, request, complete); } while (0); return res; }
/* * Gets information about the file path that is supplied and returns it to the * requestor * * TLVs: * * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd */ DWORD request_fs_stat(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); struct meterp_stat buf; LPCSTR filePath; LPSTR expanded = NULL; DWORD result = ERROR_SUCCESS; filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH); // Validate parameters if (!filePath) result = ERROR_INVALID_PARAMETER; else if (!(expanded = fs_expand_path(filePath))) result = ERROR_NOT_ENOUGH_MEMORY; else { result = fs_stat(expanded, &buf); if (0 == result) packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf, sizeof(buf)); } // Set the result and transmit the response packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); packet_transmit(remote, response, NULL); if (expanded) free(expanded); return result; }
/* * Queries an address region for its attributes, such as size and protection * * req: TLV_TYPE_HANDLE - The process handle to operate on. * req: TLV_TYPE_BASE_ADDRESS - The address to query the attributes of. */ DWORD request_sys_process_memory_query(Remote *remote, Packet *packet) { MEMORY_BASIC_INFORMATION info; Packet *response = packet_create_response(packet); HANDLE handle; LPVOID base; DWORD result = ERROR_SUCCESS; SIZE_T size = 0; handle = (HANDLE)packet_get_tlv_value_qword(packet, TLV_TYPE_HANDLE); base = (LPVOID)packet_get_tlv_value_qword(packet, TLV_TYPE_BASE_ADDRESS); // Zero the info buffer memset(&info, 0, sizeof(info)); do { // Validate parameters if (!handle) { result = ERROR_INVALID_PARAMETER; break; } // No bytes returned? Suck. if (!(size = VirtualQueryEx(handle, base, &info, sizeof(info)))) { result = GetLastError(); break; } // Pass the parameters back to the requestor packet_add_tlv_qword(response, TLV_TYPE_BASE_ADDRESS, (QWORD)info.BaseAddress); packet_add_tlv_qword(response, TLV_TYPE_ALLOC_BASE_ADDRESS, (QWORD)info.AllocationBase); packet_add_tlv_uint(response, TLV_TYPE_ALLOC_PROTECTION, info.AllocationProtect); packet_add_tlv_uint(response, TLV_TYPE_LENGTH, (DWORD)info.RegionSize); packet_add_tlv_uint(response, TLV_TYPE_MEMORY_STATE, (DWORD)info.State); packet_add_tlv_uint(response, TLV_TYPE_PROTECTION, info.Protect); packet_add_tlv_uint(response, TLV_TYPE_MEMORY_TYPE, info.Type); } while (0); // 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 #ifdef _WIN32 if(! j->adp) #else if (!j->pcap) #endif { result = ERROR_INVALID_PARAMETER; break; } lock_acquire(snifferm); 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); lock_release(snifferm); } while (0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Creates a thread in the context of the supplied process and returns the * handle that was allocated to represent it to the requestor. * * req: TLV_TYPE_HANDLE - The process handle within which to allocate the * thread. * req: TLV_TYPE_ENTRY_POINT - The entry point of the thread. * opt: TLV_TYPE_ENTRY_PARAMETER - The parameter that is passed to the thread * entry * req: TLV_TYPE_CREATION_FLAGS - Flags used for creation of the thread */ DWORD request_sys_process_thread_create(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); HANDLE process, thread = NULL; LPVOID entryPoint; LPVOID entryParam; DWORD result = ERROR_SUCCESS; DWORD createFlags; DWORD threadId; // Snag the parameters process = (HANDLE)packet_get_tlv_value_uint(packet, TLV_TYPE_PROCESS_HANDLE); entryPoint = (LPVOID)packet_get_tlv_value_uint(packet, TLV_TYPE_ENTRY_POINT); entryParam = (LPVOID)packet_get_tlv_value_uint(packet, TLV_TYPE_ENTRY_PARAMETER); createFlags = packet_get_tlv_value_uint(packet, TLV_TYPE_CREATION_FLAGS); do { // No process handle or entry point? if ((!process) || (!entryPoint)) { result = ERROR_INVALID_PARAMETER; break; } // Create the thread in the process supplied if (!(thread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)entryPoint, entryParam, createFlags, &threadId))) { result = GetLastError(); break; } // Set the thread identifier and handle on the response packet_add_tlv_uint(response, TLV_TYPE_THREAD_ID, threadId); packet_add_tlv_uint(response, TLV_TYPE_THREAD_HANDLE, (DWORD)thread); } while (0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/*! * @brief Transmit a `TLV_TYPE_RESULT` response if `response` is present. * @param result The result to be sent. * @param remote Reference to the remote connection to send the response to. * @param response the Response to add the `result` to. */ DWORD packet_transmit_response(DWORD result, Remote* remote, Packet* response) { if (response) { packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); return PACKET_TRANSMIT(remote, response, NULL); } return ERROR_NOT_ENOUGH_MEMORY; }
/* * core_channel_open * ----------------- * * Opens a channel with the remote endpoint. The response handler for this * request will establish the relationship on the other side. * * opt: TLV_TYPE_CHANNEL_TYPE * The channel type to allocate. If set, the function returns, allowing * a further up extension handler to allocate the channel. */ DWORD remote_request_core_channel_open(Remote *remote, Packet *packet) { Packet *response; DWORD res = ERROR_SUCCESS; Channel *newChannel; PCHAR channelType; DWORD flags = 0; do { dprintf( "[CHANNEL] Opening new channel for packet %p", packet ); // If the channel open request had a specific channel type if ((channelType = packet_get_tlv_value_string(packet, TLV_TYPE_CHANNEL_TYPE))) { res = ERROR_NOT_FOUND; break; } // Get any flags that were supplied flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS); dprintf( "[CHANNEL] Opening %s %u", channelType, flags ); // Allocate a response response = packet_create_response(packet); // Did the response allocation fail? if ((!response) || (!(newChannel = channel_create(0, flags)))) { res = ERROR_NOT_ENOUGH_MEMORY; break; } dprintf( "[CHANNEL] Opened %s %u", channelType, flags ); // Get the channel class and set it newChannel->cls = packet_get_tlv_value_uint(packet, TLV_TYPE_CHANNEL_CLASS); dprintf( "[CHANNEL] Channel class for %s: %u", channelType, newChannel->cls ); // Add the new channel identifier to the response if ((res = packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(newChannel))) != ERROR_SUCCESS) break; // Transmit the response dprintf( "[CHANNEL] Sending response for %s", channelType ); res = PACKET_TRANSMIT(remote, response, NULL); dprintf( "[CHANNEL] Done" ); } while (0); return res; }