tl;dr 2 how to convert the example ASM below from x32 to x64
tl;dr 3 people are welcome to comment generally about AutoHotkey, machine code, and FASM
- I have seen one example on the forums so far of ASM to machine code.
InBuf function currently 32-bit only (machine code binary buffer searching) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=28393
- Do share any others.
- ASM code is converted to machine code, and the machine code is used with DllCall to perform an action. For this particular example, it searches binary data for a binary needle, in a similar way to the InStr function.
- This example works on AHK x32 only:
Code: Select all
q:: ;test InBuf function
VarSetCapacity(vData, 100, 0)
VarSetCapacity(vDataN, 4, 0)
NumPut(0x12345678, &vData, 90, "UInt")
NumPut(0x12345678, &vDataN, 0, "UInt")
MsgBox, % InBuf(&vData, &vDataN, 100, 4) ;90
return
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)
}
- First we copy the ASM code to a file, let's call it InBuf.asm.
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.
Code: Select all
[start of file]
4D5A80000100000004001000FFFF00004001000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0A240000000000000000504500004C010200EB2E005B0000000000000000E0000F010B010147000400000002000000000000002000000020000000100000000040000010000000020000010000000000000004000000000000000030000000020000396E00000200000000100000001000000000010000000000000000001000000000000000000000000E22000054000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E6461746100000018000000001000000002000000020000000000000000000000000000400000C02E636F64650000006202000000200000000400000004000000000000000000000000000020000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031313131313131313232323232313131313131323232323200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006A006A056A1368131040006800104000E81D0000006AFF6A056A1368131040006800104000E8E80000006A00FF154C224000
[hex for InBuf]
5589E583EC0C53515256579C8B5D1483FB000F8EC20000008B4D108B451829C129D9410F8EB10000008B7D0801C78B750C31C0FCAC4B742A4B742D4B74364B74144B753F93AD93F2AE0F858B000000391F75F4EB754EADF2AE757F3947FF75F7EB68F2AE7574EB628A26F2AE756C382775F8EB569366AD93F2AE755E66391F75F7EB474E43AD8975FC89DAC1EB02895DF483E2038955F887DF87D187FB87CAF2AE75373947FF75F789FB89CA83C7038B75FC8B4DF485C97404F3A775DE8B4DF885C97404F3A675D389DF4F89F82B45089D5F5E5A595BC9C2140031C0F7D0EBF0
[hex for InBufRev]
5589E583EC0C53515256579C8B5D1483FB000F8EDE0000008B4510488B4D1883F9FF0F44C839C80F4CC829D989CF410F8EC1000000037D088B750C83E000FCAC4B74224B742A4B74354B74434B754E93AD93FDF2AE0F859B000000395F0275F3E981000000FDF2AE0F8588000000EB76FD8A26F2AE757F38670275F7EB689366AD93FDF2AE756F66395F0275F6EB574EADFDF2AE756039470175F7EB494E43AD8975FC89DAC1EB02895DF483E2038955F887DF87D1FD87FB87CAF2AE753839470175F7FC89FB89CA83C7058B75FC8B4DF485C97404F3A775DC8B4DF885C97404F3A675D189DF4789F82B45089D5F5E5A595BC9C2140031C0F7D0EBF0
[end of file]
442200000000000000000000362200004C22000000000000000000000000000000000000000000004B45524E454C33322E444C4C00005422000000000000542200000000000000004578697450726F6365737300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
- How to identify where the machine code starts/ends.
- How to convert the asm above to 64-bit.
Links:
- There are various links here. There is also a note re. converting exe to asm via OllyDbg.
InBuf function currently 32-bit only (machine code binary buffer searching) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 17#p219717