用程序验证程序在对ShellExecuteEx的调用中报告访问冲

用程序验证程序在对ShellExecuteEx的调用中报告访问冲

本文介绍了应用程序验证程序在对ShellExecuteEx的调用中报告访问冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

Application Verifier表示运行代码时存在访问冲突:

Application Verifier says there is an access violation when running the code:

var
   shi: TShellExecuteInfo;
begin
   shi := Default(TShellExecuteInfo);
   shi.cbSize := SizeOf(TShellExecuteInfo);
   shi.lpFile := PChar('C:\Windows');
   ShellExecuteEx(@shi);
end;

怎么了?

我正在应用程序下运行我的应用程序验证程序,启用了检测堆损坏的选项:

I'm running my application under the Application Verifier, with the option to detect heap corruption enabled:

  • :检查堆错误.
  • Heaps: Checks the heap errors.

在调用 ShellExecuteEx 期间,出现异常,表明存在堆损坏.

During the call to ShellExecuteEx, an exception comes up, indicating that there is heap corruption.

在调试器中运行使我可以解码异常:

Running inside a debugger allows me to decode the exception:

ExceptionAddress: 0000000074b254ad (KERNELBASE!ParseURLW+0x000000000000002d)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 0000000000000000
   Parameter[1]: 0000000008e26fe8
Attempt to read from address 0000000008e26fe8

在调试器外部运行 ,应用程序崩溃(WerFault进行事后调查,该进程死亡).

Running outside a debugger, the application crashes (WerFault takes a post-mortem and the process dies).

代码有什么问题?

program ShellExecuteTestApp;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  Winapi.ShellAPI;

var
    shi: TShellExecuteInfo;
begin
    try
        shi := Default(TShellExecuteInfo);
        shi.cbSize := SizeOf(TShellExecuteInfo);
        shi.lpFile := PChar('C:\Windows');

        WriteLn('shi.cbSize: '+IntToStr(shi.cbSize));
        WriteLn('shi.lpFile: "'+shi.lpFile+'"');
        ShellExecuteEx(@shi);
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
end.

崩溃前,它输出:

shi.cbSize: 60
shi.lpFile: "C:\Windows"

我认为这可能是 CreateProcess 中的常见错误,所以我确保lpFile是可写的:

I thought perhaps it was the common bug from CreateProcess, so i made sure the lpFile was writable:

var
   file: string;
   shi: TShellExecuteInfo;
begin
   file := 'C:\Windows';
   UniqueString({var} file);

   shi := Default(TShellExecuteInfo);
   shi.cbSize := SizeOf(TShellExecuteInfo);
   shi.lpFile := PChar(file);
   ShellExecuteEx(@shi);
end;

内存转储

使用32位版本(以使指针更易于阅读),将内存传递给 ShellExecuteEx

00423EBC   0000003C  cbSize         60 bytes
           00000000  fMask          SEE_MASK_DEFAULT
           00000000  Wnd            null
           00000000  lpVerb         null
           0041C600  lpFile         ==> 0x0041C60C
           00000000  lpParameters   null
           00000000  lpDirectory    null
           00000001  nShow          SW_NORMAL
           00000000  hInstApp       0
           00000000  lpIDList       null
           00000000  lpClass        null
           00000000  hkeyClass      0
           00000000  dwHotKey       0
           00000000  hMonitor       null
           00000000  hProcess       null

一个指向宽字符的指针:

With the one pointer to a wide char:

0041C60C  43 00 3A 00 5C 00 57 00  C.:.\.W.
0041C614  69 00 6E 00 64 00 6F 00  i.n.d.o.
0041C61C  77 00 73 00 00 00 00 00  w.s.....

然后调用:

ShellExecuteTestApp.dpr.29: ShellExecuteEx(@shi);
0041C51F 68BC3E4200       push $00423ebc       ;push address of shi structure
0041C524 E85BD6FFFF       call ShellExecuteEx  ;call imported function

Winapi.ShellAPI.pas.1798: function ShellExecuteEx; external shell32 name 'ShellExecuteExW';
00419B84 FF250C444200     jmp dword ptr [$0042440c] ;jump to ShellExecuteW inside shell32


