转移指令原理和Inline Hook

转移指令

可以修改IP,或同时可以修改CS和IP的指令统称为:转移指令

8086CPU转移行为有以下几类:

  • 只修改IP时,称为段内转移,比如:jmp ax。
  • 同时修改CS和IP时,称为段间转移,比如:jmp 1000:0。

由于转移指令对IP的修改范围不同,段内转移又分为:短转移和近转移。

  • 短转移IP的修改范围为-128~127(0xFF)
  • 近转移IP的修改范围为-32768~32767(0xFFFF)

8086CPU转移指令分为以下几类:

  • 无条件转移指令(jmp)
  • 条件转移指令(jnz jz..)
  • 循环指令(loop)
  • 过程
  • 中断(int)

操作符offset

操作符offset是伪指令,在汇编语言中由编译器处理的符号,它的功能是取得标号的偏移地址

jmp指令

jmp为无条件转移指令,可以只修改IP,也可以同时修改CS和IP。

jmp指令要给出两种信息:

  • (1) 转移的目的地址
  • (2) 转移的距离(段间转移、段内短转移、段内近转移)
jmp short 标号
jmp near ptr 标号
jcxz 标号
loop 标号 等几种汇编指令,它们对 IP的修改是根据转移目的地址和转移起始地址之间的位移来进行的。在它们对应的机器码中不包含转移的目的地址,而包含的是到目的地址的位移距离。

根据位移进行转移的jmp指令

jmp short 标号(段内短转移)

指令“jmp short 标号”的功能为(IP)=(IP)+8位位移,转到标号处执行指令

  • 8位位移 = "标号"处的地址 - jmp指令后的第一个字节的地址;
  • short指明此处的位移为8位位移动;
  • 8位位移的范围为(-128~127),用补码表示。 也就是最大一个字节(0xFF)
  • 8位位移由编译程序在编译时算出

编译后标号被翻译成了位移。

CPU不需要这个目的地址就可以实现对IP的修改。这里是依据位移进行转移。

jmp short s指令的读取和执行过程如下:

  • (1) (CS)=076C,(IP)=0000,执行完mov ax,0后CS:IP指向了EB 03(jmp short s机器码);
  • (2) 读取指令码EB 03进入指令缓冲器;
  • (3) (IP) = (IP) + 所读取指令的长度 = (IP) + 2 = 5,CS:IP指向了add ax,1;
  • (4) CPU执行指令缓冲器中的指令EB 03
  • (5) 指令执行后IP+位移=(IP) + 3 = 8,CS:IP(076C:0008) 指向->inc ax

插播HOOK知识

这里插播点X86平台下的hook知识,看到这里我们已经知道了我们可以通过修改ip的方式来让代码跳到想要的地方执行代码。

Inline Hook

inline hook是一种通过修改机器码的方式来实现hook的技术。

在没有学汇编知识前,我们可能对Hook这种技术感到很深奥,觉得这简直是一种黑魔法,凭什么他就能把正常函数替换成我们自己的假函数。

Inline Hook 原理

当我们学习了王爽老师的汇编知识后,才明白原来在底层,CPU是根据ip寄存器来控制我们要执行的指令处的。

而学习了《王爽汇编第9章转移指令的原理》后,了解了可以通过jmp指令来修改ip寄存器,目前我们已经学习了短转移的使用,这已经足够用来学HOOK了。

打开OD载入程序,然后找到执行demo函数的汇编代码处,再利用我们今天刚学的短转移知识进行机器码的修改。

首先经过单步调试后,我找到了执行demo函数处的位置,我们先记下他下条指令的地址0x00481885

接着我们需要找到标号处,也就是fake_demo函数处,也记下地址0x004817D0

好了,最后的步骤就是改机器码,根据公式计算出位移:-181(0xFFFFFF4B)

最后来执行一遍:

Hook代码开发

在了解了Hook原理后,甚至我们用手动方式实现了HOOK后,就有了思路来代码开发了。

在此之前让我们先来认识两个函数WriteProcessMemoryVirtualProtect

  • WriteProcessMemory函数可以对进程的内存进行写入,这样我们就可以修改,写入机器码了。

  • VirtualProtect函数可以更改虚拟内存中的访问保护,在Win32中代码段具有写保护,所以我们无法直接写入,可以利用此函数修改保护后再调用WriteProcessMemory修改和写入机器码。

