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

[Request]: Calling script functions #164

Closed
tuyilmaz opened this issue Jul 16, 2024 · 19 comments · Fixed by #170
Closed

[Request]: Calling script functions #164

tuyilmaz opened this issue Jul 16, 2024 · 19 comments · Fixed by #170
Assignees
Labels
request A request for a feature in HorseMenu

Comments

@tuyilmaz
Copy link
Contributor

Problem

No response

Solution

Writing a script function wrapper as in YimMenu

Reason

It's possible to add gold, cash, xp, loot tables, and collectibles instantly with script functions.

Additional context

No response

@tuyilmaz tuyilmaz added the request A request for a feature in HorseMenu label Jul 16, 2024
@Rxann Rxann self-assigned this Jul 16, 2024
@Rxann
Copy link
Contributor

Rxann commented Jul 16, 2024

Okay, I will work on it for my upcoming PR

@maybegreat48
Copy link
Contributor

It's possible to add gold, cash, xp, loot tables, and collectibles instantly with script functions.

How exactly?

@tuyilmaz
Copy link
Contributor Author

It's possible to add gold, cash, xp, loot tables, and collectibles instantly with script functions.

How exactly?

Script: net_main_offline
Signature: 22 05 24
Args: {AwardHash, false, 255, 0, false}

@maybegreat48
Copy link
Contributor

What's the function name? And can you give me an example award hash?

@tuyilmaz
Copy link
Contributor Author

Currently I don't have the latest decompiled scripts, but here is the function:

BOOL func_531(int iParam0, BOOL bParam1, Player plParam2, int iParam3, BOOL bParam4) // Position - 0x23A3F Signature - 22 05 24
{
	var unk;
	var unk13;
	var unk26;

	unk.f_1 = 10;
	unk13.f_1 = 11;
	return func_1940(iParam0, &unk26, &unk13, &unk, bParam1, plParam2, iParam3, bParam4);
}

And for award hashes:
315612159 (250 cash)
-1306394522 (1 gold)

@AAA-ALR
Copy link
Contributor

AAA-ALR commented Jul 19, 2024

UnkByteData_program RDR2.exe+0x59B29E0
UnkByteData_script_vm RDR2.exe+0x59B2940
get_script_program(int8_t*,Hash) RDR2.exe+0x2AFF0B8

void script_function_call(const Hash scriptHash, uint32_t ip, std::initializer_list<uint64_t> args)
{
	auto thread = rdr_util::FindScriptThread(scriptHash);
	auto program = get_script_program(UnkByteData_program, scriptHash);
	if (thread && program)
	{
		auto tls_ctx = rage::tlsContext::Get();
		auto stack = (uint64_t*)thread->m_Stack;
		auto og_thread = *Pointers.CurrentScriptThread;
		auto og_running_in_scrthread = rage::tlsContext::Get()->m_RunningScript;
		*Pointers.CurrentScriptThread = thread;
		rage::tlsContext::Get()->m_RunningScript = true;
		rage::scrThreadContext ctx = thread->m_Context;
		for (auto& arg : args)
			stack[ctx.m_StackPointer++] = arg;
		stack[ctx.m_StackPointer++] = 0;
		ctx.m_ProgramCounter = ip;
		ctx.m_State = rage::eThreadState::idle;
		*Pointers.ScriptVM(stack, *Pointers.ScriptGlobals, UnkByteData_script_vm, program, &ctx);
		rage::tlsContext::Get()->m_RunningScript = og_running_in_scrthread;
		*Pointers.CurrentScriptThread = og_thread;
	}
}

Added CHEAT_XP example

script_function_call(rage::joaat("net_main_offline"),0x23A3F,{0xED1FAB28, false, 0, 0, false});

Maybe there will be a lot of skid menus added soon lol

@xiaoxiao921
Copy link
Member

Nice work!

@gir489returns
Copy link

@AAA-ALR From what I can tell from your code, you're basically hijacking a (random?) script, forcing its Instruction Pointer to the function you want to call? I'm assuming FindScriptThread finds a non-running script thread? Why can't you simply just allocate a new script for the thread runner and use it? There's always a chance if you use something like freemode (IDK what RDR2 calls it), that some script will do GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH and have it return non-zero, and it thinks that the script is running, when in actuality it's just us doing script schenanigns.

tl;dr: Is there a more efficient way to create a script in the thread stack?

@AAA-ALR
Copy link
Contributor

AAA-ALR commented Jul 19, 2024

@AAA-ALR From what I can tell from your code, you're basically hijacking a (random?) script, forcing its Instruction Pointer to the function you want to call? I'm assuming FindScriptThread finds a non-running script thread? Why can't you simply just allocate a new script for the thread runner and use it? There's always a chance if you use something like freemode (IDK what RDR2 calls it), that some script will do GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH and have it return non-zero, and it thinks that the script is running, when in actuality it's just us doing script schenanigns.

tl;dr: Is there a more efficient way to create a script in the thread stack?

I don't know much about the game scripts,But this net_main_offline is like a freemod of GTA

@tuyilmaz
Copy link
Contributor Author

After a little research I've discovered there are award hashes located in:
update_4.rpf/x64/data/itemdatabase/catalog_awards_mp.rpf/catalog_awards_mp.ymt
This file contains award multipliers, too. However there is another file called 'AwardsDatabase_********' which is downloaded from the servers when you join RDO. I'm pretty sure this file contains latest gold, xp, cash multipliers for missions. It also contains all the outlaw pass unlocks, but they're server only. I'm not good at RE, so I don't know if it's possible to trigger those transactions.

