mirror of
https://github.com/github/codeql.git
synced 2025-12-17 17:23:36 +01:00
576 lines
13 KiB
C++
576 lines
13 KiB
C++
void sink(char);
|
|
void sink(char*);
|
|
void sink(char**);
|
|
|
|
using HANDLE = void*;
|
|
using DWORD = unsigned long;
|
|
using LPCH = char*;
|
|
using LPSTR = char*;
|
|
using LPCSTR = const char*;
|
|
using LPVOID = void*;
|
|
using LPDWORD = unsigned long*;
|
|
using PVOID = void*;
|
|
using ULONG_PTR = unsigned long*;
|
|
using SIZE_T = decltype(sizeof(0));
|
|
|
|
LPSTR GetCommandLineA();
|
|
LPSTR* CommandLineToArgvA(LPSTR, int*);
|
|
LPCH GetEnvironmentStringsA();
|
|
DWORD GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD);
|
|
|
|
void getCommandLine() {
|
|
char* cmd = GetCommandLineA();
|
|
sink(cmd);
|
|
sink(*cmd); // $ ir
|
|
|
|
int argc;
|
|
char** argv = CommandLineToArgvA(cmd, &argc);
|
|
sink(argv);
|
|
sink(argv[1]);
|
|
sink(*argv[1]); // $ ir
|
|
}
|
|
|
|
void getEnvironment() {
|
|
char* env = GetEnvironmentStringsA();
|
|
sink(env);
|
|
sink(*env); // $ ir
|
|
|
|
char buf[1024];
|
|
GetEnvironmentVariableA("FOO", buf, sizeof(buf));
|
|
sink(buf);
|
|
sink(*buf); // $ ir
|
|
}
|
|
|
|
typedef struct _OVERLAPPED {
|
|
ULONG_PTR Internal;
|
|
ULONG_PTR InternalHigh;
|
|
union {
|
|
struct {
|
|
DWORD Offset;
|
|
DWORD OffsetHigh;
|
|
} DUMMYSTRUCTNAME;
|
|
PVOID Pointer;
|
|
} DUMMYUNIONNAME;
|
|
HANDLE hEvent;
|
|
} OVERLAPPED, *LPOVERLAPPED;
|
|
|
|
using BOOL = int;
|
|
#define FILE_MAP_READ 0x0004
|
|
|
|
using ULONG64 = unsigned long long;
|
|
using ULONG = unsigned long;
|
|
|
|
using DWORD64 = unsigned long long;
|
|
#define MEM_EXTENDED_PARAMETER_TYPE_BITS 8
|
|
|
|
typedef struct MEM_EXTENDED_PARAMETER {
|
|
struct {
|
|
DWORD64 Type : MEM_EXTENDED_PARAMETER_TYPE_BITS;
|
|
DWORD64 Reserved : 64 - MEM_EXTENDED_PARAMETER_TYPE_BITS;
|
|
} DUMMYSTRUCTNAME;
|
|
union {
|
|
DWORD64 ULong64;
|
|
PVOID Pointer;
|
|
SIZE_T Size;
|
|
HANDLE Handle;
|
|
DWORD ULong;
|
|
} DUMMYUNIONNAME;
|
|
} MEM_EXTENDED_PARAMETER, *PMEM_EXTENDED_PARAMETER;
|
|
|
|
BOOL ReadFile(
|
|
HANDLE hFile,
|
|
LPVOID lpBuffer,
|
|
DWORD nNumberOfBytesToRead,
|
|
LPDWORD lpNumberOfBytesRead,
|
|
LPOVERLAPPED lpOverlapped
|
|
);
|
|
|
|
using LPOVERLAPPED_COMPLETION_ROUTINE = void (*)(DWORD, DWORD, LPOVERLAPPED);
|
|
|
|
BOOL ReadFileEx(
|
|
HANDLE hFile,
|
|
LPVOID lpBuffer,
|
|
DWORD nNumberOfBytesToRead,
|
|
LPOVERLAPPED lpOverlapped,
|
|
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
|
|
);
|
|
|
|
using NTSTATUS = long;
|
|
using PIO_APC_ROUTINE = void (*)(struct _DEVICE_OBJECT*, struct _IRP*, PVOID);
|
|
typedef struct _IO_STATUS_BLOCK {
|
|
union {
|
|
NTSTATUS Status;
|
|
PVOID Pointer;
|
|
} DUMMYUNIONNAME;
|
|
ULONG_PTR Information;
|
|
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
|
|
using LONGLONG = long long;
|
|
using LONG = long;
|
|
typedef struct _LARGE_INTEGER {
|
|
union {
|
|
struct {
|
|
ULONG LowPart;
|
|
LONG HighPart;
|
|
} DUMMYSTRUCTNAME;
|
|
LONGLONG QuadPart;
|
|
} DUMMYUNIONNAME;
|
|
} LARGE_INTEGER, *PLARGE_INTEGER;
|
|
|
|
using PULONG = unsigned long*;
|
|
|
|
NTSTATUS NtReadFile(
|
|
HANDLE FileHandle,
|
|
HANDLE Event,
|
|
PIO_APC_ROUTINE ApcRoutine,
|
|
PVOID ApcContext,
|
|
PIO_STATUS_BLOCK IoStatusBlock,
|
|
PVOID Buffer,
|
|
ULONG Length,
|
|
PLARGE_INTEGER ByteOffset,
|
|
PULONG Key
|
|
);
|
|
|
|
|
|
void FileIOCompletionRoutine(
|
|
DWORD dwErrorCode,
|
|
DWORD dwNumberOfBytesTransfered,
|
|
LPOVERLAPPED lpOverlapped
|
|
) {
|
|
char* buffer = reinterpret_cast<char*>(lpOverlapped->hEvent);
|
|
sink(buffer);
|
|
sink(*buffer); // $ MISSING: ir
|
|
}
|
|
|
|
void FileIOCompletionRoutine2(
|
|
DWORD dwErrorCode,
|
|
DWORD dwNumberOfBytesTransfered,
|
|
LPOVERLAPPED lpOverlapped
|
|
) {
|
|
char* buffer = reinterpret_cast<char*>(lpOverlapped->hEvent);
|
|
sink(buffer);
|
|
sink(*buffer); // $ ir
|
|
}
|
|
|
|
void FileIOCompletionRoutine3(
|
|
DWORD dwErrorCode,
|
|
DWORD dwNumberOfBytesTransfered,
|
|
LPOVERLAPPED lpOverlapped
|
|
) {
|
|
char c = reinterpret_cast<char>(lpOverlapped->hEvent);
|
|
sink(c); // $ ir
|
|
}
|
|
|
|
void readFile(HANDLE hFile) {
|
|
{
|
|
char buffer[1024];
|
|
DWORD bytesRead;
|
|
OVERLAPPED overlapped;
|
|
BOOL result = ReadFile(hFile, buffer, sizeof(buffer), &bytesRead, &overlapped);
|
|
sink(buffer);
|
|
sink(*buffer); // $ ir
|
|
}
|
|
|
|
{
|
|
char buffer[1024];
|
|
OVERLAPPED overlapped;
|
|
overlapped.hEvent = reinterpret_cast<HANDLE>(buffer);
|
|
ReadFileEx(hFile, buffer, sizeof(buffer) - 1, &overlapped, FileIOCompletionRoutine);
|
|
sink(buffer);
|
|
sink(*buffer); // $ ir
|
|
|
|
char* p = reinterpret_cast<char*>(overlapped.hEvent);
|
|
sink(p);
|
|
sink(*p); // $ MISSING: ir
|
|
}
|
|
|
|
{
|
|
char buffer[1024];
|
|
OVERLAPPED overlapped;
|
|
ReadFile(hFile, buffer, sizeof(buffer), nullptr, nullptr);
|
|
overlapped.hEvent = reinterpret_cast<HANDLE>(buffer);
|
|
char buffer2[1024];
|
|
ReadFileEx(hFile, buffer2, sizeof(buffer2) - 1, &overlapped, FileIOCompletionRoutine2);
|
|
}
|
|
|
|
{
|
|
char buffer[1024];
|
|
OVERLAPPED overlapped;
|
|
ReadFile(hFile, buffer, sizeof(buffer), nullptr, nullptr);
|
|
overlapped.hEvent = reinterpret_cast<HANDLE>(*buffer);
|
|
char buffer2[1024];
|
|
ReadFileEx(hFile, buffer2, sizeof(buffer2) - 1, &overlapped, FileIOCompletionRoutine3);
|
|
}
|
|
|
|
{
|
|
char buffer[1024];
|
|
IO_STATUS_BLOCK ioStatusBlock;
|
|
LARGE_INTEGER byteOffset;
|
|
ULONG key;
|
|
NTSTATUS status = NtReadFile(hFile, nullptr, nullptr, nullptr, &ioStatusBlock, buffer, sizeof(buffer), &byteOffset, &key);
|
|
sink(buffer);
|
|
sink(*buffer); // $ ir
|
|
}
|
|
}
|
|
|
|
LPVOID MapViewOfFile(
|
|
HANDLE hFileMappingObject,
|
|
DWORD dwDesiredAccess,
|
|
DWORD dwFileOffsetHigh,
|
|
DWORD dwFileOffsetLow,
|
|
SIZE_T dwNumberOfBytesToMap
|
|
);
|
|
|
|
PVOID MapViewOfFile2(
|
|
HANDLE FileMappingHandle,
|
|
HANDLE ProcessHandle,
|
|
ULONG64 Offset,
|
|
PVOID BaseAddress,
|
|
SIZE_T ViewSize,
|
|
ULONG AllocationType,
|
|
ULONG PageProtection
|
|
);
|
|
|
|
PVOID MapViewOfFile3(
|
|
HANDLE FileMapping,
|
|
HANDLE Process,
|
|
PVOID BaseAddress,
|
|
ULONG64 Offset,
|
|
SIZE_T ViewSize,
|
|
ULONG AllocationType,
|
|
ULONG PageProtection,
|
|
MEM_EXTENDED_PARAMETER *ExtendedParameters,
|
|
ULONG ParameterCount
|
|
);
|
|
|
|
PVOID MapViewOfFile3FromApp(
|
|
HANDLE FileMapping,
|
|
HANDLE Process,
|
|
PVOID BaseAddress,
|
|
ULONG64 Offset,
|
|
SIZE_T ViewSize,
|
|
ULONG AllocationType,
|
|
ULONG PageProtection,
|
|
MEM_EXTENDED_PARAMETER *ExtendedParameters,
|
|
ULONG ParameterCount
|
|
);
|
|
|
|
LPVOID MapViewOfFileEx(
|
|
HANDLE hFileMappingObject,
|
|
DWORD dwDesiredAccess,
|
|
DWORD dwFileOffsetHigh,
|
|
DWORD dwFileOffsetLow,
|
|
SIZE_T dwNumberOfBytesToMap,
|
|
LPVOID lpBaseAddress
|
|
);
|
|
|
|
PVOID MapViewOfFileFromApp(
|
|
HANDLE hFileMappingObject,
|
|
ULONG DesiredAccess,
|
|
ULONG64 FileOffset,
|
|
SIZE_T NumberOfBytesToMap
|
|
);
|
|
|
|
PVOID MapViewOfFileNuma2(
|
|
HANDLE FileMappingHandle,
|
|
HANDLE ProcessHandle,
|
|
ULONG64 Offset,
|
|
PVOID BaseAddress,
|
|
SIZE_T ViewSize,
|
|
ULONG AllocationType,
|
|
ULONG PageProtection,
|
|
ULONG PreferredNode
|
|
);
|
|
|
|
void mapViewOfFile(HANDLE hMapFile) {
|
|
{
|
|
LPVOID pMapView = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
|
|
char* buffer = reinterpret_cast<char*>(pMapView);
|
|
sink(buffer);
|
|
sink(*buffer); // $ ir
|
|
}
|
|
|
|
{
|
|
LPVOID pMapView = MapViewOfFile2(hMapFile, nullptr, 0, nullptr, 0, 0, 0);
|
|
char* buffer = reinterpret_cast<char*>(pMapView);
|
|
sink(buffer);
|
|
sink(*buffer); // $ ir
|
|
}
|
|
|
|
{
|
|
MEM_EXTENDED_PARAMETER extendedParams;
|
|
|
|
LPVOID pMapView = MapViewOfFile3(hMapFile, nullptr, 0, 0, 0, 0, 0, &extendedParams, 1);
|
|
char* buffer = reinterpret_cast<char*>(pMapView);
|
|
sink(buffer);
|
|
sink(*buffer); // $ ir
|
|
}
|
|
|
|
{
|
|
MEM_EXTENDED_PARAMETER extendedParams;
|
|
|
|
LPVOID pMapView = MapViewOfFile3FromApp(hMapFile, nullptr, 0, 0, 0, 0, 0, &extendedParams, 1);
|
|
char* buffer = reinterpret_cast<char*>(pMapView);
|
|
sink(buffer);
|
|
sink(*buffer); // $ ir
|
|
}
|
|
|
|
{
|
|
LPVOID pMapView = MapViewOfFileEx(hMapFile, FILE_MAP_READ, 0, 0, 0, nullptr);
|
|
char* buffer = reinterpret_cast<char*>(pMapView);
|
|
sink(buffer);
|
|
sink(*buffer); // $ ir
|
|
}
|
|
|
|
{
|
|
LPVOID pMapView = MapViewOfFileFromApp(hMapFile, FILE_MAP_READ, 0, 0);
|
|
char* buffer = reinterpret_cast<char*>(pMapView);
|
|
sink(buffer);
|
|
sink(*buffer); // $ ir
|
|
}
|
|
|
|
{
|
|
LPVOID pMapView = MapViewOfFileNuma2(hMapFile, nullptr, 0, nullptr, 0, 0, 0, 0);
|
|
char* buffer = reinterpret_cast<char*>(pMapView);
|
|
sink(buffer);
|
|
sink(*buffer); // $ ir
|
|
}
|
|
}
|
|
|
|
typedef struct _SECURITY_ATTRIBUTES
|
|
{
|
|
DWORD nLength;
|
|
LPVOID lpSecurityDescriptor;
|
|
BOOL bInheritHandle;
|
|
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
|
|
|
|
typedef DWORD (*LPTHREAD_START_ROUTINE)(
|
|
LPVOID lpThreadParameter);
|
|
|
|
HANDLE CreateThread(
|
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
SIZE_T dwStackSize,
|
|
LPTHREAD_START_ROUTINE lpStartAddress,
|
|
LPVOID lpParameter,
|
|
DWORD dwCreationFlags,
|
|
LPDWORD lpThreadId);
|
|
|
|
HANDLE CreateRemoteThread(
|
|
HANDLE hProcess,
|
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
SIZE_T dwStackSize,
|
|
LPTHREAD_START_ROUTINE lpStartAddress,
|
|
LPVOID lpParameter,
|
|
DWORD dwCreationFlags,
|
|
LPDWORD lpThreadId
|
|
);
|
|
|
|
typedef ULONG_PTR DWORD_PTR;
|
|
|
|
typedef struct _PROC_THREAD_ATTRIBUTE_ENTRY
|
|
{
|
|
DWORD_PTR Attribute;
|
|
SIZE_T cbSize;
|
|
PVOID lpValue;
|
|
} PROC_THREAD_ATTRIBUTE_ENTRY, *LPPROC_THREAD_ATTRIBUTE_ENTRY;
|
|
|
|
// This structure contains a list of attributes that have been added using UpdateProcThreadAttribute
|
|
typedef struct _PROC_THREAD_ATTRIBUTE_LIST
|
|
{
|
|
DWORD dwFlags;
|
|
ULONG Size;
|
|
ULONG Count;
|
|
ULONG Reserved;
|
|
PULONG Unknown;
|
|
PROC_THREAD_ATTRIBUTE_ENTRY Entries[1];
|
|
} PROC_THREAD_ATTRIBUTE_LIST, *LPPROC_THREAD_ATTRIBUTE_LIST;
|
|
|
|
HANDLE CreateRemoteThreadEx(
|
|
HANDLE hProcess,
|
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
SIZE_T dwStackSize,
|
|
LPTHREAD_START_ROUTINE lpStartAddress,
|
|
LPVOID lpParameter,
|
|
DWORD dwCreationFlags,
|
|
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
|
|
LPDWORD lpThreadId
|
|
);
|
|
|
|
struct S
|
|
{
|
|
int x;
|
|
};
|
|
|
|
DWORD ThreadProc1(LPVOID lpParameter)
|
|
{
|
|
S *s = (S *)lpParameter;
|
|
sink(s->x); // $ ir
|
|
return 0;
|
|
}
|
|
|
|
DWORD ThreadProc2(LPVOID lpParameter)
|
|
{
|
|
S *s = (S *)lpParameter;
|
|
sink(s->x); // $ ir
|
|
return 0;
|
|
}
|
|
|
|
DWORD ThreadProc3(LPVOID lpParameter)
|
|
{
|
|
S *s = (S *)lpParameter;
|
|
sink(s->x); // $ ir
|
|
return 0;
|
|
}
|
|
|
|
int source();
|
|
|
|
void test_create_thread()
|
|
{
|
|
SECURITY_ATTRIBUTES sa;
|
|
|
|
S s;
|
|
s.x = source();
|
|
|
|
{
|
|
DWORD threadId;
|
|
HANDLE threadHandle = CreateThread(
|
|
&sa,
|
|
0,
|
|
ThreadProc1,
|
|
&s,
|
|
0,
|
|
&threadId);
|
|
}
|
|
|
|
{
|
|
DWORD threadId;
|
|
HANDLE threadHandle = CreateRemoteThread(
|
|
nullptr,
|
|
&sa,
|
|
0,
|
|
ThreadProc2,
|
|
&s,
|
|
0,
|
|
&threadId);
|
|
}
|
|
|
|
{
|
|
DWORD threadId;
|
|
PROC_THREAD_ATTRIBUTE_LIST attrList;
|
|
HANDLE threadHandle = CreateRemoteThreadEx(
|
|
nullptr,
|
|
&sa,
|
|
0,
|
|
ThreadProc3,
|
|
&s,
|
|
0,
|
|
&attrList,
|
|
&threadId);
|
|
}
|
|
}
|
|
|
|
using size_t = decltype(sizeof(0));
|
|
|
|
volatile void * RtlCopyVolatileMemory(
|
|
volatile void *Destination,
|
|
volatile const void *Source,
|
|
size_t Length
|
|
);
|
|
|
|
volatile void * RtlCopyDeviceMemory(
|
|
volatile void *Destination,
|
|
volatile const void *Source,
|
|
size_t Length
|
|
);
|
|
|
|
void RtlCopyMemory(
|
|
void* Destination,
|
|
const void* Source,
|
|
size_t Length
|
|
);
|
|
|
|
using VOID = void;
|
|
|
|
VOID RtlCopyMemoryNonTemporal(
|
|
VOID *Destination,
|
|
const VOID *Source,
|
|
SIZE_T Length
|
|
);
|
|
|
|
using USHORT = unsigned short;
|
|
using PWSTR = wchar_t*;
|
|
using PCWSTR = const wchar_t*;
|
|
using PCUNICODE_STRING = const struct _UNICODE_STRING*;
|
|
|
|
typedef struct _UNICODE_STRING {
|
|
USHORT Length;
|
|
USHORT MaximumLength;
|
|
PWSTR Buffer;
|
|
} UNICODE_STRING, *PUNICODE_STRING;
|
|
|
|
VOID RtlCopyUnicodeString(
|
|
PUNICODE_STRING DestinationString,
|
|
PCUNICODE_STRING SourceString
|
|
);
|
|
|
|
void RtlMoveMemory(
|
|
void* Destination,
|
|
const void* Source,
|
|
size_t Length
|
|
);
|
|
|
|
volatile void * RtlMoveVolatileMemory(
|
|
volatile void *Destination,
|
|
volatile const void *Source,
|
|
size_t Length
|
|
);
|
|
|
|
void RtlInitUnicodeString(
|
|
PUNICODE_STRING DestinationString,
|
|
PCWSTR SourceString
|
|
);
|
|
|
|
void test_copy_and_move_memory() {
|
|
int x = source();
|
|
|
|
{
|
|
char dest_buffer[1024];
|
|
RtlCopyVolatileMemory(dest_buffer, &x, sizeof(x));
|
|
sink(dest_buffer[0]); // $ ir
|
|
}
|
|
{
|
|
char dest_buffer[1024];
|
|
RtlCopyDeviceMemory(dest_buffer, &x, sizeof(x));
|
|
sink(dest_buffer[0]); // $ ir
|
|
}
|
|
{
|
|
char dest_buffer[1024];
|
|
RtlCopyMemory(dest_buffer, &x, sizeof(x));
|
|
sink(dest_buffer[0]); // $ ir
|
|
}
|
|
{
|
|
char dest_buffer[1024];
|
|
RtlCopyMemoryNonTemporal(dest_buffer, &x, sizeof(x));
|
|
sink(dest_buffer[0]); // $ ir
|
|
}
|
|
{
|
|
UNICODE_STRING dest_string;
|
|
UNICODE_STRING src_string;
|
|
wchar_t buffer[1024];
|
|
buffer[0] = source();
|
|
|
|
RtlInitUnicodeString(&src_string, buffer);
|
|
sink(src_string.Buffer[0]); // $ ir
|
|
RtlCopyUnicodeString(&dest_string, &src_string);
|
|
sink(dest_string.Buffer[0]); // $ ir
|
|
}
|
|
{
|
|
char dest_buffer[1024];
|
|
RtlMoveMemory(dest_buffer, &x, sizeof(x));
|
|
sink(dest_buffer[0]); // $ ir
|
|
}
|
|
{
|
|
volatile char dest_buffer[1024];
|
|
RtlMoveVolatileMemory(dest_buffer, &x, sizeof(x));
|
|
sink(dest_buffer[0]); // $ ir
|
|
}
|
|
} |