正文
003beed0 013aefa8 FoxitReader_Lib_Full+0x18691c
通过检查栈上的参数,我们可以看出第一个是图片文件的路径,第二个是要写入的临时 PDF 文件。注意由于 ASLR,下面显示的地址可以与上面列出的模块不同。
0032e6f0 6a01 push 1
0032e6f2 6a00 push 0
0032e6f4 51 push ecx ; path to temp PDF file
0032e6f5 8bc8 mov ecx,eax
0032e6f7 8b4604 mov eax,dword ptr [esi+4]
0032e6fa 52 push edx ; path to JPEG image
0032e6fb ffd0 call eax
当 Foxit 调用该方法时通过动态地修改参数,我们可以打开其他任意地图片。因此在调用期间通过恢复上下文(尤其是x86寄存器),快速重复地调用该转换函数也就成为可能。幸运地是,每次调用不需要恢复堆。
该方法有几种实现自动化的方式。我们可以使用 Pintool,但是为了优化我决定写一个特定的工具。
最后,我写了一个小调试器,可以通过传一个图片参数来启动 Foxit Reader,并且断点在 ConvertToPDF_x86.dll 的图片转换函数的对应调用处,可以获取下一步进行回放的上下文。
CONTEXT ctx;
...
case EXCEPTION_DEBUG_EVENT:
{
EXCEPTION_DEBUG_INFO& exception = debug_event.u.Exception;
switch (exception.ExceptionRecord.ExceptionCode)
{
case STATUS_BREAKPOINT:
...
if (IsMyBp())
{
SaveContext(&ctx);
...
RunFuzzing(&ctx);
...
}
}
}
然后调试器注入一 DLL 到 Foxit 内存中(通过 RunFuzzing() 实现),并设置好要传给被调用函数的参数。
while(TRUE)
{
corrupt(image);
// call the fonction
_asm
{
push 1
push 0
lea edi, pdf_path