Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Epic's "Easy Anti Cheat" #99

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/crashpad_client_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ bool StartHandlerProcess(
}

ScopedKernelHANDLE this_process(
OpenProcess(kXPProcessAllAccess, true, GetCurrentProcessId()));
OpenProcess(kXPProcessLimitedAccess, true, GetCurrentProcessId()));
if (!this_process.is_valid()) {
PLOG(ERROR) << "OpenProcess";
return false;
Expand Down
7 changes: 5 additions & 2 deletions snapshot/win/process_reader_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ bool FillThreadContextAndSuspendCount(HANDLE process,
thread->id ==
reinterpret_cast<process_types::TEB<Traits>*>(NtCurrentTeb())
->ClientId.UniqueThread;
bool did_suspend_thread = true;

if (is_current_thread) {
DCHECK(suspension_state == ProcessSuspensionState::kRunning);
Expand All @@ -243,7 +244,9 @@ bool FillThreadContextAndSuspendCount(HANDLE process,
DWORD previous_suspend_count = SuspendThread(thread_handle);
if (previous_suspend_count == static_cast<DWORD>(-1)) {
PLOG(ERROR) << "SuspendThread";
return false;
// Must assume thread was already suspended, so we can still try to read
did_suspend_thread = false;
previous_suspend_count = 1;
}
if (previous_suspend_count <= 0 &&
suspension_state == ProcessSuspensionState::kSuspended) {
Expand Down Expand Up @@ -281,7 +284,7 @@ bool FillThreadContextAndSuspendCount(HANDLE process,
DoStackWalk(thread, process, thread_handle, is_64_reading_32);
#endif

if (!ResumeThread(thread_handle)) {
if (did_suspend_thread && !ResumeThread(thread_handle)) {
PLOG(ERROR) << "ResumeThread";
return false;
}
Expand Down
35 changes: 30 additions & 5 deletions util/win/exception_handler_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ class ClientData {
non_crash_dump_completed_event_(
std::move(non_crash_dump_completed_event)),
process_(std::move(process)),
process_promoted_(false),
crash_exception_information_address_(
crash_exception_information_address),
non_crash_exception_information_address_(
Expand Down Expand Up @@ -172,6 +173,29 @@ class ClientData {
}
HANDLE process() const { return process_.get(); }

// Promotes the process handle to full access if it hasn't already been done.
HANDLE process_promoted()
{
if (!process_promoted_)
{
// Duplicate restricted process handle for a full memory access handle.
HANDLE hAllAccessHandle = nullptr;
if (DuplicateHandle(GetCurrentProcess(),
process_.get(),
GetCurrentProcess(),
&hAllAccessHandle,
kXPProcessAllAccess,
FALSE,
0))
{
ScopedKernelHANDLE ScopedAllAccessHandle(hAllAccessHandle);
process_.swap(ScopedAllAccessHandle);
process_promoted_ = true;
}
}
return process_.get();
}

private:
void RegisterThreadPoolWaits(
WAITORTIMERCALLBACK crash_dump_request_callback,
Expand Down Expand Up @@ -232,6 +256,7 @@ class ClientData {
ScopedKernelHANDLE non_crash_dump_requested_event_;
ScopedKernelHANDLE non_crash_dump_completed_event_;
ScopedKernelHANDLE process_;
bool process_promoted_;
WinVMAddress crash_exception_information_address_;
WinVMAddress non_crash_exception_information_address_;
WinVMAddress debug_critical_section_address_;
Expand Down Expand Up @@ -459,14 +484,14 @@ bool ExceptionHandlerServer::ServiceClientConnection(
// the process, but the client will be able to, so we make a second attempt
// having impersonated the client.
HANDLE client_process = OpenProcess(
kXPProcessAllAccess, false, message.registration.client_process_id);
kXPProcessLimitedAccess, false, message.registration.client_process_id);
if (!client_process) {
if (!ImpersonateNamedPipeClient(service_context.pipe())) {
PLOG(ERROR) << "ImpersonateNamedPipeClient";
return false;
}
client_process = OpenProcess(
kXPProcessAllAccess, false, message.registration.client_process_id);
kXPProcessLimitedAccess, false, message.registration.client_process_id);
PCHECK(RevertToSelf());
if (!client_process) {
LOG(ERROR) << "failed to open " << message.registration.client_process_id;
Expand Down Expand Up @@ -543,11 +568,11 @@ void __stdcall ExceptionHandlerServer::OnCrashDumpEvent(void* ctx, BOOLEAN) {

// Capture the exception.
unsigned int exit_code = client->delegate()->ExceptionHandlerServerException(
client->process(),
client->process_promoted(),
client->crash_exception_information_address(),
client->debug_critical_section_address());

SafeTerminateProcess(client->process(), exit_code);
SafeTerminateProcess(client->process_promoted(), exit_code);
}

// static
Expand All @@ -558,7 +583,7 @@ void __stdcall ExceptionHandlerServer::OnNonCrashDumpEvent(void* ctx, BOOLEAN) {

// Capture the exception.
client->delegate()->ExceptionHandlerServerException(
client->process(),
client->process_promoted(),
client->non_crash_exception_information_address(),
client->debug_critical_section_address());

Expand Down
4 changes: 4 additions & 0 deletions util/win/xp_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ enum {
//! against a Vista+ SDK results in `ERROR_ACCESS_DENIED` when running on XP.
//! See https://msdn.microsoft.com/library/ms684880.aspx.
kXPProcessAllAccess = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF,

// A limited access version, suitable for initial access to the process.
kXPProcessLimitedAccess = PROCESS_DUP_HANDLE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE | SYNCHRONIZE,


//! \brief This is the XP-suitable value of `THREAD_ALL_ACCESS`.
//!
Expand Down
Loading