欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

再发

再发

// ---------------------------------------- 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();//释放堆栈

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功