Прочитал одну статью - "Использование DLL в программе на Visual C++" http://rsdn.org/article/baseserv/dlluse.xml Про явное и не явное подключение библиотек к программному проекту ну и расказано про относительные минусы и плюсы этих подключений Про неявное подключение библиотек к проекту всё понятно этот принцип используется и в masm32 и в C++ то есть линкеру передается обьектный файл в котором прописаны файлы линковки с библиотеками импорта эти файлы линковки обычно имеет расширение - .lib Меня заинтересовало явное подключение библиотек при котором используются две функции LoadLibraryA и GetProcAddress Ну предположим что все остальные API функции в проекте можно подключить с помощью этого тандема функций то есть как бы использовать явное подключение этих библиотечных функций Но как быть с самими этими функциями LoadLibraryA и GetProcAddress ведь их то в проекте придётся подключать не явно то есть через файл линковки - Kernel.lib Или всё таки существует какой нибудь способ эти две функции тоже как то пристегнуть к проекту явным способом не используя файл линковки - Kernel.lib Кто в теме не подскажите
Из PEB узнать базовый адрес kernel32.dll в памяти и найти адреса этих двух функций в ее таблице экспорта.
Код (ASM): ; By SIGSEGV [BITS 32] pushad call CodeStart CodeStart: pop ebp sub ebp,CodeStart ; delta offset shit mov ebx, [FS : 0x30] ; get a pointer to the PEB mov ebx, [ebx + 0x0C] ; get PEB->Ldr mov ebx, [ebx + 0x14] ; get PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry) mov ebx, [ebx] ; 2nd Entry mov ebx, [ebx] ; 3rd Entry mov ebx, [ebx + 0x10] ; Get Kernel32 Base mov [ebp+dwKernelBase] , ebx add ebx, [ebx+0x3C] ; Start of PE header mov ebx, [ebx+0x78] ; RVA of export dir add ebx, [ebp+dwKernelBase] ; VA of export dir mov [ebp+dwExportDirectory] , ebx lea edx,[ebp+api_GetProcAddress] mov ecx,[ebp+len_GetProcAddress] call GetFunctionAddress mov [ebp+AGetProcAddressA] , eax lea edx,[ebp+api_LoadLibrary] push edx push dword [ebp+dwKernelBase] call eax mov [ebp+ALoadLibraryA] , eax lea edx , [ebp+szUser32] push edx call eax lea edx , [ebp+api_MessageBoxA] push edx push eax mov ebx,[ebp+AGetProcAddressA] call ebx mov [ebp+AMessageBoxAA] , eax push 0 lea edx,[ebp+szTitle] push edx lea edx,[ebp+szMsg] push edx push 0 call eax popad push 0xBBBBBBBB ;OEP retn ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; <<<<< GetFunctionAddress >>>>>> ; ; Extracts Function Address From Export Directory and returns it in eax ; ; Parameters : Function name in edx , Length in ecx ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GetFunctionAddress: push ebx push esi push edi mov esi, [ebp+dwExportDirectory] mov esi, [esi+0x20] ;RVA of ENT add esi, [ebp+dwKernelBase] ;VA of ENT xor ebx,ebx cld looper: inc ebx lodsd add eax , [ebp+dwKernelBase] ;eax now points to the string of a function push esi ;preserve it for the outer loop mov esi,eax mov edi,edx cld push ecx repe cmpsb pop ecx pop esi jne looper dec ebx mov eax,[ebp+dwExportDirectory] mov eax,[eax+0x24] ;RVA of EOT add eax,[ebp+dwKernelBase] ;VA of EOT movzx eax , word [ebx*2+eax] ;eax now holds the ordinal of our function mov ebx,[ebp+dwExportDirectory] mov ebx,[ebx+0x1C] ;RVA of EAT add ebx,[ebp+dwKernelBase] ;VA of EAT mov ebx,[eax*4+ebx] add ebx,[ebp+dwKernelBase] mov eax,ebx pop edi pop esi pop ebx ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Data Shit ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; szTitle: db "Yo !",0 szMsg: db "GreeTz From SIGSEGV",0 szUser32 db "User32.dll",0 AGetProcAddressA: dd 0 api_GetProcAddress: db "GetProcAddress" len_GetProcAddress: dd $-api_GetProcAddress ALoadLibraryA: dd 0 api_LoadLibrary: db "LoadLibraryA",0 AMessageBoxAA: dd 0 api_MessageBoxA: db "MessageBoxA",0 dwKernelBase: dd 0 dwExportDirectory: dd 0
Переписал под синтаксис - masm32 Код (ASM): .data szTitle db "Yo !",0 szMsg db "GreeTz From SIGSEGV",0 szUser32 db "User32.dll",0 api_LoadLibrary db "LoadLibraryA",0 api_GetProcAddress db "GetProcAddress" api_MessageBoxA db "MessageBoxA",0 ;---------------------------------------- AGetProcAddressA dd 0 len_GetProcAddress dd $-api_GetProcAddress ALoadLibraryA dd 0 AMessageBoxAA dd 0 dwKernelBase dd 0 dwExportDirectory dd 0 .code ;======================================== pushad call CodeStart CodeStart: pop ebp sub ebp,CodeStart ; delta offset shit mov ebx, [FS : 30h] ; get a pointer to the PEB mov ebx, [ebx + 0Ch] ; get PEB->Ldr mov ebx, [ebx + 14h] ; get PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry) mov ebx, [ebx] ; 2nd Entry mov ebx, [ebx] ; 3rd Entry mov ebx, [ebx + 10h] ; Get Kernel32 Base mov [ebp+dwKernelBase] , ebx add ebx, [ebx+3Ch] ; Start of PE header mov ebx, [ebx+78h] ; RVA of export dir add ebx, [ebp+dwKernelBase] ; VA of export dir mov [ebp+dwExportDirectory] , ebx lea edx,[ebp+api_GetProcAddress] mov ecx,[ebp+len_GetProcAddress] call GetFunctionAddress mov [ebp+AGetProcAddressA] , eax lea edx,[ebp+api_LoadLibrary] push edx push dword ptr[ebp+dwKernelBase] call eax mov [ebp+ALoadLibraryA] , eax lea edx , [ebp+szUser32] push edx call eax lea edx , [ebp+api_MessageBoxA] push edx push eax mov ebx,[ebp+AGetProcAddressA] call ebx mov [ebp+AMessageBoxAA] , eax push 0 lea edx,[ebp+szTitle] push edx lea edx,[ebp+szMsg] push edx push 0 call eax popad push 0BBBBBBBBh ;OEP retn ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; <<<<< GetFunctionAddress >>>>>> ; ; Extracts Function Address From Export Directory and returns it in eax ; ; Parameters : Function name in edx , Length in ecx ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GetFunctionAddress: push ebx push esi push edi mov esi, [ebp+dwExportDirectory] mov esi, [esi+20h] ;RVA of ENT add esi, [ebp+dwKernelBase] ;VA of ENT xor ebx,ebx cld looper: inc ebx lodsd add eax , [ebp+dwKernelBase] ;eax now points to the string of a function push esi ;preserve it for the outer loop mov esi,eax mov edi,edx cld push ecx repe cmpsb pop ecx pop esi jne looper dec ebx mov eax,[ebp+dwExportDirectory] mov eax,[eax+24h] ;RVA of EOT add eax,[ebp+dwKernelBase] ;VA of EOT movzx eax , word ptr [ebx*2+eax] ;eax now holds the ordinal of our function mov ebx,[ebp+dwExportDirectory] mov ebx,[ebx+1Ch] ;RVA of EAT add ebx,[ebp+dwKernelBase] ;VA of EAT mov ebx,[eax*4+ebx] add ebx,[ebp+dwKernelBase] mov eax,ebx pop edi pop esi pop ebx ret но в строке Код (ASM): mov ebx, [FS : 30h] ; get a pointer to the PEB компилятор выдал ошибку Код (Text): error A2108:use of register assumed to ERROR Не подскажите как правильно прописать эту строчку правильно под синтаксисом - masm32 Прошу прощения что прописал код не в специальном окне просто я не знаю как это делается, то есть как вставлять код в окно для кодинга
[сode=аsm] ... [/соdе] Модеры, запилите уже кнопочку "Код" на панели, чтобы при нажатии весь выделенный текст в теги оборачивался.
Спасибо rmn, за подсказку синтаксиса Там кажется дальше по коду как то нужно будет освободить регистр - ebx или - fs а может быть я что то путаю короче буду вспоминать и дальше разбиратся с кодом За подсказку про теги для кода отдельное спасибо Честно говоря для меня это тоже удивительно Для уважаемого форума это мягко говоря более чем странно
Ещё раз собрал код под синтаксис - masm32 Вместо меток засунул код в функции Подставил теги но видно не правильно так что опять извиняюсь Код (ASM): ;======================================== .data szTitle db "Yo !",0 szMsg db "GreeTz From SIGSEGV",0 szUser32 db "User32.dll",0 api_LoadLibrary db "LoadLibraryA",0 api_GetProcAddress db "GetProcAddress" api_MessageBoxA db "MessageBoxA",0 ;---------------------------------------- AGetProcAddressA dd 0 len_GetProcAddress dd $-api_GetProcAddress ALoadLibraryA dd 0 AMessageBoxAA dd 0 dwKernelBase dd 0 dwExportDirectory dd 0 ;======================================== .code call CodeStart push 0 call ExitProcess ;======================================== CodeStart proc ;---------------------------------------- pushad assume fs:nothing mov ebx, fs:[30h] ;48 get a pointer to the PEB mov ebx, [ebx + 0Ch] ;12 get PEB->Ldr mov ebx, [ebx + 14h] ;20 get PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry) mov ebx, [ebx] ; 2nd Entry mov ebx, [ebx] ; 3rd Entry mov ebx, [ebx + 10h] ;16 Get Kernel32 Base mov dwKernelBase , ebx add ebx, [ebx+3Ch] ;60 Start of PE header mov ebx, [ebx+78h] ;120 RVA of export dir add ebx, dwKernelBase ; VA of export dir mov dwExportDirectory , ebx lea edx,api_GetProcAddress mov ecx,len_GetProcAddress call GetFunctionAddress mov AGetProcAddressA , eax lea edx,api_LoadLibrary push edx push dwKernelBase call eax mov ALoadLibraryA , eax lea edx , szUser32 push edx call eax lea edx , api_MessageBoxA push edx push eax mov ebx,AGetProcAddressA call ebx mov AMessageBoxAA , eax push 0 lea edx,szTitle push edx lea edx,szMsg push edx push 0 call eax popad ;---------------------------------------- ret CodeStart endp ;======================================== GetFunctionAddress proc ;---------------------------------------- push ebx push esi push edi mov esi, dwExportDirectory mov esi, [esi+20h] ;32 RVA of ENT add esi, dwKernelBase ;VA of ENT xor ebx,ebx cld looper: inc ebx lodsd add eax , dwKernelBase ;eax now points to the string of a function push esi ;preserve it for the outer loop mov esi,eax mov edi,edx cld push ecx repe cmpsb pop ecx pop esi jne looper dec ebx mov eax,dwExportDirectory mov eax,[eax+24h] ;36 RVA of EOT add eax,dwKernelBase ;VA of EOT movzx eax , word ptr [ebx*2+eax] ;eax now holds the ordinal of our function mov ebx,dwExportDirectory mov ebx,[ebx+1Ch] ;28 RVA of EAT add ebx,dwKernelBase ;VA of EAT mov ebx,[eax*4+ebx] add ebx,dwKernelBase mov eax,ebx pop edi pop esi pop ebx ;---------------------------------------- ret GetFunctionAddress endp ;======================================== Компилятор собирает без проблем но при запуске программа вылетает с ошибкой Ошибка происходит в функции - GetFunctionAddress в том месте где должно происходить копирование а точнее в этом месте - repe cmpsb я так думаю что копирование должно быть определённое количество единиц а на самом деле копирование или уходит в бесконечность или идёт переполнение подставленного отрезка памяти Скорее всего ошибка в данных которыми пользуется эта функция то есть ошибка где то в начале функции - CodeStart Код (ASM): assume fs:nothing mov ebx, fs:[30h] ;48 get a pointer to the PEB mov ebx, [ebx + 0Ch] ;12 get PEB->Ldr mov ebx, [ebx + 14h] ;20 get PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry) mov ebx, [ebx] ; 2nd Entry mov ebx, [ebx] ; 3rd Entry mov ebx, [ebx + 10h] ;16 Get Kernel32 Base mov dwKernelBase , ebx add ebx, [ebx+3Ch] ;60 Start of PE header mov ebx, [ebx+78h] ;120 RVA of export dir add ebx, dwKernelBase ; VA of export dir mov dwExportDirectory , ebx lea edx,api_GetProcAddress mov ecx,len_GetProcAddress call GetFunctionAddress С большой долей вероятности я где то неправильно что то записал Кто может определить эту ошибку или ошибки помогите пожалуйста
Хотел ещё написать про теги но не успел по времени Путём эксперемента выяснил что код нужно прописывать между этими тегами [сode=аsm] ... [/соdе] но только в тегах нужно писать буквы в большом регистре
Судя по коду должен сработать - Месаджбокс Я так полагаю если код взят от куда то значит он там работал
После анализа нашёл ошибку которую я допустил основной код в моём посте № 10 правильный только сегмент данных нужно изменить вместо моего прописанного сегмента данных Код (ASM): ;======================================== .data szTitle db "Yo !",0 szMsg db "GreeTz From SIGSEGV",0 szUser32 db "User32.dll",0 api_LoadLibrary db "LoadLibraryA",0 api_GetProcAddress db "GetProcAddress" api_MessageBoxA db "MessageBoxA",0 ;---------------------------------------- AGetProcAddressA dd 0 len_GetProcAddress dd $-api_GetProcAddress ALoadLibraryA dd 0 AMessageBoxAA dd 0 dwKernelBase dd 0 dwExportDirectory dd 0 ;======================================== нужно прописать этот сегмент по другому то есть так как это было прописано в посте № 4 у yashechka, Код (ASM): ;======================================== .data szTitle db "Yo !",0 szMsg db "GreeTz From SIGSEGV",0 szUser32 db "User32.dll",0 AGetProcAddressA dd 0 api_GetProcAddress db "GetProcAddress" len_GetProcAddress dd $-api_GetProcAddress ALoadLibraryA dd 0 api_LoadLibrary db "LoadLibraryA",0 AMessageBoxAA dd 0 api_MessageBoxA db "MessageBoxA",0 dwKernelBase dd 0 dwExportDirectory dd 0 .code ;======================================== Всё дело в обязательном тандеме переменных Код (ASM): api_GetProcAddress db "GetProcAddress" len_GetProcAddress dd $-api_GetProcAddress здесь можно обратить внимание что инициализация переменной - len_GetProcAddress происходит с помощью оператора - $ то есть адрес минус прошлый адрес получается число символов в имени - "GetProcAddress" и это число соответственно равно - 14 Так что пример работает отлично Ещё раз спасибо за этот пример - yashechka, Ну и всем конечно тоже большое спасибо за участие