DebugPort
检测EPROCESS中的DebugProt,如果不在调试的时候就是NULL,否则为一个指针,该对象负责在调试器与被调试进程之间进行调试时间的传输
KdDisableDebugger
禁用内核调试
KdenableDebugger 启用内核调试
IsDebuggerPresent/CheckRemoteDebuggerPresent
从PEB(进程环境块)偏移0x002处获得BeingDebugged,从而判断是否处于调试阶段
Hook
HOOK一些与调试相关的函数
NtOpenThread:防止调试器在程序内部创建线程
NtOpenProcess:防止OD等调试工具在进程列表中看到
KIAttachProcess:防止被附加上
NtReadVirtualMemory:防止被读内存
NtWriteVirtualMemory:防止内存被写
KdReceivePacket:KDCOM.dll中Com串口接收数据函数
KdSendPacket:KDCOM.dll中Com串口发送数据函数,Hook这两个函数来防止双机调试
花指令
花指令是程序中无用指令,故意干扰各种反汇编静态分析工具,但程序不受任何影响。加花指令后,IDA Pro等分析工具对程序静态反汇编是,会出现错误或者遭到破坏,加大逆向静分析的难度。
花指令 1
push edx
pop edx
inc ecx
dec ecx
add esp,1
sub esp,1
花指令 2
jmp Label1
db opcode
Label1;
花指令 3
jz Label
jnz Label
db opcode
Label
OOLVM
指令替代
当有几个等效的指令序列可用时,将随机选择一个,用更复杂的算法对原代码进行替换。比如:a = a ^ b 替换为 a = (~a & b) | (a & ~b),a = b + c 替换为 r = rand (); a = b - r; a = a + b; a = a + r
当前,只有整数运算符可用,因为用浮点值替代运算符会带来舍入误差和不必要的数值误差。
伪控制流
该方法通过在当前真实块之前添加一个分发器来修改函数调用图。这个新的分发器包含一个不透明值,然后有条件地跳转到真实块。真实块也将被克隆并填充以随机选择的垃圾指令。
控制流平坦化
完全弄平程序的控制流程图。
#include <stdlib.h>
int main(int argc, char** argv) {
int a = atoi(argv[1]);
if(a == 0)
return 1;
else
return 10;
return 0;
}
源代码
#include <stdlib.h>
int main(int argc, char** argv) {
int a = atoi(argv[1]);
int b = 0;
while(1) {
switch(b) {
case 0:
if(a == 0)
b = 1;
else
b = 2;
break;
case 1:
return 1;
case 2:
return 10;
default:
break;
}
}
return 0;
}
展开后,能很明显的看出代码的目的。
句柄表
可以在句柄表中去搜寻自己的句柄,来查看是否使用了调试器来调试