rendered paste body#include "amxxmodule.h"
#define TEAM_SPECTATOR 3
#define FREELOOK_ENABLE 0
#define FREELOOK_DISABLE 1
typedef unsigned int MEMADDR;
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define OFFSET_TEAM 456
const byte signature[]=
{0x8B,0x83,0xC8,0x01,0x00,0x00,0xC6,0x44,0x24,0x1C,0x01,0x83,0xF8,0x03};
byte patch[]=
{0xC6,0x44,0x24,0x1C,0x01,0xB8,0x90,0x90,0x90,0x90,0xFF,0xD0,0x85,0xC0};
#else
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#define PAGE_SIZE 4096
#define ALIGN(ar) ((long)ar & ~(PAGE_SIZE-1))
#define CBASEPLAYER_OBSERVER_FINDNEXTPLAYER "Observer_FindNextPlayer__11CBasePlayerbPCc"
#define CBASEPLAYER_OBSERVER_FINDNEXTPLAYER_SIZE 0x3E4
#define OFFSET_TEAM 476
const byte signature[]=
{0x83,0xB8,0xDC,0x01,0x00,0x00,0x03};
byte patch[]=
{0xB8,0x90,0x90,0x90,0x90,0xFF,0xD0};
#endif
cvar_t amx_adminfreelook = {"amx_adminfreelook", "1", 1, 1.0};
cvar_t amx_adminfreelookflag = {"amx_adminfreelookflag", "d"};
cvar_t *amx_afl;
cvar_t *amx_aflf;
void register_cvar()
{
CVAR_REGISTER(&amx_adminfreelook);
CVAR_REGISTER(&amx_adminfreelookflag);
amx_afl = CVAR_GET_POINTER(amx_adminfreelook.name);
amx_aflf = CVAR_GET_POINTER(amx_adminfreelookflag.name);
}
static MEMADDR get_patch_loc()
{
#ifdef WIN32
MEMORY_BASIC_INFORMATION mem;
if(!VirtualQuery(MDLL_AddToFullPack, &mem, sizeof(mem)))
return NULL;
if(mem.AllocationBase == NULL)
return NULL;
MEMADDR address = (MEMADDR)mem.AllocationBase;
IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)address;
if(IsBadReadPtr(dos, sizeof(IMAGE_DOS_HEADER)) || dos->e_magic != IMAGE_DOS_SIGNATURE)
return NULL;
address += dos->e_lfanew;
IMAGE_NT_HEADERS *pe = (IMAGE_NT_HEADERS *)address;
if(IsBadReadPtr(pe, sizeof(IMAGE_NT_HEADERS)) || pe->Signature != IMAGE_NT_SIGNATURE)
return NULL;
MEMADDR begin = address + pe->OptionalHeader.BaseOfCode;
MEMADDR end = begin + pe->OptionalHeader.SizeOfCode - sizeof(signature);
#else
Dl_info info;
if(!dladdr(MDLL_AddToFullPack, &info))
return NULL;
if(!info.dli_fbase || !info.dli_fname)
return NULL;
void *handle = dlopen(info.dli_fname, RTLD_NOW);
if(!handle)
return NULL;
void *funcaddr = dlsym(handle, CBASEPLAYER_OBSERVER_FINDNEXTPLAYER);
dlclose(handle);
MEMADDR begin = (MEMADDR)funcaddr;
MEMADDR end = begin + CBASEPLAYER_OBSERVER_FINDNEXTPLAYER_SIZE;
#endif
for(MEMADDR addr = begin; addr < end; ++addr)
{
if(!memcmp((void *)addr, signature, sizeof(signature)))
return addr;
}
return NULL;
}
inline int PrivateToIndex(const PVOID pdata)
{
if(pdata)
{
char *ptr = (char *)pdata;
#ifdef WIN32
ptr += 4;
#endif
entvars_t *pev = *(entvars_t **)ptr;
if(pev && pev->pContainingEntity)
return ENTINDEX(pev->pContainingEntity);
}
return -1;
}
int UTIL_ReadFlags(const char* c)
{
int flags = 0;
while(*c)
flags |= (1<<(*c++ - 'a'));
return flags;
}
#ifdef WIN32
int admin_freelook()
{
int team;
__asm mov eax, [ebx + OFFSET_TEAM];
__asm mov team, eax;
if(amx_afl->value == 0)
return team != TEAM_SPECTATOR;
void *pWatcher = NULL;
__asm mov pWatcher, ebx;
int id = PrivateToIndex(pWatcher);
if(MF_GetPlayerFlags(id) & UTIL_ReadFlags(amx_aflf->string))
return FREELOOK_ENABLE;
return team != TEAM_SPECTATOR;
}
#else
void admin_freelook()
{
int team;
__asm__ __volatile__("movl 8(%ebp), %eax");
__asm__ __volatile__("movl 476(%eax), %eax");
__asm__ __volatile__("movl %%team, %0":"=a"(team));
if(amx_afl->value == 0)
{
__asm__ __volatile__("cmp $3, %eax");
return;
}
void *pWatcher = NULL;
__asm__ __volatile__("movl 8(%ebp), %eax");
__asm__ __volatile__("movl %%pWatcher, %0":"=a"(pWatcher));
int id = PrivateToIndex(pWatcher);
if(MF_GetPlayerFlags(id) & UTIL_ReadFlags(amx_aflf->string))
{
__asm__ __volatile__("xor %eax, %eax");
return;
}
__asm__ __volatile__("cmp $3, %0"::"m"(team));
return;
}
#endif
void OnMetaAttach()
{
void *addr = (void *)get_patch_loc();
if(!addr)
{
SERVER_PRINT("[ADMIN FREE LOOK] patch failed.\n");
return;
}
union
{
void *func;
byte fbyte[4];
}ptob;
ptob.func = &admin_freelook;
#ifdef WIN32
patch[6] = ptob.fbyte[0];
patch[7] = ptob.fbyte[1];
patch[8] = ptob.fbyte[2];
patch[9] = ptob.fbyte[3];
DWORD oldflags;
if(VirtualProtect(addr, sizeof(signature), PAGE_EXECUTE_READWRITE, &oldflags))
{
memcpy(addr, patch, sizeof(patch));
DWORD flags;
if(VirtualProtect(addr, sizeof(signature), oldflags, &flags))
{
SERVER_PRINT("[ADMIN FREE LOOK] patch succeed.\n");
register_cvar();
return;
}
}
#else
patch[1] = ptob.fbyte[0];
patch[2] = ptob.fbyte[1];
patch[3] = ptob.fbyte[2];
patch[4] = ptob.fbyte[3];
void *addr2 = (void *)ALIGN(addr);
if(mprotect(addr2, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE|PROT_EXEC) == 0)
{
memcpy(addr, patch, sizeof(patch));
SERVER_PRINT("[ADMIN FREE LOOK] patch succeed.\n");
register_cvar();
return;
}
#endif
SERVER_PRINT("[ADMIN FREE LOOK] patch failed.\n");
return;
}