LoadLibrary 加载 DLL

sec
Article Directory

LoadLibrary 加载 DLL

尝试复现 knowDlls 无文件注入,前置实验,进程 DLL 的调用

rundll32 Rundll32 是 Win95 开始提供的一个加载 DLL 的程序,可以启动一些 DLL ,Rundll32[argument]

  1. 创建测试 DLL

    file:hello.c
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    /*
    * @Description:
    * @Author: Yuan Jie
    * @Data:
    * @LastEdit: moogila@outlook.com
    * @LastEditTime: 2022-04-02 10:06:44
    * @FileName: hello.c
    */
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    #pragma comment(lib, "user32.lib")

    __declspec(dllexport)
    BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
    MessageBox(NULL, "Hello world!", "Hello World!", 0);
    break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    break;
    }
    return TRUE;
    }

    __declspec(dllexport)
    void show()
    {
    MessageBoxA(NULL,"xsxsxs","xsxsx",0);
    }


    使用 msvc 编译

    cl hello.c /LD

    生成 hello.dll 和 hello.lib 文件

    使用 rundll32 测试

    命令 rundll32 hello.dll show

    结果

    image-20220402145746849image-20220402145746849

  2. 编写测试程序 main.cpp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    /*
    * @Description:
    * @Author: Yuan Jie
    * @Data:
    * @LastEdit: moogila@outlook.com
    * @LastEditTime: 2022-04-02 15:02:49
    * @FileName:
    */
    #include <stdlib.h>
    #include <stdio.h>
    #include <windows.h>
    #pragma comment(lib, "user32.lib")

    int main() {
    HMODULE modl = LoadLibrary(".\\hello.dll");
    if (!modl){
    char msg[30] = {0};
    sprintf(msg,"Load Dll Fail,Errcode: %d",GetLastError());
    MessageBox(NULL, msg, "ERROR", MB_OK);
    return 0;
    }
    typedef void(*show)(void);
    show p_func = (show)GetProcAddress(modl, "show");
    if (p_func){
    p_func();
    } else{
    MessageBox(NULL, "load Func Fail", "ERROR", MB_OK);
    }
    return 0;
    }

正常g++ main.cpp 编译完成之后,运行结果为

Load Dll Fail,ErrCode : 193

193 的错误为:非正常的 win32 程序

加入 -m32 编译为 32 位程序,正常运行

但是,使用 g++ main.cpp -m32 编译时,程序运行出错

image-20220402150948965image-20220402150948965

原因不详

使用 msvc 编译时

#pragma comment(lib, “user32.lib”)

是必须的

Note

  • 函数指针的使用

动态加载 Dll ,需要使用 LoadLibrary() 和 GetProcAddress()

GetProcAddress 返回函数指针需要进行类型转化,我函数指针用的不清不白,在这个地方愣住,在网上找了一圈,没有找到详细结果,最后只得接收 先 typedef 这种使用方法。

​ typedef void(*show)(void);

  • #pragma comment(lib, “user32.lib”)

    这个看得确实不太明白,目前理解来说,这很像是 java 里面的注解 (comment ?!)

    使用这个注解,提示编译器,在编译时链接动态库,也就是说,实际上,你需要在编译时指定链接库,但是,使用这个注解会让编译器自动完成,当然,这样的注解还有很多,但并非标准。

    pragma 是预处理指令

[ 参考资料 ]

  • 《Windows API 编程》清华大学出版社·冉林仓·2005

Author: 哒琳

Permalink: http://blog.jieis.cn/2021/87ed2d37-be5f-4fa3-8b10-d6988be3331a.html

Comments