X浪在处理本地图片时存在缓冲区溢出的漏洞,问题出现在Java_com_sina_filter_JpegExifExtractor_nativeExifExtrator函数,具体功能是解析JPEG格式的EXIF的信息。
vsprintf 未做任何的过滤和校验,直接处理了传来的三个参数。
printf_的调用方式
s的大小为固定的65536,v5为图片的路径。
这个漏洞似乎很好利用,直接设置超过65536大小的路径信息就可以了,但是设置路径时出现了问题,Linux查看文件名的默认的最大长度是255,路径的默认的最大长度是4096,远远没有达到我们需要的65536的长度。
EXIF格式解析的地方,也大量调用了printf_函数。
调用printf_的地方非常的多,随便找一个字段的值,将其设置为超过65536的长度就可以了。以Description的字段信息为例,使用Python生成包含EXIF信息的图片,发现EXIF头的最大大小是0xFFFF,正好位于s字段的最大长度限制内。

因为szSection只占2个字节,所以最大长度是0xFFFF,ImageDescription的长度可以设置为64993,但是仍然小于s[65536]的长度。
这里也解释了为什么要设置s的最大长度为65536,这个正是EXIF信息的最大长度。
继续分析发现了真正出现漏洞的地方是如下的代码:
将Make (271) 和 Model (272) 的字段值进行了合并,正常的逻辑是EXIF内容的所有值加起来的最大长度是0xFFFF,似乎make加model的最大长度也不会超过0xFFFF。

Make的值可以设置为64995(0xFDE3),这时Model值的正常长度是13(0xD),合并后的长度是65008(0xFDF0),显然是在0xFFFF的长度范围内。
如果将Model的偏移地址和长度设置为与Make的偏移地址和长度一致,就可以突破0xFFFF的限制,长度可达129990(0x1FBC6),同时可以控制Model的长度,来设置溢出的范围。
同时s的地址是0x0005C05C,程序的最大地址是0x00072268,差值是0x1620C,可以向程序外溢出0x99BA。
查看程序的segment表,可以向下溢出到bss段。

查看程序的防护,防护全开。
首先覆盖的是位于其下方的DATA段的导出函数:EXPORT _ZN10__cxxabiv119__terminate_handlerE