shell32.ShellExecuteExW:
75520060 8BFF             mov edi,edi
75520062 55               push ebp
75520063 8BEC             mov ebp,esp
75520065 83E4F8           and esp,-$08
75520068 51               push ecx
75520069 53               push ebx
7552006A 56               push esi
7552006B 8B7508           mov esi,[ebp+$08]
7552006E 57               push edi
7552006F 833E3C           cmp dword ptr [esi],$3c
75520072 7540             jnz $755200b4
75520074 8B5E04           mov ebx,[esi+$04]
75520077 F7C300011000     test ebx,$00100100
7552007D 7427             jz $755200a6
7552007F 8BCE             mov ecx,esi
75520081 E836000000       call $755200bc --> failure is this way

然后有很多我无法理解的东西,直到错误最终在 ParseUrlW :

And then there's a lot of stuff i can't follow, until the error finally happens in ParseUrlW:

HRESULT ParseURL(
  _In_    LPCTSTR   pcszUrl,
  _Inout_ PARSEDURL *ppu
);

带转储:

KERNELBASE.ParseURLW:
74B25480 8BFF             mov edi,edi
74B25482 55               push ebp
74B25483 8BEC             mov ebp,esp         ;save stack pointer
74B25485 8B4508           mov eax,[ebp+$08]   ;restore pcszUrl into EAX
74B25488 83EC0C           sub esp,$0c
74B2548B 85C0             test eax,eax        ;test that pcszUrl param supplied
74B2548D 0F8493010000     jz $74b25626


注意:目前,包含地址0x0908BFE8:


Note: At this moment contains address 0x0908BFE8:

0908BFE8: 00 00 00 00 00 00 00 00  ........

提供的pcszUrl字符串为空?实际上不,该地址无效.但是直到代码尝试触及它之前我们还不知道

The supplied pcszUrl string is empty? Actually no, the address is invalid. But we don't know that yet until the code tries to touch it

74B25493 57               push edi            ;save EDI
74B25494 8B7D0C           mov edi,[ebp+$0c]   ;get PARSEDURL into edi
74B25497 85FF             test edi,edi
74B25499 0F8410630300     jz $74b5b7af


注意:目前,包含0977FBDC


Note: At this moment contains 0977FBDC

PARSEDURL structure
0977FBCD   00000018   cbSize      24 bytes
           753F5BC0   pszProtocol [uninitialized junk]
           0977FEC4   cchProtocol [uninitialized junk]
           092ECFC8   pszSuffix   [uninitialized junk]
           78E6E41E   cchSuffix   [uninitialized junk]
           0977FE98   nScheme     [uninitialized junk]


74B2549F 833F18           cmp dword ptr [edi],$18  ;test that struct size is what we expect (24 bytes)
74B254A2 0F8507630300     jnz $74b5b7af

74B254A8 53               push ebx           ;save ebx
74B254A9 8BD0             mov edx,eax        ;save pcszUrl into edx
74B254AB 33DB             xor ebx,ebx

74B254AD 0FB700           movzx eax,[eax]    ;Attempt to copy 4 bytes of the string into EAX (access violation)

代码尝试使用以零扩展的方式移动.但是该地址无效,从而导致访问冲突:

The code tries to copy the first word from 0x0908BFE8 using Move with Zero-Extend. But that address is invalid, giving the access violation:

因此,在 ShellExecuteExW 代码的某处,它设置了对 ParseUrlW 的无效调用.

So somewhere in the code of ShellExecuteExW, it sets up an invalid call to ParseUrlW.

32位WinDbg,调试32位应用程序,带有符号:

32-bit WinDbg, debugging 32-bit application, with symbols:

*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

*** ERROR: Module load completed but symbols could not be loaded for image00400000

FAULTING_IP:
KERNELBASE!ParseURLW+2d
74b254ad 0fb700          movzx   eax,word ptr [eax]

EXCEPTION_RECORD:  ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 74b254ad (KERNELBASE!ParseURLW+0x0000002d)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 00000000
   Parameter[1]: 07634fe8
Attempt to read from address 07634fe8

CONTEXT:  00000000 -- (.cxr 0x0;r)
eax=07634fe8 ebx=00000000 ecx=07634fe8 edx=07634fe8 esi=00000000 edi=093dfbdc
eip=74b254ad esp=093dfbb4 ebp=093dfbc8 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
KERNELBASE!ParseURLW+0x2d:
74b254ad 0fb700          movzx   eax,word ptr [eax]       ds:002b:07634fe8=????

