Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 07/18/2025 in Posts

  1. mr-es335

    Total Path Length

    ioa747, You have come through again...and "with flying colours"!! I kinda' figur'd that the issue had to do with path length...just not sure how to correct the anomaly. All tested and working as expected! Thank you again...for your time, attention and patience to the above. All are very much appreciated! • ios747, yo9u are indeed a true blessing to this forum!
    1 point
  2. The idea is to be able to share information in the forum when a struct data needs to be shared among us. As an example, lets say that we wanna share what comes out of $tagOSVERSIONINFOEX. We could just run: #include <WinAPIMisc.au3> #include <WinAPIDiag.au3> #include <Debug.au3> #include <Sqlite.au3> Exit GetOs() Func GetOs() Local $tOSVERSIONINFOEX = DllStructCreate($tagOSVERSIONINFOEX) DllStructSetData($tOSVERSIONINFOEX, 1, DllStructGetSize($tOSVERSIONINFOEX)) Local $aCall = DllCall('kernel32.dll', 'bool', 'GetVersionExW', 'struct*', $tOSVERSIONINFOEX) If @error Or Not $aCall[0] Then Return SetError(@error, @extended, 0) Local $aArray = _WinAPI_DisplayStruct_mod($tOSVERSIONINFOEX, $tagOSVERSIONINFOEX, '', 0, 0, 0, True, 0, 1) Local $sText = _SQLite_Display2DResult($aArray, 0, True) ConsoleWrite(@CRLF & $sText & @CRLF & @CRLF) ; for those outside the editor Local $iW = 600, $iH = 300, $hGui = GUICreate(@ScriptName, $iW, $iH) GUISetFont(10, 400, 0, "Terminal") Local $idEdit = GUICtrlCreateEdit($sText, 0, 0, $iW, $iH) GUISetState() While GUIGetMsg() <> -3 WEnd GUIDelete($hGui) EndFunc ;==>GetOs ... ... and share the text that comes out: - - 0x0125DC18 <struct> 0 - 1 OSVersionInfoSize 0 DWORD 4 284 2 MajorVersion 4 DWORD 4 10 3 MinorVersion 8 DWORD 4 0 4 BuildNumber 12 DWORD 4 22631 5 PlatformId 16 DWORD 4 2 6 CSDVersion 20 WCHAR[128] 256 7 ServicePackMajor 276 USHORT 2 0 8 ServicePackMinor 278 USHORT 2 0 9 SuiteMask 280 USHORT 2 256 10 ProductType 282 BYTE 1 1 11 Reserved 283 BYTE 1 - - - 0x0125DD34 <endstruct> 284 - So the mod. I made to _WinAPI_DisplayStruct() is here ( with the complete running example from above ) This way is easier to share such. I know this is a lazy way to do it but, is a fast mod. and does what is needed to get the data as text.
    1 point
  3. I updated this with a couple new functions to make compiling and debugging variables easier. _fasmg_CompileAu3 will generate the au3 code needed for a standalone function without the library and place it on the clipboard. It will also encode/compress the opcode and generate the required code to decode/decompress, but only if its worth it. If the amount of extra au3 code it takes to decode is more than the number of characters saved from encoding, then I dont see the point. Below is the input/output you would get from the first example where base64 would not be worth it. The base64 saves us about 20 characters in the opcode, but even with a single one liner (with length precalculated when compiled) to decode the string its about 170 character long so for this example it would pick base16. Input: _('procf _main, pConsoleWriteCB, parm1, parm2') _(' mov edx, [parm1]') _(' add edx, [parm2]') _(' invoke pConsoleWriteCB, "edx = ", edx') ; _(' ret') _('endp') _fasmg_compileau3($g_sFasm) Output: ;base16 Local Static $dBinExec = Binary('0x5589E58B550C03551052E807000000656478203D2000FF5508C9C20C00') Local Static $tBinExec = DllStructCreate('byte[' & BinaryLen($dBinExec) & ']'), $bSet = DllStructSetData($tBinExec, 1, $dBinExec) Local Static $aProtect = DllCall('kernel32.dll', 'bool', 'VirtualProtect', 'struct*', $tBinExec, 'dword_ptr', DllStructGetSize($tBinExec), 'dword', 0x40, 'dword*', 0) Local Static $aFlush = DllCall('kernel32.dll', 'bool', 'FlushInstructionCache', 'handle', (DllCall('kernel32.dll', 'handle', 'GetCurrentProcess')[0]), 'struct*', $tBinExec, 'dword_ptr', DllStructGetSize($tBinExec)) ;base64 Local Static $sBinExec = 'VYnli1UMA1UQUugHAAAAZWR4ID0gAP9VCMnCDAA=' Local Static $aDec = DllCall('Crypt32.dll', 'bool', 'CryptStringToBinary', 'str', $sBinExec, 'dword', Null, 'dword', 1, 'struct*', DllStructCreate('byte[' & 29 & ']'), 'dword*', 29, 'ptr', 0, 'ptr', 0) Local Static $tBinExec = DllStructCreate('byte[' & $aDec[5] & ']', DllStructGetPtr($aDec[4])) Local Static $aProtect = DllCall('kernel32.dll', 'bool', 'VirtualProtect', 'struct*', $tBinExec, 'dword_ptr', DllStructGetSize($tBinExec), 'dword', 0x40, 'dword*', 0) Local Static $aFlush = DllCall('kernel32.dll', 'bool', 'FlushInstructionCache', 'handle', (DllCall('kernel32.dll', 'handle', 'GetCurrentProcess')[0]), 'struct*', $tBinExec, 'dword_ptr', DllStructGetSize($tBinExec)) _fasmg_Debug is the other much needed function that has been added. Ive gotten annoyed with copying callbacks from script to script just to debug and wanted something native that could handle all the basics. The function inserts ptr's to callbacks directly into the code so you cant use it in a compiled function but you wouldnt want to do that anyway. This also makes it so we dont have to pass the callback as a parameter. I have 4 callbacks setup that I think covers all my bases but let me know if not. The function excepts a comma delimited string of "type:var" parings using ":" operator to pair and will generate asm code to call the correct callback. The function excepts all autoit types allowed for dllcall and actually uses the literal string specifying the type to dynamically register a function for that variable type. I didn't always know this (never really needed to) but apparently we can register the same autoit function multiple times with DllCallbackRegister specifying different parameter types with each registration. With that functionality Im able to just create a "wildcard" type function and register the types as needed so that one callback covers most situations. The other 3 callbacks cover dll structures, raw quoted strings (no variable specified), and lastly references (ex: int*). For whatever reason, specifying the parameters in the callback as references doesn't work out right and doesn't deference so to get around that I send it to a function that creates a dllstruct at the pointer address and access it that way. I also added ability to specify hi/low values using the '|' operator. So "int64:eax|edx" would show you the combined 64bit value of eax and edx. For dll structures I made a made modified (basically a copy) version of _winapi_displaystruct that will print the data to the console instead of showing you listview. Despite the length of that function, it was actually real easy to modify by just replacing all the GUICtrlCreateListViewItem statements with _addarray() to turn it into a 2darray. All the statements are already deliminted with '|' so that worked out nice. I then pass that 2darray to _Array2DToFormatedStr() to convert and format the alignment of all the columns based on longest element in that column before printing so we have a nice table. The dashes help out with the colors too. Here is the output from the example in the helpfile: Debug Example: $_dbg = _fasmg_Debug ; (shortcut) $sTag = 'byte x;short y;char sNote[13];long odd[3];word w;dword p;char ext[3];word finish' _(_fasmg_Au3StructDef('AU3TEST', $sTag)) _('procf _main, parm1, parm2') _(' locals') _(' iTestSigned dd -12345') _(' iTestUnsigned dd 1234567') _(' stest db "This is a local string test",0') _(' sBuffer db 128 dup ?') _(' tTest AU3TEST x:11,y:22,sNote:"Test Msg",odd:333,odd+4:444,odd+8:555,w:77,p:6666,ext:"exe",finish:1234') ; _(' endl') _(" xor eax, eax") ; eax = 0 _(' mov bl, 13') ; bl = 13 _($_dbg('str:"#########################"')) ;; raw string - no variable specified _($_dbg('int:[iTestSigned]')) ; signed test _($_dbg('uint:[iTestUnsigned]')) ; unsigned test _(" cpuid") ; places cpuid string in ebx:ecx:edx _(" lea edi, [sBuffer]") ; Load address (ptr) of sBuffer into edi _(" mov [edi], ebx") ; first 4 chars of cpuid _(" mov [edi + 4], edx") ; _(" mov [edi + 8], ecx") _(" mov dword[edi + 12], 0") _($_dbg('str:edi')) ; will print cpuid string. Edi is holding ptr to local var "sBuffer" _(' mov edx, [parm1]') _(' add edx, [parm2]') _($_dbg('struct:addr tTest:' & $sTag)) ; printing structure. Only type that expects an extra ':' to specify "$sTag" _(' mov ebx, 77') _(' rdtsc') _($_dbg('str:"-----------------------"')) _($_dbg('uint*:addr iTestUnsigned')) ;testing passing a reference to it _($_dbg('uint:[iTestUnsigned]')) ; should be same _($_dbg('str:"-----------------------"')) _(' rdtsc') ; this places 64bit timestamp value in eax|edx _($_dbg('dword:ebx,uint:[iTestUnsigned],str:addr stest,dword:eax,uint64:eax|edx')); debugging multiple vars. printing 64bit timestamp stored in eax|edx _(' rdtsc') _($_dbg('uint64:eax|edx,dword:[parm1]')) _(' ret') _('endp') Console Output: ######################### [iTestSigned]: -12345 [iTestUnsigned]: 1234567 edi: GenuineIntel Struct addr tTest: ==================================================================== # Member Offset Type Size Value ==================================================================== - - 0x005EF118 <struct> 0 - 1 x 0 BYTE 1 11 - - - <alignment> 1 - 2 y 2 short 2 22 3 sNote 4 CHAR[13] 13 Test Msg - - - <alignment> 3 - 4 odd 20 long[3] 12 (4) [1] 333 - - 24 - - [2] 444 - - 28 - - [3] 555 5 w 32 WORD 2 77 - - - <alignment> 2 - 6 p 36 DWORD 4 6666 7 ext 40 CHAR[3] 3 exe - - - <alignment> 1 - 8 finish 44 WORD 2 1234 - - - <alignment> 2 - - - 0x005EF148 <endstruct> 48 - ==================================================================== ----------------------- iTestUnsigned*: 1234567 [iTestUnsigned]: 1234567 ----------------------- ebx: 77 [iTestUnsigned]: 1234567 stest*: This is a local string test eax: 3773413439 eax|edx: 3154339424745535 eax|edx: 3154339424841536 [parm1]: 5 Update 9/14/2019: I added some additional commenting/renaming options for _fasmg_Debug and also added a small example showing a new trick I learned recently used in position independent coding (pic) to establish where you are in memory. For the debugging portion you can now also optionally change the name/comment of what you are printing by adding a semicolon ";" with new name/comment. Normally the function will just use the variable name. This replaces it with whatever you put after ";". Lets say here some_var = 6  _fasmg_Debug('dword:[some_var]') ; would print to console -> [some_var]: 6  _fasmg_Debug('dword:[some_var];value of some_var') ; would print to console -> value of some_var: 6 For the trick I learned, I like this as an alternative to passing the address of the structure to your function if your using any kind of global/static variable like data reservations. Heres a partial snip from original _Ex_GlobalVars example of what Im talking about. pMem is the address of the dllstructure holding are binary code and is passed as a parameter so we can calculate the address of g_Var1: _('procf _main uses ebx, pMem, pConsoleWriteCB, parm1') _(' mov ebx, [pMem]') ; This is where are code starts in memory. _(' mov [ebx + g_Var1], 111') The alternative way can be done with these three lines below. Whenever the x86 instruction call is executed, the address of where the function needs to return to when finished (which will be the next line) is always pushed on to the stack. This is normally complemented with the ret instruction which pops that value off the stack and returns you back where you need to go next. Here we never execute ret and pop the address off to eax. delta is then subtracted from that address giving us the original starting point. _('call delta') _('delta: pop eax'); eax now equals address of delta _('sub eax, delta'); eax now equals start of memory Heres the full example I added to the zip. This also shows how with fasmg, you get true namespaces and makes any data reservation inside procedures more like static variables. Here both _subfunc1 and _subfunc2 use the same names for label delta and data reservation var. I call the function 3 times just to show the variables holding on to there values between calls. In this example the life of those variables would die when the autoit function exits since I only declared $tbinary as local and not static so keep that it mind. Also notice that I defined those with a 0 and not "?". I dont have a example but without the 0 the data is just empty and there for I think it could cause the dllstructure to not have enough bytes define to hold that extra space for variables. Using 0 will always fill the data out so are BinaryLen() calculation will match up. Func _Ex_CurrentPOS() $g_sFasm = '' _('procf _main') _(' stdcall _subfunc1') _(' stdcall _subfunc2') _(' ret') _('endp') _('proc _subfunc1') _(' call delta'); Calling anything places the address of the next instruction on the stack. we just happen to be calling the next line _(' delta: pop eax');in this function the label delta is equal to value 18 which is the offset or distance in bytes from _main _(' sub eax, delta'); after poping the address of delta (not offset - real address) to eax we subtract delta to give us the address of _main _(' add [eax+var], 2') _(' add [eax+g_var], 2') _( $_dbg('dword:[eax+var];subfunc1 var')) _( $_dbg('dword:[eax+g_var];subfunc1 g_var')) _(' stdcall _subfunc2') _(' ret') _(' var dd 0') _('endp') _('proc _subfunc2') _(' call delta') _(' delta: pop eax'); here delta=47 _(' sub eax, delta') _(' add [eax+var], 3') _(' add [eax+g_var], 3') _( $_dbg('dword:[eax+var];subfunc2 var')) _( $_dbg('dword:[eax+g_var];subfunc2 g_var')) _(' ret') _(' var dd 0') _('endp') _('g_var dd 0') Local $tBinary = _fasmg_Assemble($g_sFasm,1) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) DllCallAddress('dword', DllStructGetPtr($tBinary)) DllCallAddress('dword', DllStructGetPtr($tBinary)) DllCallAddress('dword', DllStructGetPtr($tBinary)) EndFunc
    1 point
  4. Years ago I tried to put some functionality together to do some of this here. I started off in the right direction but it ended up getting out of control. Any new thing I learned along the way (as I was creating it), I kept trying to add in and it all became a mess. One of my primary goals with that was to make sure the code could always be pre-compiled and still run. That part did work and I was able create a couple of good projects with it, but still a lot of parts I wouldn't consider correct now and certainly not manageable. Here is a redo of what I was going for there only this time I'm not going to be generating any of the assembly code. That's all going to be done using the built in macro engine already within fasm.dll and the macros written by Tomasz Grysztar (creator of fasm) so this time I don't have to worry about any of the code that gets generated. Im not going to touch the source at all. In fact there is not even going to be _fasmadd or global variables tracking anything. None of that is needed with the added basic and extended headers that you can read more about in the fasm documentation. You can use almost all of whats in the documentation section for basic/extended headers but ignore the parts about import,exports,resources,text encoding. doesn't really apply here. Here are examples I came up with that covers a lot of core functionality to write assembly code in a manner that you already know how. If/while using multiple conditional logic statements, multiple functions, local variables, global variables, structures, COM interfaces, strings as parameters, nesting function calls. These are all things you dont even have to think about when your doing it in autoit and I'm hoping this helps bring some of that same comfort to fasm. These 3 simple callback functions will be used through out the examples Global $gConsoleWriteCB = DllCallbackRegister('_ConsoleWriteCB', 'dword', 'str;dword'), $gpConsoleWriteCB = DllCallbackGetPtr($gConsoleWriteCB) Global $gDisplayStructCB = DllCallbackRegister('_DisplayStructCB', 'dword', 'ptr;str'), $gpDisplayStructCB = DllCallbackGetPtr($gDisplayStructCB) Global $gSleepCB = DllCallbackRegister('_SleepCB', 'dword', 'dword'), $gpSleepCB = DllCallbackGetPtr($gSleepCB) Func _ConsoleWriteCB($sMsg, $iVal) ConsoleWrite($sMsg & $iVal & @CRLF) EndFunc ;==>_ConsoleWriteCB Func _DisplayStructCB($pStruct, $sStr) _WinAPI_DisplayStruct(DllStructCreate($sStr, $pStruct), $sStr, 'def=' & $sStr) EndFunc ;==>_DisplayStructCB Func _SleepCB($iSleep) Sleep($iSleep) EndFunc ;==>_SleepCB proc/endp - like func and endfunc with some extra options. "uses" statement will preserve the registers specified. stdcall is the default call type if not specified. DWORD is the default parameter size if not specified. ret value is also handled for you. You don't have to worry about adjusting a number every time you throw on an extra parameter. In fact you don't ever have to specify/touch ebp/esp at all with these macros. See Basic headers -> procedures for full description. force - just a macro I added for creating a anonymous label for the first/primary function to ensure the code gets generated. The problem we are getting around is this: in our example, _main is never actually called anywhere within fasm code and fasm engine detects that and thinks the code is doing nothing. Because of that it wants to skip generating that code and all code that was called by it leaving you with nothing. This is actually a great feature but we obviously want to make an exception for our main/initial/primary function that starts it all off so thats all this does. Func _Ex_Proc() $g_sFasm = '' _('force _main') _('proc _main uses ebx, parm1, parm2') ; _('proc _main stdcall uses ebx, parm1:DWORD, parm2:DWORD'); full statement _(' mov ebx, [parm1]') _(' add ebx, [parm2]') _(' mov eax, ebx') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $iAdd = DllCallAddress('dword', DllStructGetPtr($tBinary), 'dword', 5, 'dword', 5) ConsoleWrite('Parm1+Parm2=' & $iAdd[0] & @CRLF) EndFunc ;==>_Ex_Proc Here Im showing you calling _ConsoleWriteCB autoit function we set up as a callback. Its how you would call any function in autoit from fasm. Strings - Notice Im creating and passing "edx = " string to the function on the fly. So helpful! invoke - same as a stdcall with brackets []. Use this for when calling autoit functions Func _Ex_Callback() $g_sFasm = '' _('force _main') _('proc _main, pConsoleWriteCB, parm1, parm2') _(' mov edx, [parm1]') _(' add edx, [parm2]') _(' invoke pConsoleWriteCB, "edx = ", edx') ; ;~ _(' stdcall [pConsoleWriteCB], "edx = ", edx') ; same as invoke _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) DllCallAddress('ptr', DllStructGetPtr($tBinary), 'ptr', $gpConsoleWriteCB, 'dword', 5, 'dword', 5) EndFunc ;==>_Ex_Callback Showing .while/.endw, .if/.elseif/.else/.endif usage. .repeat .until are also macros you can use. See Extended Headers -> Structuring the source. Ignore .code, .data, .end - Those are gonna be more for a full exe. invokepcd/invokepd - these are macros I added that are the same as invoke, just preserve (push/pop) ECX or both ECX and EDX during the call. Below is also a good example of what can happen when you don't preserve registers that are caller saved (us calling the function) vs callie saved (us creating the function). EAX,ECX,EDX are all caller saved so when we call another function like the autoit callback _ConsoleWriteCB, those registers could have very different values then what was in them before the call. This function below should do at least two loops, but it doesn't (at least on my pc) without preserving ECX because ECX is no longer zero when the function returns. Keep the same thought in mind for registers EBX,ESI,EDI when you are creating assembly functions (callie saved). If your functions uses those registers, You need to preserve and restore them before your code returns back to autoit or else you could cause a similar effect to autoit. "trashing" registers is a term I've seen used alot when referring to these kind of mistakes Func _Ex_IfElseWhile() $g_sFasm = '' _('force _main') _('proc _main uses ebx, pConsoleWriteCB') _(' xor edx, edx') ; edx=0 _(' mov eax, 99') ; _(' mov ebx, 10') _(' xor ecx, ecx') ; ecx=0 _(' .while ecx = 0') _(' .if eax<=100 & ( ecx | edx )') ; not true on first loop _(' inc ebx') _(' invokepcd pConsoleWriteCB, "Something True - ebx=", ebx') _(' ret') _(' .elseif eax < 99') ; Just showing you the elseif statement _(' inc ebx') _(' .else') ;~ _(' invokepcd pConsoleWriteCB, "Nothing True - ebx=", ebx') ; comment this and uncomment the line below _(' invoke pConsoleWriteCB, "Nothing True - ebx=", ebx') _(' inc edx') ; this will make next loop true _(' .endif') _(' .endw') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) DllCallAddress('dword', DllStructGetPtr($tBinary), 'ptr', $gpConsoleWriteCB) EndFunc ;==>_Ex_IfElseWhile Sub Functions : You already understand this. Not really "sub", its just another function you call. And those functions call other functions and so on. fix : syntax sugar - Look how easy it was to replace invoke statement with our actual autoit function name ptr : more sugar - same thing as using brackets [parm1] Nesting : In subfunc1 we pass the results of two function calls to the same function we are calling Func _Ex_SubProc() $g_sFasm = '' ;replace all '_ConsoleWriteCB' statments with 'invoke pConsoleWriteCB' before* assembly _('_ConsoleWriteCB fix invoke pConsoleWriteCB') _('force _main') _('proc _main uses ebx, pConsoleWriteCB, parm1, parm2') _(' mov ebx, [parm1]') _(' add ebx, [parm2]') _(' _ConsoleWriteCB, "ebx start = ", ebx') _(' stdcall _subfunc1, [pConsoleWriteCB], [parm1], [parm2]') _(' _ConsoleWriteCB, "ebx end = ", ebx') _(' ret') _('endp') ; _('proc _subfunc1 uses ebx, pConsoleWriteCB, parm1, parm2') _(' mov ebx, [parm1]') _(' _ConsoleWriteCB, " subfunc1 ebx start = ", ebx') _(' stdcall _SubfuncAdd, <stdcall _SubfuncAdd, [parm1], [parm2]>, <stdcall _SubfuncAdd, ptr parm1, ptr parm2>') ; Nesting functions _(' _ConsoleWriteCB, " _SubfuncAdd nested <5+5><5+5> = ", eax') _(' _ConsoleWriteCB, " subfunc1 ebx end = ", ebx') _(' ret') _('endp') ; _('proc _SubfuncAdd uses ebx, parm1, parm2') _(' mov ebx, [parm1]') _(' add ebx, [parm2]') _(' mov eax, ebx') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) DllCallAddress('dword', DllStructGetPtr($tBinary), 'ptr', $gpConsoleWriteCB, 'dword', 5, 'dword', 5) EndFunc ;==>_Ex_SubProc This demonstrates the struct macro. See basic headers -> Structures for more info _FasmAu3StructDef will create an equivalent formated structure definition. All elements already have a sizeof.#name created internally. So in this example sizeof.AUTSTRUCT.x would equal 8. sizeof.AUTSTRUCT.z would equal 16 (2*8). I have added an additional one sot.#name (sizeoftype) for any array that gets created. Below is the source of what gets generate from 'dword x;dword y;short z[8]'. Also dont get confused that in fasm data definitions, d is for data as in db (data byte) or dw (data word). Not double like it is in autoit's dword (double word). See intro -> assembly syntax -> data definitions struct AUTSTRUCT x dd ? y dd ? z dw 8 dup ? ends define sot.AUTSTRUCT.z 2 Func _Ex_AutDllStruct() $g_sFasm = '' Local Const $sTag = 'dword x;dword y;short z[8]' _(_FasmAu3StructDef('AUTSTRUCT', $sTag)) _('force _main') _('proc _main uses ebx, pDisplayStructCB, pAutStruct') _(' mov ebx, [pAutStruct]') ; place address of autoit structure in ebx _(' mov [ebx+AUTSTRUCT.x], 1234') _(' mov [ebx+AUTSTRUCT.y], 4321') _(' xor edx, edx') _(' mov ecx, 5') ; setup ecx for loop instruction _(' Next_Z_Index:') ; set elements 1-6 (0-5 here in fasm) _(' mov [ebx+AUTSTRUCT.z+(sot.AUTSTRUCT.z*ecx)], cx') ; cx _(' loop Next_Z_Index') _(' invoke pDisplayStructCB, [pAutStruct], "' & $sTag & '"') _(' mov [ebx+AUTSTRUCT.z+(sot.AUTSTRUCT.z*6)], 666') _(' mov [ebx+AUTSTRUCT.z+(sot.AUTSTRUCT.z*7)], 777') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $tAutStruct = DllStructCreate($sTag) DllCallAddress('ptr', DllStructGetPtr($tBinary), 'ptr', $gpDisplayStructCB, 'struct*', $tAutStruct) _WinAPI_DisplayStruct($tAutStruct, $sTag) EndFunc ;==>_Ex_AutDllStruct Here shows the locals/endl macros for creating local variables. See basic headers -> procedures. We create a local string and the same dll structure as above. Notice that you can initialize all the values of the structure on creation. There is a catch to this though that I will show you in next example. addr macro - This will preform the LEA instruction in EDX and then push the address on to the stack. This is awesome, just remember its using EDX to perform that and does not preserve it. You'll pretty much want to use that for any local variables you are passing around. Edit: I shouldn't say things like that so causally. Use the addr macro as much as you want but remember that it is adding a couple of extra instuctions each time you use it so if your calling invoke within a loop and ultimate performance is one of your goals, you should probably perform the LEA instructions before the loop and save the pointer to a separate variable that your would then use in the loop. Func _Ex_LocalVarsStruct() $g_sFasm = '' Local Const $sTag = 'dword x;dword y;short z[8]' _(_FasmAu3StructDef('POINT', $sTag)) _('force _main') _('proc _main, pDisplayStructCB') _(' locals') _(' sTAG db "' & $sTag & '", 0') ; define local string. the ', 0' at the end is to terminate the string. _(' tPoint POINT 1,2,<0,1,2,3,4,5,6,7>') ; initalize values in struct _(' endl') _(' invoke pDisplayStructCB, addr tPoint, addr sTAG') _(' mov [tPoint+POINT.x], 4321') _(' mov [tPoint+POINT.z+sot.POINT.z*2], 678') _(' invoke pDisplayStructCB, addr tPoint, addr sTAG') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $ret = DllCallAddress('ptr', DllStructGetPtr($tBinary), 'ptr', $gpDisplayStructCB) EndFunc ;==>_Ex_LocalVarsStruct Back to the catch. Alignment is the problem here but only with the initializes. I'm handling all the alignment ok so you don't have to worry about that for creating structures that need alignment, only if you are using the one liner initialize in locals. The problem comes from extra padding being defined to handle the alignment, but fasm doesn't really know its just padding so without adding extra comma's to the initiator statement, your data ends up in the padding or simply fails. The _FasmFixInit will throw in the extra commas needed to skip the padding. Func _Ex_LocalVarStructEx() $g_sFasm = '' $sTag = 'byte x;short y;char sNote[13];long odd[5];word w;dword p;char ext[3];word finish' _(_FasmAu3StructDef('POINT', $sTag)) _('force _main') _('proc _main, pDisplayStructCB') _(' locals') _(' tPoint POINT ' & _FasmFixInit('1,222,<"AutoItFASM",0>,<41,43,43,44,45>,6,7,"au3",12345', $sTag)) _(' endl') _(' invoke pDisplayStructCB, addr tPoint, "' & $sTag & '"') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) DllCallAddress('dword', DllStructGetPtr($tBinary), 'ptr', $gpDisplayStructCB) EndFunc ;==>_Ex_LocalVarStructEx I love this one and it is really not even that hard to explain. We got multiple functions and want to be able to call them individually. Here I simply use the primary function to tell me where all the functions are. I load all the offsets (byte distance from start of code) of each each function in to a dllstruct, then once its passed back to autoit, adjust all the offsets by where they are actually located in memory (pointer to dll). From there you can call each individual function as shown previously. full code is in the zip. String functions came from link below. I ended up modifying strcmp to get a value I understand. CRC32 func is all mine. Made it so easy being able to call _strlen and then use while statements like I normally would https://www.strchr.com/strcmp_and_strlen_using_sse_4.2 Func _Ex_SSE4_Library() $g_sFasm = '' _('force _main') _('proc _main stdcall, pAdd') _(' mov eax, [pAdd]') _(' mov dword[eax], _crc32') _(' mov dword[eax+4], _strlen') _(' mov dword[eax+8], _strcmp') _(' mov dword[eax+12], _strstr') _(' ret') _('endp') _('proc _crc32 uses ebx ecx esi, pStr') ; _('endp') _('proc _strlen uses ecx edx, pStr') ; _('endp') _('proc _strcmp uses ebx ecx edx, pStr1, pStr2') ; ecx = string1, edx = string2' ; _('endp') _('proc _strstr uses ecx edx edi esi, sStrToSearch, sStrToFind') ; _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $pBinary = DllStructGetPtr($tBinary) Local $sFunction_Offsets = 'dword crc32;dword strlen;dword strcmp;dword strstr' $tSSE42 = DllStructCreate($sFunction_Offsets) $ret = DllCallAddress('ptr', $pBinary, 'struct*', $tSSE42) _WinAPI_DisplayStruct($tSSE42, $sFunction_Offsets, 'Function Offsets') ;Correct all addresses $tSSE42.crc32 += $pBinary $tSSE42.strlen += $pBinary $tSSE42.strcmp += $pBinary $tSSE42.strstr += $pBinary $sTestStr = 'This is a test string!' ConsoleWrite('$sTestStr = ' & $sTestStr & @CRLF) $iCRC = DllCallAddress('int', $tSSE42.crc32, 'str', $sTestStr) ConsoleWrite('CRC32 = ' & Hex($iCRC[0]) & @CRLF) $aLen = DllCallAddress('int', $tSSE42.strlen, 'str', $sTestStr) ConsoleWrite('string len = ' & $aLen[0] & ' :1:' & @CRLF) $aFind = DllCallAddress('int', $tSSE42.strcmp, 'str', $sTestStr, 'str', 'This iXs a test') ConsoleWrite('+strcmp = ' & $aFind[0] & @CRLF) $aStr = DllCallAddress('int', $tSSE42.strstr, 'str', 'This is a test string!', 'str', 'test') ConsoleWrite('Strstr = ' & $aStr[0] & @CRLF) EndFunc ;==>_Ex_SSE4_Library I'm extremely happy I got a com interface example working. I AM. That being said.. I'm pretty fucking annoyed I cant find the original pointer when using using built in ObjCreateInterface I've tired more than just whats commented out. It anyone has any input (I know someone here does!) that would be great. Using the __ptr__ from _autoitobject works below. Example will delete the tab a couple times. Edit: Got that part figured out. Thanks again trancexx! Func _Ex_ComObjInterface() $g_sFasm = '' ;~ _AutoItObject_StartUp() ;~ Local Const $sTagITaskbarList = "QueryInterface long(ptr;ptr;ptr);AddRef ulong();Release ulong(); HrInit hresult(); AddTab hresult(hwnd); DeleteTab hresult(hwnd); ActivateTab hresult(hwnd); SetActiveAlt hresult(hwnd);" ;~ Local $oList = _AutoItObject_ObjCreate($sCLSID_TaskbarList, $sIID_ITaskbarList, $sTagITaskbarList) Local Const $sCLSID_TaskbarList = "{56FDF344-FD6D-11D0-958A-006097C9A090}", $sIID_ITaskbarList = "{56FDF342-FD6D-11D0-958A-006097C9A090}" Local Const $sTagITaskbarList = "HrInit hresult(); AddTab hresult(hwnd); DeleteTab hresult(hwnd); ActivateTab hresult(hwnd); SetActiveAlt hresult(hwnd);" Local $oList = ObjCreateInterface($sCLSID_TaskbarList, $sIID_ITaskbarList, $sTagITaskbarList) _('interface ITaskBarList,QueryInterface,AddRef,Release,HrInit,AddTab,DeleteTab,ActivateTab,SetActiveAlt') ; _('force _main') _('proc _main uses ebx, pSleepCB, oList, pGUIHwnd') _(' comcall [oList],ITaskBarList,HrInit') _(' xor ebx, ebx') _(' .repeat') _(' invoke pSleepCB, 500') ; wait _(' comcall [oList],ITaskBarList,DeleteTab,[pGUIHwnd]') ; delete _(' invoke pSleepCB, 500') ; wait _(' comcall [oList],ITaskBarList,AddTab,[pGUIHwnd]') ; add back _(' comcall [oList],ITaskBarList,ActivateTab,[pGUIHwnd]') ; actvate _(' inc ebx') _(' .until ebx=4') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $GUI = GUICreate("_Ex_ComObjInterface ------ DeleteTab") GUISetState() ;~ DllCallAddress('ptr', DllStructGetPtr($tBinary), 'ptr', $gpSleepCB, 'ptr', $oList.__ptr__, 'dword', Number($GUI)) DllCallAddress('ptr', DllStructGetPtr($tBinary), 'ptr', $gpSleepCB, 'ptr', $oList(), 'dword', Number($GUI)) EndFunc ;==>_Ex_ComObjInterface Lastly here is an example of how to use a global variable. Without using the org statement, this value is just an offset like the functions in the library example. In order for your code to know that location, it needs to know where the real starting address is so we have to pass that to our functions. Once you have it, if you write your code proper and preserve registers correctly, you can just leave in EBX. From what I understand, if all functions are following stdcall rules, that register shouldn't change in less you change it. Something cool and important to remember is these variables will hold whatever values left in them till you wipe the memory (dll structure) holding your code. keep that in mind if you made your dll structure with a static keyword. If thats the case treat them like static variables Func _Ex_GlobalVars() $g_sFasm = '' _('_ConsoleWriteCB fix invoke pConsoleWriteCB') ; _('force _main') _('proc _main uses ebx, pMem, pConsoleWriteCB, parm1') _(' mov ebx, [pMem]') ; This is where are code starts in memory. _(' mov [ebx + g_Var1], 111') _(' add [ebx + g_Var1], 222') _(' _ConsoleWriteCB, "g_Var1 = ", [ebx + g_Var1]') _(' stdcall subfunc1, [pMem], [pConsoleWriteCB], [parm1]') _(' mov eax, g_Var1') _(' ret') _('endp') ; _('proc subfunc1 uses ebx, pMem, pConsoleWriteCB, parm1') _(' mov ebx, [pMem]') _(' mov [ebx + g_Var1], 333') _(' _ConsoleWriteCB, "g_Var1 from subfunc1= ", [ebx + g_Var1]') _(' stdcall subfunc2, [pConsoleWriteCB], [parm1]') ; no memory ptr passed. ebx should be callie saved _(' _ConsoleWriteCB, "g_Var1 from subfunc1= ", [ebx + g_Var1]') _(' stdcall subfunc2, [pConsoleWriteCB], [parm1]') _(' ret') _('endp') ; _('proc subfunc2, pConsoleWriteCB, parm1') _(' add [ebx + g_Var1], 321') _(' _ConsoleWriteCB, "g_Var1 from subfunc2= ", [ebx + g_Var1]') _(' ret') _('endp') ; _('g_Var1 dd ?') ; <--------- Global Var Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $iOffset = DllCallAddress('dword', DllStructGetPtr($tBinary), 'struct*', $tBinary, 'ptr', $gpConsoleWriteCB, 'dword', 55)[0] ConsoleWrite('$iOffset = ' & $iOffset & @CRLF) Local $tGVar = DllStructCreate('dword g_Var1', DllStructGetPtr($tBinary) + $iOffset) ConsoleWrite('Directly access g_Var1 -> ' & $tGVar.g_Var1 & @CRLF) ; direct access EndFunc ;==>_Ex_GlobalVars FasmEx.zip
    1 point
×
×
  • Create New...