[Bug 46626] UPlay fails to start : "Error at hooking API LoadStringA" ( UPlay's hooking engine can' t handle ENDBR32 instruction inserted at non-hotpatch API entries due to distro build environments '-fcf-protection')

wine-bugs at winehq.org wine-bugs at winehq.org
Mon Mar 18 07:05:07 CDT 2019


https://bugs.winehq.org/show_bug.cgi?id=46626

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|UPlay fails to start :      |UPlay fails to start :
                   |"Error at hooking API       |"Error at hooking API
                   |LoadStringA"                |LoadStringA" (UPlay's
                   |                            |hooking engine can't handle
                   |                            |ENDBR32 instruction
                   |                            |inserted at non-hotpatch
                   |                            |API entries due to distro
                   |                            |build environments
                   |                            |'-fcf-protection')
     Ever confirmed|0                           |1
                 CC|                            |focht at gmx.net
             Status|UNCONFIRMED                 |NEW
                URL|                            |https://web.archive.org/web
                   |                            |/20190313080907/https://ubi
                   |                            |static3-a.akamaihd.net/orbi
                   |                            |t/launcher_installer/UplayI
                   |                            |nstaller.exe
           Keywords|                            |download, obfuscation
       Distribution|---                         |Fedora

--- Comment #6 from Anastasius Focht <focht at gmx.net> ---
Hello folks,

--- quote ---
I wonder why locally built wine does not have this problem.
compiler version? extra build flags?
--- quote ---

Here you go ...

Disassembly of hooked API entry from 'upc.com' process:

--- snip ---
Wine-dbg>x/10i LoadStringA

0x000000007e8ad30b LoadStringA       in user32: jmp    0x00000000022327b0
EntryPoint+0xffffffffffffffff in upc
0x000000007e8ad310 LoadStringA+0x5   in user32: inb    $0xf0,%al
0x000000007e8ad312 LoadStringA+0x7   in user32: pushl    0xfffffffc(%ecx)
0x000000007e8ad315 LoadStringA+0xa   in user32: pushl    %ebp
0x000000007e8ad316 LoadStringA+0xb   in user32: movl    %esp,%ebp
0x000000007e8ad318 LoadStringA+0xd   in user32: pushl    %ebx
0x000000007e8ad319 LoadStringA+0xe   in user32: pushl    %ecx
0x000000007e8ad31a LoadStringA+0xf   in user32: subl    $48,%esp
0x000000007e8ad31d LoadStringA+0x12  in user32: movl    %ecx,%ebx
0x000000007e8ad31f LoadStringA+0x14  in user32: movl    $0x0,0xffffffd4(%ebp)

Wine-dbg>x/10i LoadStringW

0x000000007e8ad0e9 LoadStringW       in user32: jmp    0x0000000002232840
EntryPoint+0xffffffffffffffff in upc
0x000000007e8ad0ee LoadStringW+0x5   in user32: inb    $0xf0,%al
0x000000007e8ad0f0 LoadStringW+0x7   in user32: pushl    0xfffffffc(%ecx)
0x000000007e8ad0f3 LoadStringW+0xa   in user32: pushl    %ebp
0x000000007e8ad0f4 LoadStringW+0xb   in user32: movl    %esp,%ebp
0x000000007e8ad0f6 LoadStringW+0xd   in user32: pushl    %ebx
0x000000007e8ad0f7 LoadStringW+0xe   in user32: pushl    %ecx
0x000000007e8ad0f8 LoadStringW+0xf   in user32: subl    $48,%esp
0x000000007e8ad0fb LoadStringW+0x12  in user32: movl    %ecx,%ebx
0x000000007e8ad0fd LoadStringW+0x14  in user32: movl    $0x7ea056e0,%eax
--- snip ---

Disassembly of same API entry, not hooked yet:

NOTE: This is from a '-fno-PIC' build. I always use no-PIC builds for
32-bit/64-bit for years to avoid all kinds of hooking issues -> bug 37540

--- snip ---
0x000000007e4ac0e9 LoadStringW       in user32: leal    0x4(%esp),%ecx
0x000000007e4ac0ed LoadStringW+0x4   in user32: andl    $-16,%esp
0x000000007e4ac0f0 LoadStringW+0x7   in user32: pushl    0xfffffffc(%ecx)
0x000000007e4ac0f3 LoadStringW+0xa   in user32: pushl    %ebp
0x000000007e4ac0f4 LoadStringW+0xb   in user32: movl    %esp,%ebp
0x000000007e4ac0f6 LoadStringW+0xd   in user32: pushl    %ebx
0x000000007e4ac0f7 LoadStringW+0xe   in user32: pushl    %ecx
0x000000007e4ac0f8 LoadStringW+0xf   in user32: subl    $48,%esp
0x000000007e4ac0fb LoadStringW+0x12  in user32: movl    %ecx,%ebx
0x000000007e4ac0fd LoadStringW+0x14  in user32: movl    $0x7e6046e0,%eax
--- snip ---

