Categories > Exploiting > Roblox >

[RELEASE] proxy based retcheck bypass

0x90

dingleberry#2286

vip

Posts: 249

Threads: 26

Joined: Dec, 2020

Reputation: 28

Posted

Saw some guy make a thread on a pretty stupid way of bypassing retcheck, so I decided to reimplement it using more modern C++

basically, it writes a return at the start of the retcheck function before calling your function, then caches the original byte, and finally sets it back.

People have been using this stupid "method" for a while, but I decided it'd be fun to embed it in a wrapper instead.

 

code:

#pragma once
#include <Windows.h>
#include <cstdint>
#include <utility>
#include <type_traits>

namespace roblox::retcheck::proxy
{
	template <typename T1, typename T2>
	const T1 functional_cast(const T2 value)
	{
		return T1(value);
	}

	template <typename T, typename T2>
	const T rebase(const T2 value)
	{
		return functional_cast<T>((functional_cast<std::uintptr_t>(value) - 0x400000 + reinterpret_cast<std::uintptr_t>(GetModuleHandle(0))));
	}

	const auto retcheck_addr = rebase<std::uintptr_t>(0x6E6890);		/* this should be the address of the retcheck function, I'll make an auto updating vers later */

	template <typename T>
	class retcheck
	{
		const std::uintptr_t ptr{};

		template <typename T1>
		class proxy
		{
			const T1 ptr{};

		public:

			template <typename... T2>
			auto operator()(T2 ... args) const
			{
				return ptr(args...);
			}

			template <typename... T2>
			void operator()(std::is_void<void> is_void, T2 ... args) const
			{
				ptr(args...);
			}

			explicit proxy(T1 ptr) : ptr(ptr) {};
		};

		const std::uint32_t set_page(const std::uintptr_t ptr, const size_t sz, const std::uint32_t page) const
		{
			DWORD old{};
			VirtualProtect(reinterpret_cast<LPVOID>(ptr), sz, page, &old);
			return old;
		}

		const std::uint8_t write_byte(const std::uintptr_t ptr, const std::uint8_t byte) const
		{
			const auto original = set_page(ptr, 1, PAGE_EXECUTE_READWRITE);
			auto virtual_ptr = reinterpret_cast<std::uint8_t*>(ptr);
			const auto original_byte = *virtual_ptr;
			*virtual_ptr = byte;
			set_page(ptr, 1, original);
			return original_byte;
		}

	public:

		template <typename... T2 >
		auto operator()(T2... args) const
		{
			const auto prox = proxy<T>(functional_cast<T>(ptr));
			const auto original_byte = write_byte(retcheck_addr, 0xC3);
			const auto result = prox(args...);
			write_byte(retcheck_addr, original_byte);
			return result;
		}

		template <typename... T2 >
		void operator()(std::is_void<void> void_enforced, T2... args) const
		{
			const auto prox = proxy<T>(functional_cast<T>(ptr));
			const auto original_byte = write_byte(retcheck_addr, 0xC3);
			prox(args...);
			write_byte(retcheck_addr, original_byte);
		}

		template <typename T1>
		explicit retcheck(const T1 val) : ptr(rebase<std::uintptr_t>(val)) {}
	};
}

 

declaration:

	using getfield_t = int(__fastcall*)(roblox::types::lua_State*, int, const char*);
	static const auto getfield = retcheck::proxy::retcheck<getfield_t>(0x015268D0);

 

calling it:

addresses::getfield(RL, idx, name);

the problems:

Besides speed and the fact that this method requires an extra address, there really isn't that much wrong with it.

The real problem resides in my implementation of the proxy, so you can declare a function's return type automatically, and it'll work perfectly, however this function MUST return.

The issue resides in whether or not the function it's wrapping returns void, as a standalone type you can not return an actual value from void, and in order to keep it 100% compatible and easy to write there had to be a pretty stupid method behind solving it.

 

Instead of using C++20 concepts, or confusing type_trait magic, I just decided it'd be easier to overload the operator, I simply added an extra argument to determine whether or not the function returns void.

 

