tools/vtable_scanner/main.cpp
author Ruben Gonzalez <drifter01620@gmail.com>
Thu May 22 09:49:27 2014 -0400 (2014-05-22)
changeset 4378 568f4497ef4a
parent 2677 f6097a2d9812
permissions -rw-r--r--
Update CS:GO team score gamedata.
     1 #include <stdio.h>
     2 #include <dlfcn.h>
     3 #include "string.h"
     4 #include "malloc.h"
     5 
     6 extern "C" char * cplus_demangle(const char *, int);
     7 #define DMGL_PARAMS	 (1 << 0)
     8 
     9 struct VOffset
    10 {
    11 	int linux_offset;
    12 	int windows_offset;
    13 };
    14 
    15 static bool FindVFunc(void *handle, void **vtable, const char* vtable_end, const char *class_function, const char *params, VOffset *offsets);
    16 
    17 int main(int argc, char **argv)
    18 {
    19 	void *handle;
    20 	void **pVtable;
    21 
    22 	VOffset offsets;
    23 	char *params = NULL;
    24 	bool ret;
    25 
    26 	if (argc < 4)
    27 	{
    28 		fprintf(stderr, "Usage: <binary> <vtable start symbol> <function> <optional: params> <optional: vtable end symbol>\n");
    29 		return -1;
    30 	}
    31 
    32 	handle = dlopen(argv[1], RTLD_NOW);
    33 
    34 	if (handle == NULL)
    35 	{
    36 		fprintf(stderr, "Failed to open server image, error [%s]\n", dlerror());
    37 		return -1;
    38 	}
    39 
    40 	pVtable = (void **)dlsym(handle, argv[2]);
    41 
    42 	if (pVtable == NULL)
    43 	{
    44 		char startSym[128];
    45 		snprintf(startSym, sizeof(startSym), "_ZTV%d%s", strlen(argv[2]), argv[2]);
    46 		pVtable = (void **)dlsym(handle, startSym);
    47 	}
    48 
    49 	if (pVtable == NULL)
    50 	{
    51 		fprintf(stderr, "Invalid vtable symbol \"%s\"\n", argv[2]);
    52 		dlclose(handle);
    53 		return -1;
    54 	}
    55 
    56 	if (argc >= 5)
    57 	{
    58 		params = argv[4];
    59 
    60 		if (params[0] == '"')
    61 		{
    62 			params++;
    63 		}
    64 
    65 		int len = strlen(params)-1;
    66 
    67 		if (params[len] == '"')
    68 		{
    69 			params[len] = '\0';
    70 		}
    71 
    72 		if (params[0] == 0)
    73 		{
    74 			params = NULL;
    75 		}
    76 	}
    77 
    78 	if (argc == 6)
    79 	{
    80 		ret = FindVFunc(handle, pVtable, argv[5], argv[3], params, &offsets);
    81 	}
    82 	else
    83 	{
    84 		ret = FindVFunc(handle, pVtable, "_ZTI", argv[3], params, &offsets);
    85 	}
    86 
    87 	if (ret)
    88 	{
    89 		if (params != NULL)
    90 		{
    91 			printf("%s%s - Win: %i  Linux : %i\n", argv[3], params, offsets.windows_offset, offsets.linux_offset);
    92 		}
    93 		else
    94 		{
    95 			printf("%s - Win: %i  Linux : %i\n", argv[3], offsets.windows_offset, offsets.linux_offset);
    96 		}
    97 		
    98 		dlclose(handle);
    99 		return 0;
   100 	}
   101 
   102 	fprintf(stderr, "Failed to find function!");
   103 	dlclose(handle);
   104 	return -1;
   105 }
   106 
   107 static bool FindVFunc(void *handle, void **vtable, const char* vtable_end, const char *class_function, const char *params, VOffset *offsets)
   108 {
   109 	Dl_info d;
   110 
   111 	int linux_offset = -1;
   112 	int windows_offset = -1;
   113 
   114 	int overloads = 0;
   115 	int location = 0;
   116 	int start_offset = -1;
   117 
   118 	for (int i=0; i< 1000; i++)
   119 	{
   120 		void *FuncPtr = vtable[i];
   121 
   122 		int status = dladdr(FuncPtr, &d);
   123 
   124 		if (!status)
   125 		{
   126 			continue;
   127 		}
   128 
   129 		if (i > 1 && strncmp(d.dli_sname, vtable_end, strlen(vtable_end)) == 0)
   130 		{
   131 			break;
   132 		}
   133 
   134 		char *name = cplus_demangle(d.dli_sname, DMGL_PARAMS);
   135 
   136 		if (name == NULL)
   137 		{
   138 			printf("Demangling failed\n");
   139 			continue;
   140 		}
   141 
   142 		char *foundfunction = strpbrk(name, ":");
   143 
   144 		if (foundfunction == NULL)
   145 		{
   146 			//printf("Couldnt split function\n");
   147 			free(name);
   148 			continue;
   149 		}
   150 
   151 		//Skip both ':' chars
   152 		foundfunction += 2;
   153 
   154 
   155 		if (strncmp(foundfunction, class_function, strlen(class_function)) == 0 && foundfunction[strlen(class_function)] == '(')
   156 		{
   157 			//printf("Symbol: %s Demangled: %s Offset: %i\n", d.dli_sname, name, i);
   158 
   159 			//We have a pointer to a function, but it may be overloaded.
   160 			overloads++;
   161 
   162 			if (start_offset == -1)
   163 			{
   164 				start_offset = i-1;
   165 			}
   166 
   167 			char *foundparams = strpbrk(foundfunction, "(");
   168 
   169 			if (foundparams == NULL)
   170 			{
   171 				printf("ARGH\n");
   172 				free(name);
   173 				continue;
   174 			}
   175 
   176 			if(params == NULL || strcmp(foundparams, params) == 0)
   177 			{
   178 				//This is actually our function - So this is the linux offset
   179 				linux_offset = i;
   180 				location = overloads;
   181 			}
   182 		}
   183 
   184 		free(name);
   185 	}
   186 
   187 	windows_offset = (overloads-location) + start_offset;
   188 
   189 	offsets->linux_offset = linux_offset - 2;
   190 	offsets->windows_offset = windows_offset - 2;
   191 
   192 	return true;
   193 }