Universal Extractor 2 64位闪退分析 (AutoIt)

Universal Extractor 2 64位闪退分析 (AutoIt)

版本:2.0.0 RC4 2023-07-24

问题现象:启动程序,拖入需解压的文件后直接退出

1、x64dbg载入主程序,设置异常选项,勾选暂停于第一次机会,F9运行,拖入需解压的文件,发生异常并断下,异常指令为

00007FF9F448D93066:8901mov word ptr ds:[rcx],ax

此时rcx值为 0xC67C6060,系统中并未分配这段内存,因此对其操作必然产生异常。查看调用堆栈如下:

可看到异常发生于 shell32.DragQueryFileW,点击来到用户模块调用处

0000000140024AE2FFD0call rax调用API-DragQueryFileW

是个间接调用,应该为不同 API 共用,如果在这里下断点可能会断下很多次

2、来到段首0x140024970下断点,重新启动程序,立刻断下了,观察rcx、rdx、r8、r9等用于传参的寄存器,发现rcx指向 API “SetProcessDpiAwarenessContext”的入口,运行到0x140024AE2 call rax 处,发现这就是决定rax指向 API 的关键

我们现在只需要中断在 DragQueryFileW,在“符号”选项卡找到 DragQueryFileW 的入口地址为0x7FF9F4616280,将段首断点的条件设置为 qword(rcx)==7FF9F4616280

