首页
社区
课程
招聘
[求助]dllmain函数出现0xC0000005: Access violation
发表于: 2016-4-20 01:56 5763

[求助]dllmain函数出现0xC0000005: Access violation

2016-4-20 01:56
5763
最近我在搞逆向,修改pe注入dll(dll已经注入成功了,可以使用MessageBOX弹窗),但是我还是不满足,希望可以在dll里面使用汇编来控制一些细节。我在dllmain函数的DLL_PROCESS_ATTACH这个部分实现我的代码,创建远程调用。结果就出错了,错误消息如下:TextView.exe 中的 0x10081280 (myhack3.dll) 处有未经处理的异常: 0xC0000005: Access violation

我贴一下我的源码大家看看什么问题:

#include "windows.h"   

#ifdef __cplusplus  
extern "C" {  
#endif  
  __declspec(dllexport) void dummy()  
  {  
    return;  
  }  
#ifdef __cplusplus  
}  
#endif//dll对外提供的函数  

BYTE g_InjectionCode[] =
{
  0x55,0x8b,0xec,0x8b,0x45,0x08,0x6a,0x00,0xe8,0x0c,0x00,0x00,0x00,
  0x52,0x65,0x76,0x65,0x72,0x73,0x65,0x43,0x6f,0x72,0x65,0x00,0xe8,
  0x14,0x00,0x00,0x00,0x77,0x77,0x77,0x2e,0x72,0x65,0x76,0x65,0x72,
  0x73,0x65,0x63,0x6f,0x72,0x65,0x2e,0x63,0x6f,0x6d,0x00,0x6a,0x00,
  0xff,0xd0,0x33,0xc0,0x8b,0xe5,0x5d,0xc3,0x33
};//汇编代码,先创建栈帧,然后把参数压栈,然后最后callMessageBox函数

/*
004010ED    55               PUSH EBP
004010EE    8BEC             MOV EBP,ESP
004010F0    8B75 08          MOV EAX,DWORD PTR SS:[EBP+8]       ; EAX = pParam           
004011F3    6A 00            PUSH 0                             ; - MB_OK (0)
004011F5    E8 0C000000      CALL 0040112C
004011FA                     <ASCII>                            ; - "ReverseCore", 0
00401201    E8 14000000      CALL 00401145
00401206                     <ASCII>                            ; - "www.reversecore.com", 0
00401215   6A 00            PUSH 0                             ; - hWnd (0)
00401217    FFD0             CALL EAX                           ; MessageBoxA(0, "www.reversecore.com", "ReverseCore", 0)
00401219    33C0             XOR EAX,EAX                        
0040121B   8BE5             MOV ESP,EBP
0040121D    5D               POP EBP                           
0040121E   C3               RETN
*/

BOOL APIENTRY DllMain(HANDLE hMoudle,DWORD reason,LPVOID lpReserved)  //dllmain函数  
{   
  HANDLE          hThread         = NULL;
  HMODULE         hMod            = NULL;
  FARPROC pFunc;
  
  hMod = LoadLibraryA("user32.dll");

  pFunc = GetProcAddress(hMod,"MessageBoxA");
  switch(reason)   
  {   
  case DLL_PROCESS_ATTACH:  //<span style="font-family: Arial, Helvetica, sans-serif;">在dll第一次加载时自动执行,以后加载则只增加引用数,不会执行</span>  
    hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&g_InjectionCode,(LPVOID)&pFunc,0,NULL);
    return TRUE;  
  default:   
    return TRUE;   
  }   
}   

在dllmain里面创建了线程,线程回调函数的地址是g_InjectionCode,参数就是messageBox的函数的地址。(这个地址存在上面汇编中的EAX,最后call EAX就是调用这段汇编)
我用vs跟了一下,vs在 g_InjectionCode的第一个byte停了下来,报0xC0000005: Access violation。这个问题该怎么解决?

[峰会]看雪.第八届安全开发者峰会10月23日上海龙之梦大酒店举办!

收藏
免费 0
支持
分享
最新回复 (15)
雪    币: 204
活跃值: (911)
能力值: (RANK:1324 )
在线值:
发帖
回帖
粉丝
2
修改内存属性试试
2016-4-20 01:59
0
雪    币: 293
活跃值: (287)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
根据所述是页没有执行属性,整个dll都注入了,直接用C写好不是更简单
2016-4-20 09:26
0
雪    币: 1787
活跃值: (340)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
明显数据段,是不能执行的。
2016-4-20 09:42
0
雪    币: 2
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
因为我是想增加一个节区,然后对节区进行操作。所以才打算用汇编完成。这个数据段我要怎么给它执行的属性呢?在dll的节区里面增加可执行属性?在代码里面如何增加可执行属性呢?
2016-4-20 09:48
0
雪    币: 2291
活跃值: (938)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
6
楼主在dllmain里面创建线程真的好么?
2016-4-20 10:31
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
7
你的visual c++ 编译器在构建 myhack3.dll 的过程中,把字节码数组 g_InjectionCode 放到了全局数据段中,通常情况该段会被映射进内存的不可执行页,于是将控制转移到这种页面时就会传递一个STATUS_ACCESS_VIOLATION(0xc0000005)异常到尝试非法引用的线程。
有几种解决办法:
1。重构你的 myhack3.c 源码,将shellcode 数组放在 DllMain() 中试试。

2。如果还是非法访问,则在 DllMain() 中,通过 windows API  VirtualAlloc() 为 shellcode 分配内存空间,接下来,通过 VirtualProtect() ,并且传入符号常量 PAGE_EXECUTE,PAGE_EXECUTE_READ,PAGE_EXECUTE_READWRITE 的其中之一,从而将 shellcode 映射的页面属性设置为可读写或可执行,或三者。建议你传入 PAGE_EXECUTE_READWRITE ,如果传入 PAGE_EXECUTE(仅执行),在写入(修改)数组时还是会生成 0xc0000005。
这 2 个函数的使用详解可以参考 MSDN 文档。

3。在桌面上右击“计算机”图标->“属性”->“高级系统设置”->点击“高级”选项卡的“性能”栏目的“设置”->“数据执行保护”选项卡,将你要注入的 dll 和可执行文件添加到 DEP 的例外列表中。  

4。将 Visual Studio 的/NXCOMPAT 链接器标志为 no,然后重新构建你的 dll 工程文件。

2016-4-20 11:00
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
8
有什么不好吗?其实有很多事情是不适合在DllMain中做的,所以创建线程去做应该才是正确的方案吧?
2016-4-20 12:01
0
雪    币: 7048
活跃值: (3522)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
9
不,dllmain创建线程好像会导致卡死的情况。
这个msdn上有介绍,好像是因为新线程也会逐个调用每个模块的dllmain。

另外汇编代码为何不直接__asm xxx?
2016-4-20 12:09
0
雪    币: 2291
活跃值: (938)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
10
不好意思,看错了,楼主虽然创建了线程,但没有wait,不会卡死。
另外关于楼主的问题,7楼给出的是正解。g_InjectionCode 所在的页面不可执行。
2016-4-20 12:33
0
雪    币: 2
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
确实是这样,按照你说的我解决了这个问题,谢谢。
2016-4-20 19:56
0
雪    币: 2
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
第一次上传的代码这里出错了
hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&g_InjectionCode,(LPVOID)&pFunc,0,NULL);
(LPVOID)&pFunc改为(LPVOID)pFunc  pFunc本来就是函数MessageBox的地址,按我第一次写的,就是取函数地址的地址了。

这是我改正后的代码。我给传一下

#include "windows.h"   
#include "iostream"

#ifdef __cplusplus  
extern "C" {  
#endif  
        __declspec(dllexport) void dummy()  
        {  
                return;  
        }  
#ifdef __cplusplus  
}  
#endif//dll对外提供的函数  

BYTE g_InjectionCode[] =
{
        0x55,0x8b,0xec,0x8b,0x45,0x08,0x6a,0x00,0xe8,0x0c,0x00,0x00,0x00,
        0x52,0x65,0x76,0x65,0x72,0x73,0x65,0x43,0x6f,0x72,0x65,0x00,0xe8,
        0x14,0x00,0x00,0x00,0x77,0x77,0x77,0x2e,0x72,0x65,0x76,0x65,0x72,
        0x73,0x65,0x63,0x6f,0x72,0x65,0x2e,0x63,0x6f,0x6d,0x00,0x6a,0x00,
        0xff,0xd0,0x33,0xc0, 0x8b,0xe5,0x5d,0xc3
};

        /*
        004010ED    55               PUSH EBP
        004010EE    8BEC             MOV EBP,ESP
        004010F0    8B75 08          MOV EAX,DWORD PTR SS:[EBP+8]       ; EAX = pParam           
        004011F3    6A 00            PUSH 0                             ; - MB_OK (0)
        004011F5    E8 0C000000      CALL 0040112C
        004011FA                     <ASCII>                            ; - "ReverseCore", 0
        00401201    E8 14000000      CALL 00401145
        00401206                     <ASCII>                            ; - "www.reversecore.com", 0
        00401215   6A 00            PUSH 0                             ; - hWnd (0)
        00401217    FFD0             CALL EAX                           ; MessageBoxA(0, "www.reversecore.com", "ReverseCore", 0)
        00401219    33C0             XOR EAX,EAX                       
        0040121B   8BE5             MOV ESP,EBP
        0040121D    5D               POP EBP                           
        0040121E   C3               RETN
        */

BOOL APIENTRY DllMain(HANDLE hMoudle,DWORD reason,LPVOID lpReserved)  //dllmain函数  
{   
       

        HANDLE          hThread         = NULL;
        HMODULE         hMod            = NULL;
        FARPROC pFunc;
        hMod = LoadLibraryA("user32.dll");

        pFunc = GetProcAddress(hMod,"MessageBoxA");

        PVOID pvMem = VirtualAlloc(NULL,sizeof(g_InjectionCode),MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);

        WriteProcessMemory(INVALID_HANDLE_VALUE,pvMem,(LPVOID)&g_InjectionCode,sizeof(g_InjectionCode),NULL);

        switch(reason)   
        {   
        case DLL_PROCESS_ATTACH:
                hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)pvMem,(LPVOID)pFunc,0,NULL);
                return TRUE;  
        default:   
                return TRUE;   
        }   
}   

先使用virtualalloc申请内存页,然后使用writevritualmem向内存页写汇编代码。内存页属性一定要是Page_Execute_ReadWrite
2016-4-20 20:01
0
雪    币: 2
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
我自己也找到了一种解决方式。g_bytecode是全局变量,那么就存放于dll文件的data节区。只要用ultraedit将data节区的属性改为e0 00 00 40既可以了,增加了可执行属性。当然这是一种取巧的行为,并不规范,所以还是推荐第一种方法。
2016-4-20 20:03
0
雪    币: 1787
活跃值: (340)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
14
肯定是不好的,创建线程,DLL卸载的时候,肯定需要 等线程结束。等了就卡死,不等dll卸载了,一样非法地址。除非能保证线程能在dll卸载之前结束,显然这只能是个约定。所以DLL main只应该做简单的初始化,复杂的动作需要导出一个初始化函数。
2016-4-20 20:11
0
雪    币: 2291
活跃值: (938)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
15
不管有没有Wait,DllMain里面创建线程本身就不该提倡。
2016-4-20 20:30
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
16
楼主这方法挺有黑客风范的,我当时还没想到,顺便也学习一下。
2016-4-20 22:57
0
游客
登录 | 注册 方可回帖
返回
//