Lucene search

K
huntrGreatergoodest0730A95E-C485-4FF2-9A5D-BB3ABFDA0B17
HistoryMay 21, 2022 - 2:15 p.m.

Use of Uninitialized Function Pointer

2022-05-2114:15:50
greatergoodest
www.huntr.dev
21
crafted input binary
function pointer
switch statement
context initialization
backtrace
binary security

EPSS

0.001

Percentile

31.9%

Description

When providing a crafted input binary to radare2, the context->read_addr function pointer is never initialized before use. This is due to the switch statement responsible for the assignment not finding a matching value for its switch cases.

Calling function


static bool vtable_is_value_in_text_section(RVTableContext *context, ut64 curAddress, ut64 *value) {
	//value at the current address
	ut64 curAddressValue;
	if (!context->read_addr (context->anal, curAddress, &curAddressValue)) { //***crash***
		return false;
	}
	//if the value is in text section
	bool ret = vtable_addr_in_text_section (context, curAddressValue);
	if (value) {
		*value = curAddressValue;
	}
	return ret;
}

Setting Logic

R_API bool r_anal_vtable_begin(RAnal *anal, RVTableContext *context) {
	context->anal = anal;
	context->abi = anal->cxxabi;
	context->word_size = (ut8) (anal->config->bits / 8);
	const bool is_arm = anal->cur->arch && r_str_startswith (anal->cur->arch, "arm");
	if (is_arm && context->word_size < 4) {
		context->word_size = 4;
	}
	const bool be = anal->config->big_endian;
	switch (context->word_size) { //*** THIS IS THE CAUSE***
	case 1:
		context->read_addr = be? vtable_read_addr_be8 : vtable_read_addr_le8;
		break;
	case 2:
		context->read_addr = be? vtable_read_addr_be16 : vtable_read_addr_le16;
		break;
	case 4:
		context->read_addr = be? vtable_read_addr_be32 : vtable_read_addr_le32;
		break;
	case 8:
		context->read_addr = be? vtable_read_addr_be64 : vtable_read_addr_le64;
		break;
	default:
		return false;
	}
	return true;
}
#define VTABLE_READ_ADDR_FUNC(fname, read_fname, sz) \
	static bool fname(RAnal *anal, ut64 addr, ut64 *buf) {\
		ut8 tmp[sz];\
		if (!anal->iob.read_at (anal->iob.io, addr, tmp, sz)) {\
			return false;\
		}\
		*buf = read_fname (tmp);\
		return true;\
	}
VTABLE_READ_ADDR_FUNC (vtable_read_addr_le8, r_read_le8, 1)
VTABLE_READ_ADDR_FUNC (vtable_read_addr_le16, r_read_le16, 2)
VTABLE_READ_ADDR_FUNC (vtable_read_addr_le32, r_read_le32, 4)
VTABLE_READ_ADDR_FUNC (vtable_read_addr_le64, r_read_le64, 8)
VTABLE_READ_ADDR_FUNC (vtable_read_addr_be8, r_read_be8, 1)
VTABLE_READ_ADDR_FUNC (vtable_read_addr_be16, r_read_be16, 2)
VTABLE_READ_ADDR_FUNC (vtable_read_addr_be32, r_read_be32, 4)
VTABLE_READ_ADDR_FUNC (vtable_read_addr_be64, r_read_be64, 8)

Backtrace

#0  0x00007ffff08ff800 in ?? ()
#1  0x00007ffff461e745 in vtable_is_value_in_text_section (context=context@entry=0x7fffffffd500,
    curAddress=curAddress@entry=1616928864, value=value@entry=0x0) at vtable.c:76
#2  0x00007ffff461e934 in vtable_is_addr_vtable_start_msvc (context=context@entry=0x7fffffffd500,
    curAddress=curAddress@entry=1616928864) at vtable.c:141
#3  0x00007ffff462008c in vtable_is_addr_vtable_start (section=<optimized out>, curAddress=1616928864, context=0x7fffffffd500)
    at vtable.c:175
#4  r_anal_vtable_search (context=context@entry=0x7fffffffd500) at vtable.c:263
#5  0x00007ffff4621cc0 in r_anal_rtti_recover_all (anal=<optimized out>) at rtti.c:89
#6  0x00007ffff5829bee in cmd_anal_rtti (input=<optimized out>, core=0x7ffff119d800) at cmd_anal.c:11602
#7  cmd_anal_virtual_functions (input=<optimized out>, core=0x7ffff119d800) at cmd_anal.c:11660
#8  cmd_anal (data=0x7ffff119d800, input=<optimized out>) at cmd_anal.c:12422
#9  0x00007ffff5950bca in r_cmd_call (cmd=0x620000000080, input=input@entry=0x602000742b70 "avrr") at cmd_api.c:549
#10 0x00007ffff5771229 in r_core_cmd_subst_i (tmpseek=<optimized out>, colon=<optimized out>, cmd=<optimized out>,
    core=<optimized out>) at cmd.c:4528
