jmp,call 指令如何翻译成字节

永夜星空 2011-04-10 08:50:40
我想把某个程序的某个函数转到自己的处理过程里,处理完毕后在跳回到原来的函数里。那么就得把原本函数的开头位置修改成jmp xxxxxxxx,或者call xxxxxxxx。 xxxxxx就是自己的处理过程的地址。
自己写的处理过程位置是用VirtualAllocEx在目标进程里申请的,地址并不是每次都一样,所以在修改跳转指令的时候就必须要跟着变,那么对于关键的跳转指令要写成什么字节内容呢?
在OD里研究了好久,始终没有发现远跳的jmp,与call翻译的规律。
甚至对于同一个jmp出现在不同位置就会被翻译成不同的字节,如:
7C8293A6 E9 556C7D83 jmp 00000000
jmp 0 出现在地址 7C8293A6 时是 E9 556C7D83

7C8293FD E9 FE6B7D83 jmp 00000000
jmp 0 出现在地址 7C8293FD 时是 E9 FE6B7D83

百思不得其解啊。哪位高手指点一下吧
...全文
436 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
Lactoferrin 2011-04-11
  • 打赏
  • 举报
回复
你怎么还是分不清什么是远跳和近跳,eb是短跳

直接给你看intel指令手册

Opcode Instruction Description
EB cb JMP rel8 Jump short, relative, displacement relative to next instruction
E9 cw JMP rel16 Jump near, relative, displacement relative to next instruction
E9 cd JMP rel32 Jump near, relative, displacement relative to next instruction
FF /4 JMP r/m16 Jump near, absolute indirect, address given in r/m16
FF /4 JMP r/m32 Jump near, absolute indirect, address given in r/m32
EA cd JMP ptr16:16 Jump far, absolute, address given in operand
EA cp JMP ptr16:32 Jump far, absolute, address given in operand
FF /5 JMP m16:16 Jump far, absolute indirect, address given in m16:16
FF /5 JMP m16:32 Jump far, absolute indirect, address given in m16:32

• Near jump—A jump to an instruction within the current code segment (the segment
currently pointed to by the CS register), sometimes referred to as an intrasegment jump.
• Short jump—A near jump where the jump range is limited to –128 to +127 from the
current EIP value.
• Far jump—A jump to an instruction located in a different segment than the current code
segment but at the same privilege level, sometimes referred to as an intersegment jump.
• Task switch—A jump to an instruction located in a different task.
Lactoferrin 2011-04-11
  • 打赏
  • 举报
回复
windows不用Task switch切换进程
永夜星空 2011-04-11
  • 打赏
  • 举报
回复
原来竟然有4种跳。开始我还以为32位程序只剩下两种了。

不过Task switch竟然这么神奇,它可以跳到别的进程吗?
永夜星空 2011-04-11
  • 打赏
  • 举报
回复 1
谢谢大家,终于发现它的规律了。其实和近跳差不多,我总结如下
JMP远跳,CALL编译成字节码的方法:
jmp远跳与CALL指令都占5个字节

JMP 32位目标地址:
E9 + (32位目标地址-下条指令地址)
E9 + (32位目标地址-(当前指令地址+5))

CALL 32位目标地址
E8 + (32位目标地址-下条指令地址)
E8 + (32位目标地址-(当前指令地址+5))
减法运算直接使用无符号运算,而且遵循结果高高低低的存储规则,CPU自己会把结果当作有符号数来认。

JMP近跳:
JMP近跳占2个字节
EB + (取低8位(32位目标地址-下条指令地址))
EB + (取低8位(32位目标地址-(当前指令地址+2)))

c++版本的转换函数如下:


void Jmp(DWORD addr1,DWORD addr2,BYTE* buff) //在buff中生成处于 位置addr1的汇编语言:“jmp addr2”的机器码。
{
buff[0]=0xE9;
*(DWORD*)(&(buff[1]))=addr2-(addr1+5);
}



用这个规律成功的改写了一个游戏的CreateMutexA函数,并实现了游戏多开,应该没错了
Lactoferrin 2011-04-10
  • 打赏
  • 举报
回复
5字节的是直接近跳
直接远跳是ea 段偏移 段选择子,一共7字节
辰岡墨竹 2011-04-10
  • 打赏
  • 举报
回复
一个远跳是EA加上4个字节的有效地址,一共5个字节,那么你就的保证修改的那个函数前面5个字节是完整的指令,如果出现有指令要跨过5个字节的话,就需要用NOP填充掉后面那条。记得一定要保存你覆盖掉的指令并再返回时执行它。
goodider 2011-04-10
  • 打赏
  • 举报
回复
去了解一下计算机系统就知道了。
Lactoferrin 2011-04-10
  • 打赏
  • 举报
回复
我想把某个程序的某个函数转到自己的处理过程里,处理完毕后在跳回到原来的函数里。那么就得把原本函数的开头位置修改成jmp xxxxxxxx,或者call xxxxxxxx。 xxxxxx就是自己的处理过程的地址。

你先要确定受害者函数前的指令长度,否则不好再跳回去
Lactoferrin 2011-04-10
  • 打赏
  • 举报
回复
e9是近跳
它后面四个字节(x64也一样)当作有符号整数,和e9的下一指令的地址相加就是目标地址

说白了e9就是把指令指针寄存器加一个数

e8类似

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