宝峰科技

 找回密码
 注册

QQ登录

只需一步,快速开始

智能终端设备维修查询系统注册会员邮箱认证须知!
查看: 3522|回复: 1

[VC函数例程] 利用DEBUG API编写Loader Path

[复制链接]
  • TA的每日心情
    开心
    2024-12-9 18:45
  • 签到天数: 124 天

    [LV.7]常住居民III

    admin 发表于 2010-9-28 20:53:43 | 显示全部楼层 |阅读模式

    欢迎您注册加入!这里有您将更精采!

    您需要 登录 才可以下载或查看,没有账号?注册

    x
    Loader并不是什么很神秘的技术,微软提供了一组Debug Api来方便第三方监视程序.这里我用Debug Api制作了一个简单的Loader程序.这个Loader要干的事有: 1.启动目标程序.2.读取/修改目标程序的内存 或 寄存器
       用到的Debug Api有:
      CreateProcess —— 用于创建被调试进程
      WaitForDebugEvent —— Debug Loop(调试循环)的主要构成函数
      ContinueDebugEvent —— 用于构成Debug Loop
      GetThreadContext —— 得到被调试进程的寄存器信息
      SetThreadContext —— 设置被调试进程的寄存器信息
      ReadProcessMemory —— 得到被调试进程的内存内容
      WriteProcessMemory —— 设置被调试进程的内存内容
       相应的数据结构如下
      CONTEXT —— 寄存器结构
      STARTUPINFO —— Start信息
      PROCESS_INFORMATION —— 进程相关信息
      DEBUG_EVENT —— Debug Event(调试事件)结构
       Loader具体代码如下:
    [C++] 纯文本查看 复制代码
    // MemoryReader.cpp : 定义控制台应用程序的入口点。
    // AntiDebug:IsDebugPresent如何避开?
    // 加壳处理不完善//
    #include "stdafx.h"
    #include "windows.h"
    #include "Commdlg.h"
    #include "winnt.h"
    
    BYTE INT3 = 0xCC;
    //写入前的
    BYTE Old;
    //页面属性
    DWORD OldProtect;
    //是否已写入INT3
    bool HasINT3 = false;
    bool IsFirstINT3 = true;
    DWORD BreakPoint = 0x00452191;
    BYTE Org[8] = {0xE8,0x4E};
    //判断是否解压完成
    bool IsUnpacked(PROCESS_INFORMATION pi)
    {
        SuspendThread(pi.hThread);
        CONTEXT context;
        ZeroMemory(&context,sizeof(CONTEXT));
        context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
        GetThreadContext(pi.hThread,&context);
        printf("Exe Info:Eax:%x,Esp:%x,Eip:%x\n",context.Eax,context.Esp,context.Eip);        
        ResumeThread(pi.hThread);
        BYTE mem[8];
        VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,PAGE_READWRITE, &OldProtect);
        ReadProcessMemory(pi.hProcess,(LPCVOID)BreakPoint,&mem,8,NULL);
        VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,OldProtect,&OldProtect);
        printf("hex num is:%x,%x,%x,%x\n",mem[0],mem[1],mem[2],mem[3]);
        if(mem[0] ^ 0xff == Org[0] && mem[1] ^ 0xff == Org[1])
        {
            //不能乱调用
            Old = mem[0];
            return TRUE;
        }
        return false;
    }
    
    //写INT3
    bool WriteINT3(PROCESS_INFORMATION pi)
    {
        //VirtualAllocEx(pi.hProcess,(LPVOID)0x0101259b,sizeof(INT3), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
        SuspendThread(pi.hThread);
        VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,PAGE_READWRITE, &OldProtect);
        bool ret = WriteProcessMemory(pi.hProcess,(LPVOID)BreakPoint,&INT3,sizeof(INT3),NULL);
        VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,OldProtect,&OldProtect);
        HasINT3 = ret;
        ResumeThread(pi.hThread);
        return ret;
    }
    
    //改回去
    bool CleanINT3(PROCESS_INFORMATION pi)
    {
        //SuspendThread(pi.hThread);
        bool ret = WriteProcessMemory(pi.hProcess,(LPVOID)BreakPoint,&Old,sizeof(Old),NULL);
        if(ret == false)
        {
            printf("改回去失败!\n");
        }
        CONTEXT context;
        ZeroMemory(&context,sizeof(CONTEXT));
        context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
        GetThreadContext(pi.hThread,&context);
        context.Eip--;
        SetThreadContext(pi.hThread,&context);
    
        printf("已经改回去了,Eax:%x\n",context.Eax);
        return ret;
    }
    
    //隐藏Debug
    void HideDebug(PROCESS_INFORMATION pi)
    {
        BYTE ISDEBUGFLAG = 0x00;
        int ISHEAPFLAG = 2;
        SuspendThread(pi.hThread);
        CONTEXT context;
        ZeroMemory(&context,sizeof(CONTEXT));
        context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
        GetThreadContext(pi.hThread,&context);
        //IsDebugPresent_Flag
        WriteProcessMemory(pi.hProcess,(LPVOID)(context.Ebx+0x2),&ISDEBUGFLAG,1,NULL);
        //NTGlobal_Flag  用0D则为70  这个为0 防止其他调试器存在
        WriteProcessMemory(pi.hProcess,(LPVOID)(context.Ebx+0x68),&ISDEBUGFLAG,1,NULL);
        //GetProcessHeap_Flag
        DWORD HeapAddress;
        ReadProcessMemory(pi.hProcess,(LPCVOID)(context.Ebx + 0x18),&HeapAddress,sizeof(HeapAddress),NULL);
        WriteProcessMemory(pi.hProcess,(LPVOID)HeapAddress,&ISHEAPFLAG,sizeof(ISHEAPFLAG),NULL);
    
        ReadProcessMemory(pi.hProcess,(LPCVOID)(context.Ebx + 0x68),&ISDEBUGFLAG,1,NULL);
        printf("NT_GLOBAL=%d\n",ISDEBUGFLAG);
        ResumeThread(pi.hThread);
    }
    
    
    int main(int argc, char* argv[])
    {
        char f_name[256];
        f_name[0] = NULL;
        OPENFILENAME filename;
        ZeroMemory(&filename,sizeof(OPENFILENAME));
        filename.lStructSize = sizeof(OPENFILENAME);
        filename.hwndOwner = NULL;
        filename.lpstrFilter = "*.exe";
        filename.lpstrFile = f_name;
        filename.nMaxFile = 256;
        filename.lpstrInitialDir = NULL;
        filename.Flags = OFN_EXPLORER | OFN_HIDEREADONLY;
        if(!GetOpenFileName(&filename))
            return 0;
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        ZeroMemory(&si,sizeof(STARTUPINFO));
        ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
        bool ret = CreateProcess(filename.lpstrFile,"",NULL,NULL,FALSE,DEBUG_PROCESS,NULL,NULL,&si,&pi);
        if(ret == false)
        {
            MessageBox(NULL,"创建进程失败!","",0);
            return -1;
        }
    
        //Anti-Anti-Debug
        HideDebug(pi);
    
        DEBUG_EVENT devent;
        int DllCount = 0;
        while(TRUE)
        {
            if(WaitForDebugEvent(&devent,1))
            {
                switch(devent.dwDebugEventCode)
                {
                case CREATE_PROCESS_DEBUG_EVENT:
                    printf("CREATE_PROCESS_DEBUG_EVENT\n");
                    break;
                case CREATE_THREAD_DEBUG_EVENT:
                    printf("CREATE_THREAD_DEBUG_EVENT\n");
                    break;
                case EXCEPTION_DEBUG_EVENT:
                    //printf("EXCEPTION_DEBUG_EVENT\n");
                     switch(devent.u.Exception.ExceptionRecord.ExceptionCode)
                    {
                    case EXCEPTION_BREAKPOINT:
                        if(HasINT3)
                        {    
                            SuspendThread(pi.hThread);
                            CONTEXT context;
                            ZeroMemory(&context,sizeof(CONTEXT));
                            context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
                            GetThreadContext(pi.hThread,&context);
                            printf("Eax:%x\n,Esi:%x\n,Eip:%x\n,Ebp:%x\n",context.Eax,context.Esi,context.Eip,context.Ebp); 
                            if(context.Eip == BreakPoint + 1)
                            {
                                if(!CleanINT3(pi))
                                {
                                    printf("清除断点失败!");
                                }
    
                                printf("Program Stopped At What We Want\n");
                                char key[256];
    
                                VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,PAGE_READWRITE, &OldProtect);
                                ReadProcessMemory(pi.hProcess,(LPCVOID)context.Edx,key,sizeof(key),NULL);
                                VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,OldProtect,&OldProtect);
                                
                                printf("读出来的东西是 %s\n",key);        
                            }
                            ResumeThread(pi.hThread);
                        }    
                        break;
                    case EXCEPTION_SINGLE_STEP:
                        printf("2 EXCEPTION_SINGLE_STEP\n");
                        break;
                    case EXCEPTION_ACCESS_VIOLATION:
                        printf("读写地址出错\n");
                        printf("%d,%x\n",devent.u.Exception.ExceptionRecord.ExceptionInformation[0],devent.u.Exception.ExceptionRecord.ExceptionAddress);
    
                        ContinueDebugEvent(pi.dwProcessId,pi.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);
    
    /*                    char Nop[3];
                        Nop[0] = 0x90;
                        Nop[1] = 0x90;
                        Nop[2] = 0x90;
                        PVOID pathAddress;
                        pathAddress = devent.u.Exception.ExceptionRecord.ExceptionAddress;
                        VirtualProtectEx(pi.hProcess,pathAddress,3,PAGE_READWRITE, &OldProtect);
                        WriteProcessMemory(pi.hProcess,pathAddress,Nop,3,NULL);
                        VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,OldProtect,&OldProtect);
    
                        ContinueDebugEvent(pi.dwProcessId,pi.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);        */        
                        break;
                    default:
                        break;
                    }
                    break;
                case LOAD_DLL_DEBUG_EVENT:
                    //获取DLL NAME太复杂,暂时做不到
                    DllCount ++;
                    printf("%d,Program Loads a Dll From BaseImage:%x,ImageName:%x\n",DllCount,devent.u.LoadDll.lpBaseOfDll,devent.u.LoadDll.lpImageName);                
                    if(!HasINT3)
                    {
                      if(IsUnpacked(pi))
                      {
                          printf("UnPacked Success!!\n");
                          WriteINT3(pi);
                          printf("Write a INT3\n");
                      }
                    }
                    break;
                case UNLOAD_DLL_DEBUG_EVENT:
                    printf("UnLoad a Dll From BaseImage:%x,ImageName:%x\n",devent.u.LoadDll.lpBaseOfDll,devent.u.LoadDll.lpImageName);                
                    if(!HasINT3)
                    {
                      if(IsUnpacked(pi))
                      {
                          printf("UnPacked Success!!\n");
                          WriteINT3(pi);
                          printf("Write a INT3\n");
                      }
                    }
                    break;
                case OUTPUT_DEBUG_STRING_EVENT:
                    break;
                case EXIT_PROCESS_DEBUG_EVENT:
                    printf("调试程序已退出");
                    break;
                default:
                    printf("%d\n",devent.dwDebugEventCode);
                    break;
                }
                ContinueDebugEvent(pi.dwProcessId,pi.dwThreadId,DBG_CONTINUE);
            }
            else
            {
            }
        }
       //KeyMake中不要这两句
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        return 0;
    }
  • TA的每日心情
    开心
    2013-6-9 11:35
  • 签到天数: 8 天

    [LV.3]偶尔看看II

    346022142 发表于 2013-4-27 23:47:48 | 显示全部楼层
    这么好的帖子 居然没人顶       写个调试器的知识都在这里了
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    免责声明

    本站中所有被研究的素材与信息全部来源于互联网,版权争议与本站无关。本站所发布的任何软件编程开发或软件的逆向分析文章、逆向分析视频、补丁、注册机和注册信息,仅限用于学习和研究软件安全的目的。全体用户必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。学习编程开发技术或逆向分析技术是为了更好的完善软件可能存在的不安全因素,提升软件安全意识。所以您如果喜欢某程序,请购买注册正版软件,获得正版优质服务!不得将上述内容私自传播、销售或者用于商业用途!否则,一切后果请用户自负!

    QQ|Archiver|手机版|小黑屋|联系我们|宝峰科技 ( 滇公网安备 53050202000040号 | 滇ICP备09007156号-2 )

    Copyright © 2001-2023 Discuz! Team. GMT+8, 2025-5-7 09:17 , File On Powered by Discuz! X3.49

    快速回复 返回顶部 返回列表