@AAA-ALR nice work, but I don't think we need the script thread for this function. We can just create our own thread and stack call the ScriptVM function then delete them.

@Rxann
Copy link
Contributor

Rxann commented Jul 19, 2024


UnkByteData_program RDR2.exe+0x59B29E0

UnkByteData_script_vm RDR2.exe+0x59B2940

get_script_program(int8_t*,Hash) RDR2.exe+0x2AFF0B8



void script_function_call(const Hash scriptHash, uint32_t ip, std::initializer_list<uint64_t> args)

{

	auto thread = rdr_util::FindScriptThread(scriptHash);

	auto program = get_script_program(UnkByteData_program, scriptHash);

	if (thread && program)

	{

		auto tls_ctx = rage::tlsContext::Get();

		auto stack = (uint64_t*)thread->m_Stack;

		auto og_thread = *Pointers.CurrentScriptThread;

		auto og_running_in_scrthread = rage::tlsContext::Get()->m_RunningScript;

		*Pointers.CurrentScriptThread = thread;

		rage::tlsContext::Get()->m_RunningScript = true;

		rage::scrThreadContext ctx = thread->m_Context;

		for (auto& arg : args)

			stack[ctx.m_StackPointer++] = arg;

		stack[ctx.m_StackPointer++] = 0;

		ctx.m_ProgramCounter = ip;

		ctx.m_State = rage::eThreadState::idle;

		*Pointers.ScriptVM(stack, *Pointers.ScriptGlobals, UnkByteData_script_vm, program, &ctx);

		rage::tlsContext::Get()->m_RunningScript = og_running_in_scrthread;

		*Pointers.CurrentScriptThread = og_thread;

	}

}



Added CHEAT_XP example


script_function_call(rage::joaat("net_main_offline"),0x23A3F,{0xED1FAB28, false, 0, 0, false});

Maybe there will be a lot of skid menus added soon lol

UnkByteData_script_vm seems to indicate if globals are enabled or not. Incredible work on this though!

@tuyilmaz
Copy link
Contributor Author

@Rxann If you haven't started working on this. I wrote a function wrapper using YimMenu and @AAA-ALR's reply. I can create a PR.

@Rxann
Copy link
Contributor

Rxann commented Jul 21, 2024

@Rxann If you haven't started working on this. I wrote a function wrapper using YimMenu and @AAA-ALR's reply. I can create a PR.

@maybegreat48 has already made an implementation that will be included into the menu soon. Thank you for asking before creating a PR though.

@maybegreat48
Copy link
Contributor

@maybegreat48 has already made an implementation that will be included into the menu soon. Thank you for asking before creating a PR though.

To add some context, our development workflow now involves a private development repository to prevent certain paid menu grifters (especially a menu named "Fortitude") from stealing our source before it makes it to HorseMenu

@tuyilmaz
Copy link
Contributor Author

@maybegreat48 I understand. May I ask if you're just implementing the function wrapper or are you doing more research on this give award thing? Thanks for your efforts btw.

@maybegreat48
Copy link
Contributor

maybegreat48 commented Jul 21, 2024

I've reversed the file containing the award hashes, but many of them don't seem to work as intended, likely due to the lack of proper YMT parsing support for RDR2

@tuyilmaz
Copy link
Contributor Author

Here is an award item from that file:
<Item key="0x12CFDBFF"> <key>0x12CFDBFF</key> <maxclaims value="-1"/> <ignoresmodifiers value="false"/> <debugonly value="false"/> <serveronly value="false"/> <awarditems> <experience value="0"/> <items> <Item> <key>currency_cash</key> <path>0x96F2DE61</path> <qty value="25000"/> </Item> </items> <unlocks/> </awarditems> </Item>
And from what I tried I found out that debugonly and serveronly awards can't be given using that script function. Can you please give more context about what made you think that they don't work as intended?

@AAA-ALR
Copy link
Contributor

AAA-ALR commented Jul 21, 2024

Here is an award item from that file: <Item key="0x12CFDBFF"> <key>0x12CFDBFF</key> <maxclaims value="-1"/> <ignoresmodifiers value="false"/> <debugonly value="false"/> <serveronly value="false"/> <awarditems> <experience value="0"/> <items> <Item> <key>currency_cash</key> <path>0x96F2DE61</path> <qty value="25000"/> </Item> </items> <unlocks/> </awarditems> </Item> And from what I tried I found out that debugonly and serveronly awards can't be given using that script function. Can you please give more context about what made you think that they don't work as intended?

NETWORK::NETWORK_AWARD_HAS_REACHED_MAXCLAIM I guess

@maybegreat48
Copy link
Contributor

maybegreat48 commented Jul 21, 2024

Can you please give more context about what made you think that they don't work as intended?

Anything that's supposed to give you gold doesn't actually give you gold
This is how the file looks for me

 <Item type="ItemDatabaseAward" key="hash_12CFDBFF">
    <key>hash_12CFDBFF</key>
    <maxclaims value="-1" />
    <ignoresmodifiers value="false" />
    <debugonly value="false" />
    <serveronly value="false" />
    <awarditems>
     <experience value="0" />
     <items itemType="ItemDatabaseAwardItem">
      <Item>
       <key>hash_00000001</key>
       <path />
       <qty value="0" />
      </Item>
     </items>
     <unlocks itemType="ItemDatabaseAwardUnlock" />
    </awarditems>
   </Item>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request A request for a feature in HorseMenu
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants