All pastes #2051773 Raw Edit

Mine

public text v1 · immutable
#2051773 ·published 2011-04-29 00:55 UTC
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;
}