3、继续运行,成功断下,发现 DragQueryFileW 运行到第三次才出现异常。根据运行到 call rax 处参数寄存器的值,参照API文档 (https://learn.microsoft.com/zh-cn/windows/win32/api/shellapi/nf-shellapi-dragqueryfilew?source=recommendations),得知 DragQueryFileW 第一次运行返回拖动的文件数,第二次运行返回文件名缓冲区大小,第三次运行应该把返回的文件名放入缓冲区。第三次运行API参数如下:

对照API参数

UINT DragQueryFileW( [in] HDROP hDrop, [in] UINT iFile, [out] LPWSTR lpszFile, UINT cch );

得知r8寄存器存放的是缓冲区地址,但现在缓冲区明显不是一个有效地址,为什么会这样呢?r8高32位全部为0,猜想是第二次运行后第三次运行前缓冲区的设置出了问题,把64位的缓冲区设置成了32位,还要继续往下分析,找到缓冲区参数设置的地方并拿到正确地址。

4、将所有断点禁用,直接在 DragQueryFileW 入口下断点,运行到第二次的时候恢复第2步的段首断点,F9后断在段首,F8单步往下执行,并观察r8的值,来到下面指令r8改变了,这就是缓冲区地址

0000000140024A4C4D:8B06mov r8,qword ptr ds:[r14]第3个参数

查看r14指向内存的数据,这里已经是32位了,还得继续向上追溯。

经分析,这一段的作用就是解析 API 的入口及参数后跳转执行,AutoIt 的解释器解释到调用 API 的脚本语句时就会进入到这里,载入 API 入口后立即依次解析参数并放入参数寄存器,参数表存放于堆栈的某段地址,每项大小0x28, 0-7字节为数据,第8字节为数据长度,第0x10字节为数据类型,代码分析如下:

000000014002497055push rbp调用API子程序段首
000000014002497148:8BECmov rbp,rsp
000000014002497448:83EC 40sub rsp,0x40
00000001400249784C:8965 C0mov qword ptr ss:[rbp-0x40],r12
000000014002497C4C:896D C8mov qword ptr ss:[rbp-0x38],r13
00000001400249804C:8975 D0mov qword ptr ss:[rbp-0x30],r14
00000001400249844C:897D D8mov qword ptr ss:[rbp-0x28],r15
000000014002498848:894D 10mov qword ptr ss:[rbp+0x10],rcxAPI入口
000000014002498C4C:8B65 10mov r12,qword ptr ss:[rbp+0x10]
00000001400249904D:8B6C24 18mov r13,qword ptr ds:[r12+0x18]参数数量
000000014002499549:8BC5mov rax,r13
000000014002499848:83F8 04cmp rax,0x4
000000014002499C7D 07jge uniextract-.1400249A5
000000014002499E48:C7C0 04000000mov rax,0x4
00000001400249A548:6BC0 08imul rax,rax,0x8
00000001400249A948:83C0 08add rax,0x8
00000001400249AD83E0 F0and eax,0xFFFFFFF0
00000001400249B048:8945 F8mov qword ptr ss:[rbp-0x8],rax暂停条件(qword(rcx)==7FF9F4616280)
00000001400249B448:2BE0sub rsp,rax
00000001400249B74D:8D7424 50lea r14,qword ptr ds:[r12+0x50]API参数表(每项大小0x28, 0-7字节为数据,第8字节为数据长度,第0x10字节为数据类型)
00000001400249BC49:83FD 00cmp r13,0x0r13存放参数数量
00000001400249C00F84 F4000000je uniextract-.140024ABA无参数直接跳转执行API,否则开始处理第一个参数
00000001400249C649:8B46 10mov rax,qword ptr ds:[r14+0x10]读取数据类型
00000001400249CA48:83F8 01cmp rax,0x1
00000001400249CE74 15je uniextract-.1400249E5整数
00000001400249D049:8B46 08mov rax,qword ptr ds:[r14+0x8]指针
00000001400249D448:83F8 09cmp rax,0x99:'\t'
00000001400249D874 10je uniextract-.1400249EA浮点数float
00000001400249DA48:83F8 0Acmp rax,0xAA:'\n'
00000001400249DE74 0Aje uniextract-.1400249EA浮点数double
00000001400249E049:8B0Emov rcx,qword ptr ds:[r14]
00000001400249E3EB 0Ajmp uniextract-.1400249EF
00000001400249E549:8D0Elea rcx,qword ptr ds:[r14]
00000001400249E8EB 05jmp uniextract-.1400249EF
00000001400249EAF241:0F1006movsd xmm0,qword ptr ds:[r14]
00000001400249EF49:83C6 28add r14,0x28参数表指向下一项
00000001400249F349:FFCDdec r13
00000001400249F60F84 BE000000je uniextract-.140024ABA
00000001400249FC49:8B46 10mov rax,qword ptr ds:[r14+0x10]处理第二个参数
0000000140024A0048:83F8 01cmp rax,0x1
0000000140024A0474 15je uniextract-.140024A1B
0000000140024A0649:8B46 08mov rax,qword ptr ds:[r14+0x8]
0000000140024A0A48:83F8 09cmp rax,0x99:'\t'
0000000140024A0E74 10je uniextract-.140024A20
0000000140024A1048:83F8 0Acmp rax,0xAA:'\n'
0000000140024A1474 0Aje uniextract-.140024A20
0000000140024A1649:8B16mov rdx,qword ptr ds:[r14]
0000000140024A19EB 0Ajmp uniextract-.140024A25
0000000140024A1B49:8D16lea rdx,qword ptr ds:[r14]
0000000140024A1EEB 05jmp uniextract-.140024A25
0000000140024A20F241:0F100Emovsd xmm1,qword ptr ds:[r14]
0000000140024A2549:83C6 28add r14,0x28
0000000140024A2949:FFCDdec r13
0000000140024A2C0F84 88000000je uniextract-.140024ABA
0000000140024A3249:8B46 10mov rax,qword ptr ds:[r14+0x10]处理第三个参数
0000000140024A3648:83F8 01cmp rax,0x1
0000000140024A3A74 15je uniextract-.140024A51
0000000140024A3C49:8B46 08mov rax,qword ptr ds:[r14+0x8]
0000000140024A4048:83F8 09cmp rax,0x99:'\t'
0000000140024A4474 10je uniextract-.140024A56
0000000140024A4648:83F8 0Acmp rax,0xAA:'\n'
0000000140024A4A74 0Aje uniextract-.140024A56
0000000140024A4C4D:8B06mov r8,qword ptr ds:[r14]第3个参数
0000000140024A4FEB 0Ajmp uniextract-.140024A5B
0000000140024A514D:8D06lea r8,qword ptr ds:[r14]
0000000140024A54EB 05jmp uniextract-.140024A5B
0000000140024A56F241:0F1016movsd xmm2,qword ptr ds:[r14]
0000000140024A5B49:83C6 28add r14,0x28
0000000140024A5F49:FFCDdec r13
0000000140024A6274 56je uniextract-.140024ABA
0000000140024A6449:8B46 10mov rax,qword ptr ds:[r14+0x10]处理第四个参数
0000000140024A6848:83F8 01cmp rax,0x1
0000000140024A6C74 15je uniextract-.140024A83
0000000140024A6E49:8B46 08mov rax,qword ptr ds:[r14+0x8]
0000000140024A7248:83F8 09cmp rax,0x99:'\t'
0000000140024A7674 10je uniextract-.140024A88
0000000140024A7848:83F8 0Acmp rax,0xAA:'\n'
0000000140024A7C74 0Aje uniextract-.140024A88
0000000140024A7E4D:8B0Emov r9,qword ptr ds:[r14]
0000000140024A81EB 0Ajmp uniextract-.140024A8D
0000000140024A834D:8D0Elea r9,qword ptr ds:[r14]
0000000140024A86EB 05jmp uniextract-.140024A8D
0000000140024A88F241:0F101Emovsd xmm3,qword ptr ds:[r14]
0000000140024A8D49:83C6 28add r14,0x28
0000000140024A914C:8D7C24 20lea r15,qword ptr ss:[rsp+0x20]
0000000140024A9649:FFCDdec r13
0000000140024A9974 1Fje uniextract-.140024ABA
0000000140024A9B49:8B46 10mov rax,qword ptr ds:[r14+0x10]处理第五个及后面的参数
0000000140024A9F48:83F8 01cmp rax,0x1
0000000140024AA374 05je uniextract-.140024AAA
0000000140024AA549:8B06mov rax,qword ptr ds:[r14]
0000000140024AA8EB 03jmp uniextract-.140024AAD
0000000140024AAA49:8D06lea rax,qword ptr ds:[r14]
0000000140024AAD49:8907mov qword ptr ds:[r15],rax
0000000140024AB049:83C6 28add r14,0x28
0000000140024AB449:83C7 08add r15,0x8
0000000140024AB8EB DCjmp uniextract-.140024A96
0000000140024ABA49:8B4424 30mov rax,qword ptr ds:[r12+0x30]
0000000140024ABF48:83F8 0Acmp rax,0xAA:'\n'
0000000140024AC374 06je uniextract-.140024ACB
0000000140024AC548:83F8 09cmp rax,0x99:'\t'
0000000140024AC975 13jne uniextract-.140024ADE
0000000140024ACB49:8B0424mov rax,qword ptr ds:[r12]
0000000140024ACFFFD0call rax
0000000140024AD14C:8B65 10mov r12,qword ptr ss:[rbp+0x10]
0000000140024AD5F241:0F114424 28movsd qword ptr ds:[r12+0x28],xmm0
0000000140024ADCEB 0Fjmp uniextract-.140024AED
0000000140024ADE49:8B0424mov rax,qword ptr ds:[r12]
0000000140024AE2FFD0call rax调用API

来到指令地址 0x140024A4C,我们看到 [r14 + 8] 记录的数据长度为4,4个字节,不就是32位吗,程序就是把这个缓冲区当32位使用的。

下面看看哪里给数据长度赋值吧,需要对参数表的长度位 [r14 + 8] 下硬件写入断点,但这段堆栈是程序运行时分配的,每次运行可能都不一样,怎么找这个地址呢?

5、第二次运行  DragQueryFileW 同样也需要解析参数表,与第三次运行  DragQueryFileW 的参数表位于同一段,就用它的数据地址作为参照,事实证明这是可行的。

重启程序,第一次断下在  DragQueryFileW  后,F4来到0x140024A4C,记下这时r14的值(第二次运行  DragQueryFileW 的参数3),然后继续运行再次来到到0x140024A4C,查看r14的值(第三次运行  DragQueryFileW 的参数3),计算出第三次比第二次的地址多0x360。

重启程序,第一次断下在  DragQueryFileW  后,F4来到0x140024A4C,在地址 [r14 + 0x360 + 8] 设置硬件写入断点,并设置断点条件为 byte(98909DE748)==4 (0x98909DE748 为 [r14 + 0x360 + 8] 实际地址),继续执行,最后一次断下的指令如下:

000000014009CC1848:8946 08mov qword ptr ds:[rsi+0x8],rax写入参数数据长度

往上看有很多不同的数据类型,经分析,这一段代码的作用就是按参数的数据类型将参数的长度写入参数堆栈中

现在我们来看看第三次运行  DragQueryFileW 的参数3类型是什么,只要在本段段首 0x14009C370 下断点,看看寄存器的值就知道了

重启程序,第二次断下在  DragQueryFileW  后,指令地址 0x14009C370 下断点,继续运行,我们看到rdx里面是数据类型,共运行了5次,数据分别是 int、hwnd、int、int、int,第一次是 API 返回数据类型,后面四次分别为第1-4个参数类型,可以看到第3个参数定义成了int,在第三个参数数据类型赋值时我们在指令地址 0x14009CC18 处将rax值改为8,第三次断下在 DragQueryFileW 后,看到r8已经传过来64位的地址,继续执行也不闪退了,编辑框中显示出来正确的文件路径,继续执行能够正确解压。

至此,问题已经很明显了,本该是64位的API参数定义成了32位而导致高32地址位丢失,从而导致异常闪退,上面5次参数类型赋值里面的4个int类型按理说应该都设置为int64,只有第3个参数发生异常是因为其他参数的数值较小,都没有超过32位的数值范围所以没有出错。

然后我到 Universal Extractor 的github (https://github.com/Bioruebe/UniExtract2) 去下载老版本的源码 (我分析的这个版本是第三方修改的,没有源码),找到了文件拖动的函数,验证了我的分析是正确的:

; Drag and drop handler for multiple file support

; http://www.autoitscript.com/forum/topic/28062-drop-multiple-files-on-any-control/page__view__findpost__p__635231

Func WM_DROPFILES_UNICODE_FUNC($hWnd, $msgID, $wParam, $lParam)

    #forceref $hWnd, $msgID, $wParam, $lParam

    Local $nSize, $pFileName

    Local $nAmt = DllCall("shell32.dll", "int", "DragQueryFileW", "hwnd", $wParam, "int", 0xFFFFFFFF, "ptr", 0, "int", 255)

    For $i = 0 To $nAmt[0] - 1

        $nSize = DllCall("shell32.dll", "int", "DragQueryFileW", "hwnd", $wParam, "int", $i, "ptr", 0, "int", 0)

        $nSize = $nSize[0] + 1

        $pFileName = DllStructCreate("wchar[" & $nSize & "]")

        DllCall("shell32.dll", "int", "DragQueryFileW", "hwnd", $wParam, "int", $i, "int", DllStructGetPtr($pFileName), "int", $nSize)

        ReDim $gaDropFiles[$i + 1]

        $gaDropFiles[$i] = DllStructGetData($pFileName, 1)

        $pFileName = 0

    Next

;~     _ArrayDisplay($gaDropFiles)

EndFunc

注意第三次调用到 DragQueryFileW 这一句:

DllCall("shell32.dll", "int", "DragQueryFileW", "hwnd", $wParam, "int", $i, "int", DllStructGetPtr($pFileName), "int", $nSize)

这个写法在32位下是没有问题的,原作者也只提供了32位的编译版本,看来原来是没有考虑64位兼容的,第三方修改这个版本编译了64位的版本却没有赋予正确的参数类型,原版的用64位编译也是一样的错误,改成如下后正常:

DllCall("shell32.dll", "int", "DragQueryFileW", "hwnd", $wParam, "int", $i, "int64", DllStructGetPtr($pFileName), "int", $nSize)

AutoIt 的可执行文件由解释器加上加密脚本组成,运行时再解密脚本解释执行,因此无法直接修改二进制文件。

解决方案一:

用“乾坤镜”反编译,将从“opt("GUIOnEventMode", 1)”开始到结束的代码复制覆盖旧版本的相应代码,并按上述方案修改代码后重新编译

解决方案二:

Hook 函数 DragQueryFileW,判断参数3不为0时,赋值如下:

参数3 = 参数1 && 0xffffffff00000000 + 参数3

代码如下:

library version;

//==============================================================================

// DllHijacker for Lazarus By lies

//==============================================================================

{$mode objfpc}{$H+}

uses

  Windows, Classes, jwaWinnt, jwaWinBase;

type

  P_Context = ^T_Context;

  EXCEPTION_POINTERS = record

    ExceptionRecord: ^_EXCEPTION_RECORD64;

    ContextRecord: P_Context;

  end;

  PEXCEPTION_POINTERS = ^EXCEPTION_POINTERS;

  M128A = record

    Low : QWord;

    High : Int64;

  end;

T_Context = record

  P1Home : QWord;

  P2Home : QWord;

  P3Home : QWord;

  P4Home : QWord;

  P5Home : QWord;

  P6Home : QWord;

  ContextFlags : DWord;

  MxCsr : DWord;

  SegCs : word;

  SegDs : word;

  SegEs : word;

  SegFs : word;

  SegGs : word;

  SegSs : word;

  EFlags : DWord;

  Dr0 : QWord;

  Dr1 : QWord;

  Dr2 : QWord;

  Dr3 : QWord;

  Dr6 : QWord;

  Dr7 : QWord;

  Rax : QWord;

  Rcx : QWord;

  Rdx : QWord;

  Rbx : QWord;

  Rsp : QWord;

  Rbp : QWord;

  Rsi : QWord;

  Rdi : QWord;

  R8 : QWord;

  R9 : QWord;

  R10 : QWord;

  R11 : QWord;

  R12 : QWord;

  R13 : QWord;

  R14 : QWord;

  R15 : QWord;

  Rip : QWord;

  Header : array[0..1] of M128A;

  Legacy : array[0..7] of M128A;

  Xmm0 : M128A;

  Xmm1 : M128A;

  Xmm2 : M128A;

  Xmm3 : M128A;

  Xmm4 : M128A;

  Xmm5 : M128A;

  Xmm6 : M128A;

  Xmm7 : M128A;

  Xmm8 : M128A;

  Xmm9 : M128A;

  Xmm10 : M128A;

  Xmm11 : M128A;

  Xmm12 : M128A;

  Xmm13 : M128A;

  Xmm14 : M128A;

  Xmm15 : M128A;

  VectorRegister : array[0..25] of M128A;

  VectorControl : QWord;

  DebugControl : QWord;

  LastBranchToRip : QWord;

  LastBranchFromRip : QWord;

  LastExceptionToRip : QWord;

  LastExceptionFromRip : QWord;

end;

const

  EXCEPTION_CONTINUE_EXECUTION = -1;

  EXCEPTION_CONTINUE_SEARCH = 0;

var

  pFunc: ^NativeUInt;

  hModule: NativeUInt;

  ModHandle: NativeUInt;

  POldGetFileVersionInfoA: Pointer;

  POldGetFileVersionInfoByHandle: Pointer;

  POldGetFileVersionInfoExA: Pointer;

  POldGetFileVersionInfoExW: Pointer;

  POldGetFileVersionInfoSizeA: Pointer;

  POldGetFileVersionInfoSizeExA: Pointer;

  POldGetFileVersionInfoSizeExW: Pointer;

  POldGetFileVersionInfoSizeW: Pointer;

  POldGetFileVersionInfoW: Pointer;

  POldVerFindFileA: Pointer;

  POldVerFindFileW: Pointer;

  POldVerInstallFileA: Pointer;

  POldVerInstallFileW: Pointer;

  POldVerLanguageNameA: Pointer;

  POldVerLanguageNameW: Pointer;

  POldVerQueryValueA: Pointer;

  POldVerQueryValueW: Pointer;

procedure GetFileVersionInfoA; assembler; nostackframe; asm jmp [rip + POldGetFileVersionInfoA] end;

procedure GetFileVersionInfoByHandle; assembler; nostackframe; asm jmp [rip + POldGetFileVersionInfoByHandle] end;

procedure GetFileVersionInfoExA; assembler; nostackframe; asm jmp [rip + POldGetFileVersionInfoExA] end;

procedure GetFileVersionInfoExW; assembler; nostackframe; asm jmp [rip + POldGetFileVersionInfoExW] end;

procedure GetFileVersionInfoSizeA; assembler; nostackframe; asm jmp [rip + POldGetFileVersionInfoSizeA] end;

procedure GetFileVersionInfoSizeExA; assembler; nostackframe; asm jmp [rip + POldGetFileVersionInfoSizeExA] end;

procedure GetFileVersionInfoSizeExW; assembler; nostackframe; asm jmp [rip + POldGetFileVersionInfoSizeExW] end;

procedure GetFileVersionInfoSizeW; assembler; nostackframe; asm jmp [rip + POldGetFileVersionInfoSizeW] end;

procedure GetFileVersionInfoW; assembler; nostackframe; asm jmp [rip + POldGetFileVersionInfoW] end;

procedure VerFindFileA; assembler; nostackframe; asm jmp [rip + POldVerFindFileA] end;

procedure VerFindFileW; assembler; nostackframe; asm jmp [rip + POldVerFindFileW] end;

procedure VerInstallFileA; assembler; nostackframe; asm jmp [rip + POldVerInstallFileA] end;

procedure VerInstallFileW; assembler; nostackframe; asm jmp [rip + POldVerInstallFileW] end;

procedure VerLanguageNameA; assembler; nostackframe; asm jmp [rip + POldVerLanguageNameA] end;

procedure VerLanguageNameW; assembler; nostackframe; asm jmp [rip + POldVerLanguageNameW] end;

procedure VerQueryValueA; assembler; nostackframe; asm jmp [rip + POldVerQueryValueA] end;

procedure VerQueryValueW; assembler; nostackframe; asm jmp [rip + POldVerQueryValueW] end; 

function VectoredHandler(ExceptionInfo: PEXCEPTION_POINTERS): integer; stdcall;

var

  WrongAddr, RightOffs: NativeUInt;

begin

  case ExceptionInfo^.ExceptionRecord^.ExceptionCode of

    EXCEPTION_SINGLE_STEP:

    begin

      if ExceptionInfo^.ExceptionRecord^.ExceptionAddress = QWord(pFunc) then

      begin

        WrongAddr := ExceptionInfo^.ContextRecord^.R8;

        if (WrongAddr <> 0) and ((WrongAddr and $FFFFFFFF) = WrongAddr) then

        begin

          RightOffs := ExceptionInfo^.ContextRecord^.Rcx;

          ExceptionInfo^.ContextRecord^.R8 := RightOffs And $FFFFFFFF00000000 + WrongAddr;

        end;

        ExceptionInfo^.ContextRecord^.Rsp := ExceptionInfo^.ContextRecord^.Rsp - $38;

        ExceptionInfo^.ContextRecord^.Rip := QWord(pFunc) + 4;

        Result := EXCEPTION_CONTINUE_EXECUTION;

        Exit;

      end

      else

      begin

        Result := EXCEPTION_CONTINUE_SEARCH;

        Exit;

      end;

    end

    else

      Result := EXCEPTION_CONTINUE_SEARCH;

  end;

end;

function GetThreadContext64(hThread: HANDLE; var lpContext: T_CONTEXT): BOOL; stdcall;

  external 'kernel32' name 'GetThreadContext';

function SetThreadContext64(hThread: HANDLE; var lpContext: T_CONTEXT): BOOL; stdcall;

  external 'kernel32' name 'SetThreadContext';

function sethwpnt(Parameter: pointer ): NativeUInt; stdcall;

type

  PMianConText = ^T_Context;

var

  MianConText: PMianConText;

  MainHnd: THandle;

begin

  MainHnd := OpenThread(THREAD_ALL_ACCESS, false, NativeUInt(Parameter^));

  New(MianConText);

  SuspendThread(MainHnd);

  MianConText^.ContextFlags := CONTEXT_DEBUG_REGISTERS;

  GetThreadContext64(MainHnd, MianConText^);

  hModule := GetModuleHandle('shell32.dll');

  if hModule = 0 then hModule := LoadLibrary('shell32.dll');

  Pointer(pFunc) := GetProcAddress(hModule, 'DragQueryFileW');

  MianConText^.Dr0 := QWord(pFunc);

  MianConText^.Dr1 := $0;

  MianConText^.Dr2 := $0;

  MianConText^.Dr3 := $0;

  MianConText^.Dr7 := $405;

  SetThreadContext64(MainHnd, MianConText^);

  ResumeThread(MainHnd);

  Dispose(MianConText);

end;

function CreateThread64(lpThreadAttributes: LPSECURITY_ATTRIBUTES;

  dwStackSize: QWORD; lpStartAddress: Pointer; lpParameter: Pointer;

  dwCreationFlags: QWORD; lpThreadId: Pointer): NativeUInt; stdcall; external 'kernel32' name 'CreateThread';

procedure main;

type

  TAddVectoredExceptionHandler = procedure(First: NativeUInt; pFunc: Pointer); stdcall;

  pmainid = ^NativeUInt;

var

  pHnd: TAddVectoredExceptionHandler;

  Proc: function(Parameter: pointer ): NativeUInt; stdcall;

  pid: pmainid;

begin

  hModule := GetModuleHandle('kernel32.dll');

  if hModule = 0 then hModule := LoadLibrary('kernel32.dll');

  Pointer(pHnd) := GetProcAddress(hModule, 'AddVectoredExceptionHandler');

  pHnd(1, @VectoredHandler);

  Proc := @sethwpnt;

  New(pid);

  pid^ := GetCurrentThreadID;

  CreateThread64(nil, 0, Proc, pid, 0, nil);

end;

exports

  GetFileVersionInfoA,

  GetFileVersionInfoByHandle,

  GetFileVersionInfoExA,

  GetFileVersionInfoExW,

  GetFileVersionInfoSizeA,

  GetFileVersionInfoSizeExA,

  GetFileVersionInfoSizeExW,

  GetFileVersionInfoSizeW,

  GetFileVersionInfoW,

  VerFindFileA,

  VerFindFileW,

  VerInstallFileA,

  VerInstallFileW,

  VerLanguageNameA,

  VerLanguageNameW,

  VerQueryValueA,

  VerQueryValueW;

begin

  ModHandle:= LoadLibrary('C:\Windows\System32\version.dll');

  if ModHandle > 0 then

  begin

    POldGetFileVersionInfoA := GetProcAddress(ModHandle, 'GetFileVersionInfoA');

    POldGetFileVersionInfoByHandle := GetProcAddress(ModHandle, 'GetFileVersionInfoByHandle');

    POldGetFileVersionInfoExA := GetProcAddress(ModHandle, 'GetFileVersionInfoExA');

    POldGetFileVersionInfoExW := GetProcAddress(ModHandle, 'GetFileVersionInfoExW');

    POldGetFileVersionInfoSizeA := GetProcAddress(ModHandle, 'GetFileVersionInfoSizeA');

    POldGetFileVersionInfoSizeExA := GetProcAddress(ModHandle, 'GetFileVersionInfoSizeExA');

    POldGetFileVersionInfoSizeExW := GetProcAddress(ModHandle, 'GetFileVersionInfoSizeExW');

    POldGetFileVersionInfoSizeW := GetProcAddress(ModHandle, 'GetFileVersionInfoSizeW');

    POldGetFileVersionInfoW := GetProcAddress(ModHandle, 'GetFileVersionInfoW');

    POldVerFindFileA := GetProcAddress(ModHandle, 'VerFindFileA');

    POldVerFindFileW := GetProcAddress(ModHandle, 'VerFindFileW');

    POldVerInstallFileA := GetProcAddress(ModHandle, 'VerInstallFileA');

    POldVerInstallFileW := GetProcAddress(ModHandle, 'VerInstallFileW');

    POldVerLanguageNameA := GetProcAddress(ModHandle, 'VerLanguageNameA');

    POldVerLanguageNameW := GetProcAddress(ModHandle, 'VerLanguageNameW');

    POldVerQueryValueA := GetProcAddress(ModHandle, 'VerQueryValueA');

    POldVerQueryValueW := GetProcAddress(ModHandle, 'VerQueryValueW');

  end;

  main;

end.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值