AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Module Coding (https://forums.alliedmods.net/forumdisplay.php?f=9)
-   -   New Way To Block Round End (https://forums.alliedmods.net/showthread.php?t=95705)

jim_yang 06-26-2009 09:51

New Way To Block Round End
 
1 Attachment(s)
As everyone knows, putting a fake bot in each team can prevent round end, but this way has a lot of disadvantage.
(1) take two server slots
(2) waste server resources to deal with server status. (kick bots when players reach some amount etc.)
(3) fake bot and real bot, what a mess!
Here, I'll show a new and hacky way to block round end without adding a stupid fake bot in each team.
This way is to block the roundend function in gamedll.
Part 1. Finding the function
Everyone knows that there are some situation to trigger the round end, such as all players in one team died off, all hostages rescued by ct, vip escaped... . All of them will trigger a log event Round_End, so my clue came out.
First, disassemble game dll, "mp.dll", then I start to search keyword "round_end", found a string:
Code:

"World triggered \"Round_End\"\n"
that's where the msg came out, but this function just log this msg, nothing else. It is obvious that it is not what we need, but every round end will show this msg, so there must be other functions call this log function. (Hope the "other functions" is one function, and that function is probably what we need). Now, jump to this log function's start address, here we got the function's name( named by the disassembler, in IDA it's sub_10093B40 ). Here we click the function name, then go to 'jump' menu, press Jump to cross reference..., now pop up a window list all functions which call this log function we selected.
I found that there are some calls from one function, then I jump to that function, I found some useful information what we exactly expected. Such as "#VIP_Escaped", "#VIP_Assassinated", "#Terrorists_Escaped"...
So lucky that I found this function, sub_10094E90, this is the round end function.
Part 2. Getting real address of this function at run-time
Now It's an easy part since we know the function address. We can get it's real address at run-time, as windows always load process to a static address, this makes things easy. The real address of function sub_10094E90 is:
Code:

mp.dll's entry + (0X10094E90 - Imagebase) // Imagebase is 0X10000000 here, so the function's offset is 0X94E90
which present in C++ is like this:
Code:

#define OFFSET_ROUNDEND 0X94E90
unsigned int gamedlladdr = reinterpret_cast<unsigned int>(GetModuleHandle("mp.dll"));
void *pfnRoundEnd = reinterpret_cast<void *>(gamedlladdr + OFFSET_ROUNDEND); //got this function

Part 3. Block this function
Now we got the function's real address, the next is to patch it.
It is easy to block a function without any conditions. No need to hook it, just write a 'retn' to this function's first byte.
So when this function is called, it become dumb.
Code:

void I_Can_Do_Some_Stuff(int a, int b)
{
    __asm retn; //we turn the first byte of this function to retn, then function return at the begining
    printf("%d", a + b);
}

The C++ code is like this:
Code:

const unsigned char retn = 0xC3; //binary of retn
DWORD oldflags;
VirtualProtect(pfnRoundEnd, sizeof(unsigned char), PAGE_READWRITE, &oldflags);
memcpy(pfnRoundEnd, &retn, sizeof(unsigned char));
VirtualProtect(pfnRoundEnd, sizeof(unsigned char), oldflags, &oldflags);

Now all works done, our patch function looks like this:
Code:

#include <what_should_be_included.h>
#define OFFSET_ROUNDEND 0X94E90
void UTIL_DISABLE_FUNC()
{
    unsigned int gamedlladdr = reinterpret_cast<unsigned int>(GetModuleHandle("mp.dll"));
    if(!gamedlladdr)
    {
        //LOG_ERROR(PLID, "[CSDM] Failed getting Game dll handle");
        return;
    }
    const unsigned char retn = 0xC3;
    void *pfnRoundEnd = reinterpret_cast<void *>(handle + OFFSET_ROUNDEND);
    DWORD oldflags;
    VirtualProtect(pfnRoundEnd, sizeof(unsigned char), PAGE_READWRITE, &oldflags);
    memcpy(pfnRoundEnd, &retn, sizeof(unsigned char));
    VirtualProtect(pfnRoundEnd, sizeof(unsigned char), oldflags, &oldflags);
}

You can add this function in Meta_Attach() or anywhere to see its effect.
Advantage:
plain & more efficient
Using this method to block round end, you don't even have to remove the map entities such as "func_bomb_target"...

Disadvantage:
Hardcoded, which means when the binary updated, there may be a little chance that the function's address would change. You need to resolve the address by disassembing the game dll again to find the new address.(same method above)

Solution:
signature scanning, I will not go too much far for this.
Finally, sorry for not handling linux, maybe someone could make it base this concept.
Thanks for reading, not well written, and sorry for my bad English.

Edit:
upload a module, noroundend_amxx.dll
and sourcecode include linux code, but not compiled and test, should work.

Credit:
bailopan for his signaturemanager class

update:
1. changed the win32 signature
2. fix a small print tip bug
3. change to only command version sv_noroundend [0/1]

Arkshine 06-26-2009 10:12

Re: New Way To Block Round End
 
Interesting stuff !

It would be nice to have a module which allow us to execute or hook all the provided function in CS, like in SourceMod if I'm right.

kielor 06-27-2009 07:17

Re: New Way To Block Round End
 
it would be nice if someone compile this into a mm plugin so there won't be infinity posts with one and the same question >_<

p.s. and it would be perfect if you add offset for linux gamelib ;)
p.p.s. we need to execute this code only once ?

xPaw 06-27-2009 08:53

Re: New Way To Block Round End
 
Quote:

Originally Posted by arkshine (Post 857614)
Interesting stuff !

It would be nice to have a module which allow us to execute or hook all the provided function in CS, like in SourceMod if I'm right.

http://forums.alliedmods.net/showthread.php?t=23152 ?

joaquimandrade 06-27-2009 09:15

Re: New Way To Block Round End
 
Thanks jim.

Yes we need a new module that make us able to hook and call every function of CS (the signature scanning stuff of sourcemod is very nice and almost update proof) . There will be a rain of new plugins then and i'm looking forward to it. I don't have the knowledge to do that. I propose that we start a fund raise to achieve that goal and give the money to the one who make it.

jim_yang 06-28-2009 09:14

Re: New Way To Block Round End
 
thanks for replies, I uploaded a module as an example. no native, just put noroundend_amxx.dll in module folder and write noroundend in config file.

kielor 07-04-2009 13:09

Re: New Way To Block Round End
 
any replies for linux version?

TheRadiance 07-05-2009 03:45

Re: New Way To Block Round End
 
Thanks you.
This is awesome..

ConnorMcLeod 07-08-2009 01:12

Re: New Way To Block Round End
 
Awesome. :mrgreen:
Any command to turn back round ends ?

jim_yang 07-08-2009 04:18

Re: New Way To Block Round End
 
hi, here is a server command version
command: sv_noroundend [0/1]
1: block round end
0: enable round end
null: check the status( whether round end or not)

updated:
see main post


All times are GMT -4. The time now is 23:06.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.