天天看点

直接构造汇编指令

   既然我们发现了指令不过就是一些字节的组合,我们可以尝试抛开C语言,自己构造指令执行。我们完全可以分配一段内存,然后将mov指令的机器码填入。但是,如何让CPU执行我们的代码呢?

   假定我们构造了一段mov指令,需要用jmp语句跳转到该指令。

   如果我们执行完mov指令后就不管了的话,我们就会发现程序会异常退出。比如下面的程序

#include "stdafx.h"

#include <iostream>

using namespace std;

int gi = 0;

unsigned char *code = 0;

unsigned char* BuildCode()

{

unsigned char *pCode = new unsigned char[10];

unsigned char *pMov = pCode;

pMov[0] = 0xC7;

pMov[1] = 0x05;

unsigned char *pAddress = pMov + 2;

*((int *)pAddress) = (int)(&gi);

unsigned char *pImm = pAddress + 4;

*((int *)pImm) = 18;

return pCode;

}

int _tmain(int argc, _TCHAR* argv[])

{

gi = 12;

code = BuildCode();

_asm jmp dword ptr [code]

return 0;

}

我们只是构造了一个mov指令,执行完毕后程序异常退出了。

因为我们执行完mov指令之后,如果不加处理,EIP所指内存的值是不确定的。CPU就会将该不确定的值解释为对应指令,这将导致不可预料的行为,因此,我们再mov指令之后应该放一条指令,让程序回到正常流程。Jmp指令正好可以达到这个目的。

// 1.3.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include <iostream>

using namespace std;

int gi = 0;

unsigned char *code = 0;

unsigned char *pReturnAddress = 0;

unsigned char* BuildCode()

{

unsigned char *pCode = new unsigned char[16];

unsigned char *pMov = pCode;

pMov[0] = 0xC7;

pMov[1] = 0x05;

unsigned char *pAddress = pMov + 2;

*((int *)pAddress) = (int)(&gi);

unsigned char *pImm = pAddress + 4;

*((int *)pImm) = 18;

unsigned char *pJmp = pImm + 4;

pJmp[0] = 0xff;

pJmp[1] = 0x25;

unsigned char *pJmpAddress = pJmp + 2;

*((int *)pJmpAddress) = (int)(&pReturnAddress);

return pCode;

}

int _tmain(int argc, _TCHAR* argv[])

{

gi = 12;

_asm

{

mov pReturnAddress, offset l

}

code = BuildCode();

_asm jmp dword ptr [code]                                                                                                                                                                                                      

l:cout << gi << endl;

return 0;

}

 mov  指令由三部分构成

   两字节的c7 05 代表操作码

  四字节的gi地址

 四字节的源操作数

jmp指令由6字节构成

 2字节的操作码  ff 25 

 4字节的目的跳转地址

我们通过调试→窗口→寄存器可以看到我们的8个通用寄存器的值

EIP(Extended Instruction Pointer)32位的指令寄存器

是将16位的IP寄存器扩展之后得到的,EIP指向哪里,CPU就将该地址作为执行指令的入口。

继续阅读