目的是反反汇编(保护技术的一种)
在程序中插入若干代码,因为反汇编工具利用的线性扫描算法没有办法正确地将代码和数据分开,导致反汇编错误。
0xE8 CALL 后面的四个字节是地址 0xE9 JMP 后面的四个字节是偏移 0xEB JMP 后面的二个字节是偏移 0xFF15 CALL 后面的四个字节是存放地址的地址 0xFF25 JMP 后面的四个字节是存放地址的地址
0x68 PUSH 后面的四个字节入栈 0x6A PUSH 后面的一个字节入栈
__asm 关键字用于调用内联汇编程序,并且可在 C 或 C++ 语句合法时出现。
_asm是 __ASM 的同义词。
__asm后跟一个程序集指令、一组括在大括号中的指令或者至少一对空大括号。
1、__asm与大括号一起使用,则该关键字表示大括号之间的每一行都是一条汇编语言语句。
如:
_asm { mov al, 2 mov dx, 0xD007 out al, dx }
2、asm不与大括号一起使用,放在代码行首部,则 asm 关键字表示此行的其余部分是一条汇编语言语句。
如:
__asm mov al, 2
__asm mov dx, 0xD007
__asm out al, dx
3、__asm做语句分隔符,可将汇编语句放在同一行代码中。
如:
__asm mov al, 2 __asm mov dx, 0xD007 __asm out al, dx
__asm {
_emit 075h #jmp $+4
_emit 2h
_emit 0E9h
_emit 0EDh
}
9是jmp指令对应的机器码,当反汇编器读取到E9时,接着会往下读取四个字节的数据作为跳转地址的偏移,所以才会看到错误的汇编代码。
call+pop/add esp/add [esp] + retn
call指令可以理解为jmp + push ip 因此如果通过add esp,4来降低栈顶即可去除push ip的影响,从而使call等价于jmp 但IDA会认为这是函数的分界,从而导致函数的范围识别错误
#include <iostream.h>
#include <windows.h>
void main()
{
DWORD p;
_asm
{
call l1
l1:
pop eax
mov p,eax//确定当前程序段的位置
call f1
_EMIT 0xEA//花指令,此处永远不会执行到
jmp l2//call结束以后执行到这里
f1://这里用F8OD会终止调试,F7跟进的话就正常,why?
pop ebx
inc ebx
push ebx
mov eax,0x11111111
ret
l2:
call f2//用ret指令实现跳转
mov ebx,0x33333333//这里永远不会执行到
jmp e//这里永远不会执行到
f2:
mov ebx,0x11111111
pop ebx//弹出压栈的地址
mov ebx,offset e//要跳转到的地址
push ebx//压入要跳转到的地址
ret//跳转
e:
mov ebx,0x22222222
}
cout<<hex<<p<<endl;
}