views:

115

answers:

4

Hi guys,

I'm trying to call MessageBoxA() directly in assembly, using gcc inline. However I need to do this in 2 ways: first is using dynamic addressing, with LoadLibrary() and GetProcAddress() - I found a tutorial about this, trying to follow it. But I'm also interested in calling directly the address of MessageBoxA, wich is 0x7e4507ea in my Windows SP3 English.

I'm trying to execute this code:

/*
 *    eax holds return value
 *    ebx will hold function addresses
 *    ecx will hold string pointers
 *    edx will hold NULL
 *
 */


int main(int argc, char **argv)
{
asm("   xor %eax, %eax          \t\n\
        xor %ebx, %ebx          \t\n\
        xor %ecx, %ecx          \t\n\
        xor %edx, %edx          \t\n\
        push $0x0               \t\n\
        push $0x44444444        \t\n\
        push $0x44444444        \t\n\
        pop %ecx                \t\n\
        mov %dl,0x3(%ecx)       \t\n\
        mov $0x7e4507ea, %ebx   \t\n\
        push   %edx             \t\n\
        push   %ecx             \t\n\
        push   %ecx             \t\n\
        push   %edx             \t\n\
        mov $0x8, %ax           \t\n\
        call *%ebx              \t\n\
        ");
}

I'm not sure if in Windows is even possible to do this, directly call the address, without specifying the library (user32.dll in this case). I know in Linux it's simple to call write() syscall, but in Windows I'm not so familiar yet..

I expect to see a message box with "DDDDDDDD". Could someone help me on that please? Appreciate any help, with tutorial links also!

Thanks a lot

+2  A: 

Write it in C first, compile and view the assembly listing to see what the compiler generated. This is the easiest way to learn. If you see an instruction that you don't understand look for it in the Intel Instruction Set Reference PDFs.

James
@James: I tried to do so, but that's not so simple. I compiled this way: gcc -c msgbox3.c -static -mpreferred-stack-boundary=2 . But the object file I've got contains some assembly instructions that didn't help so much...anyway thanks for posting.
jyzuz
@jyzuz: there's a good reason why in school you learned to read before you learned to write. For computer languages, the same holds. If you can't read assembly, you shoudln't try to write it.
MSalters
@MSalters: I'm learning reading/writing in assembly with Richard Blum book (for Linux). And also learning Windows assembly reading some articles on Internet. I think that best way to learn is to read )
jyzuz
+1  A: 

directly call the address

Sounds like a big no-no. API calls do not have a fixed address. It depends on where in memory it got loaded. Although I'm sure User32.dll is loaded at OS start-up, I wouldn't count on it ever occupying the same space.

To call an API routine, you must import it so the OS can supply you with a correct address to the call.

Jens Björnhager
@Jens: but that's kind strange, because I'm doing some tests here for some weeks, and every time I look for the address of MessageBoxA in user32.dll it returns 0x7e4507ea. Does it means that this is the address of MessageBoxA inside user32.dll or in memory?
jyzuz
`0x7e4507ea` is the address in your process space. It's reasonable stable for two reasons: First, user32.dll itself loads very early. Hence, it tends to load at the same spot every time. DLLs that load later will have to take whatever address if left. Secondly, user32.dll typically changes only when Microsoft fixed a bug in it, which isn't every week - certainly not for XP SP3, where only security bugs are fixed.
MSalters
Still a bad idea, much like calling by ordinal.
Jens Björnhager
+1  A: 

"Directly" calling MessageBoxA isn't really possible. Yes, you can add a call to 0x7e4507ea, but it doesn't really matter. You must add an entry to your Import Address Table, which says that you're calling MessageBoxA from user32.dll, and from where. When Windows loads your executable, it will see that you're calling MessageBoxA, load user32.dll for you, and patch up the actual address where MessageBoxA ended.

MSalters
@MSalters: OK I think I got it. I know that Windows Executable is completely different from Linux ELF files. This "Import Address Table" is a session in the Windows Executable file , right? I'll read more about this.. thanks for answering
jyzuz
Yes, and also known as the "IAT" section
MSalters
@MSalters: In fact it's possible. And now I'm able to do this :)
jyzuz
+2  A: 

I did this in this way:

int main ()
{
    asm("xorl %eax, %eax        \n"
        "xorl %ebx, %ebx        \n"
        "xorl %ecx, %ecx        \n"
        "xorl %edx, %edx        \n"
        "pushl %ecx             \n"
        "pushl $0x20206c6c      \n"
        "pushl $0x642e3233      \n"
        "pushl $0x72657375      \n"
        "movl %esp, %ecx        \n"
        "movl $0x7c801d7b, %ebx \n"
        "pushl %ecx             \n"
        "call *%ebx             \n"
        "movl $0xef30675e, %ecx \n"
        "addl $0x11111111, %ecx \n"
        "pushl %ecx             \n"
        "pushl $0x42656761      \n"
        "pushl $0x7373654d      \n"
        "movl %esp, %ecx        \n"
        "pushl %ecx             \n"
        "pushl %eax             \n"
        "movl $0x7c80ae40, %ebx \n"
        "call *%ebx             \n"
        "movl %esp, %ecx        \n"
        "xorl %edx, %edx        \n"
        "pushl %edx             \n"
        "pushl %ecx             \n"
        "pushl %ecx             \n"
        "pushl %edx             \n"
        "call *%eax             \n"
        "xorl %eax, %eax        \n"
        "pushl %eax             \n"
        "movl $0x7c81cb12, %eax \n"
        "call *%eax             \n"
    );
}

Even tough is perfectly possible to hardcode the addresses of the functions, I preferred to load dynamically, so that it works on any Windows (although I'm hardcoding kernel32 address)

jyzuz