Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 10/18/2019 in all areas

  1. DEPRECATED: see this new UDF
    2 points
  2. $s = "aaa" & @CRLF & "bbb" & @CRLF & "ccc" & @CRLF & "ddd" & @CRLF & "eee" $s = StringRegExpReplace($s, "((?:.*?\R){2}).*?\R(?s)(.*)", "$1$2") ConsoleWrite($s & @LF)
    2 points
  3. Just proves the versatility of AutoIt (not to mention the brilliance of the UDF's and their authors)
    1 point
  4. Ii's certainly possible. I have successfully combined the code I posted above with Melba's UDF:
    1 point
  5. #include <GUIConstantsEx.au3> #include <File.au3> Global $aInFile _FileReadToArray("20191015.txt", $aInFile, $FRTA_NOCOUNT) Global $iLines = UBound($aInFile) GUICreate("_mucitbey_", 430, 500, -1, -1) $lv = GUICtrlCreateListView("#|Card ID|[]|Date|Clock|User", 10, 60, 400, 400) Global $hImport = GUICtrlCreateButton("TXT IMPORT", 10, 10, 75, 20) Global $hExport = GUICtrlCreateButton("PDF EXPORT", 330, 10, 75, 20) For $i = 0 To $iLines - 1 $aTemp = StringSplit($aInFile[$i], ", ", $STR_NOCOUNT) GUICtrlCreateListViewItem($aTemp[0] & "|" & $aTemp[1] & "|" & $aTemp[2] & "|" & $aTemp[3] & "|" & $aTemp[4] & "|", $lv) Next GUISetState(@SW_SHOW) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd
    1 point
  6. Same here! I actually began some work on a UDF which is supposed to make creation of GUIs more easier, the plan was to make it layout based (just like GTK, but I did not know about it back then) so that I don't have to keep updating coordinates whenever I need to extend the GUI You can still find the work I started here: https://github.com/AutoIt4Life/GUIFrame/blob/master/GUIFrame.au3 It was called "Advanced Input Box", not extended! It is a very handy function that you have made, many scripters can make use of it. I see that you drew inspiration from IUP, I like IUP and use it a lot myself, it is one (and maybe only) of the sane libraries I have seen which can do cross-platform (native) GUIs in C I recall that @Xandy might have also made a similar UDF to get different kinds of paramateres/configurations via a GUI.
    1 point
  7. Thank you, @Musashi and @water, for your explanations and for updating the table to include “object”. I have been using AutoIt for nearly 20 years, but I hadn’t paid much attention to the coding best practices until now; I will be teaching a 400-level Computer Science special topics course that I am currently developing for this coming Spring semester, and a significant chunk of it will be focused on writing AutoIt scripts. I am systematically reading through all of the Wiki pages for content I would like to cover in the course, and I figured it would be a good idea to make sure I understand the coding best practices as set out in the Wiki so I can teach and emphasize them early on so that we are consistent. I love the AutoIt help file, but I am only now realizing how useful the Wiki is, too. Reading the coding best practices Wiki makes me realize how sloppy my AutoIt code is. I am actually excited to start using the coding best practices in my next scripts!
    1 point
  8. Easiest method would be to use an Ini for example: [Computers] ComputerName1 = Update ComputerName2 = Leave You could then use Local $sComputerAction = IniRead("filename.ini", "Computers", @ComputerName, "") Switch $sComputerAction Case "Update" ;~ Do an update Case "Leave" ;~ Do nothing Case "" ;~ Computer name wasn't in Ini so do something else. EndSwitch Alternatively you could use FileReadToArray and then _ArraySearch function to see if it can find a match or you could use FileRead and the use "If StringInStr($sFileRead, @ComputerName) Then ...."
    1 point
  9. Thanks @water for this hint. I couldn't find anything about it. This is my whole solution now: #include <File.au3> Local $sFile = ; fullpath to an excel file Local $sOpened = _ExcelFileOpened($sFile) If @error Then ; nobody has opened this excel file If @error = 1 Then ConsoleWrite("You can open the excel file and write to it." & @CRLF) ElseIf @error = 2 Then ConsoleWrite("File does not exist." & @CRLF) ElseIf @error = 3 Then ConsoleWrite("File ist not an excel file." & @CRLF) EndIf ElseIf @extended = 1 Then ConsoleWrite("This excel file is already opened by you with write privilege" & @CRLF) Else ConsoleWrite("This excel file is opened by " & $sOpened & @CRLF & "You can't write to the file therefor it will not be opened." & @CRLF) EndIf Exit ; #FUNCTION# ==================================================================================================================== ; Name ..........: _ExcelFileOpened ; Description ...: Returns who has the excel file opened with write privilege ; Syntax ........: _ExcelFileOpened($sFile) ; Parameters ....: $sFile - must be an excel file ; Return values .: Success - name of who has opened the excel file with write privilege, sets @extended to: ; |1 - if I am the one ; Failure - 0, sets @error to: ; |1 - excel file is not opened ; |2 - file does not exist ; |3 - file is not an excel file ; Author ........: Simpel ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _ExcelFileOpened($sFile) ; check if file exists If FileExists($sFile) = 0 Then Return SetError(2, 0, 0) ; check if file is an excel file Local $iDelimiter = StringInStr($sFile, ".", 0, -1) ; splits suffix Local $sExtension = StringTrimLeft($sFile, $iDelimiter) ; only file extension If StringLeft($sExtension, 3) <> "xls" Then Return SetError(3, 0, 0) ; if excel has created a temporary excel file with a ~$ prefix then it is already opened $iDelimiter = StringInStr($sFile, "\", 0, -1) ; splits file from path Local $sTempFile = StringLeft($sFile, $iDelimiter) & "~$" & StringTrimLeft($sFile, $iDelimiter) ; adds prefix ~$ at excel filename Local $iTempFileExist = FileExists($sTempFile) ; if this file exists then the excel file is opened If $iTempFileExist = 0 Then Return SetError(1, 0, 0) ; is not opened Local $sOwnerTempFile = _Owner($sTempFile) ; owner of the excel temp file is the one with write privilege ; find out who I am Local $sTestFile = _TempFile() ; needs file.au3 FileWrite($sTestFile, "") ; create a test file (I am definitely the owner) If @error Then Return $sOwnerTempFile ; returns only the one with write privilege to the excel file EndIf Local $sMe = _Owner($sTestFile) ; this is me FileDelete($sTestFile) ; look if I am the one created the temp excel file If $sOwnerTempFile = $sMe Then Return SetError(0, 1, $sMe) ; returns me opened excel file with write privilege and sets @extended to 1 Else Return $sOwnerTempFile ; returns the one with write privilege to the excel file EndIf EndFunc Func _Owner($sFile) ; the one who saved it last - code by siao? Local $secUtil = ObjCreate("ADsSecurityUtility") Local $secDesc = $secUtil.GetSecurityDescriptor($sFile, 1, 1) Local $sOwner = $secDesc.Owner $secUtil = Null Return $sOwner EndFunc Regards, Conrad
    1 point
  10. Thank you for your reply. i was talking about the _Process_ReadMemoryPointer function in KryMemory. It doesn't work. Is that also what you meant with "there is no pointer to a pointer? the pointer part works fine like this: $val = (_Process_ReadMemory($lovehandle, "0x" & Hex(_Process_ReadMemory($lovehandle, "0x" & Hex(_Process_ReadMemory($lovehandle, 0x7FF6ABE142E0, "uint64") + 0x28), "uint64")), "dword")) would be nice if we could use the _Process_ReadMemoryPointer function though (just to make things easier). Did you try that? I was expecting it to work like this: #include <KryMemory.au3> #include <Array.au3> $lovehandle = _Process_Open("test.exe") Local $Offset[2] $Offset[0] = 0 $Offset[1] = 0x28 $pointerrr = _Process_ReadMemoryPointer($lovehandle, 0x7FF6ABE142E0, $Offset, "uint64") ;MsgBox(0,"pointer", $pointerrr) _ArrayDisplay($pointerrr) No big deal if the function won't work anyway.
    1 point
  11. GetModuleFunc.h 1. Introduction This writing describes in detail method for retrieving the address of exported function for loaded module without using any available API on either 32bit, 64bit or ARM based Windows systems. Structures definitions are taken from Microsoft SDK 7.1, unless otherwise specified. Loaded module is searched by name, not path. The code is written in form of function that has two parameters, WCHAR pointer to the module name and CHAR pointer to the function name, written in C++ and compiled using Microsoft Visual Studio Express 2013 for Windows Desktop. Basic knowledge of C++ is assumed. Attached GetModuleFunc.h has the full code for the function. 2. NT_TIB Structure defined inside winnt.h. It's the staring point for the algorithm. It includes self-referencing field - Self pointer, offset of which is used on non-ARM systems to read Thread Environment Block data. typedef struct _NT_TIB { struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; PVOID StackBase; PVOID StackLimit; PVOID SubSystemTib; #if defined(_MSC_EXTENSIONS) union { PVOID FiberData; DWORD Version; }; #else PVOID FiberData; #endif PVOID ArbitraryUserPointer; struct _NT_TIB *Self; } NT_TIB; typedef NT_TIB *PNT_TIB; 2.1. TEBThread Environment Block is chunk of memory filled with various information about the thread. TEB is defined inside winternl.h as: typedef struct _TEB { PVOID Reserved1[12]; PPEB ProcessEnvironmentBlock; PVOID Reserved2[399]; BYTE Reserved3[1952]; PVOID TlsSlots[64]; BYTE Reserved4[8]; PVOID Reserved5[26]; PVOID ReservedForOle; // Windows 2000 only PVOID Reserved6[4]; PVOID TlsExpansionSlots; } TEB, *PTEB; After the executable is loaded by the Windows PE loader and before the thread starts running, TEB is saved to fs(x86) or gs(x64 flavor) processor register. ARM systems use different technique which utilize coprocessors scheme (it's unclear whether the coprocessor is real hardware component or emulated). Self field of NT_TIB is the TEB pointer for the current thread.Even not officially documented, this behavior is observed on/for all available Windows operating systems with NT kernel. Acquiring pointer to the TEB is done using Microsoft specific compiler intrinsics: #include <winnt.h> #include <winternl.h> #if defined(_M_X64) // x64 auto pTeb = reinterpret_cast<PTEB>(__readgsqword(reinterpret_cast<DWORD>(&static_cast<NT_TIB*>(nullptr)->Self))); #elif defined(_M_ARM) // ARM auto pTeb = reinterpret_cast<PTEB>(_MoveFromCoprocessor(15, 0, 13, 0, 2)); // CP15_TPIDRURW #else // x86 auto pTeb = reinterpret_cast<PTEB>(__readfsdword(reinterpret_cast<DWORD>(&static_cast<NT_TIB*>(nullptr)->Self))); #endif Among others, one of the fields inside the TEB is pointer to the PEB (Process Environment Block). 3. PEB Process Environment Block is memory area filled with information about a process. PEB is defined inside winternl.h as: typedef struct _PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID Reserved4[3]; PVOID AtlThunkSListPtr; PVOID Reserved5; ULONG Reserved6; PVOID Reserved7; ULONG Reserved8; ULONG AtlThunkSListPtr32; PVOID Reserved9[45]; BYTE Reserved10[96]; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; BYTE Reserved11[128]; PVOID Reserved12[1]; ULONG SessionId; } PEB, *PPEB; Pointer to the PEB is read from the TEB: auto pPeb = pTeb->ProcessEnvironmentBlock; 3.1. PEB_LDR_DATAContains information about the loaded modules for the process. Ldr field of the PEB points to PEB_LDR_DATA structure, defined inside winternl.h as: typedef struct _PEB_LDR_DATA { BYTE Reserved1[8]; PVOID Reserved2[3]; LIST_ENTRY InMemoryOrderModuleList; } PEB_LDR_DATA, *PPEB_LDR_DATA; Pointer to the PEB_LDR_DATA is read from the PEB: auto pLdrData = pPeb->Ldr; 3.2. LIST_ENTRYInMemoryOrderModuleList field of the PEB_LDR_DATA is doubly-linked list that contains the loaded modules for the process, defined inside winnt.h as: typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY; auto pModListHdr = &pLdrData->InMemoryOrderModuleList; 4. LDR_DATA_TABLE_ENTRYEach item in the list is a pointer to an LDR_DATA_TABLE_ENTRY structure, defined inside winternl.h as: typedef struct _LDR_DATA_TABLE_ENTRY { PVOID Reserved1[2]; LIST_ENTRY InMemoryOrderLinks; PVOID Reserved2[2]; PVOID DllBase; PVOID Reserved3[2]; UNICODE_STRING FullDllName; BYTE Reserved4[8]; PVOID Reserved5[3]; union { ULONG CheckSum; PVOID Reserved6; } DUMMYUNIONNAME; ULONG TimeDateStamp; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; DllBase field is the base address of the loaded module.This stucture doesn't give wanted info for the module, being its name. One option is to read FullDllName which includes full path and extract module name from it. However, some independent authors give slightly different definition which include another field - BaseDllName. Modified LDR_DATA_TABLE_ENTRY struct can be defined, including BaseDllName field and freed from superfluous fields. InMemoryOrderLinks will be iterated, so that field is the top of the struct: typedef struct _LDR_DATA_TABLE_ENTRY { /*LIST_ENTRY InLoadOrderLinks;*/ LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderList; PVOID DllBase; PVOID EntryPoint; PVOID Reserved3; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; 4.1. IterationGoing through the items in the list is straightforward. The last item points to the first, meaning the end is reached, hence it can be written: for (auto pModListCurrent = pModListHdr->Flink; pModListCurrent != pModListHdr; pModListCurrent = pModListCurrent->Flink) { // Get current module in list auto pModEntry = reinterpret_cast<PLDR_DATA_TABLE_ENTRY>(pModListCurrent); //... } 4.2. Reading Module NameThis data is stored in form of UNICODE_STRING. winternl.h definition is: typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING; Module name lookup is case insensitive. Lengths specified inside UNICODE_STRING represent bytes, which means number of WCHAR characters is half of the numbers.One of the ways to make case insensitive comparison of the specified module name and listed one is to turn both to uppercase before comparing them: for (int i = 0; i < pModEntry->BaseDllName.Length / 2 /* length is in bytes */; ++i) { if (sModuleName[i] == '\0') // the end of the string break; else if ((sModuleName[i] & ~' ') != (pModEntry->BaseDllName.Buffer[i] & ~' ')) // case-insensitive break; else if (i == iLenModule - 1) // gone through all characters and they all matched { //... the rest of the code } } iLenModule is length of the wanted module name. It's get by counting number of characters inside the string until null-terminator is encountered: int iLenModule = 0; for (; sModuleName[iLenModule]; ++iLenModule); Comparison written in this manner allows for matching function argument L"kernel32" to listed L"kernel32.dll", which mimics to a decent degree (not completely for brevity) behavior of GetModuleHandle WinAPI function. In case of two different loaded modules whose names differs only in extensions, first listed is matched. 5. PE format walkthrough The Portable Executable (PE) format is a file format for executables, object code, DLLs, etc... It describes how and where inside the file the executable code is, import table, export table, resources, and every other data needed for loader. Exported functions are listed inside the Export Table. Reaching export table is done in few steps parsing the PE data. 5.1. IMAGE_DOS_HEADER The matching module's DllBase points to the first byte of the loaded image. PE starts with legacy DOS header defined inside winnt.h as: typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header WORD e_magic; // Magic number WORD e_cblp; // Bytes on last page of file WORD e_cp; // Pages in file WORD e_crlc; // Relocations WORD e_cparhdr; // Size of header in paragraphs WORD e_minalloc; // Minimum extra paragraphs needed WORD e_maxalloc; // Maximum extra paragraphs needed WORD e_ss; // Initial (relative) SS value WORD e_sp; // Initial SP value WORD e_csum; // Checksum WORD e_ip; // Initial IP value WORD e_cs; // Initial (relative) CS value WORD e_lfarlc; // File address of relocation table WORD e_ovno; // Overlay number WORD e_res[4]; // Reserved words WORD e_oemid; // OEM identifier (for e_oeminfo) WORD e_oeminfo; // OEM information; e_oemid specific WORD e_res2[10]; // Reserved words LONG e_lfanew; // File address of new exe header } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; Therefore it can be written: auto pImageDOSHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(pModEntry->DllBase); e_lfanew is offset to a NT header. 5.2. IMAGE_NT_HEADERS Another area of PE is NT header. This is effectively the starting point of the portable executable format description. Definition and the size of it depends on bitness. For 32bit it's: typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; ...and 64bit version is: typedef struct _IMAGE_NT_HEADERS64 { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER64 OptionalHeader; } IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; 5.3. IMAGE_NT_HEADERSOptionalHeader field is another structure discribing in detail PE file. It's directly followed by number of IMAGE_DATA_DIRECTORY structures. The exact number of these structures is saved inside IMAGE_NT_HEADERS as NumberOfRvaAndSizes field. For 32bit PE IMAGE_NT_HEADERS is defined as: typedef struct _IMAGE_OPTIONAL_HEADER { // // Standard fields. // WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; // // NT additional fields. // DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; ...and for 64bit version it's: typedef struct _IMAGE_OPTIONAL_HEADER64 { WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; ULONGLONG ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; ULONGLONG SizeOfStackReserve; ULONGLONG SizeOfStackCommit; ULONGLONG SizeOfHeapReserve; ULONGLONG SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; PE files generated by Microsoft tools allways create IMAGE_NUMBEROF_DIRECTORY_ENTRIES (16) IMAGE_DATA_DIRECTORY structures, 15 of which are documented in this order (winnt.h): #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory // IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP #define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers #define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor 5.4. IMAGE_DATA_DIRECTORYDefinition is: typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; It can now be written: auto pExport = reinterpret_cast<PIMAGE_DATA_DIRECTORY>(&pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]); VirtualAddress field is RVA of the directory counting from the first byte (base) of the loaded module. If both VirtualAddress and Size fields are filled then the module exports functions. 5.5. IMAGE_EXPORT_DIRECTORY Definition is (winnt.h): typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions; // RVA from base of image DWORD AddressOfNames; // RVA from base of image DWORD AddressOfNameOrdinals; // RVA from base of image } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; Base is ordinal value of the first exported function.NumberOfFunctions is overall number of exported functions from the module. NumberOfNames is number of functions exported only by name. AddressOfFunctions is RVA of the array of RVAs of exported functions addresses. AddressOfNames is RVA of the array of RVAs of exported functions names. AddressOfNameOrdinals is RVA of the array of WORD values each representing index of function exported by name, into the array of addresses. It's: auto pExports = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(reinterpret_cast<ULONG_PTR>(pImageDOSHeader) + pExport->VirtualAddress); 6. Getting function RVAEvery exported function is accessible by odinal value. Functions exported by name are also accessible by name. Finding function by its ordinal value is fairly simple and fast. The lowest ordinal value is Base field of IMAGE_EXPORT_DIRECTORY struct. The highest ordinal value is get by adding the number of exported functions to that number, minus one of course. If the specified ordinal value is within this range, RVA is read from the array of functions addresses: if (iOrdinal) // function is wanted by its ordinal value { // Check to see if valid ordinal value is specified if (iOrdinal >= pExports->Base && iOrdinal < pExports->Base + pExports->NumberOfFunctions) dwExportRVA = pdwBufferAddress[iOrdinal - pExports->Base]; } In case of functions exported by name, name lookup needs to be performed.The code is: // Array of functions names auto pdwBufferNames = reinterpret_cast<LPDWORD>(reinterpret_cast<ULONG_PTR>(pImageDOSHeader) + pExports->AddressOfNames); // Array of functions indexes into array of addresses auto pwBufferNamesOrdinals = reinterpret_cast<LPWORD>(reinterpret_cast<ULONG_PTR>(pImageDOSHeader) + pExports->AddressOfNameOrdinals); And then the loop: // Loop through all functions exported by name for (DWORD j = 0; j < pExports->NumberOfNames; ++j) { // Read the listed function name auto sFunc = reinterpret_cast<LPCSTR>(reinterpret_cast<ULONG_PTR>(pImageDOSHeader) + pdwBufferNames[j]); //... } When the name of the function is matched (case sensitive) the RVA of the function will be read from pdwBufferAddress array at index read from pwBufferNamesOrdinals at loop counter value index: dwExportRVA = pdwBufferAddress[pwBufferNamesOrdinals[j]]; 6.1. Export ForwardingRVA of the function will resolve fonction's pointer. However there is one special case when the RVA offset points to a value inside the exports section and not to the function body which is normally found in some other sections of PE. When that happens, RVA will resolve to a null-terminated ASCII string value. This is called Export Forwarding. RVA is then replaced by the RVA value of the resolved function. if (dwExportRVA > pExport->VirtualAddress && dwExportRVA < pExport->VirtualAddress + pExport->Size) { // Read forwarded data. auto sForwarder = reinterpret_cast<LPCSTR>(reinterpret_cast<ULONG_PTR>(pImageDOSHeader) + dwExportRVA); //... } The format of the forwarding string is: ModuleName.FunctionName or ModuleName.#OrdinalValueTo resolve the RVA of the new exported function a recursive call to this function will be used. ModuleName has to be wide string. WCHAR buffer is allocated and all characters from ModuleName portion of forwarded string copied to it: WCHAR sForwarderDll[MAX_PATH]; // Reinterpret WCHAR buffer as CHAR one auto sForwarderDll_A = reinterpret_cast<CHAR*>(sForwarderDll); // Now go through all characters for (int iPos = 0; sForwarder[iPos]; ++iPos) { // Fill WCHAR buffer reading/copying from CHAR one sForwarderDll_A[2 * iPos] = sForwarder[iPos]; // copy character sForwarderDll_A[2 * iPos + 1] = '\0'; if (sForwarder[iPos] == '.') { sForwarderDll[iPos] = '\0'; // null-terminate the ModuleName string break; } } In case forwarding string specifies function name, pointer to that string is simply a pointer to a character following the dot.For OrdinalValue version the presence of hashtek character after the dot has to be checked and the hashtag string converted to integer value before recursive call made. The full code for this is: // Allocate big enough buffer for the new module name WCHAR sForwarderDll[MAX_PATH]; LPCSTR sForwarderFunc = nullptr; DWORD dwForwarderOrdinal = 0; // Reinterpret WCHAR buffer as CHAR one auto sForwarderDll_A = reinterpret_cast<CHAR*>(sForwarderDll); // Now go through all characters for (int iPos = 0; sForwarder[iPos]; ++iPos) { // Fill WCHAR buffer reading/copying from CHAR one sForwarderDll_A[2 * iPos] = sForwarder[iPos]; // copy character sForwarderDll_A[2 * iPos + 1] = '\0'; if (sForwarder[iPos] == '.') { sForwarderDll[iPos] = '\0'; // null-terminate the ModuleName string ++iPos; if (sForwarder[iPos] == '#') { ++iPos; // skip # character // OrdinalValue is hashtag, convert ASCII string to integer value for (; sForwarder[iPos]; ++iPos) { dwForwarderOrdinal *= 10; dwForwarderOrdinal += (sForwarder[iPos] - '0'); } if (dwForwarderOrdinal > MAX_ORDINAL) // something is wrong return nullptr; // Reinterpret the ordinal value as string sForwarderFunc = reinterpret_cast<LPSTR>(dwForwarderOrdinal); break; } else { sForwarderFunc = &sForwarder[iPos]; // FunctionName follows the dot break; } } } 6.2. FinalizingOnce funcion address RVA is get, it's added to the base address and returned from the function: return reinterpret_cast<LPVOID>(reinterpret_cast<ULONG_PTR>(pImageDOSHeader) + dwExportRVA); 7. ExampleThe attached zip contains two executables compiled from the source of 1K-Mandelbrot project, written by Emil Persson. The source had no explicit License Agreement. It's modified not to use WinAPI, rather to use method desribed here to call functions from used dlls and then compiled. Beautiful examples of visualisation of complex calculations, done in efficient way using OpenGL. Requirement is OpenGL 2.0. Third example is compiled for ARM. It's simple analog Direct2D clock, the original code of which is released under Artistic License/GPL by vckzdd. GetModuleFunc_Examples.zip 8. Conclusion This method isn't usually used by executables ran from user mode. It should be avoided used for production software, because it ommits taking ownership of critical section object used by windows during load/unload actions of the module, which could result in any kind of unhandled exception. Limited speed tests show that it's faster than standard GetModuleHandle/GetProcAddress method. Mimicking WinAPI behavior is achieved to a high level for valid input, with omitted special error handling and reporting. The only major difference is unsupported full-path processing. 8.1. Anti-Virus Software considerations This method enables compiling PE files with empty imports directory. In combination with accessing fs register at TEB/PEB offset it has been observed that 18.2% of AV scanners tend to flag 32bit executables, containing no code other than this function, as malware. 64 bit and ARM executables compiled from the same source never get flagged. References: Microsoft Corporation: Microsoft Portable Executable and Common Object File Format Specification, Revision 6.0 Matt Pietrek: Under The Hood - http://www.microsoft.com/msj/archive/s2ce.aspx An In-Depth Look into the Win32 Portable Executable File Format - http://msdn.microsoft.com/en-us/magazine/bb985992.aspx An In-Depth Look into the Win32 Portable Executable File Format, Part 2 - http://msdn.microsoft.com/en-us/magazine/cc301808.aspx Mark Russinovich, David A. Solomon, Alex Ionescu : Microsoft Windows Internals, 6th edition VirusTotal: Web Service - https://www.virustotal.com/ Emil Persson: 1K-Mandelbrot - http://www.humus.name/index.php?page=3D&ID=85 vckzdd: directxcode - https://code.google.com/p/directxcode/source/browse/#svn/Direct2D/Clock
    1 point
  12. GUI CREATION RELATED I think it is worth adding some elements that have an impact on how GUI's are created. I am not specifically looking for these tools or addons etc, so please advise if you think something belongs here, as I will just add what attracts my notice. NOTE - I'm getting the notion, that it could become hard to draw a line with these, and we might end up with an awful lot. Definitely a handy reference though. Sep 24 2004 - GUI Dev Stuff by Jon (back where it all started to happen in earnestness) Sep 10 2006 - XSkin.au3... Skin your GUI by Valuater Oct 24 2006 - ShapedGUI Creator by Ed_Maximized Feb 19 2007 - EzSkin_1-2-3 by Valuater Mar 02 2007 - _GuiCreateGrid() by MrCreatoR Jun 14 2007 - PNG as GUI, drop shadows, curved edges, you name it by lod3n (think this qualifies) May 10 2008 - How to convert GUI scripts to v3.2.12.0 by Jon Jun 10 2008 - PNG as GUI, drop shadows, curved edges etc UDF by goldenix Sep 08 2008 - _GUIFrame UDF by kip Dec 31 2008 - Perforated image in GUI by GreenCan Mar 08 2009 - Add a drop shadow to native AutoIt GUI Forms and Dialogs by rover Jun 21 2009 - A runtime control move/re-size utility by Malkey Sep 25 2009 - Multiple PNG images as GUI elements by JRowe (seemingly qualifies) Aug 01 2010 - GUIExtender - Original version by Melba23 Sep 10 2010 - GUIFrame UDF update by Melba23 Mar 09 2011 - _GUIDisable UDF by guinness Dec 19 2011 - Tab control example: Tabs and subtabs on demand by LarsJ Sep 09 2012 - GUISpoiler UDF by MrCreatoR Oct 19 2012 - GUIExtender - New Version by Melba23 Dec 25 2012 - GUI design concepts by guinness Jan 15 2014 - GUI Fun! by Ascend4nt Apr 24 2014 - Spotlight + Focus GUI by Ascend4nt (think this qualifies) May 7 2014 - MetroGUI UDF v4 by BBs19 Oct 09 2015 - Borderless GUI without WS_POPUP, with Drag, Resize & AeroSnap by BBs19 June 10 2023 - Glance - GUI library for AutoIt, based on Windows api by kcvinu +++++ STILL UNDER CONSTRUCTION +++++ Please Help!
    1 point
  13. When a control ID is needed for a function, -1 will refer to the last control created, in this case the input control. BTW, the help file doesn't say you need a context menu to create an UpDown control, you need an input control for it, as you found out in your second post. Koda is a frame for your script, it doesn't do everything, and what it does do usually has to be tweaked after you've created the code because it makes assumptions about your script that you may not want. This is probably one of those things that need to be tweaked after it's been done in Koda.
    1 point
×
×
  • Create New...