0×01: 简介

JapsPer项目是一个开源项目,它提供了一种基于jpeg-2000部分标准。这个项目最初是由Image Power和英属哥伦比亚大学合作完成的。目前,正在进行的JapsPer软件的维护和开发的主要作者Michael Adams进行协调,他是维多利亚大学电子和计算机工程部门的数字信号处理组(DSPG)的成员。影响的版本是2.0.12.

0×02: 分析

触发异常信息:

JapsPer指针未定义漏洞分析-RadeBit瑞安全

初步分析是由于函数jpc_dec.c函数中jpc_dequantize造成的core dumped

main() 到出错之间的调用关系1:

JapsPer指针未定义漏洞分析-RadeBit瑞安全

寄存器的信息1:

JapsPer指针未定义漏洞分析-RadeBit瑞安全

main() 到出错之间的调用关系2:

JapsPer指针未定义漏洞分析-RadeBit瑞安全

寄存器的信息2:

JapsPer指针未定义漏洞分析-RadeBit瑞安全

寄存器的信息3:

JapsPer指针未定义漏洞分析-RadeBit瑞安全

crash:

JapsPer指针未定义漏洞分析-RadeBit瑞安全
JapsPer指针未定义漏洞分析-RadeBit瑞安全

jp2_boxinfo_t *jp2_boxinfolookup(int type)遍历格式:格式

jasper的输入Jasper ./crash_in2/id_000062,sig_11,src_000901,op_ext_AO,pos_66-t jp2

其中红色的是产生crash的文件,-T代表转换成的图像格式jpg

0×01: jasper.c

jasper.c函数241行

if (!(image = jas_image_decode(in, cmdopts->infmt,cmdopts->inopts)))

infmt是固定值4(而4 代表了jp2格式);

而inopts来自怎么得到这个函数的来自参数解析函数,其值为0

in代表输入文件,它是由函数jas_stream_fopen()得来的;

jas_image.c 424 lines jas_image_decode(输入文件,fmt格式,参数选项)

jas_image_lookupfmtbyid(fmt),看fmt是否存在通过查看他的id。

对输入文件in进行解码 (*fmtinfo->ops.decode)(in,optstr)这个函数在哪定义的 ?

指针函数指向了jp2_dec.c 的97 lines,

dec = jp2_dec_create()

jp2_box_get(in)在jp2_cod.c 243 lines

box结构,将输入文件转换为box结构

box->ops 内容赋值为0, box->ops = &jp2_boxinfo_unk.ops;

typedef struct {
	structjp2_boxops_s *ops;
	structjp2_boxinfo_s *info;
	uint_fast32_ttype;
	/* Thelength of the box including the (variable-length) header. */
	uint_fast32_tlen;
	/* Thelength of the box data. */
	uint_fast32_tdatalen;
	union {
		jp2_jp_t jp;
		jp2_ftyp_tftyp;
		jp2_ihdr_t ihdr;
		jp2_bpcc_tbpcc;
		jp2_colr_tcolr;
		jp2_pclr_tpclr;
		jp2_cdef_tcdef;
		jp2_cmap_tcmap;
	}
	data;
}
jp2_box_t
error:
if (box) {
	jp2_box_destroy(box);
	调用次函数出错
}
if (dec) {
	jp2_dec_destroy(dec);
}
return 0;
}
void jp2_box_destroy(jp2_box_t *box) //jp2_cod.c 209lines {
if(box->ops->destroy) {
	(*box->ops->destroy)(box);
	调用指针函数出错 调用jp2_cdef_destroy
}
jas_free(box);
}
static void jp2_cdef_destroy(jp2_box_t *box) {
jp2_cdef_t*cdef = &box->data.cdef;
if(cdef->ents) {
	jas_free(cdef->ents);
	cdef->ents= 0;
}
}

解析jp2格式出错,定义box的结构一共21 ,其中两个决定了jp2格式的签名和类型,因此通过循环19次得到剩余19 个 box的数据,再获取JP2_BOX_CDEF这个box 的时候出错, jp2_dec.c 这个函数是获得输入文件,而jp2_cod.c这个函数是对每个box 进行创建和销毁。函数在调用 jas_free(cdef->ents) 的时候出错,而cdef->ents是在函数 *jp2_box_get(jas_stream_t*in) 调用

(*box->ops->getdata)(box, tmpstream)即调用jp2_cdef_getdata(jp2_box_t*box, jas_stream_t *in)函数的时候进行分配:

static int jp2_cdef_getdata(jp2_box_t *box,jas_stream_t *in) {
	jp2_cdef_t*cdef = &box->data.cdef;
	jp2_cdefchan_t*chan;
	unsignedint channo;
	if (jp2_getuint16(in, &cdef->numchans)) {
		printf("numchansn");
		return-1;
	}
	if(!(cdef->ents = jas_alloc2(cdef->numchans, sizeof(jp2_cdefchan_t)))) {
		printf("jas_alloc2mem n");
		return-1;
	}
	printf("memhas n");
	for (channo = 0; channo < cdef->numchans; ++channo) {
		chan= &cdef->ents[channo];
		printf("channovalue %dn", channo);
		if(jp2_getuint16(in, &chan->channo) || jp2_getuint16(in,&chan->type) ||
		jp2_getuint16(in, &chan->assoc)) {
			return-1;
		}
	}
	return 0;
}

调用上述代码红色部分,而此函数内容:

static int jp2_getuint16(jas_stream_t *in,uint_fast16_t *val) {
	uint_fast16_tv;
	int c;
	if ((c = jas_stream_getc(in)) == EOF) {
		printf("jp2_getuint16c1 value:%ldn", c);
		return-1;
	}
	v = c;
	if ((c = jas_stream_getc(in)) == EOF) {
		printf("jp2_getuint16c2 value:%dn", c);
		此时 c的值为 -1
		return-1;
	}
	v = (v<< 8) | c;
	if (val) {
		printf("vvalue:%ldn", v);
		*val= v;
	}
	return 0;
}

而函数jas_stream_getc(in)在stream.h中用宏定义的,而具体的宏内容是

#define jas_stream_getc(stream)jas_stream_getc_macro(stream)使用后者替换函数,而函数jas_stream_getc_macro(stream)也是一个宏定义,其内容如下:

#define jas_stream_getc_macro(stream)
((!((stream)->flags_& (JAS_STREAM_ERR | JAS_STREAM_EOF |
JAS_STREAM_RWLIMIT))) ?
(((stream)->rwlimit_ >= 0 && (stream)->rwcnt_ >=(stream)->rwlimit_) ?
(stream->flags_ |= JAS_STREAM_RWLIMIT, EOF) :
jas_stream_getc2(stream)): EOF)

flags_:0;执行黄色部分,而rwlimit_ : -1,rwcnt_:1;由于 1>-1 执行黄色中的红色部分,执行完成或后赋值,然后flags_的值为0×0004,然后继续执行函数: jp2_getuint16(jas_stream_t*in, uint_fast16_t *val) 中的绿色语句,此时flags_的值为0×0004 ,在函数中直接执行?表达式的最后一个选项即 EOF ,然后返回。

destroy在getdata指针函数中是怎么赋值到一个数的?

datalen == 1字节

jp2_boxinfolookup()轮询box->type

copy函数是怎么工作?

jas_stream_copy()函数:

有三个参数指针out,指针in类型都是jas_stream_t , 整型n

int all 值取决于n 此处all=0;