7-Zip 16.03

2016-09-28
2016-10-01
1 2 > >> (Page 1 of 2)
  • Igor Pavlov

    Igor Pavlov - 2016-09-28

    7-Zip 16.03 was released.

    7-Zip for 32-bit Windows:

    http://7-zip.org/a/7z1603.exe
    or
    http://7-zip.org/a/7z1603.msi

    7-Zip for 64-bit Windows x64:

    http://7-zip.org/a/7z1603-x64.exe
    or
    http://7-zip.org/a/7z1603-x64.msi

    What's new after 7-Zip 16.02:

    • Installer and SFX modules now use some protection against DLL preloading attack.
    • Some bugs were fixed in 7z, NSIS, SquashFS and RAR5 code.
     
    • VictorVG

      VictorVG - 2016-09-28

      In to archive lzma1603.7z SFX module 7zS2.sfx have version 16.02. Do your needed update for this SFX?

       
      • VictorVG

        VictorVG - 2016-09-30

        Big thanks! I update my LAN installation.

         
    • Debkdarlin

      Debkdarlin - 2016-09-30

      Can we get around the problem by using the 32-bit version, or do we have to use the 64-bit?

       
  • Byron Taz

    Byron Taz - 2016-09-28

    Thankyou Igor for this update, I'm a big fan of 7-Zip.

     
  • 1400700226

    1400700226 - 2016-09-28

    Great, that's good for transmission.

     
  • Igor Pavlov

    Igor Pavlov - 2016-09-28

    The code that must protect against DLL preloading attack uses two things:

    SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32  | LOAD_LIBRARY_SEARCH_USER_DIRS)
    

    and if SetDefaultDllDirectories function is not supported, it loads some DLLs (like UXTHEME.dll) from system folder. I didn't test that code in many systems. So if you know how to improve that code, please notify me.

     
    • Shell

      Shell - 2016-09-29

      I think I know another way of increasing the DLL security: you can temporarily change the current directory to System32 before calling LoadLibrary(). This should work on any Windows version. However, if an attacker creates a .local file with SFX's name, the DLLs would be loaded from SFX directory anyway. (UPDATE: I didn't read MSDN carefully: .local files are ignored if a manifest is present.)

      I also suggest some changes to DllSecur.c:
      1) remove Windows version check (SetDefaultDllDirectories() could appear under older systems after some patch);
      2) declare buf[] dynamically, or at least replace 100 with something like sizeof(g_Dlls)+2;
      3) replace pos with len and eliminate the call to lstrlenW().

       
      Last edit: Shell 2016-09-29
      • Igor Pavlov

        Igor Pavlov - 2016-09-29

        1) It's from NSIS source code. They suppose that we can't use SetDefaultDllDirectories() function at Vista (it works incorrectly). I didn't test it. I have no Vista now.

        2) g_Dlls can be long list (for example, if we increase it to list of 100 dlls) . We don't need big buffer. And name of one DLL (it's standard DLL) can't be larger than 100 characters.

        The main question about that code:
        Do we need to load these special DLLs, if SetDefaultDllDirectories() works correctly?
        I suppose that we don't.
        But NSIS still loads DLLs.
        So what way is more correct?

         
        • Shell

          Shell - 2016-09-29

          I have XP (x86 and x64), Vista (x86) and Win7 (x64). If you provide something to test, I can check these OSes.

          I think that no extra action is needed if SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32) succeeds. On the other hand, this function need not to be called if all DLLs are loaded with LoadLibraryEx() with the LOAD_LIBRARY_SEARCH_SYSTEM32 flag set, unless you want to know whether that flag has any effect.

          Loading DLLs by the full path to System32 with the LOAD_WITH_ALTERED_SEARCH_PATH flag for is more universal since it works even on Win95. There is no need to load all the DLLs from one place; I think it is better to load all system DLLs with LoadLibraryEx() directly from where they are loaded now. If the DLL is absent from System32, LoadLibraryEx() will fail and we detect a damaged OS distribution. UPDATE: no, the search may continue in other directories unless disabled by SetDefaultDllDirectories().

          Now my suggestions are as follows:
          1) link the SFX statically only against known DLLs (such as KERNEL32);
          2) load other system DLLs with a code similar to the following:
          HANDLE LoadSystemLibraryW(WCHAR *path)
          {
          // append path to the full path to System32
          return LoadLibraryEx(buf,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
          }

           
          Last edit: Shell 2016-09-29
          • Igor Pavlov

            Igor Pavlov - 2016-09-29

            I used my test DLL:
            http://7-zip.org/a/dlltest.7z
            you need
            1) run DebugView from sysinternals.
            2) copy UXTHEME.dll from dlltest.7z to some folder with exe files
            3) you can copy UXTHEME.dll to another files with any other "bad" dll names.
            4) run exe file (for example, old exe installer 7z1602.exe and new 7z1603.exe)
            5) if system loads dll (like UXTHEME.dll) from current folder, then you will see a name of that dll in DebugView. It means that dll attack is possible.

             
            • Shell

              Shell - 2016-09-29

              Running tests on fully updated Windows Vista x86 SP2, elevated prompt.
              R:\TEMP>ntsd -g 7z1602.exe
              ModLoad: 00400000 0040e000 image00400000
              ModLoad: 76fa0000 770c9000 ntdll.dll
              ModLoad: 77120000 771fd000 C:\Windows\system32\kernel32.dll
              Also loaded from system32: ole32, msvcrt, GDI32, USER32, ADVAPI32, RPCRT4, SHELL32, SHLWAPI, ShimEng, apphelp, IMM32, MSCTF, LPK, USP10
              ModLoad: 74090000 7422e000 C:\Windows\WinSxS\x86_microsoft.windows.common-cont
              rols_6595b64144ccf1df_6.0.6002.19373_none_5cbe60a608848a19\comctl32.dll
              ModLoad: 10000000 10005000 R:\TEMP\UxTheme.dll
              R:\TEMP\UxTheme.dll1

              R:\TEMP>ntsd -g 7z1603.exe
              ModLoad: 00400000 0040e000 image00400000
              ModLoad: 76fa0000 770c9000 ntdll.dll
              ModLoad: 77120000 771fd000 C:\Windows\system32\kernel32.dll
              Also loaded from system32: ole32, msvcrt, GDI32, USER32, ADVAPI32, RPCRT4, SHELL32, SHLWAPI, ShimEng, apphelp, IMM32, MSCTF, LPK, USP10
              ModLoad: 74090000 7422e000 C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6002.19373_none_5cbe60a608848a19\comctl32.dll
              ModLoad: 73e60000 73e9f000 C:\Windows\system32\UxTheme.dll

              Now I disable SetDefaultDllDirectories():
              R:\TEMP>ntsd -g 7z1603.exe
              ModLoad: 00400000 0040e000 image00400000
              ModLoad: 76fa0000 770c9000 ntdll.dll
              ModLoad: 77120000 771fd000 C:\Windows\system32\kernel32.dll
              Also loaded from system32: ole32, msvcrt, GDI32, USER32, ADVAPI32, RPCRT4, SHELL32, SHLWAPI
              0:000> a 405965
              00405965 xor eax,eax // as if GetProcAddress() returned NULL
              00405967
              0:000> g
              Loaded from system32: ShimEng, apphelp, IMM32, MSCTF, LPK, USP10
              ModLoad: 74090000 7422e000 C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6002.19373_none_5cbe60a608848a19\comctl32.dll
              ModLoad: 73e60000 73e9f000 C:\Windows\system32\UxTheme.dll
              Also loaded from system32: USERENV, Secur32, SETUPAPI, OLEAUT32, APPHELP, PROPSYS, DWMAPI, OLEACC, CLBCATQ - i.e. whole g_Dlls[]

              So, LoadLibraryEx() with absolute paths is sufficient. LoadLibrary() will also do as long as the DLL is present in System32.

               
              • Igor Pavlov

                Igor Pavlov - 2016-09-30

                There is BUG in 16.03 in that code.
                Correct code for Vista check must be:

                    if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0)
                

                So 16.03 calls SetDefaultDllDirectories() at Vista too.
                But NSIS writes that CoCreateInstance(&CLSID_ShellLink doesn't work in that case.
                I use CoCreateInstance(&CLSID_ShellLink
                to create links for start menu folder:

                7-Zip File Manager.lnk
                7-Zip Help.lnk
                

                So can you check it again in Vista:
                1) uninstall 7-Zip 16.03
                2) check that there is no Start menu links.
                3) install 7-Zip 16.03
                4) check links in Start menu.

                 
                • Shell

                  Shell - 2016-09-30

                  No links. CoCreateInstance() is called 3 or 4 times and always returns E_INVALIDARG.

                  If you don't like the idea about loading DLLs from the absolute path without using SetDefaultDllDirectories() at all, try calling the latter function with all flags before CoCreateInstance(). If OLE32 cannot load necessary DLLs, this will help.

                   
                  • Igor Pavlov

                    Igor Pavlov - 2016-09-30

                    Actually I'll fix that bug with version check (for Vista).
                    And now I don't know why I need to change something else.
                    Or you think that some things work incorrectly?

                     
                    • Shell

                      Shell - 2016-09-30

                      I don't. I just think that, since everything works without SetDefaultDllDirectories() (see my experiment in ntsd), this call and version check are redundant.

                      Could you probably create a test version with two SetDefaultDllDirectories() calls - one before loading DLLs and one after (but before creating links)? Maybe this will make Vista happy.

                       
                      • Igor Pavlov

                        Igor Pavlov - 2016-09-30

                        We don't know exact list of "bad" DLLs names.
                        Look, for example, winrar sfxs and installer. It contain some list of DLLs as I remember (search UXTHEME in UTF-16).

                        So if SetDefaultDllDirectories removes all attacks with any name of DLL, it's good to use it.
                        If we can't use SetDefaultDllDirectories, we preload "bad" DLLs from safe windows folder.

                         
                        • Shell

                          Shell - 2016-09-30

                          I didn't understand what a "bad" DLL is. I think that we can divide all the DLLs that an application uses into two categories: 1) Windows DLLs; 2) third-party DLLs (including application's own DLLs). An application always knows each DLL from cat. 2 it uses. It may not know the dependencies of the DLLs from cat. 1, but all such dependencies also fall in cat. 1 and thus should be present in System32.

                          It may require a thorough investigation to determine whether cat. 2 DLLs can be replaced by malware in a particular case. This means that you're right with taking extra precautions. However, if an application uses only cat. 1 DLLs, I think they can be safely loaded from System32 with a simple GetSystemDirectory()+LoadLibrary().

                          UPDATE: the above method is unsafe. According to MSDN,

                          If a DLL has dependencies, the system searches for the dependent DLLs as if they were loaded with just their module names. This is true even if the first DLL was loaded by specifying a full path.

                          So, Igor, you're right to call SetDefaultDllDirectories(). Perhaps, it is worthwhile to call SetDllDirectoryW(L"") (with empty path; this function was introduced with WinXP SP1) if SetDefaultDllDirectories() is not found - this will prevent the application from loading DLLs from the current directory (but not from its own directory).

                          Another thing is that, according to MSDN, the NSIS way also has a flaw: any dependency of DLLs from g_Dlls[] will be loaded from the current directory first. Please, consider this idea when writing your own security code.

                           
                          Last edit: Shell 2016-09-30
  • Roman

    Roman - 2016-09-30

    При попытке распаковать инсталлятор, созданный InstallAnywhere, 7-zip не справляется. Unzip.exe (http://www.info-zip.org/pub/infozip/UnZip.html) же справляется.
    Вот инсталлятор http://www.ups-software-download.com/winpower/data/Windows/Winpower_setup_Windows.zip

    Можно ли как-нибудь заставить 7-zip распаковывать такие файлы напрямую?

     
    • Shell

      Shell - 2016-09-30

      If I understand .ZIP File Format Specification correctly, setup.exe is an invalid ZIP archive. Its End of central directory specifies the start of central directory at offset 0x3E0689A, but its actual offset is 0x3E1FC9E due to the SFX module. The difference 0x19404 matches neither SFX size, nor unpacked SFX size. It can be determined only by scanning the file for both the End of central directory signature and the Start of central directory signature. However, a ZIP archive may contain several Starts of central directory (which is unlikely but still correct).

       
  • Shell

    Shell - 2016-09-30

    I have identified the problem with CoCreateInstance() on Vista. A very clever Microsoft programmer has made the following call in OLE32.DLL:

    LoadLibraryExW(L"shell32.dll",NULL,LOAD_WITH_ALTERED_SEARCH_PATH+0x0200);

    According to MSDN:

    The behavior is undefined when LOAD_WITH_ALTERED_SEARCH_PATH flag is set, and lpFileName specifiies a relative path.
    This value cannot be combined with any LOAD_LIBRARY_SEARCH flag.

    On my OS (Vista x86 SP2), if any of the LOAD_LIBRARY_SEARCH flags is specified in SetDefaultDllDirectories(), a check is performed on the path. If the path is relative, LoadLibraryEx() fails. Unfortunately, the parameter to SetDefaultDllDirectories() must contain LOAD_LIBRARY_SEARCH flags (otherwise the function fails). Thus, OLE32.DLL thinks it cannot load SHELL32.DLL (it is actually loaded, but LoadLibraryEx() returns NULL before checking the loaded libraries).

    Consider the following solution:
    static DWORD _BaseDefaultDllDirectories;
    #define SetDefaultDllDirectories(flags) (_BaseDefaultDllDirectories=flags)
    #define MyLoadLibrary(path) LoadLibraryEx(path,NULL,_BaseDefaultDllDirectories)
    #define MyLoadLibraryEx(path,file,flags) LoadLibraryEx(path,NULL,_BaseDefaultDllDirectories | flags)

    Now each DLL loaded from the application will be secured:

    If this value is used, <...> is searched for the DLL and its dependencies. Directories in the standard search path are not searched.

    On the other hand, each DLL loaded dynamically from other DLLs will NOT be secured. This is a flaw, but it resolves the issue with CoCreateInstance().

     
1 2 > >> (Page 1 of 2)

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks