When I try to call:
timeval timeout{ 0, 999 };
::GetAddrInfoExW(L"my_name", L"", NS_DNS, nullptr, nullptr, &pResult, &timeout, nullptr, nullptr, nullptr);
I got 10022 "Invalid params".
However, if I replace "&timeout" with "nullptr", I got 0 (OK).
Why the timeout causes EINVAL error?
UNICODE macro is defined, my system is Windows 10.
if timeout not 0, the lpOverlapped must be also not 0. the code can be next
#include <ws2tcpip.h>
struct QUERY_CONTEXT : OVERLAPPED
{
PADDRINFOEX _pResult;
ULONG _dwThreadId = GetCurrentThreadId();
~QUERY_CONTEXT()
{
if (PADDRINFOEX pResult = _pResult)
{
FreeAddrInfoEx(_pResult);
}
}
static void CALLBACK QueryCompleteCallback(
_In_ ULONG dwError,
_In_ ULONG /*dwBytes*/,
_In_ OVERLAPPED* lpOverlapped
)
{
static_cast<QUERY_CONTEXT*>(lpOverlapped)->OnComplete(dwError);
}
void OnComplete(_In_ ULONG dwError)
{
DbgPrint("OnComplete(%u)\n");
if (PADDRINFOEX pResult = _pResult)
{
do
{
WCHAR buf[64];
ULONG len = _countof(buf);
if (!WSAAddressToStringW(pResult->ai_addr, (ULONG)pResult->ai_addrlen, 0, buf, &len))
{
DbgPrint("%S\n", buf);
}
} while (pResult = pResult->ai_next);
}
PostThreadMessageW(_dwThreadId, WM_QUIT, dwError, 0);
delete this;
}
ULONG Query(_In_ PCWSTR pName, _In_opt_ timeval *timeout)
{
ULONG dwError = GetAddrInfoExW(pName, 0, NS_DNS, 0, 0,
&_pResult, timeout, this, QueryCompleteCallback, 0);
//
// If GetAddrInfoExW() returns WSA_IO_PENDING, GetAddrInfoExW will invoke
// the completion routine. If GetAddrInfoExW returned anything else we must
// invoke the completion directly.
//
if (dwError != WSA_IO_PENDING)
{
QueryCompleteCallback(dwError, 0, this);
}
return dwError;
}
};
///////////////////////////////////////
WSADATA wd;
if (NOERROR == WSAStartup(WINSOCK_VERSION, &wd))
{
if (QUERY_CONTEXT* pqc = new QUERY_CONTEXT {})
{
timeval timeout{ 1 };
pqc->Query(L"stackoverflow.com", &timeout);
}
MessageBoxW(0, 0, 0, 0);
WSACleanup();
}
also for dns query more efficient direct use DnsQueryEx function (GetAddrInfoExW internally call DnsQueryEx, but before this - alot of another code executed)
Related
I'm trying to hide a process from the taskmanager but it doesn't work .
I dont understand why ...
Thank you for your help in advance... !
This is my function who inject the hider_dll.dll :
int Inject(char* dll)
{
int pid = getpid();
HANDLE hProc=OpenProcess(PROCESS_ALL_ACCESS,false,pid);
if(hProc)
{
cout<<"OpenProcess success"<<endl;
}
else
{
cout<<"OpenProcess failed..."<<endl;
return 0;
}
LPVOID Vmem=VirtualAllocEx(hProc,0,strlen(dll)+1,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
DWORD wrt;
WriteProcessMemory(hProc,Vmem,dll,strlen(dll),(SIZE_T*)&wrt);
stringstream sstr;
sstr << wrt;
string str = sstr.str();
cout<<"Writed "+str+" bytes"<<endl;
FARPROC LoadLib=GetProcAddress(LoadLibrary(L"kernel32.dll"),"LoadLibraryA");
HANDLE h=CreateRemoteThread(hProc,0,0,(LPTHREAD_START_ROUTINE)LoadLib,Vmem,0,0);
if(h)
{
cout<<"CreateRemoteThread success"<<endl;
}
else
{
cout<<"CreateRemoteThread failed\r\nError:"<<GetLastError()<<endl;
return 0;
}
WaitForSingleObject(h,INFINITE);
DWORD exit;
GetExitCodeThread(h,&exit);
cout<<"Dll loaded to "<<exit<<endl;
return 1;
}
Here is a proper injector:
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
DWORD GetProcId(const char* procName)
{
DWORD procId = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof(procEntry);
if (Process32First(hSnap, &procEntry))
{
do
{
if (!_stricmp(procEntry.szExeFile, procName))
{
procId = procEntry.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &procEntry));
}
}
CloseHandle(hSnap);
return procId;
}
int main()
{
const char* dllPath = "C:\\Users\\'%USERNAME%'\\Desktop\\dll.dll"; //
const char* procName = "processname.exe"; //
DWORD procId = 0;
while (!procId)
{
procId = GetProcId(procName);
Sleep(30);
}
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, procId);
if (hProc && hProc != INVALID_HANDLE_VALUE)
{
void* loc = VirtualAllocEx(hProc, 0, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
WriteProcessMemory(hProc, loc, dllPath, strlen(dllPath) + 1, 0);
HANDLE hThread = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, loc, 0, 0);
if (hThread)
{
CloseHandle(hThread);
}
}
if (hProc)
{
CloseHandle(hProc);
}
return 0;
}
To hide processes from Task Manager you need to hook NtQuerySystemInformation() and if the argument SYSTEM_PROCESS_INFORMATION is used, you need to remove your process from the linked list of processes.
This is what your hook would look like:
// Hooked function
NTSTATUS WINAPI HookedNtQuerySystemInformation(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
)
{
NTSTATUS status = OriginalNtQuerySystemInformation(SystemInformationClass,
SystemInformation,
SystemInformationLength,
ReturnLength);
if (SystemProcessInformation == SystemInformationClass && STATUS_SUCCESS == status)
{
// Loop through the list of processes
PMY_SYSTEM_PROCESS_INFORMATION pCurrent = NULL;
PMY_SYSTEM_PROCESS_INFORMATION pNext = (PMY_SYSTEM_PROCESS_INFORMATION)
SystemInformation;
do
{
pCurrent = pNext;
pNext = (PMY_SYSTEM_PROCESS_INFORMATION)((PUCHAR)pCurrent + pCurrent->
NextEntryOffset);
if (!wcsncmp(pNext->ImageName.Buffer, L"notepad.exe", pNext->ImageName.Length))
{
if (!pNext->NextEntryOffset)
{
pCurrent->NextEntryOffset = 0;
}
else
{
pCurrent->NextEntryOffset += pNext->NextEntryOffset;
}
pNext = pCurrent;
}
} while (pCurrent->NextEntryOffset != 0);
}
return status;
}
I am trying to create new registry entries which copies the certain registry values from HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings. I am successfully able to create the new registry entries but the values and sub key are not copied.I am not able to figure out where I have done the mistake. Please help me out.below is my code:
#include<tchar.h>
#include<conio.h>
#include<Windows.h>
#include<Winreg.h>
#include<WinBase.h >
#include<TlHelp32.h>
#define MAX_PATH 1024
DWORD MigrateProxy;
DWORD ProxyEnable;
DWORD ProxyHTTP11;
LPWSTR AutoConfigURL=0;
LPWSTR ProxyServer=0;
LPWSTR ProxyOverride=0;
void CopyRegistryProxySettings(HKEY hKeyRoot, LPCWSTR Subkey, LPCWSTR ValueKey);
bool CreateNewRegistry(HKEY hKeyRoot);
void main()
{
bool bStatusFlag = false,bReadFlag=false,bWriteFlag=false;
LPCWSTR lpSubKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
LPCWSTR lpValueName = L"AutoConfigURL";
CopyRegistryProxySettings(HKEY_CURRENT_USER, lpSubKey,lpValueName);
bStatusFlag = CreateNewRegistry(HKEY_CURRENT_USER);
//bWriteFlag = RestoreOlderRegistry()
getch();
}
void CopyRegistryProxySettings(HKEY hKeyRoot, LPCWSTR Subkey, LPCWSTR ValueKey)
{
HKEY hKey = NULL;
wchar_t buffer[MAX_PATH];
DWORD dwBufLen;
DWORD dwValue = 0;
DWORD dwDataSize = sizeof(DWORD);
memset(buffer, 0, sizeof buffer);
dwBufLen = MAX_PATH;
if ( ERROR_SUCCESS == RegOpenKeyEx(hKeyRoot, Subkey, 0, KEY_ALL_ACCESS , &hKey))
{
if(ERROR_SUCCESS == RegQueryValueEx(hKey,L"AutoConfigURL",NULL,NULL,(BYTE*)buffer,&dwBufLen))
{
AutoConfigURL = buffer;
memset(buffer, 0, sizeof buffer);
}
if(ERROR_SUCCESS == RegQueryValueEx(hKey,L"ProxyServer",NULL,NULL,(BYTE*)buffer,&dwBufLen))
{
ProxyServer = buffer;
memset(buffer, 0, sizeof buffer);
}
if(ERROR_SUCCESS == RegQueryValueEx(hKey,L"ProxyOverride",NULL,NULL,(BYTE*)buffer,&dwBufLen))
{
ProxyOverride = buffer;
memset(buffer, 0, sizeof buffer);
}
if(ERROR_SUCCESS == RegQueryValueEx(hKey,L"MigrateProxy",NULL,NULL,(LPBYTE)&dwValue,&dwDataSize))
{
MigrateProxy = dwValue;
}
if(ERROR_SUCCESS == RegQueryValueEx(hKey,L"ProxyEnable",NULL,NULL,(LPBYTE)&dwValue,&dwDataSize))
{
ProxyEnable = dwValue;
}
if(ERROR_SUCCESS == RegQueryValueEx(hKey,L"ProxyHttp1.1",NULL,NULL,(LPBYTE)&dwValue,&dwDataSize))
{
ProxyHTTP11 = dwValue;
}
}
}
bool CreateNewRegistry(HKEY hKeyRoot)
{
HKEY hKey;
if (RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\NewSettings\\Internet Settings", NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS)
{
RegSetValueEx(hKey, L"AutoConfigURL", NULL,REG_SZ,(BYTE*)AutoConfigURL, (DWORD)((lstrlen(AutoConfigURL)+1)*sizeof(TCHAR)));
RegSetValueEx(hKey, L"ProxyServer", NULL,REG_SZ,(BYTE*)ProxyServer, (DWORD)((lstrlen(ProxyServer)+1)*sizeof(TCHAR)));
RegSetValueEx(hKey, L"ProxyOverride", NULL,REG_SZ,(BYTE*)ProxyOverride, (DWORD)((lstrlen(ProxyOverride)+1)*sizeof(TCHAR)));
RegSetValueEx(hKey, L"MigrateProxy", NULL,REG_DWORD,(BYTE*)MigrateProxy, (DWORD)sizeof(MigrateProxy));
RegSetValueEx(hKey, L"ProxyEnable", NULL,REG_DWORD,(BYTE*)ProxyEnable, (DWORD)sizeof(ProxyEnable));
RegSetValueEx(hKey, L"ProxyHTTP1.1", NULL, REG_DWORD,(BYTE*)ProxyHTTP11, (DWORD)sizeof(ProxyHTTP11));
}
return 1;
}
I can't get Internet Explorer or Windows Explorer to load this BHO. Sure there's no COM objects that can be created, but Explorer can't know that until it loads the DLL and checks, but LoadLibrary isn't getting called.
The message box shows when I run regsvr32.
Windows Version = 8.1
Internet Epxlorer Version = 11
Enhance Protected Mode on or off doesn't seem to make a difference.
#include <windows.h>
#include <olectl.h>
#include <stddef.h>
#include <string.h>
#define wstrlen wcslen
HINSTANCE me;
DWORD WINAPI M4(void *junk)
{
MessageBox(NULL, "Loaded", "bho", 0);
}
BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpReserved)
{
wchar_t mainexe[1024];
if (fdwReason == DLL_PROCESS_ATTACH) {
me = hInstDll;
DisableThreadLibraryCalls(me);
/* GetModuleFileNameW(NULL, mainexe, 1024); */
/* len = wstrlen(mainexe); */
HANDLE th = CreateThread(NULL, 32768, M4, NULL, 0, NULL);
}
return TRUE;
}
STDAPI DllGetClassObject(REFIID rclsid,REFIID riid,LPVOID *ppv)
{
return CLASS_E_CLASSNOTAVAILABLE;
}
STDAPI DllCanUnloadNow()
{
return FALSE;
}
const char *CLSID_NAME = "CLSID\\{2D3E480A-0000-0000-0000-64756D796C6472}";
const char *CLSID_IPS32 = "CLSID\\{2D3E480A-0000-0000-0000-64756D796C6472}\\InProcServer32";
const char *BHO = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects\\{2D3E480A-0000-0000-0000-64756D796C6472}";
const wchar_t *name = L"Redacted BHO";
const char *apt = "Apartment";
STDAPI DllRegisterServer()
{
HKEY hk;
wchar_t dllpath[1024];
GetModuleFileNameW(me,dllpath,1024);
if (RegCreateKeyEx(HKEY_CLASSES_ROOT, CLSID_NAME, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, NULL) != ERROR_SUCCESS)
return SELFREG_E_CLASS;
RegSetValueExW(hk, NULL, 0, REG_SZ, (const BYTE *)(name), (wstrlen(name) + 1) << 1);
RegCloseKey(hk);
if (RegCreateKeyEx(HKEY_CLASSES_ROOT, CLSID_IPS32, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, NULL) != ERROR_SUCCESS)
return SELFREG_E_CLASS;
RegSetValueExW(hk, NULL, 0, REG_SZ, (const BYTE *)(dllpath), (wstrlen(dllpath) + 1) << 1);
RegSetValueEx(hk, "ThreadingModel", 0, REG_SZ, (const BYTE *)(apt), 10);
RegCloseKey(hk);
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, BHO, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, NULL) != ERROR_SUCCESS)
return SELFREG_E_CLASS;
RegCloseKey(hk);
return S_OK;
}
STDAPI DllUnregisterServer()
{
RegDeleteKey(HKEY_LOCAL_MACHINE, BHO);
RegDeleteKey(HKEY_CLASSES_ROOT, CLSID_IPS32);
RegDeleteKey(HKEY_CLASSES_ROOT, CLSID_NAME);
}
For IE11 in enhanced protected mode (EPM), the registry must be updated with:
HKEY_CLASSES_ROOT\CLSID\{your BHO CLSID}\Implemented
Categories\{59FB2056-D625-48D0-A944-1A85B5AB2640}
I know, this method is outdated, just curious.
When I call ChangeClipboardChain() from atexit handler, it succeeds. When precc Ctrl-C, it fails. I know it, because other clipboard viewers don't receive WM_CHANGECBCHAIN.
This sample program exits when something is copied to clipboard 4 times:
#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
#endif
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
static void pWin32Error(const char* fmt, ...);
static int counter=0;
static HWND nextWnd = NULL;
static
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch (uMsg) {
case WM_CHANGECBCHAIN:
{
HWND wndRemove = (HWND)wParam;
HWND wndNextNext = (HWND)lParam;
printf("WM_CHANGECBCHAIN %p %p\n", (void*)wndRemove, (void*)wndNextNext);
if (nextWnd == wndRemove) {
printf("saving next window %p\n", (void*)wndNextNext);
nextWnd = wndNextNext;
} else if (nextWnd) {
printf("notifying next window %p\n", (void*)nextWnd);
return SendMessage(nextWnd,uMsg,wParam,lParam);
} else {
printf("not notifying next window %p\n", (void*)nextWnd);
}
}
break;
case WM_DRAWCLIPBOARD:
counter++;
if (counter > 4) exit(0);
printf("WM_DRAWCLIPBOARD\n");
if (nextWnd) {
printf("notifying next window %p\n", (void*)nextWnd);
return SendMessage(nextWnd,uMsg,wParam,lParam);
} else {
printf("not notifying next window %p\n", (void*)nextWnd);
}
break;
default:
return DefWindowProc( hwnd,uMsg,wParam,lParam);
}
return 0;
}
static volatile HWND global_hwnd = NULL;
WNDCLASS wndclass = {
0,/* UINT style;*/
WindowProc,/* WNDPROC lpfnWndProc;*/
0,/* int cbClsExtra;*/
0,/* int cbWndExtra;*/
NULL,/* HINSTANCE hInstance;*/
NULL,/* HICON hIcon;*/
NULL,/* HCURSOR hCursor;*/
NULL,/* HBRUSH hbrBackground;*/
NULL,/* LPCWSTR lpszMenuName;*/
_T("myclipmonitor")/* LPCWSTR lpszClassName;*/
};
static void unreg() {
HWND hwnd;
hwnd = (HWND)InterlockedExchangePointer(&global_hwnd, NULL); /* ignore the "cast to greater size" warning */
if (hwnd) {
printf("Removing self from chain: %p <- %p\n", (void*)hwnd, (void*)nextWnd);
if (!ChangeClipboardChain(hwnd, nextWnd) && GetLastError() != 0) {
pWin32Error("ChangeClipboardChain() failed");
}
}
}
static void exitproc() {
fprintf(stderr, "exitproc()\n");
unreg();
}
static
BOOL WINAPI CtrlHandler( DWORD fdwCtrlType )
{
fprintf(stderr, "CtrlHandler()\n");
unreg();
switch ( fdwCtrlType ) {
case CTRL_C_EVENT:
fprintf(stderr, "\n\n Stopping due to Ctrl-C.\n" );
break;
case CTRL_CLOSE_EVENT:
fprintf(stderr, "\n\n Stopping due to closing the window.\n" );
break;
case CTRL_BREAK_EVENT:
fprintf(stderr, "\n\n Stopping due to Ctrl-Break.\n" );
break;
// Pass other signals to the next handler - ret = FALSE
case CTRL_LOGOFF_EVENT:
fprintf(stderr, "\n\n Stopping due to logoff.\n" );
break;
case CTRL_SHUTDOWN_EVENT:
fprintf(stderr, "\n\n Stopping due to system shutdown.\n" );
break;
default:
fprintf(stderr, "\n\n Stopping due to unknown event.\n" );
}
return FALSE;
}
int _tmain(int argc, _TCHAR* argv[])
{
ATOM classatom;
HINSTANCE hinst = GetModuleHandle(NULL);
MSG msg;
wndclass.hInstance = hinst;
classatom = RegisterClass(&wndclass);
if (classatom == 0) {
pWin32Error("RegisterClass() failed");
return -1;
}
global_hwnd = CreateWindowEx(0, (LPCTSTR)classatom, NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinst, NULL);
if (!global_hwnd) {
pWin32Error("CreateWindowEx() failed");
return -1;
}
printf("hwnd = %p\n", (void*)global_hwnd);
nextWnd = SetClipboardViewer(global_hwnd);
if (!nextWnd && GetLastError() != 0) {
pWin32Error("SetClipboardViewer() failed");
return -1;
}
printf("nextWnd = %p\n", (void*)nextWnd);
atexit(exitproc);
if (0 == SetConsoleCtrlHandler( CtrlHandler, TRUE )) {
pWin32Error("SetConsoleCtrlHandler() failed");
return -1;
}
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
static char *cleanstr(char *s)
{
while(*s) {
switch((int)*s){
case 13:
case 10:
*s=' ';
break;
}
s++;
}
return s;
}
static void __pWin32Error(int level, DWORD eNum, const char* fmt, va_list args)
{
char emsg[1024];
char *pend = emsg + sizeof(emsg);
size_t count = sizeof(emsg);
unsigned u;
do {
u = (unsigned)_vsnprintf(pend - count, count, fmt, args);
if (u >= count) break;
count -= u;
u = (unsigned)_snprintf(pend - count, count, ": ");
if (u >= count) break;
count -= u;
u = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
pend - count, (DWORD)count, NULL );
if (u == 0) {
u = (unsigned)_snprintf(pend - count, count, "0x%08x (%d)", eNum, eNum);
}
} while(0);
emsg[sizeof(emsg)-1] = '\0';
pend = cleanstr(emsg);
if (pend < emsg + sizeof(emsg)-1) {
pend++;
*pend = '\0';
}
pend[-1] = '\n';
puts(emsg);
}
static void pWin32Error(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
__pWin32Error(0, GetLastError(), fmt, args);
va_end(args);
}
Has anyone managed to figure out how asynchronous calls to NtQueryDirectoryFile work?
By an asynchronous call, I mean calling NtQueryDirectoryFile on directories not opened with FILE_SYNCHRONOUS_IO_ALERT or with FILE_SYNCHRONOUS_IO_NONALERT.
For me, it seems to return STATUS_PENDING just like a normal NtReadFile request does on a normal file, but when I tried using NtWaitForSingleObject on the directory, it didn't end properly, and I still don't get all the data... why does this happen?
As far as I know, none of the Windows filesystems support asynchronous query directory calls.
The Win32 APIs never call NtQueryDirectoryFile asnchronously, so support for it is hit-or-miss.
NTFS theoretically supports asynchronous NtQueryDirectoryFile but (as I mentioned) it is not extensively tested so it may not work.
You response indicated that you called WaitForSingleObject on the directory - that's not how the async pattern works in NT - you need to call WaitForSingleObject on the event handle provided as a parameter to NtQueryDirectoryFile.
This update is a result of asking the NTFS developer for more information, he tested this scenario on his machine and it worked for him (on Windows 7).
NtQueryDirectoryFile works well in asynchronous!
pass callback in ApcRoutine, and callback data in ApcContext
asynchronous procedure calls only call when the thread is in alertable state(for example: calling SleepEx(INFINITE, TRUE), WSAaccept)
this program shows how asynchronous NtQueryDirectoryFile work.
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
#include <winnt.h>
#define LIST_DIR_SIZE 2000
#define STATUS_NO_MORE_FILES ((NTSTATUS)80000006)
typedef struct _FILE_NAMES_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAMES_INFORMATION, * PFILE_NAMES_INFORMATION;
typedef struct {
HANDLE hFile;
OVERLAPPED ol;
DECLSPEC_ALIGN(4) FILE_NAMES_INFORMATION buf[LIST_DIR_SIZE];
IO_STATUS_BLOCK iob;
bool finished;
} LIST_DIR_DATA, * PLIST_DIR_DATA; // my private data
__kernel_entry NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryDirectoryFile(
_In_ HANDLE FileHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_Out_writes_bytes_(Length) PVOID FileInformation,
_In_ ULONG Length,
_In_ FILE_INFORMATION_CLASS FileInformationClass,
_In_ BOOLEAN ReturnSingleEntry,
_In_opt_ PUNICODE_STRING FileName,
_In_ BOOLEAN RestartScan
);
#define NTDLL_extern(s) typedef decltype(&s) s##T;s##T s##F;
#define NTDLL_import(s) s##F = (s##T)GetProcAddress(ntdll, #s);
NTDLL_extern(NtOpenFile);
NTDLL_extern(NtQueryDirectoryFile);
NTDLL_extern(NtClose);
NTDLL_extern(RtlInitUnicodeString);
HMODULE ntdll;
VOID NTAPI callback(
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved) {
UNREFERENCED_PARAMETER(Reserved);
PFILE_NAMES_INFORMATION file_info = ((PLIST_DIR_DATA)ApcContext)->buf;
do {
fputws(file_info->FileName, stdout);
putwchar(L'\t');
file_info = (PFILE_NAMES_INFORMATION)((char*)file_info + file_info->NextEntryOffset);
} while (file_info->NextEntryOffset);
fputws(file_info->FileName, stdout);
putwchar(L'\t');
PLIST_DIR_DATA c = (PLIST_DIR_DATA)ApcContext;
if (IoStatusBlock->Information != 0) {
NTSTATUS status = NtQueryDirectoryFileF(
c->hFile,
NULL,
callback,
ApcContext,
&c->iob,
c->buf,
sizeof(c->buf),
FILE_INFORMATION_CLASS(12),
FALSE, NULL, FALSE);
switch (status) {
case STATUS_PENDING:
break;
default:
fputs("warning: status != STATUS_PENDING", stderr);
}
}
else {
c->finished = true;
}
}
BOOL init() {
ntdll = LoadLibraryW(L"NtDLL.dll");
if (ntdll == NULL) {
fputs("LoadLibraryW", stderr);
return FALSE;
}
NTDLL_import(NtQueryDirectoryFile);
NTDLL_import(NtOpenFile);
NTDLL_import(NtClose);
NTDLL_import(RtlInitUnicodeString);
if (NtCloseF != NULL && NtOpenFileF != NULL && NtCloseF != NULL) {
return TRUE;
}
else {
fputs("GetProcAddress", stderr);
return FALSE;
}
}
int main() {
if (init() == FALSE) {
fputs("error: init() failed!", stderr);
return -1;
}
NTSTATUS status;
PLIST_DIR_DATA data = new LIST_DIR_DATA{};
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING s;
RtlInitUnicodeStringF(&s, L"\\??\\c:\\Windows\\System32");
InitializeObjectAttributes(
&ObjectAttributes,
&s,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = NtOpenFileF(
&data->hFile,
FILE_READ_DATA | FILE_LIST_DIRECTORY, // | FILE_TRAVERSE | SYNCHRONIZE
&ObjectAttributes,
&data->iob,
FILE_SHARE_READ,
FILE_DIRECTORY_FILE); // | FILE_SYNCHRONOUS_IO_NONALERT
}
if (status < 0 || data->hFile == NULL) {
fputs("error: NtOpenFile failed", stderr);
return -2;
}
status = NtQueryDirectoryFileF(
data->hFile,
NULL,
callback,
data,
&data->iob,
data->buf,
sizeof(data->buf),
FILE_INFORMATION_CLASS(12),
FALSE, NULL, FALSE);
switch (status) {
case STATUS_PENDING:
break;
default:
fputs("warning: status != STATUS_PENDING", stderr);
}
for (;data->finished==false;) SleepEx(INFINITE, TRUE); // put main thread into alertable wait
NtCloseF(data->hFile);
FreeLibrary(ntdll);
return 0;
}
if you want UTF-8 output, try this (note: recommand use support UTF-8 terminal)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winternl.h>
#include <winnt.h>
#include <crtdbg.h>
#include <cstdio>
#define LIST_DIR_SIZE 200
#define STATUS_NO_MORE_FILES ((NTSTATUS)80000006)
typedef struct _FILE_NAMES_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAMES_INFORMATION, * PFILE_NAMES_INFORMATION;
typedef struct {
HANDLE hFile;
OVERLAPPED ol;
DECLSPEC_ALIGN(4) FILE_NAMES_INFORMATION buf[LIST_DIR_SIZE];
IO_STATUS_BLOCK iob;
bool finished;
} LIST_DIR_DATA, * PLIST_DIR_DATA; // my private data
__kernel_entry NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryDirectoryFile(
_In_ HANDLE FileHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_Out_writes_bytes_(Length) PVOID FileInformation,
_In_ ULONG Length,
_In_ FILE_INFORMATION_CLASS FileInformationClass,
_In_ BOOLEAN ReturnSingleEntry,
_In_opt_ PUNICODE_STRING FileName,
_In_ BOOLEAN RestartScan
);
#define NTDLL_extern(s) typedef decltype(&s) s##T;s##T s##F;
#define NTDLL_init(s) s##F = (s##T)GetProcAddress(ntdll, #s);
NTDLL_extern(NtOpenFile);
NTDLL_extern(NtQueryDirectoryFile);
NTDLL_extern(NtClose);
NTDLL_extern(RtlInitUnicodeString);
HMODULE ntdll;
HANDLE heap;
VOID NTAPI callback(
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved) {
UNREFERENCED_PARAMETER(Reserved);
PLIST_DIR_DATA c = (PLIST_DIR_DATA)ApcContext;
if (IoStatusBlock->Information){
PFILE_NAMES_INFORMATION file_info = c->buf;
ULONG_PTR length = 0;
ULONG last;
do {
last = file_info->NextEntryOffset;
file_info->FileNameLength /= 2; // wide char length always base of 2 in bytes
length += (
file_info->FileIndex=WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS,
file_info->FileName, file_info->FileNameLength,
NULL, 0,
NULL, NULL)
)+1;
if (file_info->FileIndex == 0) { // FileIndex is how many byte is the UTF-8 string
_RPTF0(_CRT_WARN, "WideCharToMultiByte failed!");
}
file_info = (PFILE_NAMES_INFORMATION)((char*)file_info + file_info->NextEntryOffset);
} while (last);
LPSTR pData = (LPSTR)HeapAlloc(heap, HEAP_NO_SERIALIZE, length), ptr=pData;
if (ptr == NULL) {
_RPTF0(_CRT_ERROR, "HeapAlloc failed!");
return;
}
file_info = c->buf;
do {
last = file_info->NextEntryOffset;
if (WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS,
file_info->FileName, file_info->FileNameLength,
pData, file_info->FileIndex,
NULL, NULL)==0) {
_RPTF0(_CRT_WARN, "WideCharToMultiByte failed!");
}
pData += file_info->FileIndex;
*pData++ = '\n';
file_info = (PFILE_NAMES_INFORMATION)((char*)file_info + file_info->NextEntryOffset);
} while (last);
// use data here
fwrite(ptr, length, 1, stdout);
// use data here
HeapFree(heap, HEAP_NO_SERIALIZE, ptr);
NTSTATUS status = NtQueryDirectoryFileF(
c->hFile,
NULL,
callback,
ApcContext,
&c->iob,
c->buf,
sizeof(c->buf),
FILE_INFORMATION_CLASS(12),
FALSE, NULL, FALSE);
switch (status) {
case STATUS_PENDING:
break;
default:
_RPTF0(_CRT_WARN, "status != STATUS_PENDING");
}
}else{
c->finished = true;
}
}
BOOL init() {
ntdll = LoadLibraryW(L"NtDLL.dll");
if (ntdll == NULL) {
_RPTF0(_CRT_ERROR, "fail to load NtDLL.dll");
return FALSE;
}
NTDLL_init(NtQueryDirectoryFile);
NTDLL_init(NtOpenFile);
NTDLL_init(NtClose);
NTDLL_init(RtlInitUnicodeString);
if (NtCloseF != NULL &&
NtOpenFileF != NULL &&
NtCloseF != NULL &&
(heap = HeapCreate(HEAP_NO_SERIALIZE, 4096,0))!=NULL
){
return TRUE;
}
else {
_RPTF0(_CRT_ERROR, "failed to load function and create heap");
return FALSE;
}
}
int main() {
if (init() == FALSE) {
_RPTF0(_CRT_ERROR, "init failed");
return -1;
}
SetConsoleCP(CP_UTF8);
NTSTATUS status;
PLIST_DIR_DATA data = new LIST_DIR_DATA{};
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING s;
RtlInitUnicodeStringF(&s, L"\\??\\c:\\Users");
InitializeObjectAttributes(
&ObjectAttributes,
&s,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = NtOpenFileF(
&data->hFile,
FILE_READ_DATA | FILE_LIST_DIRECTORY, // | FILE_TRAVERSE | SYNCHRONIZE
&ObjectAttributes,
&data->iob,
FILE_SHARE_READ,
FILE_DIRECTORY_FILE); // | FILE_SYNCHRONOUS_IO_NONALERT
}
if (status < 0 || data->hFile == NULL) {
_RPTF0(_CRT_ERROR, "NtOpenFile failed!");
return -2;
}
status = NtQueryDirectoryFileF(
data->hFile,
NULL,
callback,
data,
&data->iob,
data->buf,
sizeof(data->buf),
FILE_INFORMATION_CLASS(12),
FALSE, NULL, FALSE);
switch (status) {
case STATUS_PENDING:
break;
default:
_RPTF0(_CRT_WARN, "status != STATUS_PENDING");
}
for (;data->finished==false;) SleepEx(INFINITE, TRUE); // put main thread into alertable wait
if (NtCloseF(data->hFile)<0) {
_RPTF0(_CRT_ERROR, "NtClose failed!");
}
if (FreeLibrary(ntdll) == FALSE) {
_RPTF0(_CRT_WARN, "failed to Free libary");
}
if (HeapDestroy(heap) == FALSE) {
_RPTF0(_CRT_WARN, "fail to destroy heap");
}
}