首页
社区
课程
招聘
OD插件 DebugPrivilege( C代码)
发表于: 2005-11-22 16:36 13896

OD插件 DebugPrivilege( C代码)

2005-11-22 16:36
13896

上次我们 Disable 了 OD 的 DebugPrivilege 权限, 可能会有问题.
正好想学学写 OD 的插件, 就有了这个东东, 只修改被调试进程的 DebugPrivilege 权限.

插件参考了 IsDebugPresent 的 ASM 代码, 用C 实现, 有三个命令.

1. 手动 Disable 子进程 DebugPrivlege
2. 手动 Enable  子进程 DebugPrivlege
3. 程序加载和 Restart 时可选择自动 Disable DebugPrivlege

程序在 VC6 下编译通过, 有一个问题花了我好长时间才解决,
OD 手册中提到的 DllEntryPoint() 编译能通过, 但就是不执行.
看了看 OD 自带的 VC 例子 和其他的例子, 都是 DllEntryPoint().

后来我改成 DllMain() 才正确, 这个是不是 OD Pulgin 的一个小问题?
第一次学写 插件, 请各位多指点.

#include <windows.h>

#include "plugin.h"
#include "resource.h"

HINSTANCE        hinst;                // DLL instance
HWND             hwmain;               // Handle of main OllyDbg window
char  Name[]="DebugPrivilege";

// Entry point into a plugin DLL. Many system calls require DLL instance
// which is passed to DllEntryPoint() as one of parameters. Remember it.
// Preferrable way is to place initializations into ODBG_Plugininit() and
// cleanup in ODBG_Plugindestroy().

BOOL WINAPI DllMain(HINSTANCE hi,DWORD reason,LPVOID reserved)
{
  if (reason==DLL_PROCESS_ATTACH)
                hinst=hi;                      // Mark plugin instance
  
  return 1;                            // Report success
}

BOOL AdjustPrivilege(int pid, BOOL bEnable)
{
    HANDLE hProcess;
        HANDLE hToken=0;
    TOKEN_PRIVILEGES tkp;
   
        tkp.PrivilegeCount = 1;  
        tkp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
   
        if( ! LookupPrivilegeValue(NULL, "SeDebugPrivilege", &tkp.Privileges[0].Luid) )
        {
                MessageBox(hwmain, "LookupPrivilegeValue error", Name, MB_OK|MB_ICONERROR);
                return 0;
        }
       
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (! hProcess)
        {
                MessageBox(hwmain, "OpenProcess error", Name, MB_OK|MB_ICONERROR);
                return 0;
        }
  

          if( ! OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken) )
        {
                CloseHandle(hProcess);
                MessageBox(hwmain, "OpenProcessToken error", Name, MB_OK|MB_ICONERROR);
                return 0;
        }

    if( ! AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, NULL))
        {
                CloseHandle(hToken);
                CloseHandle(hProcess);
                MessageBox(hwmain, "AdjustTokenPrivileges error", Name, MB_OK|MB_ICONERROR);
                return 0;
        }
   
       
        CloseHandle(hToken);
        CloseHandle(hProcess);
    return 1;
}

BOOL CALLBACK DlgOptionProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    int AutoDisable;
        int SleepTime;
        char textbuffer[8];

        if (uMsg == WM_INITDIALOG)
        {
                //read params from ini & update windows
        AutoDisable= Pluginreadintfromini(hinst,"AutoDisable", 0);
        SleepTime  = Pluginreadintfromini(hinst,"Sleeptime",500);
               
        CheckDlgButton(hWnd, IDC_AUTO, AutoDisable);
               
                wsprintf(textbuffer, "%d", SleepTime);
        SetDlgItemText(hWnd,IDC_SLEEPTIME,textbuffer);
      
        }
   
        else if( uMsg == WM_CLOSE)
        EndDialog(hWnd, 0);
   
        else if( uMsg == WM_COMMAND)
        {
  
                        if (wParam==(UINT)IDC_QUIT)
                EndDialog(hWnd, 0);
            
                        else if( wParam==(UINT)IDC_SAVE)     
                        {
                AutoDisable=IsDlgButtonChecked(hWnd, IDC_AUTO);     
                Pluginwriteinttoini(hinst, "AutoDisable", AutoDisable);
               
                GetDlgItemText(hWnd, IDC_SLEEPTIME, textbuffer, 10);
                SleepTime=atoi(textbuffer);
                Pluginwriteinttoini(hinst, "Sleeptime", SleepTime);
                        }   
    }
    else
         return FALSE;
   
    return TRUE;
}

