afan 发表于 2019-9-17 23:19:39

本帖最后由 afan 于 2019-9-18 11:36 编辑

chishingchan 发表于 2019-9-17 21:57
老大,顶楼的附件已换了

以下代码已完善至26#

MsgBox(0, '', _BinarySearch('snapshot.exe', '0x534E415345524E554D008F0A'))

Func _BinarySearch($FilePath, $sBin)
      If StringLeft($sBin, 2) = '0x' Then $sBin = StringTrimLeft($sBin, 2)

      Local $hFile = _WinAPI_CreateFile($FilePath, 2, 2, 1)
      If Not $hFile Then Return SetError(1)
      Local $Result = _WinAPI_SetFilePointer($hFile, 0)

      Local $Buffer = DllStructCreate('byte')
      Local $ptr = DllStructGetPtr($Buffer)
      Local $Read, $Pos
      Do
                $Read = 0
                $Result = _WinAPI_ReadFile($hFile, $ptr, 1024, $Read)
                If Not $Result Then
                        _WinAPI_CloseHandle($hFile)
                        Return SetError(2)
                EndIf
                $Result = StringTrimLeft(DllStructGetData($Buffer, 1), 2)
                $Result = StringInStr($Result, $sBin)
                If $Result > 0 Then
                        $Result = ($Result - 1) / 2
                        ExitLoop
                EndIf
                $Pos += $Read
      Until 0

      _WinAPI_CloseHandle($hFile)
      If Not $Result Then Return SetError(3)
      Return $Pos + $Result
EndFunc   ;==>_BinarySearch

afan 发表于 2019-9-17 23:21:05

晕倒搞了半天原来是有人在后台搞动作代码标签没了

zch11230 发表于 2019-9-17 23:30:32

压成ZIP不就好了么。老少皆宜

繁星 发表于 2019-9-18 00:55:22

afan 发表于 2019-9-17 23:19


A大这样定义,如果碰到查找的数据刚好在上组和下组之间呢,还需要再将上次读取的数据连接当前的查找一次{:face (460):}

haijie1223 发表于 2019-9-18 01:28:01

afan 发表于 2019-9-17 23:19


a版辛苦了,stringinstr完全可以啊,楼主非要挖坑
MsgBox(0, 0, _BinarySearch2($File, $Hex))
Func _BinarySearch2($sFile, $sBin)
        If Not FileExists($sFile) Then Return SetError(1, 0, -1)       
        Local $hFile = FileOpen($sFile, 16)
        Local $bData = FileRead($hFile)
        FileClose($hFile)
        Local $ipos = StringInStr(StringTrimLeft($bData,2), StringTrimLeft($sBin, 2))
        If Not @error Then Return ($ipos - Mod($ipos, 2)) / 2
        Return SetError(2, 0, -1)
EndFunc   ;==>_BinarySearch2

绿色风 发表于 2019-9-18 02:48:26

afan 发表于 2019-9-17 23:21
晕倒搞了半天原来是有人在后台搞动作代码标签没了

折腾插件,最开始,搞的 code  au3 不能共存。

现在Ok的了,不影响之前的。 标签 pre

afan 发表于 2019-9-18 07:12:04