Let's look at the package which you reported to be a problem...

https://dl.winehq.org/wine-builds/fedora/29/i686/wine-devel-common-4.1-3.1.i686.rpm

Dump the content:

--- snip ---
$ rpm2cpio ./wine-devel-common-4.1-3.1.i686.rpm | cpio -idmv
--- snip ---

Disassembly of the affected API entry:

--- snip ---
$ gdb opt/wine-devel/lib/wine/user32.dll.so -batch -ex 'disassemble
LoadStringW'
Dump of assembler code for function LoadStringW:
   0x0008b860 <+0>:    endbr32 
   0x0008b864 <+4>:    lea    0x4(%esp),%ecx
   0x0008b868 <+8>:    and    $0xfffffff0,%esp
   0x0008b86b <+11>:    pushl  -0x4(%ecx)
   0x0008b86e <+14>:    push   %ebp
   0x0008b86f <+15>:    mov    %esp,%ebp
   0x0008b871 <+17>:    push   %edi
   0x0008b872 <+18>:    push   %esi
   0x0008b873 <+19>:    push   %ebx
   0x0008b874 <+20>:    call   0x202e0
   0x0008b879 <+25>:    add    $0x6b787,%ebx
...
--- snip ---

There we go. ENDBR is a special instruction. Intel's CET (Control-Flow
Enforcement Technology) introduced a new mechanism called IBT (Indirect Branch
Tracking). According to IBT, each indirect branch should land on dedicated
ENDBR instruction (end branch).

https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf

If the processor does not support Indirect Branch Tracking (IBT), the
instruction is a NOP (see [0], pages 15ff. and 130f.)

How does this get in?

https://build.opensuse.org/package/view_file/Emulators:Wine:Fedora/wine-devel/wine-devel.spec?expand=1

--- snip ---
%build
%ifarch x86_64
export CFLAGS="$(echo "%{optflags}" | sed -e 's/-O2//' -e
's/-Wp,-D_FORTIFY_SOURCE=2//') -O2"
%else
export CFLAGS="$(echo "%{optflags}" | sed -e 's/-Wp,-D_FORTIFY_SOURCE=2//')"
%endif
--- snip ---

>From my local Fedora 28 build host:

--- snip ---
$ rpmbuild --showrc  | grep ^optflags
optflags              : %{__global_compiler_flags} -m64 -mtune=generic
-fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection
--- snip ---

--- snip ---
$ gcc -dumpspecs | grep cf-protection
--- snip ---

The culprit is '-fcf-protection' which causes the insertion of ENDBR
instruction in API entry code. If you use rpmbuild environment then it's
active. If you build without rpmbuild using gcc defaults or own CFLAGS then
it's not active.

Apparently Uplay hooking engine can't handle/decode this instruction, refusing
to hot-patch the entry.

It's unfortunate that
https://source.winehq.org/git/wine.git/commit/9b90cfc2817e171e7a9698605deecc3438712af8
had no corresponding Bugzilla bug report otherwise the issue could have been
properly analysed/explained earlier.

I still see many times patches committed that appear to be out of the blue
without any background information what they ought to fix. Sometimes it's
possible to guess .. many times not. I don't know why it's so hard to create
tracking bugs referring to real world apps/games. This lack of traceability
causes later additional efforts on figuring out things in case of regressions
and/or do really proper fixes.

ProtectionID scan for documentation:

--- snip ---
-=[ ProtectionID v0.6.9.0 DECEMBER]=-
(c) 2003-2017 CDKiLLER & TippeX
Build 24/12/17-21:05:42
Ready...
Scanning -> C:\Program Files (x86)\Ubisoft\Ubisoft Game Launcher\upc.exe
File Type : 32-Bit Exe (Subsystem : Win GUI / 2), Size : 12171608 (0B9B958h)
Byte(s) | Machine: 0x14C (I386)
Compilation TimeStamp : 0x5C7FCB72 -> Wed 06th Mar 2019 13:30:26 (GMT)
[TimeStamp] 0x5C7FCB72 -> Wed 06th Mar 2019 13:30:26 (GMT) | PE Header | - |
Offset: 0x00000170 | VA: 0x00400170 | -
[TimeStamp] 0x5C7FCB71 -> Wed 06th Mar 2019 13:30:25 (GMT) | Export | - |
Offset: 0x00028CB4 | VA: 0x0259D6B4 | -
[TimeStamp] 0x5C7FCB72 -> Wed 06th Mar 2019 13:30:26 (GMT) | DebugDirectory | -
| Offset: 0x00AE1AA4 | VA: 0x030564A4 | -
[TimeStamp] 0x5C7FCB72 -> Wed 06th Mar 2019 13:30:26 (GMT) | DebugDirectory | -
| Offset: 0x00AE1AC0 | VA: 0x030564C0 | -
[TimeStamp] 0x5C7FCB72 -> Wed 06th Mar 2019 13:30:26 (GMT) | DebugDirectory | -
| Offset: 0x00AE1ADC | VA: 0x030564DC | -
-> File Appears to be Digitally Signed @ Offset 0B99E00h, size : 01B58h / 07000
byte(s)
[!] Executable uses TLS callbacks (1 total... 0 invalid addresses)
[LoadConfig] Struct determined as v8 (Expected size 140 | Actual size 64)
[!] Executable uses SEH Tables (/SAFESEH) (42117 calculated 42117 recorded... 0
invalid addresses) 
[LoadConfig] CodeIntegrity -> Flags 0x5352 | Catalog 0x5344 (21316) | Catalog
Offset 0xF26A4B2F | Reserved 0x460D8931
[LoadConfig] GuardAddressTakenIatEntryTable 0x671517AF | Count 0x23EEDC28
(602856488)
[LoadConfig] GuardLongJumpTargetTable 0x1 | Count 0x4A5C3A44 (1247558212)
[LoadConfig] HybridMetadataPointer 0x696B6E65 | DynamicValueRelocTable
0x6F57736E
[LoadConfig] FailFastIndirectProc 0x70736B72 | FailFastPointer 0x5C656361
[LoadConfig] UnknownZero1 0x6B726F77
[File Heuristics] -> Flag #1 : 00000100000001001101001100000111 (0x0404D307)
[Entrypoint Section Entropy] : 7.88 (section #6) ".ubx1   " | Size : 0xB0A708
(11577096) byte(s)
[DllCharacteristics] -> Flag : (0x8140) -> ASLR | DEP | TSA
[SectionCount] 8 (0x8) | ImageSize 0x2D0F000 (47247360) byte(s)
[Export] 0% of function(s) (0 of 137) are in file | 0 are forwarded | 136 code
| 0 data | 0 uninit data | 0 unknown | 
[VersionInfo] Company Name : Ubisoft
[VersionInfo] Product Name : Uplay
[VersionInfo] Product Version : 85.0.6025
[VersionInfo] File Description : Uplay launcher
[VersionInfo] File Version : 3.0
[VersionInfo] Original FileName : upc.exe
[VersionInfo] Internal Name : Uplay game launcher
[VersionInfo] Legal Copyrights : (c) Ubisoft
[ModuleReport] [IAT] Modules -> KERNEL32.dll | USER32.dll | SHELL32.dll |
ole32.dll | libUbiCustomEvent.dll | libcef.dll | WS2_32.dll | IPHLPAPI.DLL |
WINHTTP.dll | RPCRT4.dll | d3d9.dll | gdiplus.dll | dwmapi.dll | GDI32.dll |
COMDLG32.dll | ADVAPI32.dll | LIBEAY32.dll | Secur32.dll | CRYPT32.dll |
IMM32.dll | KERNEL32.dll | KERNEL32.dll
[Debug Info] (record 1 of 3) (file offset 0xAE1AA0)
Characteristics : 0x0 | TimeDateStamp : 0x5C7FCB72 (Wed 06th Mar 2019 13:30:26
(GMT)) | MajorVer : 0 / MinorVer : 0 -> (0.0)
Type : 2 (0x2) -> CodeView | Size : 0x81 (129) 
AddressOfRawData : 0x2C56010 | PointerToRawData : 0xAE1610
CvSig : 0x53445352 | SigGuid F26A4B2F-8931-460D-AF17156728DCEE23
Age : 0x1 (1) | Pdb :
D:\JenkinsWorkspace\workspace\client_build_release\client\build\working_directory\RelWithDebInfo\upc.pdb
[Debug Info] (record 2 of 3) (file offset 0xAE1ABC)
Characteristics : 0x0 | TimeDateStamp : 0x5C7FCB72 (Wed 06th Mar 2019 13:30:26
(GMT)) | MajorVer : 0 / MinorVer : 0 -> (0.0)
Type : 12 (0xC) -> Undocumented | Size : 0x14 (20) 
AddressOfRawData : 0x2C56094 | PointerToRawData : 0xAE1694
[Debug Info] (record 3 of 3) (file offset 0xAE1AD8)
Characteristics : 0x0 | TimeDateStamp : 0x5C7FCB72 (Wed 06th Mar 2019 13:30:26
(GMT)) | MajorVer : 0 / MinorVer : 0 -> (0.0)
Type : 13 (0xD) -> Undocumented | Size : 0x3F8 (1016) 
AddressOfRawData : 0x2C560A8 | PointerToRawData : 0xAE16A8
[!] Ubisoft UBX detected !
[!] VM Protect  detected !
[CompilerDetect] -> Borland Delphi (unknown version) - 20% probability
- Scan Took : 2.857 Second(s) [00000085Fh (2143) tick(s)] [506 of 580 scan(s)
done]
--- snip ---

$ sha1sum UplayInstaller.exe 
8ec8e8fc9fab1d1105570a37dd43251c313c380c  UplayInstaller.exe

$ du -sh UplayInstaller.exe 
86M    UplayInstaller.exe

$ wine --version
wine-4.4-

Regards

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.


More information about the wine-bugs mailing list