• 断点检测学习


    突然看到了一种反调试的手段,检测api函数的首字节是否为0xcc,即int 3类型的断点,来反调试,尝试一下

    1. #include
    2. #include
    3. void fun(int a) {
    4. a++;
    5. a--;
    6. a += 5;
    7. a -= 5;
    8. return;
    9. }
    10. int main() {
    11. void (*ptr)(int) = NULL;
    12. ptr = fun;
    13. int i =0;
    14. char *arr=(char*)(ptr);
    15. for (i = 0; i < 99; i++) {
    16. printf("0x%2x\t", arr[i]);
    17. }
    18. return 0;
    19. }

    最开始的时候就遇到了一个问题,我用的virtual studio ,但是这是c++编译的,导致最后的函数指针不是指向的fun函数,这里可以很清楚的看到。

    额,不太清楚编译的原理,那我用纯c,直接用devc++,里面有自带的gcc编译器

    然后就和我预想的一样了,fun就是那个函数指针,在fun里多打一点断点(有个问题,为什么fun函数编译出来会有个nop,不是很懂)

    执行结果上面就有预期的0xCC了,可见,ida确实是用的int 3断点

    这种方法很简单,也很容易绕过,我们来看一下硬件断点,硬件断点基于DRx寄存器,换句话说,可以通过检测DRx寄存器来检测硬件断点

    可以通过SetThreadContext直接设置指定线程的调试寄存器

    DRx寄存器可以直接操作,但是需要设置特权级CPL等于0,这里采用比较简单的方法,直接用GetThreadContext获取当前线程的上下文

    我一共下了3个硬件断点,执行结果如下

    可见,确实用DRx寄存器来设置了硬件断点,而该程序正常执行情况(没有断点)如下

    1. #include
    2. #include
    3. #include
    4. const char *strr = (const char*)"hello touful";
    5. int main()
    6. {
    7. printf("enter\n");
    8. //获取当前线程的句柄
    9. HANDLE hThread = GetCurrentThread();
    10. //创建一个CONTEXT结构体
    11. CONTEXT threadContext;
    12. threadContext.ContextFlags = CONTEXT_ALL;
    13. //获取当前线程的运行上下文
    14. if (!GetThreadContext(hThread, &threadContext))
    15. {
    16. printf("GetThreadContext failed\n");
    17. return 0;
    18. }
    19. printf("DRO = 0x%x\n", threadContext.Dr0);
    20. printf("DR1 = 0x%x\n", threadContext.Dr1);
    21. printf("DR2 = 0x%x\n", threadContext.Dr2);
    22. printf("DR3 = 0x%x\n", threadContext.Dr3);
    23. printf("exit\n");
    24. return 0;
    25. }

    这里顺便贴出CONTEXT结构体的定义

    1. typedef struct DECLSPEC_NOINITALL _CONTEXT {
    2. //
    3. // The flags values within this flag control the contents of
    4. // a CONTEXT record.
    5. //
    6. // If the context record is used as an input parameter, then
    7. // for each portion of the context record controlled by a flag
    8. // whose value is set, it is assumed that that portion of the
    9. // context record contains valid context. If the context record
    10. // is being used to modify a threads context, then only that
    11. // portion of the threads context will be modified.
    12. //
    13. // If the context record is used as an IN OUT parameter to capture
    14. // the context of a thread, then only those portions of the thread's
    15. // context corresponding to set flags will be returned.
    16. //
    17. // The context record is never used as an OUT only parameter.
    18. //
    19. DWORD ContextFlags;
    20. //
    21. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
    22. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
    23. // included in CONTEXT_FULL.
    24. //
    25. DWORD Dr0;
    26. DWORD Dr1;
    27. DWORD Dr2;
    28. DWORD Dr3;
    29. DWORD Dr6;
    30. DWORD Dr7;
    31. //
    32. // This section is specified/returned if the
    33. // ContextFlags word contians the flag CONTEXT_FLOATING_POINT.
    34. //
    35. FLOATING_SAVE_AREA FloatSave;
    36. //
    37. // This section is specified/returned if the
    38. // ContextFlags word contians the flag CONTEXT_SEGMENTS.
    39. //
    40. DWORD SegGs;
    41. DWORD SegFs;
    42. DWORD SegEs;
    43. DWORD SegDs;
    44. //
    45. // This section is specified/returned if the
    46. // ContextFlags word contians the flag CONTEXT_INTEGER.
    47. //
    48. DWORD Edi;
    49. DWORD Esi;
    50. DWORD Ebx;
    51. DWORD Edx;
    52. DWORD Ecx;
    53. DWORD Eax;
    54. //
    55. // This section is specified/returned if the
    56. // ContextFlags word contians the flag CONTEXT_CONTROL.
    57. //
    58. DWORD Ebp;
    59. DWORD Eip;
    60. DWORD SegCs; // MUST BE SANITIZED
    61. DWORD EFlags; // MUST BE SANITIZED
    62. DWORD Esp;
    63. DWORD SegSs;
    64. //
    65. // This section is specified/returned if the ContextFlags word
    66. // contains the flag CONTEXT_EXTENDED_REGISTERS.
    67. // The format and contexts are processor specific
    68. //
    69. BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
    70. } CONTEXT;

    对于内存断点,是以页的方式添加的,设置页的权限位就行了,最常用的两种断点实现了最常用的检测方式

  • 相关阅读:
    Java服务中心面试题目,微服务治理面试
    join on后面 加条件 与 where后面加条件的区别
    物联网毕业设计 - 基于单片机的静脉输液流速流量监测系统
    vue3 elementPlus 表格实现行列拖拽及列检索功能
    Ioc容器加载过程-bean生命周期源码解析
    队列与堆栈:原理、区别、算法效率和应用场景的探究
    linux中sshd是什么(ssh服务无法启动解决办法)
    【最详细最全】Linux启动nginx
    Three.js--》实现3d地球模型展示
    MVSNet论文笔记
  • 原文地址:https://blog.csdn.net/m0_75098930/article/details/134518751