flat assembler
Message board for the users of flat assembler.
Index
> Windows > Super simple fasm app? |
Author |
|
kohlrak 12 Oct 2009, 01:31
Unfortunately, you need an invoke or the program will crash (particularly, a call to ExitProcess). However, if you don't mind crashing...
[code]format PE console ;console window[ mov eax, 54/code] Though, you don't declare variables in assembly, technically. Essentually, unlike HLLs, assembly outputs EXACTLY what you give it. HLLs have a little wiggle room. |
|||
12 Oct 2009, 01:31 |
|
Pinecone_ 12 Oct 2009, 01:49
kohlrak wrote: Unfortunately, you need an invoke or the program will crash (particularly, a call to ExitProcess). However, if you don't mind crashing... Here it is so you don't have to look it up: Code: ; Example of making 32-bit PE program as raw code and data format PE GUI entry start section '.text' code readable executable start: push 0 push _caption push _message push 0 call [MessageBoxA] push 0 call [ExitProcess] section '.data' data readable writeable _caption db 'Win32 assembly program',0 _message db 'Hello World!',0 section '.idata' import data readable writeable dd 0,0,0,RVA kernel_name,RVA kernel_table dd 0,0,0,RVA user_name,RVA user_table dd 0,0,0,0,0 kernel_table: ExitProcess dd RVA _ExitProcess dd 0 user_table: MessageBoxA dd RVA _MessageBoxA dd 0 kernel_name db 'KERNEL32.DLL',0 user_name db 'USER32.DLL',0 _ExitProcess dw 0 db 'ExitProcess',0 _MessageBoxA dw 0 db 'MessageBoxA',0 section '.reloc' fixups data readable discardable ; needed for Win32s Here's the equivalent with includes: Code: format PE GUI entry start include '%include%\win32a.inc' section '.text' code readable executable start: invoke MessageBox, 0, _message, _caption, 0 invoke ExitProcess, 0 section '.data' data readable writeable _caption db 'Win32 assembly program', 0 _message db 'Hello World!', 0 section '.idata' import data readable writeable library kernel32, 'kernel32.dll',\ user32, 'user32.dll' include '%include%\api\kernel32.inc' include '%include%\api\user32.inc' Or exactly what you asked for in your first post: Code: format PE GUI entry start section '.code' code readable executable start: mov eax, 1 ret |
|||
12 Oct 2009, 01:49 |
|
birdus 12 Oct 2009, 02:49
When you execute:
call [ExitProcess] or: invoke ExitProcess isn't it just executing several lines of assembly language in a subroutine in another module? I guess one of the things I was curious about was what the precise few lines of assembly were that were required to exit vs. making the subroutine call. Additionally, trying to get a feel for the sections required by fasm. Looks like they all start out with: format PE GUI entry start section '.code' code readable executable followed by instructions, followed by the data section. In a book I've got on Turbo Assembler, the data section comes before the code section, which makes more sense to me, but I'll get used to fasm's different order of sections. Is there a document that can guide me through these most basic aspects of fasm (so as not to have you kind folks lead me by the hand)? I appreciate the help!!! Thanks, Jay |
|||
12 Oct 2009, 02:49 |
|
birdus 12 Oct 2009, 02:53
As a quick followup, in the DOS examples I see in the book I'm looking at, each program ends with:
Exit: mov ah, 04Ch mov al, 0 int 21h I was just assuming that a program written for fasm (even for Windows) would end with something similar. Is this way off base? Thanks, Jay |
|||
12 Oct 2009, 02:53 |
|
birdus 12 Oct 2009, 02:57
One more thing. Is there a simple example console app I can look at somewhere? Maybe something like hello, world? Again, right now, just going for ultra simple so I can get a grip on the basic layout of a fasm app. Then I'll have a framework to begin learning about registers, jumps, control structures, etc.
Thanks, Jay |
|||
12 Oct 2009, 02:57 |
|
revolution 12 Oct 2009, 03:23
birdus: The order of sections is purely up to the programmers choice. You can put the data section first if you want to. You can have multiple data section with multiple code sections with an import section etc. all in one exe in whatever order you feel is suitable.
To make a console app just start with "format pe console". Then you can use the standard input and output functions to access the console. |
|||
12 Oct 2009, 03:23 |
|
birdus 12 Oct 2009, 04:18
Thanks, revolution!
Jay |
|||
12 Oct 2009, 04:18 |
|
sleepsleep 12 Oct 2009, 06:09
i would suggest u try using the win32ax.inc
they speed up the job and well, save time and our brain damages. |
|||
12 Oct 2009, 06:09 |
|
Uwar 12 Oct 2009, 21:55
The extremly simple APP (no includes, no invokes)
Code: ; NAKED WIN32APP in FASM format PE GUI entry main struc WNDCLASSEX{ .cbsize dd 0x00000000 .style dd 0x00000000 .lpfnwndproc dd 0x00000000 .cbclsextra dd 0x00000000 .cbwndextra dd 0x00000000 .hinstance dd 0x00000000 .hicon dd 0x00000000 .hcursor dd 0x00000000 .hbrbackground dd 0x00000000 .lpszmenuname dd 0x00000000 .lpszclassname dd 0x00000000 .hiconsm dd 0x00000000 } struc POINT{ .x dd 0x00000000 .y dd 0x00000000 } struc MSG{ .hwnd dd 0x00000000 .message dd 0x00000000 .wparam dd 0x00000000 .lparam dd 0x00000000 .time dd 0x00000000 .pt POINT } section '.code' code readable executable ;------------------------------------------------------------------------------ wndproc: push ebp mov ebp,esp cmp dword [ebp + 0x0C], 0x00000002 jz case_WM_DESTROY cmp dword [ebp + 0x0C], 0x00000201 jz case_WM_LBUTTONDOWN push case_DEFAULT retn case_WM_DESTROY: push 0x00000000 call [user32.PostQuitMessage] mov eax, 0x00000000 leave retn 0x0010 case_WM_LBUTTONDOWN: push 0x00000000 push sz_wndcaption push sz_message push 0x00000000 call [user32.MessageBoxA] mov eax, 0x00000000 leave retn 0x0010 case_DEFAULT: mov eax, [ebp + 0x08] mov ebx, [ebp + 0x0C] mov ecx, [ebp + 0x10] mov edx, [ebp + 0x14] push edx push ecx push ebx push eax call [user32.DefWindowProcA] leave retn 0x0010 ;------------------------------------------------------------------------------ winmain: push ebp mov ebp, esp mov dword [wndclass.cbsize], 0x00000030 mov dword [wndclass.style], 0x00000003 mov dword [wndclass.lpfnwndproc], wndproc mov dword [wndclass.cbclsextra], 0x00000000 mov dword [wndclass.cbwndextra], 0x00000000 push dword [hinstance] pop dword [wndclass.hinstance] push 0x00007F00 push 0x00000000 call [user32.LoadIconA] mov [wndclass.hicon], eax mov [wndclass.hiconsm], eax push 0x00007F00 push 0x00000000 call [user32.LoadCursorA] mov [wndclass.hcursor], eax mov dword [wndclass.hbrbackground], 0x00000006 mov dword [wndclass.lpszmenuname], 0x00000000 mov dword [wndclass.lpszclassname], sz_wndcls push wndclass call [user32.RegisterClassExA] push 0x00000000 push dword [ebp + 0x08] push 0x00000000 push 0x00000000 push 0x00000258 push 0x00000320 push 0x00000000 push 0x00000000 push 0x00CF0000 push sz_wndcaption push sz_wndcls push 0x00000000 call [user32.CreateWindowExA] mov [hwnd], eax push 0x00000001 push dword [hwnd] call [user32.ShowWindow] push dword[hwnd] call [user32.UpdateWindow] messagepump: push 0x00000000 push 0x00000000 push 0x00000000 push msg call [user32.GetMessageA] cmp eax, 0x00000000 jz winmainend push msg call [user32.TranslateMessage] push msg call [user32.DispatchMessageA] push messagepump retn winmainend: mov eax,[msg.wparam] leave retn 0010h ;------------------------------------------------------------------------------ main: push 0x00000000 call [kernel32.GetModuleHandleA] mov [hinstance], eax call [kernel32.GetCommandLineA] mov [cmdline], eax push 0x000000A push dword [cmdline] push 0x00000000 push dword [hinstance] call winmain push 0x00000000 call [kernel32.ExitProcess] ;------------------------------------------------------------------------------ section '.data' data readable writeable ;------------------------------------------------------------------------------ hinstance: dd 0x00000000 cmdline: dd 0x00000000 hwnd: dd 0x00000000 ;------------------------------------------------------------------------------ wndclass WNDCLASSEX msg MSG ;------------------------------------------------------------------------------ sz_wndcls: db 'wndcls', 0 sz_wndcaption: db '<caption>',0 sz_message: db 'Received click "message".',0 ;------------------------------------------------------------------------------ section '.eimport' import data readable writable ;------------------------------------------------------------------------------ dd 0,0,0, RVA kernel_name, RVA kernel_table dd 0,0,0, RVA user_name, RVA user_table dd 0,0,0,0,0 ; end kernel_table: kernel32.ExitProcess dd RVA ExitProcess kernel32.GetCommandLineA dd RVA GetCommandLineA kernel32.GetModuleHandleA dd RVA GetModuleHandleA dd 0x00000000 ; end user_table: user32.MessageBoxA dd RVA MessageBoxA user32.LoadIconA dd RVA LoadIconA user32.LoadCursorA dd RVA LoadCursorA user32.DefWindowProcA dd RVA DefWindowProcA user32.RegisterClassExA dd RVA RegisterClassExA user32.CreateWindowExA dd RVA CreateWindowExA user32.PostQuitMessage dd RVA PostQuitMessage user32.ShowWindow dd RVA ShowWindow user32.UpdateWindow dd RVA UpdateWindow user32.GetMessageA dd RVA GetMessageA user32.TranslateMessage dd RVA TranslateMessage user32.DispatchMessageA dd RVA DispatchMessageA dd 0x00000000 ; end kernel_name db 'KERNEL32.DLL', 0 user_name db 'USER32.DLL', 0 ; kernel32 imports ExitProcess dw 0 db 'ExitProcess', 0 GetCommandLineA dw 0 db 'GetCommandLineA', 0 GetModuleHandleA dw 0 db 'GetModuleHandleA', 0 ; user32 imports MessageBoxA dw 0 db 'MessageBoxA', 0 LoadIconA dw 0 db 'LoadIconA', 0 LoadCursorA dw 0 db 'LoadCursorA', 0 DefWindowProcA dw 0 db 'DefWindowProcA', 0 RegisterClassExA dw 0 db 'RegisterClassExA', 0 CreateWindowExA dw 0 db 'CreateWindowExA', 0 PostQuitMessage dw 0 db 'PostQuitMessage', 0 ShowWindow dw 0 db 'ShowWindow', 0 UpdateWindow dw 0 db 'UpdateWindow', 0 GetMessageA dw 0 db 'GetMessageA', 0 TranslateMessage dw 0 db 'TranslateMessage', 0 DispatchMessageA dw 0 db 'DispatchMessageA', 0 ;------------------------------------------------------------------------------ |
|||
12 Oct 2009, 21:55 |
|
LocoDelAssembly 12 Oct 2009, 22:18
Uwar, an small contribution:
Code: ;------------------------------------------------------------------------------ wndproc: cmp dword [esp + 0x08], 0x00000002 je case_WM_DESTROY cmp dword [esp + 0x08], 0x00000201 je case_WM_LBUTTONDOWN jmp [user32.DefWindowProcA] ; WARNING: THIS IS POSSIBLE ONLY BECAUSE THIS FUNCTION HAS THE SAME PROTOTYPE WNDPROC HAS case_WM_DESTROY: push 0x00000000 call [user32.PostQuitMessage] xor eax, eax retn 0x0010 case_WM_LBUTTONDOWN: push 0x00000000 push sz_wndcaption push sz_message push 0x00000000 call [user32.MessageBoxA] xor eax, eax retn 0x0010 ;------------------------------------------------------------------------------ Unless you have an specific purpose for those PUSH label/RETN, you better use JMP label instead, it is much more efficient (not only for the extra instruction and memory read and write, but also because you sabotage the return buffer because of that unpaired RETN with a CALL) |
|||
12 Oct 2009, 22:18 |
|
birdus 13 Oct 2009, 01:22
Wow!!! So that's like the most basic C app back in the early days of Windows development! I.e., before wrapping all the details in a class library.
Of course it's not nearly the simplest asm app you can build for fasm, but it's still very interesting! I guess it IS the simplest WINDOWS app (i.e., app with a window, or, non-console app) you can build (without using libraries). Quite educational for me! Thanks!!! Jay |
|||
13 Oct 2009, 01:22 |
|
bitshifter 13 Oct 2009, 03:57
Hi birdus, welcome to FASM forum, its nice to see new members
Learning ASM and Win32 are two totally different things... You will pull your hair out trying to learn them both at same time. Learning Win32 is best viewed in its native language, C. http://winprog.org/tutorial/ After, you can easily identify with ASM. http://win32assembly.online.fr/tutorials.html Also there are nice examples in FASM/EXAMPLES folder. |
|||
13 Oct 2009, 03:57 |
|
birdus 13 Oct 2009, 05:08
Thanks for the welcome, bitshifter.
Right now, I am definitely interested ONLY in learning assembly language! I did find the Windows example fun and interesting, though! Thanks for the links. Jay |
|||
13 Oct 2009, 05:08 |
|
Uwar 13 Oct 2009, 14:03
Of course it is a super simple GUI Windows App.
Previous listing with the local variables and improvements suggested by LocoDelAssembly: Code: format PE GUI entry main ; windows constants CS_HREDRAW = 0x00000002 CS_VREDRAW = 0x00000001 IDC_ARROW = 0x00007F00 IDI_APPLICATION = 0x00007F00 WS_OVERLAPPEDWINDOW = 0x00CF0000 SW_SHOWDEFAULT = 0x0000000A WM_CREATE = 0x00000001 WM_DESTROY = 0x00000002 MB_ICONERROR = 0x00000010 section '.code' code readable executable ;------------------------------------------------------------------------------ showerror: push EBP mov EBP, ESP ; CHAR [0x10] l_buff ; STRING l_sz_buff = &l_buff sub ESP, 0x14 .l_sz_buff equ EBP - 0x14 .l_buff equ EBP - 0x10 lea EAX, [.l_buff] mov dword [.l_sz_buff], EAX call [kernel32.getLastError] push EAX push .sz_fmt push dword [.l_sz_buff] call [user32.wsprintf] add ESP, 0x0C ; cleans up the stack after CDECL user32.wsprintf push MB_ICONERROR push .sz_caption push dword [.l_sz_buff] push 0x00000000 call [user32.messageBox] leave retn .sz_fmt db '0x%08X', 0x00 ; static const .sz_caption db 'Msg', 0x00 ; static const ;------------------------------------------------------------------------------ wndproc: ; (o_hwnd : HANDLE, o_hmsg : HANDLE, o_wparam : DWORD, o_lparam : DWORD) : DWORD push EBP mov EBP, ESP .o_hwnd equ EBP + 0x08 .o_hmsg equ EBP + 0x0C .o_wparam equ EBP + 0x10 .o_lparam equ EBP + 0x14 cmp dword [.o_hmsg], WM_DESTROY je .case_WM_DESTROY leave jmp [user32.defWindowProc] .end: leave retn 0x10 .case_WM_DESTROY: push dword 0x00000000 call [user32.postQuitMessage] xor EAX, EAX jmp .end ;------------------------------------------------------------------------------ winmain: ; (o_hinstance : HANDLE, o_hprevinstance : HANDLE, o_sz_cmdline : STRING , o_cmdshow : DWORD) : DWORD push EBP mov EBP, ESP .o_hinstance equ EBP + 0x08 .o_hprevinstance equ EBP + 0x0C ; obsolete .o_sz_cmdline equ EBP + 0x10 .o_cmdshow equ EBP + 0x14 ; WNDCLASSEX l_wndclassex ; HANDLE l_hwndclassex = &l_wndclassex ; MSG l_msg ; HANDLE l_hmsg = &l_msg ; HANDLE l_hwnd sub ESP, 0x58 .l_hwnd equ EBP - 0x58 ; HANDLE sizeof 0x04 .l_hmsg equ EBP - 0x54 ; HANDLE sizeof 0x04 .l_msg.hwnd equ EBP - 0x50 ; struct MSG sizeof 0x1C .l_msg.message equ EBP - 0x4C .l_msg.wparam equ EBP - 0x48 .l_msg.lparam equ EBP - 0x44 .l_msg.time equ EBP - 0x40 .l_msg.pt.x equ EBP - 0x3C .l_msg.pt.y equ EBP - 0x38 .l_hwndclassex equ EBP - 0x34 ; HANDLE sizeof 0x04 .l_wndclassex.size equ EBP - 0x30 ; struct WNDCLASSEX sizeof 0x30 .l_wndclassex.style equ EBP - 0x2C .l_wndclassex.wndproc equ EBP - 0x28 .l_wndclassex.clsextrabytes equ EBP - 0x24 .l_wndclassex.wndextrabytes equ EBP - 0x20 .l_wndclassex.hinstance equ EBP - 0x1C .l_wndclassex.hicon equ EBP - 0x18 .l_wndclassex.hcursor equ EBP - 0x14 .l_wndclassex.hbrbackground equ EBP - 0x10 .l_wndclassex.menuname equ EBP - 0x0C .l_wndclassex.classname equ EBP - 0x08 .l_wndclassex.hiconsm equ EBP - 0x04 lea EAX, [EBP - 0x30] mov dword [.l_hwndclassex], EAX lea EAX, [EBP - 0x50] mov dword [.l_hmsg ], EAX ; l_wndclassex.size = 0x00000030 mov dword [.l_wndclassex.size], 0x00000030 ; l_wndclassex.style = CS_VREDRAW | CS_HREDRAW mov dword [.l_wndclassex.style], CS_HREDRAW or CS_VREDRAW; ; l_wndclassex.wndproc = &defwndproc mov dword [.l_wndclassex.wndproc], wndproc ; l_wndclassex.clsextrabytes = 0x00000000 mov dword [.l_wndclassex.clsextrabytes], 0x00000000 ; wndclassex.wndextrabytes = 0x00000000 mov dword [.l_wndclassex.wndextrabytes], 0x00000000 ; l_wndclass.hinstance = o_hinstance push dword [.o_hinstance] pop dword [.l_wndclassex.hinstance] ; l_wndclassex.hicon = wndclassex.hiconsm = user32.loadIcon(0x00000000, 0x00007F00) push dword IDI_APPLICATION push dword 0x00000000 call [user32.loadIcon] mov dword [.l_wndclassex.hicon ], EAX mov dword [.l_wndclassex.hiconsm], EAX ; l_wndclassex.hcursor = user32.loadCursor(0x00000000, 0x00007F00) push dword IDC_ARROW push dword 0x00000000 call [user32.loadCursor] mov dword [.l_wndclassex.hcursor], EAX ; l_wndclassex.hbrbackground = gdi32.getStockObject(0x00000000) push dword 0x00000000 call [gdi32.getStockObject] mov dword [.l_wndclassex.hbrbackground], EAX ; l_wndclassex.menuname = 0x00000000 mov dword [.l_wndclassex.menuname], 0x00000000 ; l_wndclassex.classname = .sz_clsname mov dword [.l_wndclassex.classname], .sz_clsname ; registerClassEx(l_wndclassex) push dword [.l_hwndclassex] call [user32.registerClassEx] cmp EAX, 0x00000000 je .error ; l_hwnd = createWindowEx( ; 0x00000000, ; l_wndclassex.classname, ; &sz_wndcaption, ; WS_OVERLAPPEDWINDOW, ; 0x00000000, ; 0x00000000, ; 0x00000320, ; 0x00000258, ; 0x00000000, ; 0x00000000, ; o_hinstance, ; 0x00000000, ; ) push dword 0x00000000 push dword [.o_hinstance] push dword 0x00000000 push dword 0x00000000 push dword 0x00000258 push dword 0x00000320 push dword 0x00000000 push dword 0x00000000 push dword WS_OVERLAPPEDWINDOW push .sz_wndcaption push dword [.l_wndclassex.classname] push dword 0x00000000 call [user32.createWindowEx] cmp EAX, 0x00000000 je .error mov [.l_hwnd], EAX ; user32.showWindow(l_hwnd, o_cmdshow) push dword [.o_cmdshow] push dword [.l_hwnd ] call [user32.showWindow] ; user32.updateWindow(l_hwnd) push dword [.l_hwnd] call [user32.updateWindow] cmp EAX, 0x00000000 je .error .msgpump: ; if(user32.getMessage(l_msg, 0x00, 0x00, 0x00) == 0x00) jump .end push dword 0x00000000 push dword 0x00000000 push dword 0x00000000 push dword [.l_hmsg] call [user32.getMessage] cmp EAX, 0x00000000 je .end ; user32.translateMessage(l_msg) push dword [.l_hmsg] call [user32.translateMessage] ; user32.DispatchMessageA(&msg) push dword [.l_hmsg] call [user32.dispatchMessage] ; jump msgpump jmp .msgpump .end: mov EAX, [.l_msg.wparam] leave retn 0x10 .error: call showerror jmp .end .sz_clsname db 'clsname', 0x00 ; static const .sz_wndcaption db 'windowdemo', 0x00 ; static const ;------------------------------------------------------------------------------ main: ; () : VOID push ebp mov ebp, esp ; winmain( ; kernel32.getModuleHandle(0x00000000), ; 0x00000000, ; kernel32.getCommandLineA(), ; SW_SHOWDEFAULT ; ) push dword SW_SHOWDEFAULT call [kernel32.getCommandLine] cmp EAX, dword 0x00000000 je .error push EAX push dword 0x00000000 push dword 0x00000000 call [kernel32.getModuleHandle] cmp EAX, dword 0x00000000 je .error push EAX call winmain .end: ; return 0 push dword 0x00000000 call [kernel32.exitProcess] leave .error: call showerror jmp .end ;------------------------------------------------------------------------------ section '.data' data readable writeable ;------------------------------------------------------------------------------ db 0x00 ; to prevent empty data section in PE ;------------------------------------------------------------------------------ section '.eimport' import data readable writable ;------------------------------------------------------------------------------ dd 0,0,0, RVA sz_kernel32!dll, RVA kernel32 dd 0,0,0, RVA sz_user32!dll, RVA user32 dd 0,0,0, RVA sz_gdi32!dll, RVA gdi32 dd 0,0,0, 0, 0 ; end kernel32: .exitProcess dd RVA kernel32!dll.ExitProcess .getCommandLine dd RVA kernel32!dll.GetCommandLineA .getModuleHandle dd RVA kernel32!dll.GetModuleHandleA .getLastError dd RVA kernel32!dll.GetLastError dd 0x00000000 ; end user32: .messageBox dd RVA user32!dll.MessageBoxA .loadIcon dd RVA user32!dll.LoadIconA .loadCursor dd RVA user32!dll.LoadCursorA .defWindowProc dd RVA user32!dll.DefWindowProcA .registerClassEx dd RVA user32!dll.RegisterClassExA .createWindowEx dd RVA user32!dll.CreateWindowExA .postQuitMessage dd RVA user32!dll.PostQuitMessage .showWindow dd RVA user32!dll.ShowWindow .updateWindow dd RVA user32!dll.UpdateWindow .getMessage dd RVA user32!dll.GetMessageA .translateMessage dd RVA user32!dll.TranslateMessage .dispatchMessage dd RVA user32!dll.DispatchMessageA .wsprintf dd RVA user32!dll.wsprintfA dd 0x00000000 ; end gdi32: .getStockObject dd RVA gdi32!dll.GetStockObject dd 0x00000000 ; end sz_kernel32!dll db 'KERNEL32.DLL', 0 sz_user32!dll db 'USER32.DLL', 0 sz_gdi32!dll db 'GDI32.DLL', 0 ; kernel32 imports kernel32!dll: .ExitProcess dw 0 db 'ExitProcess', 0 .GetCommandLineA dw 0 db 'GetCommandLineA', 0 .GetModuleHandleA dw 0 db 'GetModuleHandleA', 0 .GetLastError dw 0 db 'GetLastError', 0 ; user32 imports user32!dll: .MessageBoxA dw 0 db 'MessageBoxA', 0 .LoadIconA dw 0 db 'LoadIconA', 0 .LoadCursorA dw 0 db 'LoadCursorA', 0 .DefWindowProcA dw 0 db 'DefWindowProcA', 0 .RegisterClassExA dw 0 db 'RegisterClassExA', 0 .CreateWindowExA dw 0 db 'CreateWindowExA', 0 .PostQuitMessage dw 0 db 'PostQuitMessage', 0 .ShowWindow dw 0 db 'ShowWindow', 0 .UpdateWindow dw 0 db 'UpdateWindow', 0 .GetMessageA dw 0 db 'GetMessageA', 0 .TranslateMessage dw 0 db 'TranslateMessage', 0 .DispatchMessageA dw 0 db 'DispatchMessageA', 0 .wsprintfA dw 0 db 'wsprintfA', 0 ; gdi32 imports gdi32!dll: .GetStockObject dw 0 db 'GetStockObject', 0 ;------------------------------------------------------------------------------ |
|||
13 Oct 2009, 14:03 |
|
Alphonso 13 Oct 2009, 15:41
Hi birdus and welcome to asm. I think it's the invokes and includes that are what actually make it ultra simple. I'm not a professional programmer and don't know C but having tried some of the other assemblers have found FASM is very intuitive and easy to learn, at least for the basic stuff I use it for.
Pinecone_ wrote:
Still, if it works then we could add the API's as required. Here's a rough snippet with no includes, invokes or imports even to display a 'Goodbye' Messagebox. Code: format PE GUI 4.0 entry start section '.code' code readable executable start: mov esi,[esp] and esi,0ffff0000h ;Alignment is searches best friend @@: mov ax,[esi] cmp ax,'MZ' je PossibleStart ;Look for start of Kernel32.dll sub esi,10000h ;64k byte alignment jnz @b ret ;Failed?, probably crash before this PossibleStart : mov ebx,[esi+3ch] ;offset to PE [MZ + 3Ch] cmp dword [esi+ebx],'PE' ;If MZ start then PE header should be here jne @b ;Fluke MZ, try again mov eax,[esi+ebx+78h] ;Export Table mov ecx,[esi+eax+4*6] ;No. of Names mov edi,[esi+eax+4*7] ;Address Table mov ebx,[esi+eax+4*8] ;Name Pointer Table mov ebp,[esi+eax+4*9] ;Ordinal Table mov edx,ebx ;EDX = Name Pointer Table @@: mov eax,[esi+ebx] ;Get Name Pointer and search cmp dword[esi+eax],'GetP' ;for GetProcessAddress in Name Pointer Table je Found_GetP add ebx,4 loop @b ;Just in case cant find it ret ;give up Found_GetP: cmp dword[esi+eax+4],'rocA' je Found_rocA add ebx,4 jmp @b Found_rocA: cmp dword[esi+eax+8],'ddre' je Found_ddre add ebx,4 jmp @b Found_ddre: ;good enough or should we check for 'ss,0'? sub ebx,edx ;Name Pointer Table offset to GetProcessAddress 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 push LoadLibrary push esi call edi ;GetProcAddress,kernel32.dll,LoadLibraryA push u32 call eax ;LoadLibrary,user32.dll push MessageBox push eax call edi ;GetProcAddress,user32.dll,MessageBoxA push 0 push Caption push Message push 0 call eax ;MessageBox,0,Message,Caption,0 ret ;lookup ExitProcess if you want it :p MessageBox db 'MessageBoxA',0 LoadLibrary db 'LoadLibraryA',0 u32 db 'user32.dll',0 Caption db 'Hello',0 Message db 'Goodbye',0 |
|||
13 Oct 2009, 15:41 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.