// ODBG_Plugindata() is a "must" for valid OllyDbg plugin. It must fill in
// plugin name and return version of plugin interface. If function is absent,
// or version is not compatible, plugin will be not installed. Short name
// identifies it in the Plugins menu. This name is max. 31 alphanumerical
// characters or spaces + terminating '\0' long. To keep life easy for users,
// this name should be descriptive and correlate with the name of DLL.
extc int _export cdecl ODBG_Plugindata(char shortname[32])
{
  strcpy(shortname, Name);       // Name of plugin
  return PLUGIN_VERSION;
}

// OllyDbg calls this obligatory function once during startup. Place all
// one-time initializations here. If all resources are successfully allocated,
// function must return 0. On error, it must free partially allocated resources
// and return -1, in this case plugin will be removed. Parameter ollydbgversion
// is the version of OllyDbg, use it to assure that it is compatible with your
// plugin; hw is the handle of main OllyDbg window, keep it if necessary.
// Parameter features is reserved for future extentions, do not use it.
extc int _export cdecl ODBG_Plugininit(int ollydbgversion,HWND hw,ulong *features)
{
  // This plugin uses all the newest features, check that version of OllyDbg is
  // correct. I will try to keep backward compatibility at least to v1.99.
  if (ollydbgversion<PLUGIN_VERSION)
    return -1;

  // Keep handle of main OllyDbg window. This handle is necessary, for example,
  // to display message box.
  hwmain=hw;

  // Register window class for MDI window that will display plugins. Please
  // note that formally this class belongs to instance of main OllyDbg program,
  // not a plugin DLL. String winclass gets unique name of new class.
  // Keep it to create window and unregister on shutdown.

  // Plugin successfully initialized. Now is the best time to report this fact
  // to the log window. To conform OllyDbg look and feel, please use two lines.
  // The first, in black, should describe plugin, the second, gray and indented
  // by two characters, bears copyright notice.
  Addtolist(0,0, "DebugPrivilege plugin v1.0");
  Addtolist(0,-1,"  Copyright (C) 2000-2006 Simonzh2000" );
   
  return 0;
}

// Function adds items either to main OllyDbg menu (origin=PM_MAIN) or to popup
// menu in one of standard OllyDbg windows. When plugin wants to add own menu
// items, it gathers menu pattern in data and returns 1, otherwise it must
// return 0. Except for static main menu, plugin must not add inactive items.
// Item indices must range in 0..63. Duplicated indices are explicitly allowed.
extc int _export cdecl ODBG_Pluginmenu(int origin,char data[4096],void *item)
{
  
  switch (origin)
  {
    // Menu creation is very simple. You just fill in data with menu pattern.
    // Some examples:
    // 0 Aaa,2 Bbb|3 Ccc|,,  - linear menu with 3items, relative IDs 0, 2 and 3,
    //                         separator between second and third item, last
    //                         separator and commas are ignored;
    // #A{0Aaa,B{1Bbb|2Ccc}} - unconditional separator, followed by popup menu
    //                         A with two elements, second is popup with two
    //                         elements and separator inbetween.
    case PM_MAIN:                      // Plugin menu in main window
      strcpy(data,"0 Disable,1 Enable,2 Option|3 About");
      // If your plugin is more than trivial, I also recommend to include Help.
      return 1;
   
        case PM_DISASM:                    // Popup menu in Disassembler  
      return 1;
   
        default: break;                    // Any other window
  }
  return 0;                            // Window not supported by plugin
}