FAULTING_THREAD:    00003ff4
DEFAULT_BUCKET_ID:  INVALID_POINTER_READ
PROCESS_NAME:       image00400000
ERROR_CODE:         (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.
EXCEPTION_CODE:     (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.
EXCEPTION_PARAMETER1:  00000000
EXCEPTION_PARAMETER2:  07634fe8
READ_ADDRESS:       07634fe8

FOLLOWUP_IP:
shell32!GetUrlSchemeW+28
754c66be 85c0            test    eax,eax

NTGLOBALFLAG:                2000100
APPLICATION_VERIFIER_FLAGS:  80000001
APP:                         image00400000
ANALYSIS_VERSION:            6.3.9600.17237 (debuggers(dbg).140716-0327) x86fre
PRIMARY_PROBLEM_CLASS:       INVALID_POINTER_READ
BUGCHECK_STR:                APPLICATION_FAULT_INVALID_POINTER_READ
LAST_CONTROL_TRANSFER:       from 754c66be to 74b254ad

STACK_TEXT:
093dfbc8 754c66be 07634fe8 093dfbdc 00000000 KERNELBASE!ParseURLW+0x2d
093dfbf8 75522df8 0746fff0 07604f68 00000002 shell32!GetUrlSchemeW+0x28
093dfe98 75522b1a 093dfec4 00000000 0746fff0 shell32!CShellExecute::CreateParsingBindCtx+0x1d6
093dfecc 755224da 00000000 0746fff0 00000000 shell32!CShellExecute::ParseOrValidateTargetIdList+0x37
093dfef0 7551fd5a 093dff80 768b983a 07604f68 shell32!CShellExecute::_DoExecute+0x40
093dfef8 768b983a 07604f68 768b9770 768b9770 shell32!<lambda_e76b82c5cb7f9f82cbe0fd97ad5190bf>::<lambda_invoker_stdcall>+0x1a
093dff80 73d08484 0019fd94 73d08460 21439000 shcore!_WrapperThreadProc+0xca
093dff94 772c2fea 0019fd94 25ae5778 00000000 KERNEL32!BaseThreadInitThunk+0x24
093dffdc 772c2fba ffffffff 772dec22 00000000 ntdll!__RtlUserThreadStart+0x2f
093dffec 00000000 768b9770 0019fd94 00000000 ntdll!_RtlUserThreadStart+0x1b


STACK_COMMAND:       .cxr 0x0 ; kb
SYMBOL_STACK_INDEX:  1
SYMBOL_NAME:         shell32!GetUrlSchemeW+28
FOLLOWUP_NAME:       MachineOwner
MODULE_NAME:         shell32
IMAGE_NAME:          shell32.dll
DEBUG_FLR_IMAGE_TIMESTAMP:  0
FAILURE_BUCKET_ID:   INVALID_POINTER_READ_c0000005_shell32.dll!GetUrlSchemeW
BUCKET_ID:
APPLICATION_FAULT_INVALID_POINTER_READ_shell32!GetUrlSchemeW+28
ANALYSIS_SOURCE:     UM
FAILURE_ID_HASH_STRING:  um:invalid_pointer_read_c0000005_shell32.dll!geturlschemew
FAILURE_ID_HASH:     {89d9bcf0-5ef6-4e90-df6b-f05dc028e062}
Followup:            MachineOwner
---------

奖金阅读

  • 在delphi7中执行访问冲突ShellExecute
  • Bonus Reading

    • Access Violation ShellExecute in delphi7
    • 推荐答案

      正如@RaymondChen所说,这是Windows 10中的错误.

      As @RaymondChen said, it's a bug in Windows 10.

      • I only encountered it because Application Verifier caught it.
      • it's a one-in-a-million chance that you'd actually ever encounter it in the wild

      雷蒙德太谦虚了,不能接受声誉.所以我用他的答案作为自己的答案.

      Raymond's too modest to accept reputation; so i use his answer as my own.

      这篇关于应用程序验证程序在对ShellExecuteEx的调用中报告访问冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

      1403页,肝出来的..

09-07 01:58