- when I convert InBuf asm file to exe, how do I know where the bytes I need start/end in the exe
- how to convert InBuf x32 asm file to x64 asm file
- (also, how to convert bytes in the exe back to an asm file)
see also:
best AutoHotkey machine code functions - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=32242
tl;dr
A function that uses machine code, only works with AHK 32-bit.
Some info about it, in case someone is able to make a 64-bit version.
(Btw any info on writing asm, for asm to exe, for use in AHK functions would be interesting.)
See InBuf by wOxxOm here together with code for and links to other interesting machine code functions:
Machine code binary buffer searching regardless of NULL - Scripts and Functions - AutoHotkey Community
https://autohotkey.com/board/topic/23627-machine-code-binary-buffer-searching-regardless-of-null/
The InBuf function:
Code: Select all
InBuf(haystackAddr, needleAddr, haystackSize, needleSize, StartOffset=0)
{ Static fun
IfEqual,fun,
{
h=
( LTrim join
5589E583EC0C53515256579C8B5D1483FB000F8EC20000008B4D108B451829C129D9410F8E
B10000008B7D0801C78B750C31C0FCAC4B742A4B742D4B74364B74144B753F93AD93F2AE0F
858B000000391F75F4EB754EADF2AE757F3947FF75F7EB68F2AE7574EB628A26F2AE756C38
2775F8EB569366AD93F2AE755E66391F75F7EB474E43AD8975FC89DAC1EB02895DF483E203
8955F887DF87D187FB87CAF2AE75373947FF75F789FB89CA83C7038B75FC8B4DF485C97404
F3A775DE8B4DF885C97404F3A675D389DF4F89F82B45089D5F5E5A595BC9C2140031C0F7D0EBF0
)
VarSetCapacity(fun,StrLen(h)//2)
Loop % StrLen(h)//2
NumPut("0x" . SubStr(h,2*A_Index-1,2), fun, A_Index-1, "Char")
}
Return DllCall(&fun
, "uint",haystackAddr, "uint",needleAddr
, "uint",haystackSize, "uint",needleSize
, "uint",StartOffset)
}
Code: Select all
format PE GUI 4.0
entry start
include 'win32a.inc'
section '.data' data readable writeable
hayStack db '1111111122222111111'
Needle db '22222'
section '.code' code readable executable
start:
push 0 5 19 Needle hayStack
call InBuf
push -1 5 19 Needle hayStack
call InBufRev
invoke ExitProcess,0
proc InBuf stdcall uses ebx ecx edx esi edi, hayStack,Needle,hayStackSize,NeedleSize,StartOffset
local lNeedleRemDwords:DWORD ;(NeedleSize-4)>>2
local lNeedleRemTail:DWORD ;Needle remainder byte count (NeedleSize-4) mod 4 -> (0..3)
local lNeedleRemPtr4:DWORD ;&Needle[4]
pushfd
mov ebx,[NeedleSize]
cmp ebx,0
jle .NotFound
mov ecx,[hayStackSize]
mov eax,[StartOffset]
sub ecx,eax
sub ecx,ebx
inc ecx ;repetitions=hayStackSize-StartOffset-NeedleSize+1
jle .NotFound
mov edi,[hayStack]
add edi,eax ;edi=&(hayStack[StartOffset])
;load Needle FirstByte
mov esi,[Needle]
xor eax,eax
cld
lodsb ; AL=Needle[0], keep EAX now!
;decide on needle length
dec ebx
jz .NeedleLenIs1
dec ebx
jz .NeedleLenIs2
dec ebx
jz .NeedleLenIs3
dec ebx
jz .NeedleLenIs4
dec ebx
jnz .NeedleLenIsLong
;.NeedleLenIs5:
xchg eax,ebx
lodsd ;AL=Needle[0]
xchg eax,ebx ;EBX=bytes 1..5 of Needle
.ScanNeedleLenIs5:
repne scasb
jne .NotFound
cmp [edi],ebx
jne .ScanNeedleLenIs5
jmp .Found
.NeedleLenIs4:
dec esi
lodsd ;EAX=first 4 bytes of Needle
.ScanNeedleLenIs4:
repne scasb
jne .NotFound
cmp [edi-1],eax
jne .ScanNeedleLenIs4
jmp .Found
.NeedleLenIs1:
repne scasb
jne .NotFound
jmp .Found
.NeedleLenIs2:
mov ah,[esi]
.ScanNeedleLenIs2:
repne scasb
jne .NotFound
cmp [edi],ah
jne .ScanNeedleLenIs2
jmp .Found
.NeedleLenIs3:
xchg ebx,eax
lodsw
xchg ebx,eax
.ScanNeedleLenIs3:
repne scasb
jne .NotFound
cmp [edi],bx
jne .ScanNeedleLenIs3
jmp .Found
.NeedleLenIsLong:
; get (needleSize-1)//4, (needleSize-1) mod 4
dec esi ;ESI=&(Needle[0])
inc ebx ;EBX=NeedleSize-4
lodsd ;EAX=first 4 bytes of Needle
mov [lNeedleRemPtr4],esi
mov edx,ebx
shr ebx,2
mov [lNeedleRemDwords],ebx
and edx,3
mov [lNeedleRemTail],edx
xchg ebx,edi ;EBX=save EDI buf ptr for scasb
xchg edx,ecx ;EDX=save ECX counter for scasb
.ScanNeedleLenIsLong:
xchg edi,ebx ;load saved buf ptr
xchg ecx,edx ;load saved counter
.ScanNeedleLenIsLongJustScan:
repne scasb
jne .NotFound
;check all 4 bytes
cmp [edi-1],eax
jne .ScanNeedleLenIsLongJustScan
;check up to Needle's tail
mov ebx,edi
mov edx,ecx
add edi,3
mov esi,[lNeedleRemPtr4]
mov ecx,[lNeedleRemDwords]
test ecx,ecx
jz .ScanNeedleLenIsLongTail
repe cmpsd
jne .ScanNeedleLenIsLong
.ScanNeedleLenIsLongTail:
mov ecx,[lNeedleRemTail]
test ecx,ecx
jz .ScanNeedleLenIsLongFound
repe cmpsb
jne .ScanNeedleLenIsLong
.ScanNeedleLenIsLongFound:
mov edi,ebx ;FOUND!
.Found:
dec edi
mov eax,edi
sub eax,[hayStack]
.popOut:
popfd
ret
.NotFound:
xor eax,eax
not eax
jmp .popOut
endp
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
proc InBufRev stdcall uses ebx ecx edx esi edi, hayStack,Needle,hayStackSize,NeedleSize,StartOffsetOfLastByte
local lNeedleRemDwords:DWORD ;(NeedleSize-4)>>2
local lNeedleRemTail:DWORD ;Needle remainder byte count (NeedleSize-4) mod 4 -> (0..3)
local lNeedleRemPtr4:DWORD ;&Needle[4]
pushfd
mov ebx,[NeedleSize]
cmp ebx,0
jle .NotFound
mov eax,[hayStackSize]
dec eax
mov ecx,[StartOffsetOfLastByte]
cmp ecx,-1
cmovE ecx,eax
cmp eax,ecx
cmovL ecx,eax
sub ecx,ebx
mov edi,ecx
inc ecx ;repetitions=min(hayStackSize-1,StartOffsetOfLastByte)-NeedleSize+2
jle .NotFound
add edi,[hayStack] ;edi=&(hayStack[min(hayStackSize-1,StartOffsetOfLastByte)-NeedleSize+1])
;load Needle FirstByte
mov esi,[Needle]
and eax,0
cld
lodsb ; AL=Needle[0], keep EAX now!
;decide on needle length
dec ebx
jz .NeedleLenIs1
dec ebx
jz .NeedleLenIs2
dec ebx
jz .NeedleLenIs3
dec ebx
jz .NeedleLenIs4
dec ebx
jnz .NeedleLenIsLong
;.NeedleLenIs5:
xchg eax,ebx
lodsd ;AL=Needle[0]
xchg eax,ebx ;EBX=bytes 1..4 of Needle (0-based)
std
.ScanNeedleLenIs5:
repne scasb
jne .NotFound
cmp [edi+2],ebx
jne .ScanNeedleLenIs5
jmp .Found
.NeedleLenIs1:
std
repne scasb
jne .NotFound
jmp .Found
.NeedleLenIs2:
std
mov ah,[esi] ;AH=Needle[1]
.ScanNeedleLenIs2:
repne scasb
jne .NotFound
cmp [edi+2],ah
jne .ScanNeedleLenIs2
jmp .Found
.NeedleLenIs3:
xchg ebx,eax
lodsw
xchg ebx,eax
std
.ScanNeedleLenIs3:
repne scasb
jne .NotFound
cmp [edi+2],bx
jne .ScanNeedleLenIs3
jmp .Found
.NeedleLenIs4:
dec esi
lodsd ;EAX=first 4 bytes of Needle
std
.ScanNeedleLenIs4:
repne scasb
jne .NotFound
cmp [edi+1],eax
jne .ScanNeedleLenIs4
jmp .Found
.NeedleLenIsLong:
; get (needleSize-1)//4, (needleSize-1) mod 4
dec esi ;ESI=&(Needle[0])
inc ebx ;EBX=NeedleSize-4
lodsd ;EAX=first 4 bytes of Needle
mov [lNeedleRemPtr4],esi
mov edx,ebx
shr ebx,2
mov [lNeedleRemDwords],ebx
and edx,3
mov [lNeedleRemTail],edx
xchg ebx,edi ;EBX=save EDI buf ptr for scasb
xchg edx,ecx ;EDX=save ECX counter for scasb
.ScanNeedleLenIsLong:
std
xchg edi,ebx ;load saved buf ptr
xchg ecx,edx ;load saved counter
.ScanNeedleLenIsLongJustScan:
repne scasb
jne .NotFound
;check all 4 bytes
cmp [edi+1],eax
jne .ScanNeedleLenIsLongJustScan
;check up to Needle's tail
cld
mov ebx,edi
mov edx,ecx
add edi,5
mov esi,[lNeedleRemPtr4]
mov ecx,[lNeedleRemDwords]
test ecx,ecx
jz .ScanNeedleLenIsLongTail
repe cmpsd
jne .ScanNeedleLenIsLong
.ScanNeedleLenIsLongTail:
mov ecx,[lNeedleRemTail]
test ecx,ecx
jz .ScanNeedleLenIsLongFound
repe cmpsb
jne .ScanNeedleLenIsLong
.ScanNeedleLenIsLongFound:
mov edi,ebx ;FOUND!
.Found:
inc edi
mov eax,edi
sub eax,[hayStack]
.popOut:
popfd
ret
.NotFound:
xor eax,eax
not eax
jmp .popOut
endp
data import
library kernel32,'KERNEL32.DLL'
import kernel32,ExitProcess,'ExitProcess'
end data
flat assembler
http://flatassembler.net/
(When I first tried to compile the asm to exe, it said that is was missing include files, I moved FASM.EXE to the INCLUDE folder and it worked.)
I compiled simply by doing: Run, "%vPathFASM%" "%vPathAsm%".
I read the contents of the exe file as a hex string.
The required hex string used in the function was in the exe file, however I would not have known which bytes to copy and paste into the function.
The resulting exe was 2048 bytes in size: 1074+224+750, the required code of 224 bytes began at 1074 bytes.
5589E583EC0C53515256579C8B5D1483FB000F8EC20000008B4D108B451829C129D9410F8EB10000008B7D0801C78B750C31C0FCAC4B742A4B742D4B74364B74144B753F93AD93F2AE0F858B000000391F75F4EB754EADF2AE757F3947FF75F7EB68F2AE7574EB628A26F2AE756C382775F8EB569366AD93F2AE755E66391F75F7EB474E43AD8975FC89DAC1EB02895DF483E2038955F887DF87D187FB87CAF2AE75373947FF75F789FB89CA83C7038B75FC8B4DF485C97404F3A775DE8B4DF885C97404F3A675D389DF4F89F82B45089D5F5E5A595BC9C2140031C0F7D0EBF0
Btw does anyone have any recommended tools for asm to exe, or exe to asm.
Also I haven't found too much on AHK and machine code except:
MCode Tutorial (Compiled Code in AHK) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=32
[EDIT:]
I have often used InBuf to search through binary data in the address space.
RegExMatch can only search for an even number of bytes at even byte intervals, so you could run a RegExMatch search twice, altering/cropping the search needle as required. (This can be a problem though, especially on a needle of under 10 bytes.)
RegEx, however, has the advantage of being able to search case insensitive.
Btw also, what is the best method, for opening binary data, and replacing null bytes with spaces.
Btw I have a file searcher, and it is complete apart from that I would be interested in the best methods for searching for text/data.
E.g. binary data / ANSI/UTF-8/UTF-16 LE case sensitive/insensitive.
A function like this could do binary data, and case insensitive text, 2 runs of RegEx could do UTF-16 LE (text offset at even/odd bytes), but I'm not sure about ANSI/UTF-8 case insensitive.
Thanks.
[EDIT:] See the BINARY DATA section, here, for more binary-related links:
jeeswg's homepage - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=17&t=30931&p=144437#p144437