繁星 发表于 2019-9-18 00:55
A大这样定义,如果碰到查找的数据刚好在上组和下组之间呢,还需要再将上次读取的数据连接当前的查找一次{ ...

有这问题没完善

afan 发表于 2019-9-18 07:16:15

haijie1223 发表于 2019-9-18 01:28
a版辛苦了,stringinstr完全可以啊,楼主非要挖坑

我是一直用stringinstr查找定值二进制数据的,不过查找的位置和他的不同,以为不是他需要的,没想到mod一下就行,阿杰帅如发哥

afan 发表于 2019-9-18 07:18:16

绿色风 发表于 2019-9-18 02:48
折腾插件,最开始,搞的 code  au3 不能共存。

现在Ok的了,不影响之前的。 标签 pre
...

奈斯 辛苦了~

chishingchan 发表于 2019-9-18 07:33:43

谢谢两位老大!

afan 发表于 2019-9-18 11:17:25

本帖最后由 afan 于 2019-9-18 11:33 编辑

对于大文件,一次性读取再匹配还是存在效率问题的,因此,分段读取还是有必要,特别是搜索的数据越靠前优势越大,因此完善了一下
#include-once
#include <WinAPI.au3>

Func _BinarySearch($FilePath, $sBin)
      If StringLeft($sBin, 2) = '0x' Then $sBin = StringTrimLeft($sBin, 2)

      Local $hFile = _WinAPI_CreateFile($FilePath, 2, 2, 1)
      If Not $hFile Then Return SetError(1)
      Local $Result = _WinAPI_SetFilePointer($hFile, 0)

      Local $Buffer = DllStructCreate('byte')
      Local $ptr = DllStructGetPtr($Buffer)
      Local $len = StringLen($sBin)
      Local $Read, $last = '', $_Result, $iPos
      Do
                $Read = 0
                $Result = _WinAPI_ReadFile($hFile, $ptr, 1024, $Read)
                If Not $Result Then
                        _WinAPI_CloseHandle($hFile)
                        Return SetError(2)
                EndIf
                If ($Read / 2) < $len Then
                        _WinAPI_CloseHandle($hFile)
                        Return -1
                EndIf
               
                $Result = StringTrimLeft(DllStructGetData($Buffer, 1), 2)
                $_Result = StringInStr($Result, $sBin)
                If $_Result > 0 Then
                        $_Result = ($_Result - 1) / 2
                        ExitLoop
                Else
                        $_Result = $last & StringMid($Result, 1, $len)
                        $_Result = StringInStr($_Result, $sBin)
                        If $_Result > 0 Then
                              $_Result = ($_Result - 1) / 2
                              $iPos -= $len / 2
                              ExitLoop
                        Else
                              $last = StringMid($Result, 1024 * 2 - $len + 1)
                        EndIf
                EndIf
                $iPos += $Read
      Until 0

      _WinAPI_CloseHandle($hFile)
      If Not $_Result Then Return SetError(3)
      Return $iPos + $_Result
EndFunc   ;==>_BinarySearch

cashiba 发表于 2019-9-18 13:16:16

难得这么多高手一起粗现....
:face (7):

bemylife 发表于 2019-9-25 14:19:15

不错不错,学习了

tubaba 发表于 2019-9-27 10:32:01

与A版一样,下面这个是替换二进制文件字符串,修改未压缩的autoit程序中类窗口别名


#Region ;**** 由 AccAu3Wrapper_GUI 创建指令 ****
#AccAu3Wrapper_Icon=water_melon.ico
#AccAu3Wrapper_Outfile=Compresspackage.exe
#AccAu3Wrapper_UseX64=n
#AccAu3Wrapper_Res_Language=2052
#AccAu3Wrapper_Res_requestedExecutionLevel=None
#EndRegion ;**** 由 AccAu3Wrapper_GUI 创建指令 ****
#include <math.au3>
#include <file.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <Constants.au3>
#include <WinAPI.au3>
#include '_Res.au3'
DllCall('User32.dll', 'BOOL', 'ChangeWindowMessageFilter', 'UINT', 0x0233, 'DWORD', 1)
DllCall('User32.dll', 'BOOL', 'ChangeWindowMessageFilter', 'UINT', 0x0049, 'DWORD', 1)
Global $aDroppedFiles
Global $sSearchStr = 'AutoIt v3 GUI'
Global $rReplaceStr = 'Tubaba GUI'
Global $hGUI = GUICreate('Autoit Exe类名修改', 200, 80, -1, -1, BitOR($WS_POPUPWINDOW, $WS_CAPTION), BitOR($GUI_WS_EX_PARENTDRAG, $WS_EX_ACCEPTFILES))
Global $iButton = GUICtrlCreateButton('打開', 40, 37, 120, 40)
Global $iPic = GUICtrlCreatePic('', 0, 0, 200, 80, BitOR($SS_NOTIFY, $WS_GROUP, $WS_BORDER, $WS_CLIPSIBLINGS), $GUI_WS_EX_PARENTDRAG)
GUICtrlSetState(-1, $GUI_DROPACCEPTED)
GUISetState(@SW_SHOW)
WinSetOnTop($hGUI, '', 1)
GUIRegisterMsg(0x0233, "WM_DROPFILES")

While 1
        $msg = GUIGetMsg()
        Select
                Case $msg = -3
                        Exit
                Case $msg = $iButton
                        $OpenFile = FileOpenDialog('目标文件', @ScriptDir & '\', '所有文件(*.*)', 1 + 2, '', $hGUI)
                        If @error Then ContinueLoop
                        _Check($OpenFile)
                Case $msg = $GUI_EVENT_DROPPED
                        $OpenFile = $aDroppedFiles
                        _Check($OpenFile)
        EndSelect
WEnd

Func _Check($OpenFile)
        Local $szDrive, $szDir, $szFName, $szExt
        Local $TestPath = _PathSplit($OpenFile, $szDrive, $szDir, $szFName, $szExt)
        Local $UpxPath = _UpxBin()
        Local $sCmd = @ComSpec & ' /c ""' & $UpxPath & '"'
        $sCmd &= ' -t ' & '"' & $OpenFile & '"'
        Local $res = _Std($sCmd)
        Switch $res
                Case 1
                        If StringInStr($res, 'NotPackedException: not packed by UPX') Then
                                _Patch($OpenFile)
                        EndIf
                Case 0
                        If StringInStr($res, 'Tested 1 file') Then
                                Local $TipPos
                                _WindowGetPos($hGUI, $TipPos)
                                ToolTip('正在备份程序->"' & $OpenFile & '"', $TipPos, $TipPos, Default, 0, 4)
                                FileCopy($OpenFile, $TestPath & $TestPath & $TestPath & $TestPath & '.packed', 1)
                                _WindowGetPos($hGUI, $TipPos)
                                ToolTip('正在备份程序->"' & $OpenFile & '"', $TipPos, $TipPos, Default, 0, 4)
                                $sCmd = @ComSpec & ' /c ""' & $UpxPath & '"'
                                $sCmd &= ' -d ' & '"' & $OpenFile & '"'
                                Local $res1 = _Std($sCmd)
                                Switch $res1
                                        Case 0
                                                If StringInStr($res1, 'Unpacked 1 file') Then
                                                        _Patch($OpenFile)
                                                EndIf
                                EndSwitch
                        EndIf
                Case Else
                        MsgBox(0, 0, 1)
        EndSwitch
;~         _Patch($OpenFile)
EndFunc   ;==>_Check

Func _Patch($OpenFile)
        WinSetTitle($hGUI, '', '正在處理..' & $OpenFile)
        Local $hFile, $sText, $nBytes, $tBuffer, $Replaced, $TipPos
        Local $szDrive, $szDir, $szFName, $szExt
        Local $TestPath = _PathSplit($OpenFile, $szDrive, $szDir, $szFName, $szExt)
        $hFile = FileOpen($OpenFile, 16)
        $sText = FileRead($hFile)
        FileClose($hFile)
        If Not StringInStr($sText, _Str2UnicodeStr($sSearchStr)) Then
                _WindowGetPos($hGUI, $TipPos)
                ToolTip('无法识别->"' & $OpenFile & '"', $TipPos, $TipPos, Default, 0, 4)
                AdlibRegister('_CloseToolTip', 3000)
                        WinSetTitle($hGUI, '', 'Compresspackage')
                Return SetError(1, 0, 0)
        EndIf
        _WindowGetPos($hGUI, $TipPos)
        ToolTip('正在备份程序->"' & $OpenFile & '"', $TipPos, $TipPos, Default, 0, 4)
        FileCopy($OpenFile, $TestPath & $TestPath & $TestPath & $TestPath & '.bak', 1)
        _WindowGetPos($hGUI, $TipPos)
        ToolTip('正在修补程序->"' & $OpenFile & '"', $TipPos, $TipPos, Default, 0, 4)
        $tBuffer = DllStructCreate("byte[" & BinaryLen($sText) & "]")
        $Search = _Str2UnicodeStr($sSearchStr)
        $Replace = _Str2UnicodeStr($rReplaceStr)
        If StringLen($Search) > StringLen($Replace) Then
                Do
                        $Replace = $Replace & '0'
                Until StringLen($Replace) = StringLen($Search)
                ElseIf StringLen($Search) < StringLen($Replace) Then
                $Replace = StringMid($Replace,1,StringLen($Search))
        EndIf
       
       
       
       
        $Replaced = StringReplace($sText, $Search, $Replace)
        DllStructSetData($tBuffer, 1, $Replaced)
        $hFile = _WinAPI_CreateFile($OpenFile, 2)
        _WinAPI_WriteFile($hFile, DllStructGetPtr($tBuffer), BinaryLen($Replaced), $nBytes)
        _WinAPI_CloseHandle($hFile)
        WinSetTitle($hGUI, '', 'Compresspackage')
        ToolTip('')
        _MSGBOXEX($hGUI, 0, '', '完成')
EndFunc   ;==>_Patch

Func _Str2UnicodeStr($Str)
        Local $Return='',$n = 1
        $Return = StringTrimLeft(StringToBinary($Str,2),2)
        Return $Return
EndFunc

Func _CloseToolTip()
        AdlibUnRegister('_CloseToolTip')
        ToolTip('')
EndFunc   ;==>_CloseToolTip

Func WM_DROPFILES($hWnd, $msgID, $wParam, $lParam)
        Local $nSize, $pFileName
        Local $nAmt = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", 0xFFFFFFFF, "ptr", 0, "int", 255)
        $aDroppedFiles = 0
        Dim $aDroppedFiles[$nAmt + 1]
        For $i = 0 To $nAmt - 1
                $nSize = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", 0, "int", 0)
                $nSize = $nSize + 1
                $pFileName = DllStructCreate("char[" & $nSize & "]")

                DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", _
                                DllStructGetPtr($pFileName), "int", $nSize)
                $aDroppedFiles += 1
                $aDroppedFiles[$aDroppedFiles] = DllStructGetData($pFileName, 1)
                $pFileName = 0
        Next
        ReDim $aDroppedFiles[$aDroppedFiles + 1]
EndFunc   ;==>WM_DROPFILES

Func _MSGBOXEX($hWnd, $flag, $title, $text, $timeout = 0) ;hook msgbox
        Local $hInst = _WinAPI_GetWindowLong($hWnd, $GWL_HINSTANCE)
        Local $iThreadId = _WinAPI_GetCurrentThreadId()
        Local $hCallBack = DllCallbackRegister("_CallBack", "int", "int;hWnd;hWnd")
        Local $pCallBack = DllCallbackGetPtr($hCallBack)
        Local $hHook = _WinAPI_SetWindowsHookEx($WH_CBT, $pCallBack, $hInst, $iThreadId)
        Local $Mkmsg = MsgBox($flag, $title, $text, $timeout, $hWnd)
        _WinAPI_UnhookWindowsHookEx($hHook)
        DllCallbackFree($hCallBack)
        Return $Mkmsg
EndFunc   ;==>_MSGBOXEX

Func _CallBack($iCode, $wParam, $lParam)
        ;If ($iCode = 5) And ($wParam <> $hGUI) Then
        If ($iCode = $WH_CBT) And (_WinAPI_GetParent($wParam) > 0) Then
                Local $WINDOWRECT = DllStructCreate($tagRECT)
                Local $MSGBOXRECT = DllStructCreate($tagRECT)
                Local $WINDOWRECT = _WinAPI_GetWindowRect(_WinAPI_GetParent($wParam))
                Local $MSGBOXRECT = _WinAPI_GetWindowRect($wParam)
                Local $WLeft = DllStructGetData($WINDOWRECT, 'Left')
                Local $WTop = DllStructGetData($WINDOWRECT, 'Top')
                Local $WRight = DllStructGetData($WINDOWRECT, 'Right')
                Local $WBottom = DllStructGetData($WINDOWRECT, 'Bottom')
                Local $MLeft = DllStructGetData($MSGBOXRECT, 'Left')
                Local $MTop = DllStructGetData($MSGBOXRECT, 'Top')
                Local $MRight = DllStructGetData($MSGBOXRECT, 'Right')
                Local $MBottom = DllStructGetData($MSGBOXRECT, 'Bottom')


                Local $X = $WLeft + (($WRight - $WLeft) - ($MRight - $MLeft)) / 2
                Local $Y = $WTop + (($WBottom - $WTop) - ($MBottom - $MTop)) / 2
                WinMove($wParam, "", $X, $Y, Default, Default)

        EndIf
        Return 0
EndFunc   ;==>_CallBack

Func _WindowGetPos($hWnd, ByRef $aArray)
        Local $tRect = _WinAPI_GetWindowRect($hWnd)
        Local $cLeft = DllStructGetData($tRect, 'Left')
        Local $cTop = DllStructGetData($tRect, 'Top')
        Local $cRight = DllStructGetData($tRect, 'Right')
        Local $cBottom = DllStructGetData($tRect, 'Bottom')
        $aArray = $cLeft
        $aArray = $cBottom
EndFunc   ;==>_WindowGetPos

Func _Std($cmdline)
        Local $res, $line, $sout, $serr
        Local $pid = Run($cmdline, @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
        ProcessWaitClose($pid)
        While 1
                $line = StdoutRead($pid,False,True)
                If @error Then ExitLoop
                $sout &= $line
        WEnd
        While 1
                $line = StderrRead($pid,False,True)
                If @error Then ExitLoop
                $serr &= $line
        WEnd
        StdioClose($pid)
        If Not $serr = '' And Not $pid = 0 Then
                $res = 1
                $Res = BinaryToString($serr)
        Else
                $res = 0
                $Res = BinaryToString($sout)
        EndIf
        Return $res
EndFunc   ;==>_Std


页: 1 [2]
查看完整版本: 【已解决】关于在可执行文件中查找数据