zoukankan      html  css  js  c++  java
  • 试写foxit reader的ConvertToPDF功能的wrapper

      相比于直接fuzzing大型程序本身,针对程序的某一特定功能写wrapper后再fuzzing则要高效的多。网上搜了下,仅有两篇关于foxit reader的wrapper文章,一个用python,另外一个用C++,而且针对的foxit reader版本也比较旧。本篇的目的通过分析C++的wrapper原理,来写出最新版foxit reader(Version:  9.1.0.5096)的ConvertToPDF功能的wrapper。

      首先看下ConvertToPDF_x86.dll插件的反汇编部分

      

      刚开始分配0x2760h大小的内存,然后可以看到

      .text:10015BC7                 mov     ecx, eax
      .text:10015BC9                 call    sub_100150C0

       从这两句可以猜测ConvertToPDF_x86.dll插件中存在虚函数,因为ecx中存储有类实例的this指针,它作为隐藏的第一个参数传递给sub_100150C0。具体原理可参考http://www.openrce.org/articles/full_view/23。然后继续跟进sub_100150C0函数,如下

      

      根据这段代码可以确定esi中存储有虚函数表的首地址,虚函数表的具体函数如下:

      

      ConvertToPDF_x86.dll插件的主要构成函数如上图,我们只需函数之间的确定执行流程、每个函数的主要参数内容及个数即可完成wrapper。

      主要的函数流程依次为

      ConvertToPDF_x86!CreateFXURLToHtml+0x450

      ConvertToPDF_x86!CreateFXURLToHtml+0xc90

      ConvertToPDF_x86!CreateFXPDFConvertor+0x90

      参数个数的确定,因为函数的调用约定遵循thiscall,所以每次调用完函数后,由被调用函数自动清除函数参数,具体代码为ret xx

      

    64dd020c  0000000a
    0:000:x86> bp ConvertToPDF_x86!CreateFXURLToHtml+0x450
    0:000:x86> g
    Breakpoint 1 hit
    ConvertToPDF_x86!CreateFXURLToHtml+0x450:
    64a73f10 55              push    ebp
    0:000:x86> uf ConvertToPDF_x86!CreateFXURLToHtml+0x450
    ConvertToPDF_x86!CreateFXURLToHtml+0x450:
    64a73f10 55              push    ebp
    64a73f11 8bec            mov     ebp,esp
    64a73f13 6aff            push    0FFFFFFFFh
    64a73f15 68a804dc64      push    offset ConvertToPDF_x86!ConnectedPDF::ConnectedPDFSDK::FCP_SendEmailNotification+0x2cc28 (64dc04a8)
    64a73f1a 64a100000000    mov     eax,dword ptr fs:[00000000h]
    64a73f20 50              push    eax
    64a73f21 83ec14          sub     esp,14h
    64a73f24 53              push    ebx

    。。。。。。。。。。。。。。。。。。 

    ConvertToPDF_x86!CreateFXURLToHtml+0xb70:
    64a74630 33c0            xor     eax,eax
    64a74632 8b4df4          mov     ecx,dword ptr [ebp-0Ch]
    64a74635 64890d00000000  mov     dword ptr fs:[0],ecx
    64a7463c 59              pop     ecx
    64a7463d 5f              pop     edi
    64a7463e 5e              pop     esi
    64a7463f 5b              pop     ebx
    64a74640 8be5            mov     esp,ebp
    64a74642 5d              pop     ebp
    64a74643 c20400          ret     4          //参数个数为1

      参数内容为0x2

    据此可以确定另外两个函数的参数个数和内容。

    网上参考的的wrapper的具体代码内容如下

    /*
    foxit-fuzz.cpp - simple console wrapper for ConvertToPDF_x86.dll
    @richinseattle / rjohnson@moflow.org
    
    NOTES:
    
    Must install the foxit pdf printer globally
    Harness targets foxit 9.0 API by default
    Can target 7.3.4 if FOXIT_734 is defined and ConvertToPDF_x86.734.dll is in path
    
    afl-fuzz.exe -i %INPUT_DIR% -o foxit_out -D %DynamoRIO_ROOT%in32 -t 20000 -- -coverage_module ConvertToPDF.dll -target_module foxit-fuzz.exe -target_method convert_to_pdf -nargs 2 -fuzz_iterations 5000  -- %CD%foxit-fuzz.exe @@ NUL
    */
    
    #include <Windows.h>
    #include <String.h>
    #include <iostream>
    using namespace std;
    
    typedef void * (__stdcall *CreateFXPDFConvertor_t)();
    typedef int(__thiscall *InitLocale_t)(void *_this, int, wchar_t * lc_str);
    typedef int(__thiscall *InitPrinter_t)(void* _this, wchar_t *printer_name);
    typedef int(__thiscall *InitPdfConverter_t)(void* _this, int mode);
    #ifdef FOXIT_734
    typedef int(__thiscall *ConvertToPdf_t)(void* _this, wchar_t *convert_buf, int p2, int p3);
    #else
    typedef int(__thiscall *ConvertToPdf_t)(void* _this, wchar_t *convert_buf, int p2, int p3, int p4, int p5, int p6, int p7, int p8);
    #endif
    
    typedef struct ConverterFuncTable_t
    {
        ConvertToPdf_t     ConvertToPdf;
        InitPdfConverter_t InitPdfConverter;
        InitPrinter_t      InitPrinter;
        //InitLocale_t       InitLocale;
    
    } ConverterFuncTable;
    
    typedef struct ConverterClass_t
    {
        ConverterFuncTable_t *vfp_table;
    } ConverterClass;
    
    #ifdef FOXIT_734
    char *target_library = "ConvertToPDF_x86.734.dll";
    #else
    char *target_library = "ConvertToPDF_x86.dll";
    #endif
    char *target_function = "CreateFXPDFConvertor";
    
    wchar_t * printer_name = L"Foxit Reader PDF Printer";
    
    ConverterClass *pdfconverter = NULL;
    
    
    int init_target_library()
    {
        int retVal = 0;
    
        CreateFXPDFConvertor_t CreateFXPDFConvertor = (CreateFXPDFConvertor_t)GetProcAddress(LoadLibraryA(target_library), target_function);
    
        // create an instance of CreateFXPDFConvertor
        pdfconverter = (ConverterClass *)CreateFXPDFConvertor();
        ConverterFuncTable *vfp_table = pdfconverter->vfp_table;
    
        cout << "Function table:   " << endl;
        cout << "CreateFXPDFConvertor: " << hex << CreateFXPDFConvertor << endl;
        cout << "InitPdfConverter:     " << hex << vfp_table->InitPdfConverter << "  CreateFXPDFConvertor+0x" << hex << (unsigned long)vfp_table->InitPdfConverter - (unsigned long)CreateFXPDFConvertor << endl;
        cout << "InitPrinter:          " << hex << vfp_table->InitPrinter << "  CreateFXPDFConvertor+0x" << hex << (unsigned long)vfp_table->InitPrinter - (unsigned long)CreateFXPDFConvertor << endl;
        cout << "ConvertToPdf:         " << hex << vfp_table->ConvertToPdf << "  CreateFXPDFConvertor+0x" << hex << (unsigned long)vfp_table->ConvertToPdf - (unsigned long)CreateFXPDFConvertor << endl << endl;
    
        // init converter 
        retVal = vfp_table->InitPdfConverter(pdfconverter, 2);
        if (retVal)
            cout << "Error: InitPdfConverter(): " << retVal << endl;
    
        // init printer device  
        retVal = vfp_table->InitPrinter(pdfconverter, printer_name);
        if (retVal)
            cout << "Error: InitPrinter(): " << retVal << endl;
    
        return retVal;
    }
    
    extern "C" __declspec(dllexport) int wmain(int argc, wchar_t *argv[]);
    extern "C" __declspec(dllexport) int convert_to_pdf(ConvertToPdf_t convert, wchar_t * converter_buf);
    
    int convert_to_pdf(ConvertToPdf_t convert, wchar_t * converter_buf)
    {
    #ifdef FOXIT_734
        return convert(pdfconverter, converter_buf, 0, 0);
    #else    
        return convert(pdfconverter, converter_buf, 0, 0, 0, 0, 0, 0, 0);
    #endif
    }
    
    
    int wmain(int argc, wchar_t *argv[])
    {
        int retVal = 0;
    
        int converter_buf_count = 0;
        int converter_buf_size = 0;
        wchar_t *converter_buf = NULL;
    
        wchar_t *input_path = NULL;
        wchar_t *output_path = L"nul";
    
    #ifdef FOXIT_734
        cout << "foxit-fuzz (target v7.3.4) - rjohnson@moflow.org" << endl << endl;
    #else    
        cout << "foxit-fuzz (target v9.0) - rjohnson@moflow.org" << endl << endl;
    #endif
    
        if (argc < 2)
        {
            wcout << "usage: " << argv[0] << " <input> [output]" << endl;
            return -1;
        }
    
        if (GetFileAttributesW(argv[1]) == -1)
        {
            cout << "error: input file path" << endl;
            return -1;
        }
        input_path = argv[1];
    
        if (argc == 3)
            output_path = argv[2];
    
        // setup buffer for converting PDF
        converter_buf_count = 0x1000;
        converter_buf_size = converter_buf_count * sizeof(wchar_t);
        converter_buf = (wchar_t *)calloc(converter_buf_count, sizeof(wchar_t));
    
        wcsncpy_s(converter_buf, converter_buf_count, input_path, wcslen(input_path));
        wcsncpy_s(converter_buf + (0x208 / sizeof(wchar_t)), converter_buf_count - (0x208 / sizeof(wchar_t)), output_path, wcslen(output_path));
    
        // create pdfconverter class and initialize library 
        if (init_target_library())
        {
            cout << "Error intializing target library" << endl;
            return -1;
        }
    
        // execute wrapper for fuzzing
        retVal = convert_to_pdf(pdfconverter->vfp_table->ConvertToPdf, converter_buf);
        free(converter_buf);
    
        if (retVal)
        {
            cout << "Error: ConvertToPdf(): " << retVal << endl;
            return -1;
        }
    
        return 0;
    }

      重点说明的代码为

      wcsncpy_s(converter_buf + (0x208 / sizeof(wchar_t)), converter_buf_count - (0x208 / sizeof(wchar_t)), output_path, wcslen(output_path));

      其中0x208表示input_path与output_path的间隔距离。

      其实不用更改上述的任何代码,直接编译即可使用

      用winafl时注意命令行要改为

      afl-fuzz.exe -i %INPUT_DIR% -o foxit_out -D %DynamoRIO_ROOT%in32 -t 20000 -- -coverage_module ConvertToPDF.dll -coverage_module foxit-fuzz.exe -target_module foxit-fuzz.exe -target_method convert_to_pdf -nargs 2 -fuzz_iterations 5000 -- %CD%foxit-fuzz.exe @@ NUL

      否则报错,运行结果如下图所示:

      跑了三天,一个crash都没有,,,,,,,估计已经被很多人跑了,fuzz好难

  • 相关阅读:
    Flume案例:目录文件到HDFS
    Flume案例:本地文件到HDFS
    12c多租户架构下部署GoldenGate12c
    ogg_sqlserver_oracle_winerver2008
    ogg异构oracle-mysql
    搜索引擎 反向索引,为什么称之为反向索引?
    ORACLE 11G 之DATAGUARD搭建逻辑standby
    Java并发锁控制API详解
    Java中的锁分类与使用
    Spring Cloud入门(含案例介绍及源码)
  • 原文地址:https://www.cnblogs.com/st404/p/9384704.html
Copyright © 2011-2022 走看看