/*************************************************
*功能:内联HOOK 函数,可以劫持函数的原本流程
*
*函数名:InlineHook
*参数:(原函数地址)、(fake函数地址)
*by: 《王爽汇编笔记》
************************************************/
void InlineHook(DWORD dwHookAddr, LPVOID pFunAddr)
{
BYTE jmpCode[5] = {0xE9};
//计算偏移
*(DWORD*)(&jmpCode[1]) = (DWORD)pFunAddr - dwHookAddr - 5;
// 保存以前的属性用于还原
DWORD OldProtext = 0;
DWORD dwWritten;
// 因为要往代码段写入数据,又因为代码段是不可写的,所以需要修改属性
VirtualProtect((LPVOID)dwHookAddr, 5, PAGE_EXECUTE_READWRITE, &OldProtext);
WriteProcessMemory(GetCurrentProcess(), (FARPROC)dwHookAddr, jmpCode, 5, &dwWritten);
VirtualProtect((LPVOID)dwHookAddr, 5, OldProtext, &OldProtext);
} int main()
{
//故意让程序暂停
getchar();
//执行函数
InlineHook((DWORD)&demo, &fake_demo);
demo();
}

转移的目的地址在指令中的jmp指令

jmp far ptr 标号(远转移、段间转移)

  • (CS) = 标号所在段的段地址;
  • (IP) = 标号所在段中的偏移地址。
  • far ptr 指明了指令用标号的段地址 和 偏移地址修改 CS和IP

Win32中的远转移可以跳到其他DLL的空间,其中关键的机器码是0xFF25 + 目标地址

转移地址在寄存器或内存中的jmp指令

jmp 16位寄存器功能:IP=(16位寄存器)[段内转移]

转移地址在内存中的jmp指令有两周格式:

  • jmp word ptr [...] (段内转移)

  • jmp dword ptr [...] (段间转移)

功能:从内存单元地址处开始存放着两个字,高地址出的字是转移目的段地址低地址处是转移目的偏移地址

1:(CS) = (内存单元地址+2)

2:(IP) = (内存单元地址)

jcxz指令和loop指令

jcxz指令

jcxz指令为有条件转移指令,所有的有条件转移指令都是短转移,在对应的机器码中包含转移的位移而不是目的地址。对IP的修改范围都为-128~127(0xff)。

指令格式:jcxz 标号 (如果cx=0,则转移到标号处执行。)

当(cx) = 0时,(IP) = (IP) + 8位位移

  • 8位位移 = "标号" 处的地址 - jcxz指令后的第一个字节的地址;
  • 8位位移的范围为-128~127,用补码表示;
  • 8位位移由编译程序在编译时算出。

当(cx)!=0时,程序向下执行什么都不做!

loop指令

loop指令为循环指令,所有的循环指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。

对IP的修改范围都为-128~127(0xFF)。

指令格式:loop 标号 ((cx) = (cx) - 1,如果(cx) ≠ 0,转移到标号处执行)。

(cx) = (cx) - 1;如果 (cx) != 0,(IP) = (IP) + 8位位移。

  • 8位位移 = ""标号""处的地址 - loop指令后的第一个字节的地址;
  • 8位位移的范围为-128~127,用补码表示;
  • 8位位移由编译程序在编译时算出。

如果(cx)= 0,什么也不做(程序向下执行)。

几种跳转指令和对应的机器码

注:(Win32 x86架构下)

机器码 指令 解释
0xE8 CALL 后面的四个字节是地址 (近转移)
0xE9 JMP 后面的四个字节是偏移 (近转移)
0xEB JMP 后面的二个字节是偏移 (近转移 8086)
0xFF15 CALL 后面的四个字节是存放地址的地址 (远转移)
0xFF25 JMP 后面的四个字节是存放地址的地址 (远转移)
0x68 PUSH 后面的四个字节入栈
0x6A PUSH 后面的一个字节入栈

参考文献:

https://www.cnblogs.com/Archimedes/p/14823218.html inline hook原理和实现

https://blog.csdn.net/wzsy/article/details/17163589 几种跳转指令和对应的机器码

https://blog.csdn.net/qq_39654127/article/details/88698911 王爽《汇编语言》笔记(详细)

《王爽汇编第四版 第9章》