It also automatically rebases addresses, I really should've made a template argument as to whether or not this should be done, but I just didn't think about it in the moment, feel free to update it yourself.

 

Here's how you'd call a function that returns void using the proxy:

addresses::pushlstring(std::is_void<void>(), RL, str, len)

so if your function has a void return type, always supply std::is_void<void>() as the very first argument to it.

 

I wrote this wrapper based on this guy's thread https://wearedevs.net/forum/t/20356

I'll probably write an auto updating implementation soon, but if you can't get the address of the retcheck function

this thread probably isn't for you anyway

  • 0

Posts: 0

Threads: 0

Joined: ?

Reputation:

Replied

might use just because it's by 0x90 and 0x90 most poggers

 

nice release cooler than Final's

  • 0

TaxiDriver08

JustMarie

Posts: 1547

Threads: 39

Joined: Dec, 2020

Reputation: 6

Replied

i luv tis code.....

  • 0

JustMarie#0709

 

0x90

dingleberry#2286

vip

Posts: 249

Threads: 26

Joined: Dec, 2020

Reputation: 28

Replied

@63568

there's no real reason to use this over something like Eternal's, I just wrote it in a more modern way because a thread reminded me of variable's old retcheck bypass that barely worked LOL

  • 0

Added

@TaxiDriver08

ngl I'm not proud of it LOL

  • 0

Posts: 1258

Threads: 84

Joined: Feb, 2021

Reputation: 79

Replied

what is retcheck?

lmao i am dumb

  • 0

https://media.discordapp.net/attachments/1013939973671624917/1027279180192292944/unknown.png
https://media.discordapp.net/attachments/1010670716062007347/1108945330847883274/image.png

0x90

dingleberry#2286

vip

Posts: 249

Threads: 26

Joined: Dec, 2020

Reputation: 28

Replied

@Hiroku

It's a check in roblox, basically for every call instruction in assembly there's something called the return address pushed to the stack.

The return address tells the return instruction what to jump to when it's hit, basically it's checking if the return address is within a roblox segment, if not then flag the user.

  • 0

Posts: 2099

Threads: 10

Joined: Sep, 2020

Reputation: 62

Replied

Vouch 90 is a god

  • 0

Discord : Doctor Doom#0550

TaxiDriver08

JustMarie

Posts: 1547

Threads: 39

Joined: Dec, 2020

Reputation: 6

Replied

@0x90

no it quality code senpai

  • 0

JustMarie#0709

 

Posts: 1258

Threads: 84

Joined: Feb, 2021

Reputation: 79

Replied

@63907oh ok thank you

  • 0

https://media.discordapp.net/attachments/1013939973671624917/1027279180192292944/unknown.png
https://media.discordapp.net/attachments/1010670716062007347/1108945330847883274/image.png

pepsi

PePsIDeveloper

vip

Posts: 309

Threads: 6

Joined: Apr, 2021

Reputation: 16

Replied

MY GOD THIS IS WHAT MY DEMON IS LOOKING FOR AM FREEEEEEEEEEEEEEEEEEEEEE.

  • 0

https://cdn.discordapp.com/attachments/661621789591470090/1013919752294498314/Untitled_1366_768_px_1546_202_px_2.gif

Posts: 91

Threads: 7

Joined: May, 2020

Reputation: 29

Replied

Cool and good release will vouch for it, I legit made mine in less than 5 minutes (same with the gettop hook that was like 5 minutes too) tbh but that's besides the point

  • 0

sniff

pepsi

PePsIDeveloper

vip

Posts: 309

Threads: 6

Joined: Apr, 2021

Reputation: 16

Replied

@57156am pretty sure 0x90 is talk about in this thread lol "Saw some guy make a thread on a pretty stupid way of bypassing retcheck"

  • 0

https://cdn.discordapp.com/attachments/661621789591470090/1013919752294498314/Untitled_1366_768_px_1546_202_px_2.gif

Users viewing this thread:

( Members: 0, Guests: 1, Total: 1 )