再发
// ---------------------------------------- CCodeILFactory.cpp ---------------------------------
// VMPackLib
#include "stdafx.h"
#include "CCodeILFactory.h"
CCodeILFactory::CCodeILFactory()
{
}
/**
* 中间字节码指令工厂初始化,主要是生成某些虚拟机核心指令机器代码,
* 并将该代码复制到m_CodeEngine虚拟内存中
*
* VirtualAddress:虚拟内存相应的虚拟地址
*/
void CCodeILFactory::Init(DWORD VirtualAddress) // *
{
// 计算与虚拟机相关代码的各虚拟地址与空间长度
int nJumpTableAddr = VirtualAddress;
int nCodeEngineAddr = nJumpTableAddr + JumpTableLen;
int nEnterStubAddr = nCodeEngineAddr + CodeEngineLen;
int mVMEnterStubCodeAddr = nEnterStubAddr + EnterStubAddrLen;
int nVMCodeAddr = mVMEnterStubCodeAddr + VMEnterCodeLen;
// 为每段代码分配相关的内存空间
m_JumpTable.CreateVirtualMemory(nJumpTableAddr, JumpTableLen);
m_CodeEngine.CreateVirtualMemory(nCodeEngineAddr, CodeEngineLen);
m_EnterStub.CreateVirtualMemory(nEnterStubAddr, EnterStubAddrLen);
m_VMEnterStubCode.CreateVirtualMemory(mVMEnterStubCodeAddr, VMEnterCodeLen);
m_VMCode.CreateVirtualMemory(nVMCodeAddr, VMCodeLen);
// 将各内存空间信息传递给VMFactory虚拟机工厂
VMFactory.SetupVirtualMemory(&m_JumpTable, &m_CodeEngine, &m_EnterStub, &m_VMEnterStubCode, &m_VMCode);
// 初始化虚拟机
VMFactory.InitVM();
}
/**
* 反汇编指定代码
*
* CodeList:用于返回反汇编后所得的每个指令
* base_addr:欲反汇编代码的基地址,一般是某个函数的基址
* VirtualAddress:欲反汇编代码所在的虚拟地址
*/
void CCodeILFactory::DisasmFunction(list<CodeNode *> * CodeList, char * base_addr, DWORD VirtualAddress) // *
{
// 函数起始地址
DWORD Start_VirtualAddress = VirtualAddress;
// 函数结束地址
DWORD End_VirtualAddress = 0;
// 用于保存反汇编结果
t_disasm da;
CodeNode * code = NULL;
int len =0;
int KeepNum = 0;
// 计算出函数的结尾
while (TRUE)
{
code = new CodeNode;
// 反汇编base_addr的代码
len = Disasm(base_addr, MAXCMDSIZE, VirtualAddress, &da, DISASM_CODE);
// 将反汇编结果da复制到disasm中,并加入到CodeList列表中
memcpy(&code->disasm, &da, sizeof(t_disasm));
CodeList->push_back(code);
// 递减所剩代码长度
if (KeepNum >= len && KeepNum != 0 )
KeepNum -= len;
// 如果da指令是跳转指令
if (IsJumpCmd(&da))
{
// 并且跳转的目标地址是向前跳转,则计算从当前指令至目标地址的代码长度
if (da.jmpconst && da.jmpconst > VirtualAddress)
{
KeepNum = da.jmpconst - VirtualAddress;
}
}
// 如果是int3指令,即断点指令,则直接跳出
if (_stricmp(da.result, "int3") == 0)
{
break;
}
// 如果找到返回指令
if (_stricmp(da.result, "retn") == 0)
{
// 并且已没有更多的代码,则说明函数结束
if (KeepNum - len <= 0)
break;
}
base_addr += len;
VirtualAddress += len;
}
End_VirtualAddress = VirtualAddress;
// 确定每个指令的类型等信息
BOOL NextJMCALL = FALSE;
list<CodeNode*>::iterator itr;
// 遍历CodeList中的每个语句
for (itr = CodeList->begin(); itr != CodeList->end(); itr++)
{
CodeNode * code = * itr;
t_disasm t_da;
// 得到语句的反汇编结果
memcpy(&t_da, &code->disasm, sizeof(t_disasm));
// 真是一个奇怪的判断
if (code)
{
if (NextJMCALL)
{
NextJMCALL = FALSE;
// 表示code指令是JMP或CALL指令后的指令
code->IsJmcNextType = TRUE;
}
// 如果是跳转指令
if (IsJumpCmd(&t_da))
{
NextJMCALL = TRUE;
// 如果存在跳转地址
if (t_da.jmpconst)
{
// 跳转的范围在CodeList中
if (t_da.jmpconst > Start_VirtualAddress && t_da.jmpconst < End_VirtualAddress)
{
// 搜索code跳转指令跳转的目标
CodeNode * tmpNode = SearchAddrAsList(CodeList, code);
// 确实找到跳转目标
if (tmpNode)
{
// 标明tmpNode指令是从其他地方跳转过来的
tmpNode->IsJmcFromType = TRUE;
}
}
else
{
// 为跳到外部的指令
code->IsJmcBeSideType = TRUE;
}
}
// 没有跳转地址,则表示是动态跳转
else
{
code->IsJmcDynamicType = TRUE;
}
}
// 是函数调用指令
else if (IsCallCmd(&t_da))
{
NextJMCALL = TRUE;
code->IsCallType = TRUE;
}
}
}
}
/**
* 检测da中反汇编指令是否是跳转指令
*
* 返回值:是则返回TRUE,否则FALSE
*/
BOOL CCodeILFactory::IsJumpCmd(t_disasm * da) // *
{
// CALL不属于跳转指令
if ((da->cmdtype & C_CAL) == C_CAL)
{
return FALSE;
}
if ((da->cmdtype & C_JMP) == C_JMP)
{
return TRUE;
}
if ((da->cmdtype & C_JMC) == C_JMC)
{
return TRUE;
}
return FALSE;
}
/**
* 检测da中反汇编指令是否是函数调用指令
*
* 返回值:是则返回TRUE,否则FALSE
*/
BOOL CCodeILFactory::IsCallCmd(t_disasm * da) // *
{
if ((da->cmdtype & C_CAL ) == C_CAL)
{
return TRUE;
}
return FALSE;
}
BOOL CCodeILFactory::IsRetnCmd(t_disasm* da)
{
char strretn[32] = "RETN\0";
_strlwr_s(da->result,TEXTLEN);
_strlwr_s(strretn,32);
if( strstr(strretn,da->result) )
{
return TRUE;
}
return FALSE;
}
/**
* 在指令List列表中,搜索跳转指令node跳转的目标指令
*
* List:指令列表
* node: 跳转指令
*
* 返回值:找到node是跳转向List中的哪个指令,则返回该目标指令,否则NULL
*/
CodeNode * CCodeILFactory::SearchAddrAsList(list<CodeNode*> * List, CodeNode * node) // *
{
// node是一个跳转指令,现在获取其跳转地址
DWORD GotoAddr = node->disasm.jmpconst;
DWORD LastAddr = 0;
list<CodeNode*>::iterator itr;
// 遍历List中的每个语句
for (itr = List->begin(); itr != List->end(); itr++)
{
CodeNode * code = * itr;
t_disasm t_da;
// 获取语句反汇编代码
memcpy(&t_da, &code->disasm, sizeof(t_disasm));
// 检测node是否欲跳转至t_da
if (GotoAddr == t_da.ip)
{
node->IsJmcType = TRUE;
return code;
}
// 否则,如果跳转地址在t_da指令之后,则保存t_da的地址
else if (GotoAddr > t_da.ip)
{
LastAddr = t_da.ip;
}
// 否则,如果跳转地址在t_da指令之前
else if (GotoAddr < t_da.ip)
{
if (LastAddr)
{
// 指令跳转地址不明确
node->IsJmcUndefineType = TRUE;
}
}
}
return NULL;
}
/**
* 将指定指令列表CodeList编译为虚拟机字节码
*
* baseaddr:代码基址
* CodeList:欲编译的指令
* ErrText:返回出错信息
*
* 返回值:成功返回TRUE,否则FALSE
*/
BOOL CCodeILFactory::BuildCode(char * baseaddr, list<CodeNode*> * CodeList, char * ErrText) // *
{
return VMFactory.BuildVMCode(baseaddr, CodeList, ErrText);
}
// ----------------------------------- CCodeILFactory.h ----------------------------------------
// VMPackLib
#ifndef __CCODEILFACTORY__
#define __CCODEILFACTORY__
#include <Windows.h>
#include <stdio.h>
#include "CVirtualMemory.h"
#include "CVMFactory.h"
#include "asm\disasm.h"
/**
* 中间语言字节码工厂
*/
class CCodeILFactory
{
public:
CVirtualMemory m_JumpTable; // JMP表
CVirtualMemory m_CodeEngine; // VM指令引擎
CVirtualMemory m_EnterStub; // 重新进入vm的代码
CVirtualMemory m_VMEnterStubCode; // 重新进入的vmcode
CVirtualMemory m_VMCode; // 通常的vmcode
public:
// 虚拟机工厂
CVMFactory VMFactory;
public:
CCodeILFactory();
public:
void Init(DWORD VirtualAddress);
public:
// 编译汇编代码为VM字节码,返回成功失败
BOOL BuildCode(char* baseaddr,list<CodeNode*> *CodeList,char* ErrText);
public:
// 反汇编代码,识别出函数结束的地方.添加到提供的链表中
// CodeList : 输出汇编链表
// base_addr: 2进制代码
// VirtualAddress : 虚拟地址
void DisasmFunction(list<CodeNode*> *CodeList,char* base_addr, DWORD VirtualAddress);
private:
// 是否是跳转指令
BOOL IsJumpCmd(t_disasm* da);
// 是否是函数调用指令
BOOL IsCallCmd(t_disasm* da);
// 是否是返回指令
BOOL IsRetnCmd(t_disasm* da);
//从链表中搜索一个地址的节点
CodeNode* SearchAddrAsList( list<CodeNode*>* List,CodeNode* node );
};// END CLASS DEFINITION CCodeILFactory
#endif // __CCODEILFACTORY__
// ------------------------------------------ VCommand.h----------------------------------------
// 漏发的文件
// "VMEND"结束标记
#define VM_END __asm push esi \
__asm dec ebp \
__asm inc ebp \
__asm dec esi \
__asm inc esp
#define INTCC __asm _emit 0xCC
// 进入虚拟机
void VStartVM();
//检测堆栈是否覆盖
void DCheckESP();
//带D的为内部Handler
//内部push pop只做32位操作,段寄存器也当寄存器处理
void DPushReg32();
void DPushImm32();
void DPushMem32();
void DPopReg32();//弹回寄存器
void DFree();//释放堆栈
