Skip to content

Instantly share code, notes, and snippets.

@mattn
Created August 24, 2017 15:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattn/bd015d67befac8a8a97040c8ff72bbe4 to your computer and use it in GitHub Desktop.
Save mattn/bd015d67befac8a8a97040c8ff72bbe4 to your computer and use it in GitHub Desktop.
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <stdio.h>
typedef struct _STRING {
WORD Length;
WORD MaximumLength;
CHAR *Buffer;
} STRING, *PSTRING;
typedef struct _UNICODE_STRING {
WORD Length;
WORD MaximumLength;
WCHAR *Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _CURDIR {
UNICODE_STRING DosPath;
LONG Handle;
} CURDIR, *PCURDIR;
typedef struct _RTL_DRIVE_LETTER_CURDIR {
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
STRING DosPath;
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
typedef struct _PEB_FREE_BLOCK {
struct _PEB_FREE_BLOCK *Next;
ULONG Size;
} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;
typedef struct _ACTIVATION_CONTEXT_DATA {
} ACTIVATION_CONTEXT_DATA, *PACTIVATION_CONTEXT_DATA;
typedef struct _ASSEMBLY_STORAGE_MAP {
} ASSEMBLY_STORAGE_MAP, *PASSEMBLY_STORAGE_MAP;
typedef struct _FLS_CALLBACK_INFO {
} FLS_CALLBACK_INFO, *PFLS_CALLBACK_INFO;
typedef struct _PEB_LDR_DATA {
ULONG Length;
UCHAR Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID EntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
#define RTL_MAX_DRIVE_LETTERS 32
#define RTL_DRIVE_LETTER_VALID (USHORT)0x0001
typedef struct _RTL_USER_PROCESS_PARAMETERS {
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
HANDLE ConsoleHandle;
HANDLE ConsoleFlags;
HANDLE StandardInput;
HANDLE StandardOutput;
HANDLE StandardError;
CURDIR CurrentDirectory; // ProcessParameters
UNICODE_STRING DllPath; // ProcessParameters
UNICODE_STRING ImagePathName; // ProcessParameters
UNICODE_STRING CommandLine; // ProcessParameters
ULONG Environment; // NtAllocateVirtualMemory
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle; // ProcessParameters
UNICODE_STRING DesktopInfo; // ProcessParameters
UNICODE_STRING ShellInfo; // ProcessParameters
UNICODE_STRING RuntimeData; // ProcessParameters
RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32];
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)(
HANDLE ProcessHandle,
DWORD ProcessInformationClass,
PVOID ProcessInformation,
DWORD ProcessInformationLength,
PDWORD ReturnLength);
typedef struct _PROCESS_BASIC_INFORMATION {
PVOID Reserved1;
PVOID PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
PVOID
GetPebAddress(HANDLE ProcessHandle) {
_NtQueryInformationProcess NtQueryInformationProcess =
(_NtQueryInformationProcess)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
PROCESS_BASIC_INFORMATION pbi;
NtQueryInformationProcess(ProcessHandle, 0, &pbi, sizeof(pbi), NULL);
return pbi.PebBaseAddress;
}
#ifdef _WIN64
# define peb_offset (0x20)
#else
# define peb_offset (0x10)
#endif
int
main(int argc, char* argv[]) {
DWORD pid;
HANDLE hProcess;
PVOID pebAddress;
PRTL_USER_PROCESS_PARAMETERS rtlUserProcParams;
CURDIR currentDirectory;
WCHAR *currentDirectoryContents;
pid = atoi(argv[1]);
hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if (hProcess == NULL) {
return 1;
}
pebAddress = GetPebAddress(hProcess);
if (!pebAddress) {
return 1;
}
if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + peb_offset,
&rtlUserProcParams, sizeof(rtlUserProcParams), NULL)) {
return 1;
}
if (!ReadProcessMemory(hProcess, &rtlUserProcParams->CurrentDirectory,
&currentDirectory, sizeof(currentDirectory), NULL)) {
return 1;
}
currentDirectoryContents = (WCHAR *)malloc(currentDirectory.DosPath.Length+1);
if (!ReadProcessMemory(hProcess, currentDirectory.DosPath.Buffer,
currentDirectoryContents, currentDirectory.DosPath.Length, NULL)) {
free(currentDirectoryContents);
return 1;
}
CloseHandle(hProcess);
int len = WideCharToMultiByte(GetACP(), 0,
currentDirectoryContents, currentDirectory.DosPath.Length / 2,
NULL, 0, NULL, NULL);
char *curdir = (CHAR *)malloc(len + 1);
WideCharToMultiByte(GetACP(), 0,
currentDirectoryContents, currentDirectory.DosPath.Length / 2,
curdir, len, NULL, NULL);
curdir[len] = 0;
printf("%s\n", curdir);
free(currentDirectoryContents);
}
/* vim:set et sw=2 ts=2: */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment