首页
社区
课程
招聘
[求助]win32API奔溃,安装SEH无法截获异常
2016-1-27 19:21 4846

[求助]win32API奔溃,安装SEH无法截获异常

2016-1-27 19:21
4846
我用vs写了一段程序,功能是将一段代码拷贝到指定内存区,然后跳到那里去执行。然而,如果那段程序不调api,可以正常跑。我调了一下LoadLibraryA,进入这个api后程序直接奔溃了,我尝试安装SEH异常处理函数来截获异常,奇怪的是竟然毫无反应。程序如下:
////////////////////////////////////////////////////////////////////////////////
//说明:改程序拷贝一段代码到新内存地址,然后跳到那个地址去执行//////////////////
////////////////////////////////////////////////////////////////////////////////
#pragma comment(linker,"/SUBSYSTEM:CONSOLE /ENTRY:entry /BASE:0x00400000")
#include <Windows.h>
#include <stdio.h>
void ShowError();
EXCEPTION_DISPOSITION
        __cdecl
        _except_handler( struct _EXCEPTION_RECORD *ExceptionRecord,
        void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
        void * DispatcherContext )
{
        // 指明是我们让流程转到我们的异常处理程序的
        MessageBox(0,"发生异常","消息",0);
        // 告诉操作系统重新执行出错的指令
        return ExceptionContinueExecution;
}
int entry(){
        DWORD ProtectOut;
        DWORD opstart;//要写入的代码首地址
        DWORD oplenth;//要写入的代码的长度
        char* str="x.dll";
        DWORD baseadr=0x00401500;
        HANDLE hProcess=GetCurrentProcess();
        //安装SEH
        DWORD handler = (DWORD)_except_handler;
        __asm
        {
                // 创建EXCEPTION_REGISTRATION结构:
                push handler // handler函数的地址
                        push FS:[0] // 前一个handler函数的地址
                mov FS:[0],ESP // 安装新的EXECEPTION_REGISTRATION结构
        }
        //设置分页属性使之变为可读写和可执行
        if(!VirtualProtectEx(hProcess, (LPVOID)0x00401500, 2,PAGE_EXECUTE_WRITECOPY, &ProtectOut))
        {
                ShowError();
                return FALSE;
        }
        //写入数据到0x00401500的地方
        //第一个双字放LoadLibraryA的地址
        DWORD pointer=(DWORD)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA");
        if (!pointer)
        {
                ShowError();
                return FALSE;
        }
        if(!WriteProcessMemory(hProcess,(void *)baseadr,&pointer,4,NULL))
        {
                ShowError();
                return FALSE;
        }
        baseadr+=4;
        //第二个双字放GetProcAddress的地址
        pointer=(DWORD)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "GetProcAddress");
        if (!pointer)
        {
                ShowError();
                return FALSE;
        }
        if(!WriteProcessMemory(hProcess,(void *)baseadr,&pointer,4,NULL))
        {
                ShowError();
                return FALSE;
        }
        //第三、四个双字放字符串"x.dll"
        baseadr+=4;
        if(!WriteProcessMemory(hProcess,(void *)baseadr,str,6,NULL))
        {
                ShowError();
                return FALSE;
        }
        baseadr+=8;
        str="start";
        //第五、六个双字放字符串"start
        if(!WriteProcessMemory(hProcess,(void *)baseadr,str,6,NULL))
        {
                ShowError();
                return FALSE;
        }
        //然后将一段代码拷贝到0x00401518的内存地址
        _asm{
                call o
                        //以下这段代码拷贝到0x00401518的内存地址
                        pushad
                        pushf
                        push 0x00401508
                        call far ds:[0x00401500]
                test eax,eax
                        jz e
                        //获取并调用导出函数
                        push 0x00401510
                        push  eax
                        call far ds:[0x00401504]
                test eax,eax
                        jz e
                        call far eax
e:
                popf
                        popad
                        push 0x00401000
                        retn
o:
                //计算代码长度
                call p
p:                pop eax
                pop ebx
                mov opstart,ebx
                sub eax,ebx
                sub eax,5
                mov oplenth,eax
        }
        baseadr=0x00401518;
        if(!WriteProcessMemory(hProcess,(void *)baseadr,(LPVOID)opstart,oplenth,NULL))
        {
                ShowError();
                return FALSE;
        }
        //跳到0x00401518执行代码
        _asm{
                push 0x00401518
                        retn
        }

                __asm
                {
                        // 移去我们的EXECEPTION_REGISTRATION结构
                        mov eax,[ESP]    // 获取前一个结构
                        mov FS:[0], EAX // 安装前一个结构
                                add esp, 8       // 将我们的EXECEPTION_REGISTRATION弹出堆栈
                }
end:
        system("pause");
        return 0;
}
void ShowError()
{
        DWORD dwRet = 0;
        char *lpMsgBuf = NULL;
        DWORD ErrorCode = GetLastError();
        dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL, ErrorCode, 0x400, (LPTSTR)&lpMsgBuf, 0, NULL);
        MessageBox(NULL, lpMsgBuf, NULL, MB_OK | MB_ICONINFORMATION);  
        LocalFree(lpMsgBuf);
}

求解!!!!!!!

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
打赏
分享
最新回复 (6)
雪    币: 218
活跃值: (2824)
能力值: ( LV7,RANK:140 )
在线值:
发帖
回帖
粉丝
yeyeshun 2 2016-1-27 20:54
2
0
1.VirtualProtectEx的属性应该是PAGE_EXECUTE_READWRITE吧。
2.pushf改成pushfd,在我这里pushf被编译成pushfw了。
3.“//跳到0x00401518执行代码”的操作应该是call,而不是push/ret,你用push/ret相当于跳转,执行完了之后肯定要跪,因为EIP不知道要返回哪里了。

顺便提醒一下,要玩这些东西,建议先学会调试
雪    币: 433
活跃值: (1825)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
萌克力 2016-1-27 21:18
3
0
问题应该是出在调用api上 尝试换一个普通的api  比如信息框之类的再试试呢? 内存运行有很多弊端,但是api肯定是可以调用的 我试过...
雪    币: 108
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
冰雪之地 2016-1-28 05:34
4
0
执行完后我用     
push 0x00401000
      retn
返回 0x00401000
,关键是还没完,进入LoadLibraryA后就已经奔溃了
你说调试,我看见有个加壳程序叫asprotect2.x的,就是把代码拷来拷去,我就是想也那样玩玩
OD我用的很熟练
雪    币: 108
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
冰雪之地 2016-1-28 05:39
5
0
windows核心编程里面说可以修改进程的PE入口处代码来插入dll,但并没提供源码,所以我要的就是LoadLibraryA和GetProcAddress
雪    币: 108
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
冰雪之地 2016-1-28 06:10
6
0
哈哈,问题已解决,还真是pushf和popf这个指令有问题,改为pushfd和popfd就ok了,可我不明白,这两个指令为什么会影响到api,真是怪了
雪    币: 218
活跃值: (2824)
能力值: ( LV7,RANK:140 )
在线值:
发帖
回帖
粉丝
yeyeshun 2 2016-1-28 12:20
7
0
所以叫你自己编译一个用OD载入看啊,看了就知道了,pushfw的话esp-2,pushfd的话esp-4.
具体什么原因我没有深入进去看,也许是对齐的问题吧
游客
登录 | 注册 方可回帖
返回