View Single Post
Author Message
jim_yang
Veteran Member
Join Date: Aug 2006
Old 06-26-2009 , 09:51   New Way To Block Round End
Reply With Quote #1

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]
Attached Files
File Type: zip noroundend_amxx.zip (81.8 KB, 3196 views)
__________________
Project : CSDM all in one - 99%
<team balancer#no round end#entity remover#quake sounds#fake full#maps management menu#players punishment menu#no team flash#colored flashbang#grenade trails#HE effect#spawn protection#weapon arena#weapon upgrade#auto join#no weapon drop#one name>

Last edited by jim_yang; 08-15-2009 at 07:22. Reason: fix a return value bug
jim_yang is offline