#11 r_core_cmd_subst (core=core@entry=0x7ffff119d800, cmd=<optimized out>, cmd@entry=0x621000006500 "avrr") at cmd.c:3401
#12 0x00007ffff577781f in run_cmd_depth (cmd=<optimized out>, core=0x7ffff119d800) at cmd.c:5430
#13 r_core_cmd (core=core@entry=0x7ffff119d800, cstr=<optimized out>, cstr@entry=0x7ffff5a89e5a "avrr", log=log@entry=false)
    at cmd.c:5513
#14 0x00007ffff5791087 in r_core_cmd0 (core=core@entry=0x7ffff119d800, cmd=cmd@entry=0x7ffff5a89e5a "avrr") at cmd.c:5670
#15 0x00007ffff57df095 in cmd_anal_all (core=core@entry=0x7ffff119d800, input=<optimized out>, input@entry=0x6020003663f2 "aa")
    at cmd_anal.c:11302
#16 0x00007ffff5828df8 in cmd_anal (data=0x7ffff119d800, input=0x6020003663f1 "aaa") at cmd_anal.c:12435
#17 0x00007ffff5950bca in r_cmd_call (cmd=0x620000000080, input=input@entry=0x6020003663f0 "aaaa") at cmd_api.c:549
#18 0x00007ffff5771229 in r_core_cmd_subst_i (tmpseek=<optimized out>, colon=<optimized out>, cmd=<optimized out>,
    core=<optimized out>) at cmd.c:4528
#19 r_core_cmd_subst (core=core@entry=0x7ffff119d800, cmd=<optimized out>, cmd@entry=0x6210000c6d00 "aaaa") at cmd.c:3401
#20 0x00007ffff577781f in run_cmd_depth (cmd=<optimized out>, core=0x7ffff119d800) at cmd.c:5430
#21 r_core_cmd (core=core@entry=0x7ffff119d800, cstr=<optimized out>, cstr@entry=0x7ffff3ac5aa9 "aaaa", log=log@entry=false)
    at cmd.c:5513
#22 0x00007ffff5791087 in r_core_cmd0 (core=core@entry=0x7ffff119d800, cmd=cmd@entry=0x7ffff3ac5aa9 "aaaa") at cmd.c:5670
#23 0x00007ffff3ab1ef4 in r_main_radare2 (argc=<optimized out>, argv=<optimized out>) at radare2.c:1471
#24 0x00007ffff38cf09b in __libc_start_main (main=0x5555555562d0 <main>, argc=4, argv=0x7fffffffded8, init=<optimized out>,
    fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdec8) at ../csu/libc-start.c:308
#25 0x0000555555556afa in _start ()

ASAN

AddressSanitizer:DEADLYSIGNAL
=================================================================
==100644==ERROR: AddressSanitizer: SEGV on unknown address 0x7f4f322ff800 (pc 0x7f4f322ff800 bp 0x7ffca2f5f440 sp 0x7ffca2f5f118 T0)
==100644==The signal is caused by a READ memory access.
==100644==Hint: PC is at a non-executable region. Maybe a wild jump?
    #0 0x7f4f322ff7ff  (<unknown module>)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (<unknown module>) 
==100644==ABORTING

Valgrind

==58932== Conditional jump or move depends on uninitialised value(s)
==58932==    at 0x716ECB9: r_anal_get_reg_profile (anal.c:250)
==58932==    by 0x716EE8F: r_anal_set_reg_profile (anal.c:262)
==58932==    by 0x716F2FC: r_anal_set_bits (anal.c:325)
==58932==    by 0x5FC31AA: r_core_init (core.c:3057)
==58932==    by 0x5FC3EB6: r_core_new (core.c:919)
==58932==    by 0x7FBF79A: r_main_radare2 (radare2.c:489)
==58932==    by 0x800509A: (below main) (libc-start.c:308)
==58932==
==58932== Conditional jump or move depends on uninitialised value(s)
==58932==    at 0x716EEDE: r_anal_set_reg_profile (anal.c:258)
==58932==    by 0x716F2FC: r_anal_set_bits (anal.c:325)
==58932==    by 0x5FC31AA: r_core_init (core.c:3057)
==58932==    by 0x5FC3EB6: r_core_new (core.c:919)
==58932==    by 0x7FBF79A: r_main_radare2 (radare2.c:489)
==58932==    by 0x800509A: (below main) (libc-start.c:308)
==58932==
==58932== Conditional jump or move depends on uninitialised value(s)
==58932==    at 0x716F2A9: r_anal_set_bits (anal.c:324)
==58932==    by 0x5FC31AA: r_core_init (core.c:3057)
==58932==    by 0x5FC3EB6: r_core_new (core.c:919)
==58932==    by 0x7FBF79A: r_main_radare2 (radare2.c:489)
==58932==    by 0x800509A: (below main) (libc-start.c:308)
==58932==
==58932==
==58932== More than 1000 different errors detected.  I'm not reporting any more.
==58932== Final error counts will be inaccurate.  Go fix your program!
==58932== Rerun with --error-limit=no to disable this cutoff.  Note
==58932== that errors may occur in your program without prior warning from
==58932== Valgrind, because errors are no longer being displayed.

Proof of Concept

radare2 -AA -q minified_crash

https://github.com/GreaterGoodest/pocs/blob/master/minified_crash

EPSS

0.001

Percentile

31.9%

Related for 0730A95E-C485-4FF2-9A5D-BB3ABFDA0B17