// This optional function receives commands from plugin menu in window of type
// origin. Argument action is menu identifier from ODBG_Pluginmenu(). If user
// activates automatically created entry in main menu, action is 0.
extc void _export cdecl ODBG_Pluginaction(int origin,int action,void *item)
{
  if (origin==PM_MAIN)
  {
    switch (action)
        {
      case 0:
              if (AdjustPrivilege(Plugingetvalue(VAL_PROCESSID), FALSE))
                          Addtolist(0,-1, "  DebugPrivilege disabled");
                  
                  break;

      case 1:
              if (AdjustPrivilege(Plugingetvalue(VAL_PROCESSID), TRUE))
                          Addtolist(0,-1, "  DebugPrivilege enabled");
         
                  break;

          case 2:
                  DialogBox(hinst, MAKEINTRESOURCE(IDD_OPTION), hwmain, (DLGPROC)DlgOptionProc);
                  break;
      
          case 3:
        // Menu item "About", displays plugin info. If you write your own code,
        // please replace with own copyright!
        MessageBox(hwmain,
          "DebugPrivilege plugin v1.0\nCopyright (C) 2000-2006 Simonzh2000",
          Name, MB_OK|MB_ICONINFORMATION);
        break;

      default: break;
    }
  }
  else if (origin==PM_DISASM)
  {

  }
}

DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
        int SleepTime  = Pluginreadintfromini(hinst,"Sleeptime",500);
        int pid=0;

        while(!pid)
        {
                Sleep(SleepTime);
        pid=Plugingetvalue(VAL_PROCESSID);
        }

    if (AdjustPrivilege(pid, FALSE))
        {
                Addtolist(0,-1, "  DebugPrivilege disabled");
                return 0;
        }
       
        return 1;
}

// Function is called when user opens new or restarts current application.
// Plugin should reset internal variables and data structures to initial state.
extc void _export cdecl ODBG_Pluginreset(void)
{
    int AutoDisable= Pluginreadintfromini(hinst,"AutoDisable", 0);  

        if (AutoDisable)
        {
                CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
        }
}

// This function receives possible keyboard shortcuts from standard OllyDbg
// windows. If it recognizes shortcut, it must process it and return 1,
// otherwise it returns 0.
extc int _export cdecl ODBG_Pluginshortcut(int origin,int ctrl,int alt,int shift,int key,void *item)
{
  return 0;                            // Shortcut not recognized
}

// OllyDbg calls this optional function when user wants to terminate OllyDbg.
// All MDI windows created by plugins still exist. Function must return 0 if
// it is safe to terminate. Any non-zero return will stop closing sequence. Do
// not misuse this possibility! Always inform user about the reasons why
// termination is not good and ask for his decision!
extc int _export cdecl ODBG_Pluginclose(void)
{
   return 0;
}

// OllyDbg calls this optional function once on exit. At this moment, all MDI
// windows created by plugin are already destroyed (and received WM_DESTROY
// messages). Function must free all internally allocated resources, like
// window classes, files, memory and so on.
extc void _export cdecl ODBG_Plugindestroy(void)
{
}

// If you define ODBG_Pluginmainloop, this function will be called each time
// from the main Windows loop in OllyDbg. If there is some debug event from
// the debugged application, debugevent points to it, otherwise it is NULL. Do
// not declare this function unnecessarily, as this may negatively influence
// the overall speed!

/*
extc void _export cdecl ODBG_Pluginmainloop(DEBUG_EVENT *debugevent)
{
}
*/

附件:debugsrc.rar


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (16)
雪    币: 398
活跃值: (1078)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
2
忘了上传编译好的 DLL 了. 附件:dll.rar
2005-11-22 16:56
0
雪    币: 14940
活跃值: (4728)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
3
好东西.还带源码.爽~
2005-11-22 17:08
0
雪    币: 212
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
支持!辛苦了!
2005-11-22 18:56
0
雪    币: 267
活跃值: (235)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
5
支持的说
2005-11-22 19:20
0
雪    币: 216
活跃值: (370)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
6
你这个完全不需要CreateThread,直接调用即可。
IsDebugPresent的那个老代码这么做也很不科学
要从ini中取出一个sleep的值,从程序设计上来说是一件很失败的事,呵呵。
2005-11-22 19:45
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
7
顶楼主和楼上的~   
2005-11-22 19:58
0
雪    币: 61
活跃值: (160)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
8
good
2005-11-22 20:06
0
雪    币: 398
活跃值: (1078)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
9
最初由 goldenegg 发布
你这个完全不需要CreateThread,直接调用即可。
IsDebugPresent的那个老代码这么做也很不科学
要从ini中取出一个sleep的值,从程序设计上来说是一件很失败的事,呵呵。


不 CreateThread 我也试过,
但 Plugin_reset 中 Plugingetvalue(VAL_PROCESSID) 不成功,
怎么直接调用?

还有一个办法就是 Plugin_Mainloop 中找第一次异常,
但个人感觉这样还不如 CreateThread.
2005-11-23 07:27
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
up...........
2005-11-23 09:16
0
雪    币: 172
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
不错,
哈哈,正好可以学习一下ollydbg插件编写.

楼主辛苦了.
谢谢
2005-11-23 09:18
0
雪    币: 234
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
这个强!!!!!!!!
2005-11-23 09:50
0
雪    币: 216
活跃值: (370)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
13
最初由 simonzh2000 发布


不 CreateThread 我也试过,
但 Plugin_reset 中 Plugingetvalue(VAL_PROCESSID) 不成功,
怎么直接调用?
........


puluginreset时调试还没开始呢。

No,后者才是正确的方法,你Sleep的值,跟系统调度有关,
有可能子进程的检测代码选运行了,
然后你才去设置那个权限。
因为这种形式不稳定。
所以最初IsDebug插件是hardcode了一个sleep值,
后来居然改为从ini中读取。

在mainloop中找异常,代码也很少。并不比createthread麻烦。
而且这与系统调度无关,从程序架构上来说这是一个健壮的架构。
2005-11-24 12:33
0
雪    币: 398
活跃值: (1078)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
14
最初由 goldenegg 发布

在mainloop中找异常,代码也很少。并不比createthread麻烦。
而且这与系统调度无关,从程序架构上来说这是一个健壮的架构。


在 Mainloop 找异常, 有点类似 Hook, 影响 OD 整个调试过程,
所以这个办法也不是没有缺点.

IsDebugPresent 的方法虽然有问题, 但是经过大量测试的.

当然最好的解决办法是 OD 的作者应该再加一个函数:
子进程加载完毕后调用一次.
2005-11-24 16:18
0
雪    币: 216
活跃值: (370)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
15
最初由 simonzh2000 发布


在 Mainloop 找异常, 有点类似 Hook, 影响 OD 整个调试过程,
所以这个办法也不是没有缺点.

........


事实上这个开销并不大,你可以profile一下。
它比创建新线程的开销要小很多。

与hook不一样,hook有很多种:

1. 通过修改代码的方法hookapi,在修改代码的时候可能带来问题。特别是,如果有两个这样的hook,能正常工作吗?
2. 通过修改引入表的hook,没有修改代码问题,但两个这样的hook直接冲突。
3. windows的hook,SetWindowsHookEx当不指定线程时会搞得每个进程中都有dll,现在我最讨厌这一点了,看到哪个程序这么做就去把它干掉。如果指定线程还好。这种hook用来搞windows的消息,搞不定api。

mainloop实际上都没有这样的问题。没有修改代码问题,没有冲突问题。
而你提到的性能问题,事实上也并不存在。事实上让od来增加这样一个函数,
只不过是把你的工作移到od里。mainloop的哪几句代码对od的影响,小于创建一个线程,也远小于给plugin加个壳。

2005-11-24 16:32
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
有点不明白,但是觉得有启发,
我就先撒个尿,
以后有用了,明白了再来看。
顶!!
2005-12-28 15:02
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
看高手分析,顶
2006-2-6 08:48
0
游客
登录 | 注册 方可回帖
返回
//