flat assembler
Message board for the users of flat assembler.
Index
> Windows > access API when using format binary |
Author |
|
revolution 02 Dec 2013, 20:49
You're going to find trouble if you really want to do API function binding the "hard way". You need to scan the memory space looking for DLL signatures and then try to find the function you want within the DLL. It is tricky because you have to be careful when generating an exception by reading unallocated memory areas. Also, different versions of the OS put things in different places so even finding a reliable starting point is problematic.
In short: It can be done, but it requires much more more effort than necessary. |
|||
02 Dec 2013, 20:49 |
|
xoru 02 Dec 2013, 20:53
I understand, so would you suggest I push a LoadLibrary and GetProcAddress to the binary chunks?
|
|||
02 Dec 2013, 20:53 |
|
revolution 02 Dec 2013, 20:58
xoru wrote: I understand, so would you suggest I push a LoadLibrary and GetProcAddress to the binary chunks? Compare that to how much time you would likely spend coding up and debugging a memory scanning, exception handling, export searching piece of code. |
|||
02 Dec 2013, 20:58 |
|
xoru 02 Dec 2013, 21:03
revolution wrote:
Good point, I think I was merely hoping for some magical solution that was already known to someone who came across this problem. I'll go with the easy solution, thanks for your input! _________________ HLT |
|||
02 Dec 2013, 21:03 |
|
xoru 02 Dec 2013, 23:54
Now, I don't want to go off-topic too much, however when I keep assembling binary chunks, I would love a practical method to access the correct address to labels defined in these chunks. Currently I'm using the next macro users can call to initialize a chunk and determine the absolute base address for this code;
Code: macro init32 { USE32 call _init32_findBase _init32_findBase: pop eax sub eax, ($ - 1) push ebp mov ebp, esp sub esp, 4 mov [ebp - 4], eax data_base equ [ebp - 4] } - However, this is not available in e.g. a proc, only in labels and the main code. What is a more proper way to determine the base address and resolve label addresses everywhere in the code? _________________ HLT |
|||
02 Dec 2013, 23:54 |
|
xoru 04 Dec 2013, 15:02
Even though the simple solution seemed wise, I forgot that the small assembled chunks should be executed from external processes as well (as callback functions). In those situations, I cannot rely on pushing function addresses to the chunk.
I looked around on the web a lot, and found some code on these forums; http://board.flatassembler.net/topic.php?p=103427#103427 And some code elsewhere which resulted in me making two procs to search for GetProcAddress. I'm sure it's not the best solution out there, but it gets me where I wanna be. Code: proc findk32 PUSH ESI EDI XOR ECX, ECX ; ECX = 0 MOV ESI, [FS:ECX + 0x30] ; ESI = &(PEB) ([FS:0x30]) MOV ESI, [ESI + 0x0C] ; ESI = PEB->Ldr MOV ESI, [ESI + 0x1C] ; ESI = PEB->Ldr.InInitOrder next_module: MOV EAX, [ESI + 0x08] ; EBP = InInitOrder[X].base_address MOV EDI, [ESI + 0x20] ; EBP = InInitOrder[X].module_name (unicode) MOV ESI, [ESI] ; ESI = InInitOrder[X].flink (next module) ; check if first char is 'k' MOV CX, 'k' CMP [EDI], CX ; modulename[0] == 'k' ? JNE next_module ; check if second char is 'e' MOV CX, 'e' CMP [EDI + 2], CX ; modulename[1] == 'e' ? JNE next_module ; find null char at correct location (kernel32.dll\0) XOR ECX, ECX CMP [EDI + 12*2], CX ; modulename[12] == 0 ? JNE next_module ; No: try next module. POP EDI ESI ret endp proc findgpa base_address PUSH EBP ESI EDI MOV ESI, [base_address] MOV EBX, [ESI + 3ch] ; offset to PE, MZ + 3ch MOV EAX, [ESI + EBX + 78h] ; export table MOV ECX, [ESI + EAX + 4 * 6] ; number of names MOV EDI, [ESI + EAX + 4 * 7] ; address table MOV EBX, [ESI + EAX + 4 * 8] ; name ptr table MOV EBP, [ESI + EAX + 4 * 9] ; Ordinal table MOV EDX, EBX ; EDX = name ptr table findgpa_nex1: MOV EAX, [ESI + EBX] ; Get name pointer and search CMP DWORD [ESI + EAX], 'GetP' ; for GetProcAddress in name ptr table JE findgpa_found_getP ADD EBX, 4 ; try again loop findgpa_nex1 JMP findgpa_return ; give up findgpa_found_getP: CMP DWORD [ESI + EAX + 4], 'rocA' JE findgpa_found_rocA ADD EBX, 4 JMP findgpa_nex1 findgpa_found_rocA: CMP DWORD [ESI + EAX + 8], 'ddre' JE findgpa_found_ddre ADD EBX, 4 JMP findgpa_nex1 findgpa_found_ddre: SUB EBX, EDX ; Name ptr table offset to GetProcAddress SHR EBX, 1 ; Ordinals are 'words', adjust for ordinals ADD EBP, ESI MOVZX EBX, WORD [EBP + EBX] ; Ordinal table offset SHL EBX, 2 ; Back to dword steps ADD EBX, EDI ; Position in address table worked out from ordinal table MOV EDI, [ESI + EBX] ; RVA ADD EDI, ESI ; EDI = GetProcAddress function ; ESI = HMODULE to kernel32.dll ; EDI = GetProcAddress@8 MOV EDX, ESI MOV EAX, EDI findgpa_return: POP EDI ESI EBP ret endp Also; I'd love to have some opinions regarding my previous post, so let's call this a bump post as well Cheers! _________________ HLT |
|||
04 Dec 2013, 15:02 |
|
typedef 05 Dec 2013, 07:34
xoru wrote: Hi there, Are you making injectors (injecting self-aware code) or some sort of framework? If it's a framework you can simply add headers to your binary indicating which library the binary depends on and where the addresses to the functions should be put (in the binary). Possibilities are endless. You can even save yourself some time and make a reference table where each windows DLL has an index. The index will be used in the binary instead of the actual name of the DLL. Code: format binary as "ext" ; structure representing API dependency ; struct ;{ ; DWORD dwDepends; number of DLLS ; DWORD dwEntryPoint; pointer to block of executable code ;} ; struct { ; WORD wIndex; If index < 0, then loading custom DLL ; DWORD dwAddress; pointer to address to be filled with appropriate function address ; DWORD pszDLL; pointer to chars containing dll name to load (can be at the end of code) ; DWORD pszFunction; pointer to name of function in referenced DLL. ; } ; header ; number of DLLs dd 2 dd entry_point ; first dll referenced dw 0 ; (user32.dll) See table below dd fnMsgBox dd 0 ; not needed. Used table dd pszMsgBox ; 2nd dll referenced (Custom, or can also be added to table. You decide) dw -1 ; dd fnAdd dd pszCustomDLL dd pszAdd ;; pointers fnMsgBox dd 0 fnAdd dd 0 ;; code entry_point: push 0 push 0 push 0 push 0 call dword[fnMsgBox] ; add 3+2 push 3 push 2 call dword[fnAdd] ; ... more code ; data pszMsgBox db 'MessageBoxW',0 pszAdd db 'Add',0 pszCustomDLL db 'customlib.dll',0 And the table in your interpreter could be something like. Code: dd dwUser32; ;Index = 0 dd dwKernel32; ... dwUser32 db 'user32.dll',0 dwKernel32 db 'kernel32.dll',0 Your interpreter loads the binary, parses the headers and loads and maps appropriate DLL functions then passes control to your binary code under an exception handler of course. |
|||
05 Dec 2013, 07:34 |
|
xoru 05 Dec 2013, 11:47
Hi typedef,
Thanks for your reply. I'm doing neither, my implementation of fASM in my project is allowing Lua coders in AutoPlay Media Studio to assemble functions they can use in interaction with application programming interfaces with Windows, Libraries (such as cURL) etc. Lua functions are functions in the LuaVM, not blocks of machine instructions, so these cannot be called as (e.g.) a window subclass function. These binary chunks allow the programmer to have this possibility. Another reason for why I'm using the binary fASM format, is so that the programmer can implement (e.g.) a fast and small CRC32 (or any other) algorithm in their Lua projects, without having a DLL or Lua module as dependency. I'm building a set of includes for the assembler that will allow the programmer to interface with Windows API easily so that they can also call external functions from within their code. Anyhow, that is pretty much why I'm doing all this. The last step for me is to figure out how to determine the absolute addresses to data labels with easy for the programmer. I know how to determine the base address of the code (it's never a fixed address, VirtualAlloc(Null, ....)) and from that, determine the absolute address of the label. I'm probably missing a beautiful feature of fASM which will allow me to do that more easily, but I'm not sure which one! Cheers, Bas _________________ HLT |
|||
05 Dec 2013, 11:47 |
|
baldr 05 Dec 2013, 14:36
xoru,
Have you seen alien module? It allows DLL functions to be called from Lua almost directly. Compile-and-run approach can be implemented as custom FASM.DLL build (with proper Lua bindings) which recognizes special symbols like Kernel32.DLL!GetCommandLineA as a references to external addresses and properly snaps them before execution. Arguments conversion is still non-trivial task (that's why I recommend alien). |
|||
05 Dec 2013, 14:36 |
|
xoru 05 Dec 2013, 14:51
baldr wrote: xoru, Hi there baldr, I have heard from Alien, also my own module (specific to AutoPlay Media Studio) does also allow for calling DLL functions as if they were native Lua functions (http://www.memoryex.net/mx.html) and catches calling convention automatically, this is not my problem. My problem is that some systems (in DLL's, modules or WinAPI) require a callback function. Lua functions can't do the trick in that case, so real-time assembly is the solution I have chosen so that a Lua scripter can also create callback functions for these systems. I also chose for real-time assembly (or when using the package IMXLH in combination with MemoryEx; pre-assembled code inside compiled Lua files) to enable a programmer to implement fast algorithms and data processing routines without having to include an external module, DLL or library just for that reason. This real-time assembly is already implemented and used, however by implementing more macro-ic features I am trying to make it easier for more people to write fASM code that can help them out in their AMS Lua project. My only set-back now is relative / absolute label addresses when accessing data inside the assembly. _________________ HLT |
|||
05 Dec 2013, 14:51 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.