for (unsigned int i = 0; i < vAsm.size(); i++) //对所有跳转指令的下一条指令,跳转指令目的地,以及最后一条指令做标记
{
if (IsBranch(vAsm[i].stAsm.Instruction.BranchType) && vAsm[i].stAsm.Instruction.AddrValue != 0)
{
vAsm[i + 1].states = true;
for (unsigned int x = 0; x < vAsm.size(); x++)
{
if (vAsm[x].stAsm.VirtualAddr == vAsm[i].stAsm.Instruction.AddrValue)
{
vAsm[x].states = true;
}
}
}
}
vAsm[vAsm.size() - 1].states = true;
CodeBlock stBlock;
for (unsigned int i = 0; i < vAsm.size(); i++)
{
if (vAsm[i].states == true)
{
stBlock.Entry = (int)stBlock.vAsm[0].VirtualAddr;
if (!IsBranch(vAsm[i - 1].stAsm.Instruction.BranchType) || vAsm[i - 1].stAsm.Instruction.AddrValue == 0) //如果尾指令不是跳转指令
{
stBlock.iBranch1 = (int)vAsm[i].stAsm.VirtualAddr;
stBlock.iBranch2 = (int)vAsm[i].stAsm.VirtualAddr;
srand(unsigned int(time(NULL)));
stBlock.nBrType = rand() % 8; //当成JMP指令来处理
}
else if (IsBranch(vAsm[i - 1].stAsm.Instruction.BranchType) && vAsm[i - 1].stAsm.Instruction.AddrValue != 0) //如果尾指令是跳转指令
{
stBlock.nBrType = tranbr(vAsm[i - 1].stAsm.Instruction.BranchType);
stBlock.iBranch1 = (int)vAsm[i].stAsm.VirtualAddr;
stBlock.iBranch2 = (int)vAsm[i - 1].stAsm.Instruction.AddrValue;
if (stBlock.nBrType == 10) //如果是JMP指令,随便找一条跳转指令模拟JMP
{
srand(unsigned int(time(NULL)));
stBlock.nBrType = rand() % 8;
stBlock.iBranch1 = stBlock.iBranch2;
}
if (stBlock.nBrType < 0) //对于JNC Label \ Label2: 指令,将其转换为JC Label2 \ Label1:
{
stBlock.nBrType = -stBlock.nBrType;
int k;
k = stBlock.iBranch1;
stBlock.iBranch1 = stBlock.iBranch2;
stBlock.iBranch2 = k;
}
stBlock.vAsm.pop_back(); //删除尾指令
}
vBlocks.push_back(stBlock);
stBlock.vAsm.clear();
stBlock.vAsm.push_back(vAsm[i].stAsm);
}
else
{
stBlock.vAsm.push_back(vAsm[i].stAsm);
}
}
vBlocks[vBlocks.size() - 1].vAsm.push_back(vAsm[vAsm.size() - 1].stAsm); //将代码切割成基本块
接下来,因为要把代码全部移到新添加的区块,所以要正所有基本块的后继区块的地址(VA地址)。
for (unsigned int i = 0; i < vBlocks.size() - 1; i++)
{
srand(unsigned int(time(NULL)));
chanblock(vBlocks, i, rand() % (unsigned int)vBlocks.size());
}
//先将基本块随机交换位置,打乱代码空间局部性
int pBase = (int)pe.getaddr(pCopy, vt_offset, vt_va);
vector<int> vOldEntry;
const int jmpsize = 17; //每个基本块后都会添加一段指令,以跳转到Dispatch,需要用到该字段计算新的Entry
for (unsigned int i = 0; i < vBlocks.size(); i++)
{
vOldEntry.push_back(vBlocks[i].Entry);
}
//记录所有基本块的原入口
vBlocks[0].Entry = pBase;
for (unsigned int i = 1; i < vBlocks.size(); i++)
{
static int len = 0;
for (unsigned int x = 0; x < vBlocks[i - 1].vAsm.size(); x++)
{
memcpy(xde.instr, vBlocks[i - 1].vAsm[x].CompleteInstr, 64);
xde.cip = 0;
XEDParseAssemble(&xde);
len += xde.dest_size; //这里出现设计失误了,本来应该记录一下指令长度的
}
len += jmpsize; //基本块尾部跳转到Dispatch的指令长度
vBlocks[i].Entry = pBase + len;
}
//更新所有基本块的入口
for (unsigned int i = 0; i < vBlocks.size(); i++)
{
for (unsigned int x = 0; x < vOldEntry.size(); x++)
{
if (vBlocks[i].iBranch1 == vOldEntry[x])
{
vBlocks[i].iBranch1 = vBlocks[x].Entry;
}
if (vBlocks[i].iBranch2 == vOldEntry[x])
{
vBlocks[i].iBranch2 = vBlocks[x].Entry;
}
}
}
//修正所有区块的后继区块