MessageBoxA в сборке Windows AT&T

Я пытаюсь вызвать MessageBoxA() непосредственно в сборке, используя встроенный gcc. Однако мне нужно сделать это двумя способами: во-первых, использовать динамическую адресацию с помощью LoadLibrary() и GetProcAddress() - я нашел руководство по этому поводу, пытаясь следовать ему. Но я также заинтересован в том, чтобы позвонить напрямую по адресу MessageBoxA, который равен 0x7e4507ea в моем Windows SP3 English.

Я пытаюсь выполнить этот код:

/*
 *    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\
        ");
}

Я не уверен, возможно ли это сделать в Windows, напрямую вызывая адрес, не указывая библиотеку (в данном случае user32.dll). Я знаю, что в Linux просто вызвать системный вызов write(), но в Windows я еще не так хорошо знаком.

Я ожидаю увидеть окно сообщения с "DDDDDDDD". Может ли кто-нибудь помочь мне в этом, пожалуйста? Благодарим за любую помощь, включая ссылки на учебники!

Большое спасибо


person jyz    schedule 08.09.2010    source источник
comment
Эй, как вы упомянули в комментарии, вы сделали это. Не могли бы вы описать мне, как вы ладите с IAT? в приведенном выше примере   -  person Mohammad Sina Karvandi    schedule 03.11.2016


Ответы (4)


Сначала напишите его на C, скомпилируйте и просмотрите листинг сборки, чтобы увидеть, что сгенерировал компилятор. Это самый простой способ научиться. Если вы видите инструкцию, которую не понимаете, найдите ее в PDF-файлах Intel Instruction Set Reference.

person James    schedule 08.09.2010
comment
Я пытался так сделать, но это не так просто. Я скомпилировал так: gcc -c msgbox3.c -static -mpreferred-stack-boundary=2 . Но объектный файл, который у меня есть, содержит некоторые инструкции по сборке, которые не очень помогли... в любом случае, спасибо за публикацию. - person jyz; 09.09.2010
comment
@jyzuz: есть веская причина, по которой в школе ты научился читать, прежде чем научился писать. То же самое верно и для компьютерных языков. Если вы не умеете читать ассемблер, не пытайтесь его написать. - person MSalters; 09.09.2010
comment
@MSalters: я учусь читать/писать на ассемблере по книге Ричарда Блюма (для Linux). А также изучаю сборку Windows, читая статьи в Интернете. Я думаю, что лучший способ учиться — это читать и практиковаться. Я не могу записать, когда я был ребенком, если я сначала стал экспертом в чтении, прежде чем написать слово ... но я думаю, что вы никогда не научитесь программированию, не пытаясь и не делая ошибок. Может быть, я пытаюсь бежать быстрее, чем мои ноги... ну... мне очень любопытно, хе-хе ;) - person jyz; 09.09.2010

Я сделал это следующим образом:

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"
    );
}

Даже жесткие вполне можно хардкодить адреса функций, я предпочитал загружать динамически (хотя я хардкодим адрес ядра32), чтобы работало на любой Windows XP (SP1, 2, 3)

person jyz    schedule 18.10.2010
comment
Рандомизация адресного пространства в значительной степени меняет эту картину. Жестко запрограммированные адреса и сбой стали синонимами. - person IInspectable; 28.03.2015

сразу звоните по адресу

Звучит как большое нет-нет. Вызовы API не имеют фиксированного адреса. Это зависит от того, где в памяти он был загружен. Хотя я уверен, что User32.dll загружается при запуске ОС, я бы не стал рассчитывать, что он когда-либо займет одно и то же место.

Чтобы вызвать подпрограмму API, вы должны импортировать ее, чтобы ОС могла предоставить вам правильный адрес для вызова.

person Jens Björnhager    schedule 09.09.2010
comment
но это довольно странно, потому что я провожу здесь несколько тестов уже несколько недель, и каждый раз, когда я ищу адрес MessageBoxA в user32.dll, он возвращает 0x7e4507ea. Означает ли это, что это адрес MessageBoxA внутри user32.dll или в памяти? - person jyz; 09.09.2010
comment
0x7e4507ea — это адрес в пространстве вашего процесса. Он достаточно стабилен по двум причинам: во-первых, сам user32.dll загружается очень рано. Следовательно, он имеет тенденцию загружаться в одном и том же месте каждый раз. DLL, которые загружаются позже, должны будут взять любой адрес, если он останется. Во-вторых, user32.dll обычно меняется только тогда, когда Microsoft исправляет в нем ошибку, что происходит не каждую неделю — уж точно не для XP SP3, где исправляются только ошибки безопасности. - person MSalters; 09.09.2010
comment
Все еще плохая идея, так же, как звонить по порядковому номеру. - person Jens Björnhager; 09.09.2010

«Напрямую» вызвать MessageBoxA на самом деле невозможно. Да, вы можете добавить вызов 0x7e4507ea, но это не имеет большого значения. Вы должны добавить запись в таблицу адресов импорта, в которой говорится, что вы звоните MessageBoxA из user32.dll и откуда. Когда Windows загрузит ваш исполняемый файл, она увидит, что вы вызываете MessageBoxA, загрузит для вас user32.dll и исправит фактический адрес, где заканчивается MessageBoxA.

person MSalters    schedule 09.09.2010
comment
ОК, думаю, я понял. Я знаю, что исполняемый файл Windows полностью отличается от файлов ELF для Linux. Эта таблица адресов импорта является сеансом в исполняемом файле Windows, верно? Я прочитаю об этом больше .. спасибо за ответ - person jyz; 09.09.2010
comment
Да, и также известный как раздел IAT - person MSalters; 10.09.2010
comment
На самом деле это возможно. И теперь я могу это сделать :) - person jyz; 07.10.2010