Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1547448
  • 博文数量: 596
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 173
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-06 15:50
个人简介

在线笔记

文章分类

全部博文(596)

文章存档

2016年(1)

2015年(104)

2014年(228)

2013年(226)

2012年(26)

2011年(11)

分类: Windows平台

2014-12-11 14:49:30


  1. // test.cpp : 定义控制台应用程序的入口点。
    //


    #include "stdafx.h"
    #include


    PROCESS_INFORMATION _agentProcInfo;


    BOOL StartAgent(void)
    {
        STARTUPINFO     startup_info;

        DWORD32         ret;
    WCHAR exe[MAX_PATH] = L"notepad.exe";
        //launch agent
        ZeroMemory(&startup_info, sizeof(STARTUPINFO));
        ZeroMemory(&_agentProcInfo, sizeof(_agentProcInfo));


        startup_info.cb = sizeof(startup_info);
        startup_info.lpDesktop = const_cast(TEXT("Winsta0\\default"));


        ret = CreateProcess(NULL, exe, NULL, NULL, FALSE,
                            NORMAL_PRIORITY_CLASS, NULL, NULL,
                            &startup_info, &_agentProcInfo);




        return ret;
    }




    enum TerminationStatus {
      TERMINATION_STATUS_NORMAL_TERMINATION,   // zero exit status
      TERMINATION_STATUS_ABNORMAL_TERMINATION, // non-zero exit status
      TERMINATION_STATUS_PROCESS_WAS_KILLED,   // e.g. SIGKILL or task manager kill
      TERMINATION_STATUS_PROCESS_CRASHED,      // e.g. Segmentation fault
      TERMINATION_STATUS_STILL_RUNNING,        // child hasn't exited yet
      TERMINATION_STATUS_MAX_ENUM
    };


    // Exit codes with special meanings on Windows.
    const DWORD kNormalTerminationExitCode = 0;
    const DWORD kDebuggerInactiveExitCode = 0xC0000354;
    const DWORD kKeyboardInterruptExitCode = 0xC000013A;
    const DWORD kDebuggerTerminatedExitCode = 0x40010004;
    // This exit code is used by the Windows task manager when it kills a
    // process.  It's value is obviously not that unique, and it's
    // surprising to me that the task manager uses this value, but it
    // seems to be common practice on Windows to test for it as an
    // indication that the task manager has killed something if the
    // process goes away.
    const DWORD kProcessKilledExitCode = 1;


    void Check()
    {
    TerminationStatus status;
    DWORD tmp_exit_code;
    CloseHandle(_agentProcInfo.hProcess );
    //CloseHandle(_agentProcInfo.hProcess );
    /*
    我最近调试程序才发觉,CloseHandle这个函数的一个怪异的行为。我突然想到可以利用这个行为来欺骗或者对抗调试器。
    这个怪异的行为是这样的,调用CloseHandle释放一个无效句柄,如果进程在调试器之外,那么函数返回FALSE,而GetLastError得到ERROR_INVALID_HANDLE;但是如果进程在调试器内,那么系统将抛出异常C0000008H。


    一、首先说如何得到一个无效句柄呢?


    方法一:一个句柄释放多次次
    这个方法看似没问题,但实际有很大的隐患。因为新创建的内核对象是总是寻找句柄表的空白记录,因此有可能存在已经释放过的句柄又被利用,而这时再次释放会很不安全。


    方法二:硬编码一个足够大的句柄值
    用procexp.exe看一下就会发现进程里的句柄值很少大于1000h,因此赌一下也是可以的


    方法三:释放一个不可关闭的句柄
    这个我认为是最安全的一种方法,首先自己随便调用一个CreateXXX得到一个句柄h1,再调用SetHandleInformation将句柄h1设为不可关闭的,最后调用CloseHandle释放它就行了


    */
    if (!GetExitCodeProcess(_agentProcInfo.hProcess, &tmp_exit_code))
    {
    printf("Error");
    }

        switch (tmp_exit_code)
        {
            case kNormalTerminationExitCode:
                status = TERMINATION_STATUS_NORMAL_TERMINATION;
                break;


            case kDebuggerInactiveExitCode:  // STATUS_DEBUGGER_INACTIVE.
            case kKeyboardInterruptExitCode:  // Control-C/end session.
            case kDebuggerTerminatedExitCode:  // Debugger terminated process.
            case kProcessKilledExitCode:  // Task manager kill.
                status = TERMINATION_STATUS_PROCESS_WAS_KILLED;
                break;


            default:
                // All other exit codes indicate crashes.
                status = TERMINATION_STATUS_PROCESS_CRASHED;
                break;
        }
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
    StartAgent();

    Check();


    return 0;
    }





阅读(1953) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~