转移指令原理和Inline Hook的更多相关文章

  1. android inline hook

    最近终于沉下心来对着书把hook跟注入方面的代码敲了一遍,打算写几个博客把它们记录下来. 第一次介绍一下我感觉难度最大的inline hook,实现代码参考了腾讯GAD的游戏安全入门. inline ...

  2. Inline Hook

    @author: dlive IAT Hook时如果要钩取的API不在IAT中(LoadLibrary后调用),则无法使用该技术.而Inline Hook不存在这个限制. 0x01 Inline Ho ...

  3. INLINE HOOK过简单驱动保护的理论知识和大概思路

    这里的简单驱动保护就是简单的HOOK掉内核API的现象 找到被HOOK的函数的当前地址在此地址处先修改页面保护属性然后写入5个字节.5个字节就是一个简单的JMP指令.这里说一下JMP指令,如下: 00 ...

  4. x86平台inline hook原理和实现

    概念 inline hook是一种通过修改机器码的方式来实现hook的技术. 原理 对于正常执行的程序,它的函数调用流程大概是这样的: 0x1000地址的call指令执行后跳转到0x3000地址处执行 ...

  5. Android Hook框架adbi的分析(2)--- inline Hook的实现

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/74452308 一. Android Hook框架adbi源码中inline Hoo ...

  6. Android Hook框架adbi的分析(3)---编译和inline Hook实践

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/75200800 一.序言 在前面的博客中,已经分析过了Android Hook框架a ...

  7. iOS开发UI篇—程序启动原理和UIApplication

    iOS开发UI篇—程序启动原理和UIApplication   一.UIApplication 1.简单介绍 (1)UIApplication对象是应用程序的象征,一个UIApplication对象就 ...

  8. 对付ring0 inline hook

    对付ring0 inline hook的基本思路是这样的,自己写一个替换的内核函数,以NtOpenProcess为例,就是MyNtOpenProcess.然后修改SSDT表,让系统服务进入自己的函数M ...

  9. iOS开发UI篇—程序启动原理和UIApplication1

    iOS开发UI篇—程序启动原理和UIApplication   一.UIApplication 1.简单介绍 (1)UIApplication对象是应用程序的象征,一个UIApplication对象就 ...

随机推荐

  1. 【PHP数据结构】线性查找与二分查找

    欢迎来到查找的世界,在学习完各种数据结构之后,总算走到了这一步,不知道大家有什么感想呢?反正我是边学边忘,现在让我去说说图的那几个算法还是在蒙圈的状态中.不过学习嘛,就是一步一步的来,暂时搞不懂的东西 ...

  2. 如何创建 Office LTSC 2021 VL(批量许可)版本的安装 ISO

    Office LTSC 2021 发布 2021 年 9 月 16 日,微软正式发布了支持 Office 2021 的部署工具(Office Deployment Tool),这意味着 Office ...

  3. Java基础系列(28)- 方法的定义和调用

    方法的定义 Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法: 修饰符 返回值类型 方法名(参数类型 参数名){ -- 方法体 -- retu ...

  4. SonarScanner扫描Maven项目使用说明

    最近在学习使用sonar扫描代码,已经成功扫描python项目,而扫描java代码不成功. 在网上找到的扫描java项目文章,经过尝试之后也没有成功. 本人自己研究了sonar官方的使用说明文章,将其 ...

  5. 『GoLang』包

    可见性规则 在Go语言中,标识符必须以一个大写字母开头,这样才可以被外部包的代码所使用,这被称为导出.标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的.但是包名不管 ...

  6. P3306-[SDOI2013]随机数生成器【BSGS】

    正题 题目链接:https://www.luogu.com.cn/problem/P3306 题目大意 给出一个\(p,a,b,x_1,t\),有\(x_i=ax_{i-1}+b\) 求一个最小的\( ...

  7. Superedge的新特性和未来之路

    作者 王冬,腾讯云高级研发工程师,专注于Kubernetes.容器等云原生领域,SuperEdge 核心开发人员,现负责腾讯云边缘容器TKE Edge私有化相关工作. 背景 2021年9月27号,,在 ...

  8. SpringCloud升级之路2020.0.x版-25.OpenFeign简介与使用

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent OpenFeign 的由来和实现思路 在微服务系统中,我们经常会进行 RPC 调用.在 S ...

  9. bash是什么?

    bash shell就是一个bash程序 ​ --解释器,启动器 ​ --解释器: ​ 用户交互输入 如vim 文本文件输入 脚本本质: !/bin/bash !/usr/bin/python 读取方 ...

  10. 独家对话阿里云函数计算负责人不瞋:你所不知道的 Serverless

    作者 | 杨丽 出品 | 雷锋网产业组 "Serverless 其实离我们并没有那么遥远". 如果你是一名互联网研发人员,那么极有可能了解并应用过 Serverless 这套技术体 ...