与s值的结束地址相差0x8D,对内存破坏的影响最小,但是这是一个被动调用的函数,只有程序出现异常才有可能触发,另外即使触发也需要处理传递参数的问题。
继续向下溢出到bss段,JNI调用出现了异常。
出现异常的是以下的代码:
dword_6C184和dword_6C188对应的参数是jclass和jmethodID:
调用代码是:
原始的逻辑是调用ExifInfo的构造函数创建Object对象,理论上可以替换jclass和jmethodID来构造指定的对象。
然后是三个CallVoidMethod进行了对象函数的调用:
CallVoidMethod函数的原始类型是:
dword_6C18C dword_6C190 dword_6C194 对应的参数是jmethodID。
对应的函数逻辑是:
对应的JAVA代码是:
至此,已经可以控制的参数是dword_6C184 dword_6C188,对应的是NewObject的jclass和jmethodID参数;
dword_6C18C dword_6C190 dword_6C194 对应的是三个CallVoidMethod的jmethodID参数。
可以支持调用函数的参数类型为:
仅在Unidbg的调试环境测试,与真机和系统版本有差异。
int printf_(char *s, const char *format, ...)
{
int v4; // [sp+4h] [bp-Ch]
va_list va; // [sp+18h] [bp+8h] BYREF
va_start(va, format);
vsprintf(s, format, va);
if ( s[0x10000] )
_android_log_write(4, "native-log", s);
return _stack_chk_guard - v4;
}
int printf_(char *s, const char *format, ...)
{
int v4; // [sp+4h] [bp-Ch]
va_list va; // [sp+18h] [bp+8h] BYREF
va_start(va, format);
vsprintf(s, format, va);
if ( s[0x10000] )
_android_log_write(4, "native-log", s);
return _stack_chk_guard - v4;
}
{
ReleaseStringUTFChars(jnienv, a3, v5);
printf_(s, "error: can not open ' %s ' ", v5);
v14 = 0;
}
{
ReleaseStringUTFChars(jnienv, a3, v5);
printf_(s, "error: can not open ' %s ' ", v5);
v14 = 0;
}
.data:0005C05C ; char s[65536]
.data:0005C05C s DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C05C ; DATA XREF: sub_FDE4+4E↑o
.data:0005C05C ; sub_FDE4:loc_FEBA↑o ...
.data:0005C06D DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C07E DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C08F DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0A0 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0B1 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0C2 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0D3 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0E4 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0F5 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C106 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C117 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C128 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C139 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C14A DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C15B DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C05C ; char s[65536]
.data:0005C05C s DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C05C ; DATA XREF: sub_FDE4+4E↑o
.data:0005C05C ; sub_FDE4:loc_FEBA↑o ...
.data:0005C06D DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C07E DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C08F DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0A0 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0B1 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0C2 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0D3 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0E4 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C0F5 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C106 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C117 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C128 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C139 DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C14A DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.data:0005C15B DCB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
getconf NAME_MAX /
255
getconf PATH_MAX /
4096
getconf NAME_MAX /
255
getconf PATH_MAX /
4096
printf_(s, "Java_com_sina_filter_JpegExifExtractor_nativeExifExtrator: parse start");
v15 = TinyEXIF::EXIFInfo::parseFrom((TinyEXIF::EXIFInfo *)&v61, (const unsigned __int8 *)p, v115[0]);
if ( v15 )
{
printf_(s, "EXIF parse failed err code: %d", v15);
printf_(s, "ProjectionType %d", HIWORD(v87));
}
else
{
printf_(s, "EXIF parse success");
if ( v61 )
printf_(s, "ImageResolution %d x %d", (_DWORD)v61, HIDWORD(v61));
if ( v62 )
printf_(s, "RelatedImageResolution %d x %d ", (_DWORD)v62, HIDWORD(v62));
if ( *((_DWORD *)v63 - 3) )
printf_(s, "Description %s", v63);
if ( *((_DWORD *)v64 - 3) || *((_DWORD *)v65 - 3) )
printf_(s, "CameraModel make: %s, model: %s", v64, v65);
printf_(s, "Orientation %d", v66);
printf_(s, "Resolution %lf x %lf", v67, v68);
printf_(s, "ResolutionUnit %d", (unsigned __int16)v69);
printf_(s, "BitsPerSample %d", HIWORD(v69));
if ( *((_DWORD *)v70 - 3) )
printf_(s, "Software %s", v70);
if ( *((_DWORD *)v71 - 3) )
printf_(s, "DateTime %s", v71);
if ( *((_DWORD *)v72 - 3) )
printf_(s, "DateTimeOriginal %s", v72);
if ( *((_DWORD *)v73 - 3) )
printf_(s, "DateTimeDigitized %s", v73);
if ( *((_DWORD *)v74 - 3) )
printf_(s, "SubSecTimeOriginal %s", v74);
if ( *((_DWORD *)v75 - 3) )
printf_(s, "Copyright %s", v75);
printf_(s, "ExposureTime %0.10lf s", v76);
printf_(s, "FNumber %lf", v77);
printf_(s, "ExposureProgram %d", v78);
printf_(s, "ISOSpeed %d", v79);
printf_(s, "ShutterSpeedValue %0.10lf", v80);
printf_(s, "ApertureValue %0.10lf", v81);
printf_(s, "BrightnessValue %0.10lf", v82);
printf_(s, "ExposureBiasValue %lf", v83);
printf_(s, "SubjectDistance %lf", v84);
printf_(s, "FocalLength %lf mm", v85);
printf_(s, "Flash %d", (unsigned __int16)v86);
if ( i_3 != i_1 )
{
printf_(s, "SubjectArea: ");
i_2 = i_3;
for ( i = i_1; i != i_2; ++i_2 )
printf_(s, "%d", *i_2);
}
printf_(s, "MeteringMode %d", HIWORD(v86));
printf_(s, "LightSource %d", (unsigned __int16)v87);
printf_(s, "ProjectionType %d", HIWORD(v87));
printf_(s, "LensInfo.FStopMin %lf", v91);
printf_(s, "LensInfo.FStopMax %lf", v92);
printf_(s, "LensInfo.FocalLengthMin %lf mm", v93);
printf_(s, "LensInfo.FocalLengthMax %lf mm", v94);
printf_(s, "LensInfo.DigitalZoomRatio %lf ", v95);
printf_(s, "LensInfo.FocalLengthIn35mm %lf ", v96);
printf_(s, "LensInfo.FocalPlaneXResolution %0.10lf", v97);
printf_(s, "LensInfo.FocalPlaneYResolution %0.10lf ", v98);
printf_(s, "LensInfo.FocalPlaneResolutionUnit %d", v99);
if ( *((_DWORD *)v100 - 3) || *((_DWORD *)v101 - 3) )
printf_(s, "LensInfo.Model %s - %s", v100, v101);
if ( TinyEXIF::EXIFInfo::Geolocation_t::hasLatLon((TinyEXIF::EXIFInfo::Geolocation_t *)&v102) == 1 )
{
printf_(s, "GeoLocation.Latitude %0.10lf", v102);
printf_(s, "GeoLocation.Longitude %0.10lf", v103);
}
if ( TinyEXIF::EXIFInfo::Geolocation_t::hasAltitude((TinyEXIF::EXIFInfo::Geolocation_t *)&v102) == 1 )
{
printf_(s, "GeoLocation.Altitude %lf m", v104);
printf_(s, "GeoLocation.AltitudeRef %d", v105);
}
if ( TinyEXIF::EXIFInfo::Geolocation_t::hasRelativeAltitude((TinyEXIF::EXIFInfo::Geolocation_t *)&v102) == 1 )
printf_(s, "GeoLocation.RelativeAltitude %lf", v106);
if ( TinyEXIF::EXIFInfo::Geolocation_t::hasOrientation((TinyEXIF::EXIFInfo::Geolocation_t *)&v102) == 1 )
{
printf_(s, "GeoLocation.RollDegree %lf", v107);
printf_(s, "GeoLocation.PitchDegree %lf", v108);
printf_(s, "GeoLocation.YawDegree %lf", v109);
}
printf_(s, "GeoLocation.GPSDOP %lf", v110);
printf_(s, "GeoLocation.GPSDifferential %d", v111);
if ( *((_DWORD *)v112 - 3) )
printf_(s, "GeoLocation.GPSMapDatum %s", v112);
if ( *((_DWORD *)v113 - 3) )
printf_(s, "GeoLocation.GPSTimeStamp %s", v113);
if ( *((_DWORD *)v114 - 3) )
printf_(s, "GeoLocation.GPSDateStamp %s", v114);
}
if ( p )
operator delete(p);
printf_(s, "Java_com_sina_filter_JpegExifExtractor_nativeExifExtrator exif obj setup start");
printf_(s, "Java_com_sina_filter_JpegExifExtractor_nativeExifExtrator: parse start");
v15 = TinyEXIF::EXIFInfo::parseFrom((TinyEXIF::EXIFInfo *)&v61, (const unsigned __int8 *)p, v115[0]);
if ( v15 )
{
printf_(s, "EXIF parse failed err code: %d", v15);
printf_(s, "ProjectionType %d", HIWORD(v87));
}
else
{
printf_(s, "EXIF parse success");
if ( v61 )
printf_(s, "ImageResolution %d x %d", (_DWORD)v61, HIDWORD(v61));
if ( v62 )
printf_(s, "RelatedImageResolution %d x %d ", (_DWORD)v62, HIDWORD(v62));
if ( *((_DWORD *)v63 - 3) )
printf_(s, "Description %s", v63);
if ( *((_DWORD *)v64 - 3) || *((_DWORD *)v65 - 3) )
printf_(s, "CameraModel make: %s, model: %s", v64, v65);
printf_(s, "Orientation %d", v66);
printf_(s, "Resolution %lf x %lf", v67, v68);
printf_(s, "ResolutionUnit %d", (unsigned __int16)v69);
printf_(s, "BitsPerSample %d", HIWORD(v69));
if ( *((_DWORD *)v70 - 3) )
printf_(s, "Software %s", v70);
if ( *((_DWORD *)v71 - 3) )
printf_(s, "DateTime %s", v71);
if ( *((_DWORD *)v72 - 3) )
printf_(s, "DateTimeOriginal %s", v72);
if ( *((_DWORD *)v73 - 3) )
printf_(s, "DateTimeDigitized %s", v73);
if ( *((_DWORD *)v74 - 3) )
printf_(s, "SubSecTimeOriginal %s", v74);
if ( *((_DWORD *)v75 - 3) )
printf_(s, "Copyright %s", v75);
printf_(s, "ExposureTime %0.10lf s", v76);
printf_(s, "FNumber %lf", v77);
printf_(s, "ExposureProgram %d", v78);
printf_(s, "ISOSpeed %d", v79);
printf_(s, "ShutterSpeedValue %0.10lf", v80);
printf_(s, "ApertureValue %0.10lf", v81);
printf_(s, "BrightnessValue %0.10lf", v82);
printf_(s, "ExposureBiasValue %lf", v83);
printf_(s, "SubjectDistance %lf", v84);
printf_(s, "FocalLength %lf mm", v85);
printf_(s, "Flash %d", (unsigned __int16)v86);
if ( i_3 != i_1 )
{
printf_(s, "SubjectArea: ");
i_2 = i_3;
for ( i = i_1; i != i_2; ++i_2 )
printf_(s, "%d", *i_2);
}
printf_(s, "MeteringMode %d", HIWORD(v86));
printf_(s, "LightSource %d", (unsigned __int16)v87);
printf_(s, "ProjectionType %d", HIWORD(v87));
printf_(s, "LensInfo.FStopMin %lf", v91);
printf_(s, "LensInfo.FStopMax %lf", v92);
printf_(s, "LensInfo.FocalLengthMin %lf mm", v93);
printf_(s, "LensInfo.FocalLengthMax %lf mm", v94);
printf_(s, "LensInfo.DigitalZoomRatio %lf ", v95);
printf_(s, "LensInfo.FocalLengthIn35mm %lf ", v96);
printf_(s, "LensInfo.FocalPlaneXResolution %0.10lf", v97);
printf_(s, "LensInfo.FocalPlaneYResolution %0.10lf ", v98);
printf_(s, "LensInfo.FocalPlaneResolutionUnit %d", v99);
if ( *((_DWORD *)v100 - 3) || *((_DWORD *)v101 - 3) )
printf_(s, "LensInfo.Model %s - %s", v100, v101);
if ( TinyEXIF::EXIFInfo::Geolocation_t::hasLatLon((TinyEXIF::EXIFInfo::Geolocation_t *)&v102) == 1 )
{
printf_(s, "GeoLocation.Latitude %0.10lf", v102);
printf_(s, "GeoLocation.Longitude %0.10lf", v103);
}
if ( TinyEXIF::EXIFInfo::Geolocation_t::hasAltitude((TinyEXIF::EXIFInfo::Geolocation_t *)&v102) == 1 )
{
printf_(s, "GeoLocation.Altitude %lf m", v104);
printf_(s, "GeoLocation.AltitudeRef %d", v105);
}
if ( TinyEXIF::EXIFInfo::Geolocation_t::hasRelativeAltitude((TinyEXIF::EXIFInfo::Geolocation_t *)&v102) == 1 )
printf_(s, "GeoLocation.RelativeAltitude %lf", v106);
if ( TinyEXIF::EXIFInfo::Geolocation_t::hasOrientation((TinyEXIF::EXIFInfo::Geolocation_t *)&v102) == 1 )
{
printf_(s, "GeoLocation.RollDegree %lf", v107);
printf_(s, "GeoLocation.PitchDegree %lf", v108);
printf_(s, "GeoLocation.YawDegree %lf", v109);
}
printf_(s, "GeoLocation.GPSDOP %lf", v110);
printf_(s, "GeoLocation.GPSDifferential %d", v111);
if ( *((_DWORD *)v112 - 3) )
printf_(s, "GeoLocation.GPSMapDatum %s", v112);
if ( *((_DWORD *)v113 - 3) )
printf_(s, "GeoLocation.GPSTimeStamp %s", v113);
if ( *((_DWORD *)v114 - 3) )
printf_(s, "GeoLocation.GPSDateStamp %s", v114);
}
if ( p )
operator delete(p);
printf_(s, "Java_com_sina_filter_JpegExifExtractor_nativeExifExtrator exif obj setup start");
printf_(s, "CameraModel make: %s, model: %s", v64, v65);
printf_(s, "CameraModel make: %s, model: %s", v64, v65);
Arch: arm-32-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
Arch: arm-32-little
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!
最后于 2025-10-11 16:11
被易之生生编辑
,原因: