1、
向指定地址写入代码
A、JMP地址转换公式推导
B、计算实际地址函数RealJmp_Addr
C、测试
【240】JMP指令 -> 机器码 --> 0xE9
【260】指令"JMP 88881234" --> 翻译成机器码 --> "E9 88881234"
【328】打开 OD 看一下,JMP指令是否如我们上面猜想的那样翻译的
【440】我们自己改几条指令(把它们改成JMP指令),发现 机器码后面的立即数是不同的:
后面3个byte是相同的,第1个byte的值不同
ZC: 应该是 JMP指令 跳转的是相对位置?
【645】十六进制0x88881234
【695】指令所在的地址为: 0x010073BB
它们的差为: 0x87879E79
【815】0x87879E79 - 0x5 ==> 0x87879E74 ==> 这就是 OD中显示的地址
ZC: 其实 E9 后面的立即数 就是 0x88881234 与 下一条指令地址 的差,它的相对地址是 通过下一条指令 计算得来的。(想象这样一个情景,有时用OD断下(内存断点?)的时候,我们观察的是此时EIP的上面一条指令,此处应该也是这个道理?当CPU在执行A指令的时候 EIP实际已经指向了下一条指令了?EIP实际指向的是将要执行现在还没执行的指令?稍微查了一下 貌似是这样子的。于是 段内偏移 应该 是相对EIP指向的地址来计算?)
【825】OD中的 立即数 的高地位是倒着的
【905】看一下"dd 10073BB+1",这里 "+1"是为了跳过字节"E9"
【1035】"db 10073BB+1"
ZC: 饶了半天,连 CPU 小端存储格式/大端存储格式 都讲不出来么...
【1185】
定义JMP结构
typedef struct _JMPCODE
{
BYTE E9;
ULONG JMPADDR;
} JMPCODE,*PJMPCODE;
ZC: (x86)公式 应该是: 机器码相对地址=目标指令地址(段内绝对地址) - JMP的下一条指令的地址
【1720】把 第19课 的代码复制过来
【1910】
NTSTATUS DriverEntry(PDRIVER_OBJECT _pDrvierObject, PUNICODE_STRING B)
{
ULONG cur, old, ulOffset;
cur = GetNt_CurAddr() ;
old = GetNt_OldAddr();
if (cur != old)
{
ulOffset = old - (cur + 5);
KdPrint(("要写入的地址 : 0x%08X", ulOffset));
// 【2830】写入 我们的 JMP指令
KdPrint(("NtOpenProcess被Hook了"));
}
else
KdPrint(("NtOpenProcess没有被Hook"));
_pDrvierObject->DriverUnload = DDK_Unload;
return 1;
}
【2550】改为使用 结构体JMPCODE 的方式
【2675】编译失败,找不到 BYTE类型
【2820】添加"#include <windef.h>"
ZC: BYTE 改成 byte 不是也可以么?
【2990】打开 KernelDetective ,看看我们计算的信息是否正确
【3130】用 DriverMonitor加载我们的驱动
【3430】信息是一致的
【3570】理论上,我们的 JMP相关代码 这样写就可以:(使用 JCode 的写法)
if (cur!=old)
{
JCode.E9=0xE9;
JCode.JMPADDR=cur-old-5;
KdPrint(("需要写入的地址是%X",JCode.JMPADDR));
_asm
{
mov ebx,cur
lea ecx,JCode
mov ax,byte ptr [ecx]
mov byte ptr[ebx],ax //jmp
mov eax,[ecx+1] //B
mov [ebx+1],eax
}
//写入JMP
KdPrint(("NtOpenProcess被HOOK了"));
}
【4115】理论上这样就可以了 (ZC: 貌似 虽然细节上可能还需要弄弄(mov eax,dword ptr [ecx+1]),但是应该确实可以了)
【4130】还有 涉及到 更改页面保护之类的...
2、